bfa_hw_cb.c (4374B)
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 15void 16bfa_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 31static void 32bfa_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 */ 45static void 46bfa_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 58void 59bfa_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 68void 69bfa_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 */ 97static void 98bfa_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 */ 105void 106bfa_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 114void 115bfa_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 132void 133bfa_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 153void 154bfa_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 */ 165void 166bfa_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 177void 178bfa_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}