linux/drivers/scsi/bfa/bfa_hw_cb.c
<<
>>
Prefs
   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}
 183