bfa_hw_cb.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
  3. * Copyright (c) 2014- QLogic Corporation.
  4. * All rights reserved
  5. * www.qlogic.com
  6. *
  7. * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License (GPL) Version 2 as
  11. * published by the Free Software Foundation
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. */
  18. #include "bfad_drv.h"
  19. #include "bfa_modules.h"
  20. #include "bfi_reg.h"
  21. void
  22. bfa_hwcb_reginit(struct bfa_s *bfa)
  23. {
  24. struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
  25. void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
  26. int fn = bfa_ioc_pcifn(&bfa->ioc);
  27. if (fn == 0) {
  28. bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
  29. bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK);
  30. } else {
  31. bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
  32. bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
  33. }
  34. }
  35. static void
  36. bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
  37. {
  38. writel(__HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq),
  39. bfa->iocfc.bfa_regs.intr_status);
  40. }
  41. /*
  42. * Actions to respond RME Interrupt for Crossbow ASIC:
  43. * - Write 1 to Interrupt Status register
  44. * INTX - done in bfa_intx()
  45. * MSIX - done in bfa_hwcb_rspq_ack_msix()
  46. * - Update CI (only if new CI)
  47. */
  48. static void
  49. bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci)
  50. {
  51. writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq),
  52. bfa->iocfc.bfa_regs.intr_status);
  53. if (bfa_rspq_ci(bfa, rspq) == ci)
  54. return;
  55. bfa_rspq_ci(bfa, rspq) = ci;
  56. writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
  57. mmiowb();
  58. }
  59. void
  60. bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
  61. {
  62. if (bfa_rspq_ci(bfa, rspq) == ci)
  63. return;
  64. bfa_rspq_ci(bfa, rspq) = ci;
  65. writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
  66. mmiowb();
  67. }
  68. void
  69. bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
  70. u32 *num_vecs, u32 *max_vec_bit)
  71. {
  72. #define __HFN_NUMINTS 13
  73. if (bfa_ioc_pcifn(&bfa->ioc) == 0) {
  74. *msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
  75. __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
  76. __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
  77. __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
  78. __HFN_INT_MBOX_LPU0);
  79. *max_vec_bit = __HFN_INT_MBOX_LPU0;
  80. } else {
  81. *msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
  82. __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
  83. __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
  84. __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
  85. __HFN_INT_MBOX_LPU1);
  86. *max_vec_bit = __HFN_INT_MBOX_LPU1;
  87. }
  88. *msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
  89. __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
  90. *num_vecs = __HFN_NUMINTS;
  91. }
  92. /*
  93. * Dummy interrupt handler for handling spurious interrupts.
  94. */
  95. static void
  96. bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec)
  97. {
  98. }
  99. /*
  100. * No special setup required for crossbow -- vector assignments are implicit.
  101. */
  102. void
  103. bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
  104. {
  105. WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
  106. bfa->msix.nvecs = nvecs;
  107. bfa_hwcb_msix_uninstall(bfa);
  108. }
  109. void
  110. bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa)
  111. {
  112. int i;
  113. if (bfa->msix.nvecs == 0)
  114. return;
  115. if (bfa->msix.nvecs == 1) {
  116. for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++)
  117. bfa->msix.handler[i] = bfa_msix_all;
  118. return;
  119. }
  120. for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
  121. bfa->msix.handler[i] = bfa_msix_lpu_err;
  122. }
  123. void
  124. bfa_hwcb_msix_queue_install(struct bfa_s *bfa)
  125. {
  126. int i;
  127. if (bfa->msix.nvecs == 0)
  128. return;
  129. if (bfa->msix.nvecs == 1) {
  130. for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
  131. bfa->msix.handler[i] = bfa_msix_all;
  132. return;
  133. }
  134. for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++)
  135. bfa->msix.handler[i] = bfa_msix_reqq;
  136. for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
  137. bfa->msix.handler[i] = bfa_msix_rspq;
  138. }
  139. void
  140. bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
  141. {
  142. int i;
  143. for (i = 0; i < BFI_MSIX_CB_MAX; i++)
  144. bfa->msix.handler[i] = bfa_hwcb_msix_dummy;
  145. }
  146. /*
  147. * No special enable/disable -- vector assignments are implicit.
  148. */
  149. void
  150. bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
  151. {
  152. if (msix) {
  153. bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix;
  154. bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
  155. } else {
  156. bfa->iocfc.hwif.hw_reqq_ack = NULL;
  157. bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
  158. }
  159. }
  160. void
  161. bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
  162. {
  163. *start = BFI_MSIX_RME_QMIN_CB;
  164. *end = BFI_MSIX_RME_QMAX_CB;
  165. }