PageRenderTime 96ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/scsi/bfa/bfa_sgpg.c

https://bitbucket.org/abioy/linux
C | 231 lines | 150 code | 47 blank | 34 comment | 13 complexity | e406552fc7a115dd6ef865caeb82ba54 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /*
  2. * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
  3. * All rights reserved
  4. * www.brocade.com
  5. *
  6. * Linux driver for Brocade Fibre Channel Host Bus Adapter.
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License (GPL) Version 2 as
  10. * published by the Free Software Foundation
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. */
  17. #include <bfa.h>
  18. BFA_TRC_FILE(HAL, SGPG);
  19. BFA_MODULE(sgpg);
  20. /**
  21. * bfa_sgpg_mod BFA SGPG Mode module
  22. */
  23. /**
  24. * Compute and return memory needed by FCP(im) module.
  25. */
  26. static void
  27. bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
  28. u32 *dm_len)
  29. {
  30. if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
  31. cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
  32. *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
  33. *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
  34. }
  35. static void
  36. bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
  37. struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
  38. {
  39. struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
  40. int i;
  41. struct bfa_sgpg_s *hsgpg;
  42. struct bfi_sgpg_s *sgpg;
  43. u64 align_len;
  44. union {
  45. u64 pa;
  46. union bfi_addr_u addr;
  47. } sgpg_pa;
  48. INIT_LIST_HEAD(&mod->sgpg_q);
  49. INIT_LIST_HEAD(&mod->sgpg_wait_q);
  50. bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
  51. mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
  52. mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
  53. align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
  54. mod->sgpg_arr_pa += align_len;
  55. mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
  56. align_len);
  57. mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
  58. align_len);
  59. hsgpg = mod->hsgpg_arr;
  60. sgpg = mod->sgpg_arr;
  61. sgpg_pa.pa = mod->sgpg_arr_pa;
  62. mod->free_sgpgs = mod->num_sgpgs;
  63. bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
  64. for (i = 0; i < mod->num_sgpgs; i++) {
  65. bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
  66. bfa_os_memset(sgpg, 0, sizeof(*sgpg));
  67. hsgpg->sgpg = sgpg;
  68. hsgpg->sgpg_pa = sgpg_pa.addr;
  69. list_add_tail(&hsgpg->qe, &mod->sgpg_q);
  70. hsgpg++;
  71. sgpg++;
  72. sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
  73. }
  74. bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
  75. bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
  76. bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
  77. }
  78. static void
  79. bfa_sgpg_initdone(struct bfa_s *bfa)
  80. {
  81. }
  82. static void
  83. bfa_sgpg_detach(struct bfa_s *bfa)
  84. {
  85. }
  86. static void
  87. bfa_sgpg_start(struct bfa_s *bfa)
  88. {
  89. }
  90. static void
  91. bfa_sgpg_stop(struct bfa_s *bfa)
  92. {
  93. }
  94. static void
  95. bfa_sgpg_iocdisable(struct bfa_s *bfa)
  96. {
  97. }
  98. /**
  99. * bfa_sgpg_public BFA SGPG public functions
  100. */
  101. bfa_status_t
  102. bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
  103. {
  104. struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
  105. struct bfa_sgpg_s *hsgpg;
  106. int i;
  107. bfa_trc_fp(bfa, nsgpgs);
  108. if (mod->free_sgpgs < nsgpgs)
  109. return BFA_STATUS_ENOMEM;
  110. for (i = 0; i < nsgpgs; i++) {
  111. bfa_q_deq(&mod->sgpg_q, &hsgpg);
  112. bfa_assert(hsgpg);
  113. list_add_tail(&hsgpg->qe, sgpg_q);
  114. }
  115. mod->free_sgpgs -= nsgpgs;
  116. return BFA_STATUS_OK;
  117. }
  118. void
  119. bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
  120. {
  121. struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
  122. struct bfa_sgpg_wqe_s *wqe;
  123. bfa_trc_fp(bfa, nsgpg);
  124. mod->free_sgpgs += nsgpg;
  125. bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
  126. list_splice_tail_init(sgpg_q, &mod->sgpg_q);
  127. if (list_empty(&mod->sgpg_wait_q))
  128. return;
  129. /**
  130. * satisfy as many waiting requests as possible
  131. */
  132. do {
  133. wqe = bfa_q_first(&mod->sgpg_wait_q);
  134. if (mod->free_sgpgs < wqe->nsgpg)
  135. nsgpg = mod->free_sgpgs;
  136. else
  137. nsgpg = wqe->nsgpg;
  138. bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
  139. wqe->nsgpg -= nsgpg;
  140. if (wqe->nsgpg == 0) {
  141. list_del(&wqe->qe);
  142. wqe->cbfn(wqe->cbarg);
  143. }
  144. } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
  145. }
  146. void
  147. bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
  148. {
  149. struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
  150. bfa_assert(nsgpg > 0);
  151. bfa_assert(nsgpg > mod->free_sgpgs);
  152. wqe->nsgpg_total = wqe->nsgpg = nsgpg;
  153. /**
  154. * allocate any left to this one first
  155. */
  156. if (mod->free_sgpgs) {
  157. /**
  158. * no one else is waiting for SGPG
  159. */
  160. bfa_assert(list_empty(&mod->sgpg_wait_q));
  161. list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
  162. wqe->nsgpg -= mod->free_sgpgs;
  163. mod->free_sgpgs = 0;
  164. }
  165. list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
  166. }
  167. void
  168. bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
  169. {
  170. struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
  171. bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
  172. list_del(&wqe->qe);
  173. if (wqe->nsgpg_total != wqe->nsgpg)
  174. bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
  175. wqe->nsgpg_total - wqe->nsgpg);
  176. }
  177. void
  178. bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
  179. void *cbarg)
  180. {
  181. INIT_LIST_HEAD(&wqe->sgpg_q);
  182. wqe->cbfn = cbfn;
  183. wqe->cbarg = cbarg;
  184. }