Skip to content

Commit

Permalink
[SCSI] bfa: Brocade-1860 Fabric Adapter Hardware Enablement
Browse files Browse the repository at this point in the history
- Added support for Brocade-1860 Fabric Adapter.
- Made changes to support single firmware image per asic type.
- Combined bfi_cbreg.h and bfi_ctreg.h defines into bfi_reg.h with
  only minimal defines used by host.
- Added changes to setup CPE/RME Queue register offsets based on
  firmware response.
- Removed queue register offset initializations and added register offsets
  to BFI config response message.
- Added Brocade-1860 asic specific interrupt status definitions and
  mailbox interfaces.

Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Krishna Gudipati authored and James Bottomley committed Jun 29, 2011
1 parent 43ffdf4 commit 1118920
Show file tree
Hide file tree
Showing 18 changed files with 1,262 additions and 1,371 deletions.
14 changes: 8 additions & 6 deletions drivers/scsi/bfa/bfa.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ struct bfa_cb_qe_s {
struct list_head qe;
bfa_cb_cbfn_t cbfn;
bfa_boolean_t once;
u32 rsvd;
void *cbarg;
};

Expand Down Expand Up @@ -205,11 +204,9 @@ struct bfa_iocfc_regs_s {
void __iomem *intr_mask;
void __iomem *cpe_q_pi[BFI_IOC_MAX_CQS];
void __iomem *cpe_q_ci[BFI_IOC_MAX_CQS];
void __iomem *cpe_q_depth[BFI_IOC_MAX_CQS];
void __iomem *cpe_q_ctrl[BFI_IOC_MAX_CQS];
void __iomem *rme_q_ci[BFI_IOC_MAX_CQS];
void __iomem *rme_q_pi[BFI_IOC_MAX_CQS];
void __iomem *rme_q_depth[BFI_IOC_MAX_CQS];
void __iomem *rme_q_ctrl[BFI_IOC_MAX_CQS];
};

Expand Down Expand Up @@ -238,6 +235,8 @@ struct bfa_hwif_s {
u32 *nvecs, u32 *maxvec);
void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
u32 *end);
int cpe_vec_q0;
int rme_vec_q0;
};
typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);

Expand All @@ -257,7 +256,6 @@ struct bfa_iocfc_s {
struct bfi_iocfc_cfg_s *cfginfo;
struct bfa_dma_s cfgrsp_dma;
struct bfi_iocfc_cfgrsp_s *cfgrsp;
struct bfi_iocfc_cfg_reply_s *cfg_reply;
struct bfa_dma_s req_cq_ba[BFI_IOC_MAX_CQS];
struct bfa_dma_s req_cq_shadow_ci[BFI_IOC_MAX_CQS];
struct bfa_dma_s rsp_cq_ba[BFI_IOC_MAX_CQS];
Expand All @@ -277,8 +275,11 @@ struct bfa_iocfc_s {
((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
#define bfa_msix_uninstall(__bfa) \
((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
#define bfa_isr_mode_set(__bfa, __msix) \
((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
#define bfa_isr_mode_set(__bfa, __msix) do { \
if ((__bfa)->iocfc.hwif.hw_isr_mode_set) \
(__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix); \
} while (0)

#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \
((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, \
__nvecs, __maxvec))
Expand Down Expand Up @@ -321,6 +322,7 @@ void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
u32 *end);
void bfa_hwct_reginit(struct bfa_s *bfa);
void bfa_hwct2_reginit(struct bfa_s *bfa);
void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
Expand Down
209 changes: 131 additions & 78 deletions drivers/scsi/bfa/bfa_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "bfad_drv.h"
#include "bfa_modules.h"
#include "bfi_ctreg.h"
#include "bfi_reg.h"

BFA_TRC_FILE(HAL, CORE);

Expand Down Expand Up @@ -173,6 +173,58 @@ bfa_reqq_resume(struct bfa_s *bfa, int qid)
}
}

static inline void
bfa_isr_rspq(struct bfa_s *bfa, int qid)
{
struct bfi_msg_s *m;
u32 pi, ci;
struct list_head *waitq;

bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);

ci = bfa_rspq_ci(bfa, qid);
pi = bfa_rspq_pi(bfa, qid);

while (ci != pi) {
m = bfa_rspq_elem(bfa, qid, ci);
WARN_ON(m->mhdr.msg_class >= BFI_MC_MAX);

bfa_isrs[m->mhdr.msg_class] (bfa, m);
CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
}

/*
* update CI
*/
bfa_rspq_ci(bfa, qid) = pi;
writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
mmiowb();

/*
* Resume any pending requests in the corresponding reqq.
*/
waitq = bfa_reqq(bfa, qid);
if (!list_empty(waitq))
bfa_reqq_resume(bfa, qid);
}

static inline void
bfa_isr_reqq(struct bfa_s *bfa, int qid)
{
struct list_head *waitq;

qid &= (BFI_IOC_MAX_CQS - 1);

bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);

/*
* Resume any pending requests in the corresponding reqq.
*/
waitq = bfa_reqq(bfa, qid);
if (!list_empty(waitq))
bfa_reqq_resume(bfa, qid);
}

void
bfa_msix_all(struct bfa_s *bfa, int vec)
{
Expand All @@ -197,7 +249,7 @@ bfa_intx(struct bfa_s *bfa)

for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
if (intr & (__HFN_INT_RME_Q0 << queue))
bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
bfa_isr_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
}
intr &= ~qintr;
if (!intr)
Expand All @@ -211,7 +263,7 @@ bfa_intx(struct bfa_s *bfa)

for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
if (intr & (__HFN_INT_CPE_Q0 << queue))
bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
bfa_isr_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
}
intr &= ~qintr;
if (!intr)
Expand All @@ -225,32 +277,25 @@ bfa_intx(struct bfa_s *bfa)
void
bfa_isr_enable(struct bfa_s *bfa)
{
u32 intr_unmask;
u32 umsk;
int pci_func = bfa_ioc_pcifn(&bfa->ioc);

bfa_trc(bfa, pci_func);

bfa_msix_install(bfa);
intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
__HFN_INT_LL_HALT);

if (pci_func == 0)
intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
__HFN_INT_MBOX_LPU0);
else
intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
__HFN_INT_MBOX_LPU1);

writel(intr_unmask, bfa->iocfc.bfa_regs.intr_status);
writel(~intr_unmask, bfa->iocfc.bfa_regs.intr_mask);
bfa->iocfc.intr_mask = ~intr_unmask;

if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
umsk = __HFN_INT_ERR_MASK_CT2;
umsk |= pci_func == 0 ?
__HFN_INT_FN0_MASK_CT2 : __HFN_INT_FN1_MASK_CT2;
} else {
umsk = __HFN_INT_ERR_MASK;
umsk |= pci_func == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK;
}

writel(umsk, bfa->iocfc.bfa_regs.intr_status);
writel(~umsk, bfa->iocfc.bfa_regs.intr_mask);
bfa->iocfc.intr_mask = ~umsk;
bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
}

Expand All @@ -263,20 +308,9 @@ bfa_isr_disable(struct bfa_s *bfa)
}

void
bfa_msix_reqq(struct bfa_s *bfa, int qid)
bfa_msix_reqq(struct bfa_s *bfa, int vec)
{
struct list_head *waitq;

qid &= (BFI_IOC_MAX_CQS - 1);

bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);

/*
* Resume any pending requests in the corresponding reqq.
*/
waitq = bfa_reqq(bfa, qid);
if (!list_empty(waitq))
bfa_reqq_resume(bfa, qid);
bfa_isr_reqq(bfa, vec - bfa->iocfc.hwif.cpe_vec_q0);
}

void
Expand All @@ -290,57 +324,40 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
}

void
bfa_msix_rspq(struct bfa_s *bfa, int qid)
bfa_msix_rspq(struct bfa_s *bfa, int vec)
{
struct bfi_msg_s *m;
u32 pi, ci;
struct list_head *waitq;

qid &= (BFI_IOC_MAX_CQS - 1);

bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);

ci = bfa_rspq_ci(bfa, qid);
pi = bfa_rspq_pi(bfa, qid);

if (bfa->rme_process) {
while (ci != pi) {
m = bfa_rspq_elem(bfa, qid, ci);
bfa_isrs[m->mhdr.msg_class] (bfa, m);
CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
}
}

/*
* update CI
*/
bfa_rspq_ci(bfa, qid) = pi;
writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
mmiowb();
if (!bfa->rme_process)
return;

/*
* Resume any pending requests in the corresponding reqq.
*/
waitq = bfa_reqq(bfa, qid);
if (!list_empty(waitq))
bfa_reqq_resume(bfa, qid);
bfa_isr_rspq(bfa, vec - bfa->iocfc.hwif.rme_vec_q0);
}

void
bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
{
u32 intr, curr_value;
bfa_boolean_t lpu_isr, halt_isr, pss_isr;

intr = readl(bfa->iocfc.bfa_regs.intr_status);

if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
bfa_ioc_mbox_isr(&bfa->ioc);
if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
halt_isr = intr & __HFN_INT_CPQ_HALT_CT2;
pss_isr = intr & __HFN_INT_ERR_PSS_CT2;
lpu_isr = intr & (__HFN_INT_MBOX_LPU0_CT2 |
__HFN_INT_MBOX_LPU1_CT2);
intr &= __HFN_INT_ERR_MASK_CT2;
} else {
halt_isr = intr & __HFN_INT_LL_HALT;
pss_isr = intr & __HFN_INT_ERR_PSS;
lpu_isr = intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1);
intr &= __HFN_INT_ERR_MASK;
}

intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
if (lpu_isr)
bfa_ioc_mbox_isr(&bfa->ioc);

if (intr) {
if (intr & __HFN_INT_LL_HALT) {
if (halt_isr) {
/*
* If LL_HALT bit is set then FW Init Halt LL Port
* Register needs to be cleared as well so Interrupt
Expand All @@ -351,15 +368,14 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
writel(curr_value, bfa->ioc.ioc_regs.ll_halt);
}

if (intr & __HFN_INT_ERR_PSS) {
if (pss_isr) {
/*
* ERR_PSS bit needs to be cleared as well in case
* interrups are shared so driver's interrupt handler is
* still called even though it is already masked out.
*/
curr_value = readl(
bfa->ioc.ioc_regs.pss_err_status_reg);
curr_value &= __PSS_ERR_STATUS_SET;
writel(curr_value,
bfa->ioc.ioc_regs.pss_err_status_reg);
}
Expand Down Expand Up @@ -491,7 +507,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
/*
* Initialize chip specific handlers.
*/
if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
if (bfa_asic_id_ctc(bfa_ioc_devid(&bfa->ioc))) {
iocfc->hwif.hw_reginit = bfa_hwct_reginit;
iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
Expand All @@ -501,6 +517,8 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CT;
iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CT;
} else {
iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
Expand All @@ -511,6 +529,15 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CB +
bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CB +
bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
}

if (bfa_asic_id_ct2(bfa_ioc_devid(&bfa->ioc))) {
iocfc->hwif.hw_reginit = bfa_hwct2_reginit;
iocfc->hwif.hw_isr_mode_set = NULL;
}

iocfc->hwif.hw_reginit(bfa);
Expand Down Expand Up @@ -614,6 +641,8 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
int i;

bfa->rme_process = BFA_TRUE;
for (i = 0; i < BFI_IOC_MAX_CQS; i++)
bfa->iocfc.hwif.hw_rspq_ack(bfa, i);

for (i = 0; hal_mods[i]; i++)
hal_mods[i]->start(bfa);
Expand Down Expand Up @@ -669,6 +698,26 @@ bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
complete(&bfad->disable_comp);
}

/**
* configure queue registers from firmware response
*/
static void
bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg)
{
int i;
struct bfa_iocfc_regs_s *r = &bfa->iocfc.bfa_regs;
void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);

for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
r->cpe_q_ci[i] = kva + be32_to_cpu(qreg->cpe_q_ci_off[i]);
r->cpe_q_pi[i] = kva + be32_to_cpu(qreg->cpe_q_pi_off[i]);
r->cpe_q_ctrl[i] = kva + be32_to_cpu(qreg->cpe_qctl_off[i]);
r->rme_q_ci[i] = kva + be32_to_cpu(qreg->rme_q_ci_off[i]);
r->rme_q_pi[i] = kva + be32_to_cpu(qreg->rme_q_pi_off[i]);
r->rme_q_ctrl[i] = kva + be32_to_cpu(qreg->rme_qctl_off[i]);
}
}

/*
* Update BFA configuration from firmware configuration.
*/
Expand All @@ -688,6 +737,11 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)

iocfc->cfgdone = BFA_TRUE;

/*
* configure queue register offsets as learnt from firmware
*/
bfa_iocfc_qreg(bfa, &cfgrsp->qreg);

/*
* Configuration is complete - initialize/start submodules
*/
Expand Down Expand Up @@ -879,7 +933,6 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)

switch (msg->mh.msg_id) {
case BFI_IOCFC_I2H_CFG_REPLY:
iocfc->cfg_reply = &msg->cfg_reply;
bfa_iocfc_cfgrsp(bfa);
break;
case BFI_IOCFC_I2H_UPDATEQ_RSP:
Expand Down
Loading

0 comments on commit 1118920

Please sign in to comment.