1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. 4 * Copyright (c) 2014- QLogic Corporation. 5 * All rights reserved 6 * www.qlogic.com 7 * 8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter. 9 */ 10 11 #include "bfad_drv.h" 12 #include "bfa_modules.h" 13 #include "bfi_reg.h" 14 15 void 16 bfa_hwcb_reginit(struct bfa_s *bfa) 17 { 18 struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; 19 void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); 20 int fn = bfa_ioc_pcifn(&bfa->ioc); 21 22 if (fn == 0) { 23 bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); 24 bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK); 25 } else { 26 bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS); 27 bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK); 28 } 29 } 30 31 static void 32 bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq) 33 { 34 writel(__HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq), 35 bfa->iocfc.bfa_regs.intr_status); 36 } 37 38 /* 39 * Actions to respond RME Interrupt for Crossbow ASIC: 40 * - Write 1 to Interrupt Status register 41 * INTX - done in bfa_intx() 42 * MSIX - done in bfa_hwcb_rspq_ack_msix() 43 * - Update CI (only if new CI) 44 */ 45 static void 46 bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci) 47 { 48 writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq), 49 bfa->iocfc.bfa_regs.intr_status); 50 51 if (bfa_rspq_ci(bfa, rspq) == ci) 52 return; 53 54 bfa_rspq_ci(bfa, rspq) = ci; 55 writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); 56 } 57 58 void 59 bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci) 60 { 61 if (bfa_rspq_ci(bfa, rspq) == ci) 62 return; 63 64 bfa_rspq_ci(bfa, rspq) = ci; 65 writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); 66 } 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 89 *msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | 90 __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS); 91 *num_vecs = __HFN_NUMINTS; 92 } 93 94 /* 95 * Dummy interrupt handler for handling spurious interrupts. 96 */ 97 static void 98 bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec) 99 { 100 } 101 102 /* 103 * No special setup required for crossbow -- vector assignments are implicit. 104 */ 105 void 106 bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs) 107 { 108 WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS)); 109 110 bfa->msix.nvecs = nvecs; 111 bfa_hwcb_msix_uninstall(bfa); 112 } 113 114 void 115 bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa) 116 { 117 int i; 118 119 if (bfa->msix.nvecs == 0) 120 return; 121 122 if (bfa->msix.nvecs == 1) { 123 for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++) 124 bfa->msix.handler[i] = bfa_msix_all; 125 return; 126 } 127 128 for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++) 129 bfa->msix.handler[i] = bfa_msix_lpu_err; 130 } 131 132 void 133 bfa_hwcb_msix_queue_install(struct bfa_s *bfa) 134 { 135 int i; 136 137 if (bfa->msix.nvecs == 0) 138 return; 139 140 if (bfa->msix.nvecs == 1) { 141 for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) 142 bfa->msix.handler[i] = bfa_msix_all; 143 return; 144 } 145 146 for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++) 147 bfa->msix.handler[i] = bfa_msix_reqq; 148 149 for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) 150 bfa->msix.handler[i] = bfa_msix_rspq; 151 } 152 153 void 154 bfa_hwcb_msix_uninstall(struct bfa_s *bfa) 155 { 156 int i; 157 158 for (i = 0; i < BFI_MSIX_CB_MAX; i++) 159 bfa->msix.handler[i] = bfa_hwcb_msix_dummy; 160 } 161 162 /* 163 * No special enable/disable -- vector assignments are implicit. 164 */ 165 void 166 bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) 167 { 168 if (msix) { 169 bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix; 170 bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; 171 } else { 172 bfa->iocfc.hwif.hw_reqq_ack = NULL; 173 bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; 174 } 175 } 176 177 void 178 bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end) 179 { 180 *start = BFI_MSIX_RME_QMIN_CB; 181 *end = BFI_MSIX_RME_QMAX_CB; 182 } 183