diff options
Diffstat (limited to 'drivers/scsi/bfa/bfa_hw_cb.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_hw_cb.c | 130 |
1 files changed, 80 insertions, 50 deletions
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c index 977e681ec803..ea24d4c6e67a 100644 --- a/drivers/scsi/bfa/bfa_hw_cb.c +++ b/drivers/scsi/bfa/bfa_hw_cb.c @@ -17,14 +17,14 @@ #include "bfad_drv.h" #include "bfa_modules.h" -#include "bfi_cbreg.h" +#include "bfi_reg.h" void bfa_hwcb_reginit(struct bfa_s *bfa) { struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); - int i, q, fn = bfa_ioc_pcifn(&bfa->ioc); + int fn = bfa_ioc_pcifn(&bfa->ioc); if (fn == 0) { bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); @@ -33,29 +33,6 @@ bfa_hwcb_reginit(struct bfa_s *bfa) bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS); bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK); } - - for (i = 0; i < BFI_IOC_MAX_CQS; i++) { - /* - * CPE registers - */ - q = CPE_Q_NUM(fn, i); - bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q)); - bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q)); - bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q)); - - /* - * RME registers - */ - q = CPE_Q_NUM(fn, i); - bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q)); - bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q)); - bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q)); - } -} - -void -bfa_hwcb_reqq_ack(struct bfa_s *bfa, int reqq) -{ } static void @@ -65,16 +42,36 @@ bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq) bfa->iocfc.bfa_regs.intr_status); } -void -bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq) +/* + * Actions to respond RME Interrupt for Crossbow ASIC: + * - Write 1 to Interrupt Status register + * INTX - done in bfa_intx() + * MSIX - done in bfa_hwcb_rspq_ack_msix() + * - Update CI (only if new CI) + */ +static void +bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci) { + writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq), + bfa->iocfc.bfa_regs.intr_status); + + if (bfa_rspq_ci(bfa, rspq) == ci) + return; + + bfa_rspq_ci(bfa, rspq) = ci; + writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); + mmiowb(); } -static void -bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq) +void +bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci) { - writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq), - bfa->iocfc.bfa_regs.intr_status); + if (bfa_rspq_ci(bfa, rspq) == ci) + return; + + bfa_rspq_ci(bfa, rspq) = ci; + writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); + mmiowb(); } void @@ -104,43 +101,71 @@ bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap, } /* + * Dummy interrupt handler for handling spurious interrupts. + */ +static void +bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec) +{ +} + +/* * No special setup required for crossbow -- vector assignments are implicit. */ void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs) { - int i; - WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS)); bfa->msix.nvecs = nvecs; - if (nvecs == 1) { - for (i = 0; i < BFA_MSIX_CB_MAX; i++) + bfa_hwcb_msix_uninstall(bfa); +} + +void +bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa) +{ + int i; + + if (bfa->msix.nvecs == 0) + return; + + if (bfa->msix.nvecs == 1) { + for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++) bfa->msix.handler[i] = bfa_msix_all; return; } - for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++) - bfa->msix.handler[i] = bfa_msix_reqq; - - for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++) - bfa->msix.handler[i] = bfa_msix_rspq; - - for (; i < BFA_MSIX_CB_MAX; i++) + for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++) bfa->msix.handler[i] = bfa_msix_lpu_err; } -/* - * Crossbow -- dummy, interrupts are masked - */ void -bfa_hwcb_msix_install(struct bfa_s *bfa) +bfa_hwcb_msix_queue_install(struct bfa_s *bfa) { + int i; + + if (bfa->msix.nvecs == 0) + return; + + if (bfa->msix.nvecs == 1) { + for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) + bfa->msix.handler[i] = bfa_msix_all; + return; + } + + for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++) + bfa->msix.handler[i] = bfa_msix_reqq; + + for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) + bfa->msix.handler[i] = bfa_msix_rspq; } void bfa_hwcb_msix_uninstall(struct bfa_s *bfa) { + int i; + + for (i = 0; i < BFI_MSIX_CB_MAX; i++) + bfa->msix.handler[i] = bfa_hwcb_msix_dummy; } /* @@ -149,13 +174,18 @@ bfa_hwcb_msix_uninstall(struct bfa_s *bfa) void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) { - bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix; - bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; + if (msix) { + bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix; + bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; + } else { + bfa->iocfc.hwif.hw_reqq_ack = NULL; + bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; + } } void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end) { - *start = BFA_MSIX_RME_Q0; - *end = BFA_MSIX_RME_Q7; + *start = BFI_MSIX_RME_QMIN_CB; + *end = BFI_MSIX_RME_QMAX_CB; } |