Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
0004  * Copyright (c) 2014- QLogic Corporation.
0005  * All rights reserved
0006  * www.qlogic.com
0007  *
0008  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
0009  */
0010 
0011 #include "bfad_drv.h"
0012 #include "bfa_modules.h"
0013 #include "bfi_reg.h"
0014 
0015 void
0016 bfa_hwcb_reginit(struct bfa_s *bfa)
0017 {
0018     struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
0019     void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
0020     int fn = bfa_ioc_pcifn(&bfa->ioc);
0021 
0022     if (fn == 0) {
0023         bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
0024         bfa_regs->intr_mask   = (kva + HOSTFN0_INT_MSK);
0025     } else {
0026         bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
0027         bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
0028     }
0029 }
0030 
0031 static void
0032 bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
0033 {
0034     writel(__HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq),
0035             bfa->iocfc.bfa_regs.intr_status);
0036 }
0037 
0038 /*
0039  * Actions to respond RME Interrupt for Crossbow ASIC:
0040  * - Write 1 to Interrupt Status register
0041  *              INTX - done in bfa_intx()
0042  *              MSIX - done in bfa_hwcb_rspq_ack_msix()
0043  * - Update CI (only if new CI)
0044  */
0045 static void
0046 bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci)
0047 {
0048     writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq),
0049         bfa->iocfc.bfa_regs.intr_status);
0050 
0051     if (bfa_rspq_ci(bfa, rspq) == ci)
0052         return;
0053 
0054     bfa_rspq_ci(bfa, rspq) = ci;
0055     writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
0056 }
0057 
0058 void
0059 bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
0060 {
0061     if (bfa_rspq_ci(bfa, rspq) == ci)
0062         return;
0063 
0064     bfa_rspq_ci(bfa, rspq) = ci;
0065     writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
0066 }
0067 
0068 void
0069 bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
0070          u32 *num_vecs, u32 *max_vec_bit)
0071 {
0072 #define __HFN_NUMINTS   13
0073     if (bfa_ioc_pcifn(&bfa->ioc) == 0) {
0074         *msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
0075                    __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
0076                    __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
0077                    __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
0078                    __HFN_INT_MBOX_LPU0);
0079         *max_vec_bit = __HFN_INT_MBOX_LPU0;
0080     } else {
0081         *msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
0082                    __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
0083                    __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
0084                    __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
0085                    __HFN_INT_MBOX_LPU1);
0086         *max_vec_bit = __HFN_INT_MBOX_LPU1;
0087     }
0088 
0089     *msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
0090                 __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
0091     *num_vecs = __HFN_NUMINTS;
0092 }
0093 
0094 /*
0095  * Dummy interrupt handler for handling spurious interrupts.
0096  */
0097 static void
0098 bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec)
0099 {
0100 }
0101 
0102 /*
0103  * No special setup required for crossbow -- vector assignments are implicit.
0104  */
0105 void
0106 bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
0107 {
0108     WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
0109 
0110     bfa->msix.nvecs = nvecs;
0111     bfa_hwcb_msix_uninstall(bfa);
0112 }
0113 
0114 void
0115 bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa)
0116 {
0117     int i;
0118 
0119     if (bfa->msix.nvecs == 0)
0120         return;
0121 
0122     if (bfa->msix.nvecs == 1) {
0123         for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++)
0124             bfa->msix.handler[i] = bfa_msix_all;
0125         return;
0126     }
0127 
0128     for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
0129         bfa->msix.handler[i] = bfa_msix_lpu_err;
0130 }
0131 
0132 void
0133 bfa_hwcb_msix_queue_install(struct bfa_s *bfa)
0134 {
0135     int i;
0136 
0137     if (bfa->msix.nvecs == 0)
0138         return;
0139 
0140     if (bfa->msix.nvecs == 1) {
0141         for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
0142             bfa->msix.handler[i] = bfa_msix_all;
0143         return;
0144     }
0145 
0146     for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++)
0147         bfa->msix.handler[i] = bfa_msix_reqq;
0148 
0149     for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
0150         bfa->msix.handler[i] = bfa_msix_rspq;
0151 }
0152 
0153 void
0154 bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
0155 {
0156     int i;
0157 
0158     for (i = 0; i < BFI_MSIX_CB_MAX; i++)
0159         bfa->msix.handler[i] = bfa_hwcb_msix_dummy;
0160 }
0161 
0162 /*
0163  * No special enable/disable -- vector assignments are implicit.
0164  */
0165 void
0166 bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
0167 {
0168     if (msix) {
0169         bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix;
0170         bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
0171     } else {
0172         bfa->iocfc.hwif.hw_reqq_ack = NULL;
0173         bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
0174     }
0175 }
0176 
0177 void
0178 bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
0179 {
0180     *start = BFI_MSIX_RME_QMIN_CB;
0181     *end = BFI_MSIX_RME_QMAX_CB;
0182 }