summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2011-06-13 15:52:40 -0700
committerJames Bottomley <JBottomley@Parallels.com>2011-06-29 15:50:50 -0500
commit8b070b4a022f86dd5098308e36426ce29b6b8960 (patch)
tree6e6e2077aa3de449d4e3917392eb0179a635f1ad /drivers/scsi/bfa
parent775c7742adfd7726f05914198bf33eaa3b9f64bb (diff)
downloadlinux-8b070b4a022f86dd5098308e36426ce29b6b8960.tar.bz2
[SCSI] bfa: Brocade-1860 Fabric Adapter 16Gbs support and flash controller fixes.
- Added support for 16Gbps. - Added logic to flush pending mailbox command queue when IOC is disabled. - Fix to Halt the flash controller during fw initialization - since when asic blck is programmed flash controller's continuous access blocks f/w access to flash. - Added new asic based card types and modified IOC get card model routine. - Added PLL init fix to do LPU reset every time we do a memory initialization, since not doing so will cause LPU to be uninitialized during driver load. - Added fix to Halt flash controller before PLL initialization. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r--drivers/scsi/bfa/bfa_defs.h18
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h6
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c68
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h7
-rw-r--r--drivers/scsi/bfa/bfa_ioc_ct.c42
-rw-r--r--drivers/scsi/bfa/bfad.c3
-rw-r--r--drivers/scsi/bfa/bfad_attr.c3
-rw-r--r--drivers/scsi/bfa/bfad_im.c5
-rw-r--r--drivers/scsi/bfa/bfi.h2
-rw-r--r--drivers/scsi/bfa/bfi_reg.h7
10 files changed, 130 insertions, 31 deletions
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index be1ba54fa193..7dbf3624d169 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -40,7 +40,12 @@ enum {
BFA_MFG_TYPE_ASTRA = 807, /* Astra mezz card */
BFA_MFG_TYPE_LIGHTNING_P0 = 902, /* Lightning mezz card - old */
BFA_MFG_TYPE_LIGHTNING = 1741, /* Lightning mezz card */
- BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */
+ BFA_MFG_TYPE_PROWLER_F = 1560, /* Prowler FC only cards */
+ BFA_MFG_TYPE_PROWLER_N = 1410, /* Prowler NIC only cards */
+ BFA_MFG_TYPE_PROWLER_C = 1710, /* Prowler CNA only cards */
+ BFA_MFG_TYPE_PROWLER_D = 1860, /* Prowler Dual cards */
+ BFA_MFG_TYPE_CHINOOK = 1867, /* Chinook cards */
+ BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */
};
#pragma pack(1)
@@ -53,7 +58,8 @@ enum {
(type) == BFA_MFG_TYPE_WANCHESE || \
(type) == BFA_MFG_TYPE_ASTRA || \
(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
- (type) == BFA_MFG_TYPE_LIGHTNING))
+ (type) == BFA_MFG_TYPE_LIGHTNING || \
+ (type) == BFA_MFG_TYPE_CHINOOK))
/*
* Check if the card having old wwn/mac handling
@@ -337,6 +343,11 @@ struct bfa_ioc_attr_s {
#define BFA_MFG_SUPPLIER_PARTNUM_SIZE 20
#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE 20
#define BFA_MFG_SUPPLIER_REVISION_SIZE 4
+/*
+ * Initial capability definition
+ */
+#define BFA_MFG_IC_FC 0x01
+#define BFA_MFG_IC_ETH 0x02
#pragma pack(1)
@@ -425,7 +436,8 @@ enum bfa_port_speed {
BFA_PORT_SPEED_16GBPS = 16,
BFA_PORT_SPEED_AUTO =
(BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
- BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS),
+ BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS |
+ BFA_PORT_SPEED_16GBPS),
};
#define bfa_port_speed_t enum bfa_port_speed
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index ece51ec7620b..24c4cfb30098 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -66,6 +66,9 @@ fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
case RPSC_OP_SPEED_8G:
return BFA_PORT_SPEED_8GBPS;
+ case RPSC_OP_SPEED_16G:
+ return BFA_PORT_SPEED_16GBPS;
+
case RPSC_OP_SPEED_10G:
return BFA_PORT_SPEED_10GBPS;
@@ -94,6 +97,9 @@ fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
case BFA_PORT_SPEED_8GBPS:
return RPSC_OP_SPEED_8G;
+ case BFA_PORT_SPEED_16GBPS:
+ return RPSC_OP_SPEED_16G;
+
case BFA_PORT_SPEED_10GBPS:
return RPSC_OP_SPEED_10G;
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 9c6e493cb9c7..b9413c2e67ff 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -85,7 +85,7 @@ static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);
static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
@@ -971,6 +971,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
static void
bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
{
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
}
@@ -1081,7 +1082,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
/*
* Flush any queued up mailbox requests.
*/
- bfa_ioc_mbox_hbfail(iocpf->ioc);
+ bfa_ioc_mbox_flush(iocpf->ioc);
bfa_ioc_hw_sem_get(iocpf->ioc);
}
@@ -1399,6 +1400,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
if (!fwvalid) {
bfa_ioc_boot(ioc, boot_type, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
return;
}
@@ -1434,6 +1436,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
* Initialize the h/w for any other states.
*/
bfa_ioc_boot(ioc, boot_type, boot_env);
+ bfa_ioc_poll_fwinit(ioc);
}
static void
@@ -1668,7 +1671,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
* Cleanup any pending requests.
*/
static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)
{
struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
struct bfa_mbox_cmd_s *cmd;
@@ -2178,22 +2181,28 @@ bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
struct bfi_mbmsg_s m;
int mc;
- if (!bfa_ioc_msgget(ioc, &m))
- return;
+ if (bfa_ioc_msgget(ioc, &m)) {
+ /*
+ * Treat IOC message class as special.
+ */
+ mc = m.mh.msg_class;
+ if (mc == BFI_MC_IOC) {
+ bfa_ioc_isr(ioc, &m);
+ return;
+ }
- /*
- * Treat IOC message class as special.
- */
- mc = m.mh.msg_class;
- if (mc == BFI_MC_IOC) {
- bfa_ioc_isr(ioc, &m);
- return;
+ if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+ return;
+
+ mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
}
- if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
- return;
+ bfa_ioc_lpu_read_stat(ioc);
- mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+ /*
+ * Try to send pending mailbox commands
+ */
+ bfa_ioc_mbox_poll(ioc);
}
void
@@ -2392,8 +2401,33 @@ bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
/*
* model name
*/
- snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
- BFA_MFG_NAME, ioc_attr->card_type);
+ if (ioc->asic_gen == BFI_ASIC_GEN_CT2) {
+ int np = bfa_ioc_get_nports(ioc);
+ char c;
+ switch (ioc_attr->card_type) {
+ case BFA_MFG_TYPE_PROWLER_F:
+ case BFA_MFG_TYPE_PROWLER_N:
+ case BFA_MFG_TYPE_PROWLER_C:
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN,
+ "%s-%u-%u",
+ BFA_MFG_NAME, ioc_attr->card_type, np);
+ break;
+ case BFA_MFG_TYPE_PROWLER_D:
+ if (ioc_attr->ic == BFA_MFG_IC_FC)
+ c = 'F';
+ else
+ c = 'P';
+
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN,
+ "%s-%u-%u%c",
+ BFA_MFG_NAME, ioc_attr->card_type, np, c);
+ break;
+ default:
+ break;
+ }
+ } else
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+ BFA_MFG_NAME, ioc_attr->card_type);
}
enum bfa_ioc_state
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 8c9bbdf26482..527e613530e3 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -136,6 +136,7 @@ struct bfa_ioc_regs_s {
void __iomem *hfn_mbox;
void __iomem *lpu_mbox_cmd;
void __iomem *lpu_mbox;
+ void __iomem *lpu_read_stat;
void __iomem *pss_ctl_reg;
void __iomem *pss_err_status_reg;
void __iomem *app_pll_fast_ctl_reg;
@@ -277,6 +278,7 @@ struct bfa_ioc_hwif_s {
void (*ioc_sync_leave) (struct bfa_ioc_s *ioc);
void (*ioc_sync_ack) (struct bfa_ioc_s *ioc);
bfa_boolean_t (*ioc_sync_complete) (struct bfa_ioc_s *ioc);
+ bfa_boolean_t (*ioc_lpu_read_stat) (struct bfa_ioc_s *ioc);
};
#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func)
@@ -338,7 +340,10 @@ bfa_status_t bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode);
} while (0)
#define bfa_ioc_ownership_reset(__ioc) \
((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
-
+#define bfa_ioc_lpu_read_stat(__ioc) do { \
+ if ((__ioc)->ioc_hwif->ioc_lpu_read_stat) \
+ ((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc)); \
+} while (0)
void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc);
void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 6710a8016601..5b5579401d43 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -192,11 +192,14 @@ static struct { u32 hfn, lpu; } ct_p1reg[] = {
{ HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT }
};
-static struct { uint32_t hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu; } ct2_reg[] = {
+static struct { uint32_t hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu, lpu_read; }
+ ct2_reg[] = {
{ CT2_HOSTFN_LPU0_MBOX0, CT2_LPU0_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
- CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT },
+ CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT,
+ CT2_HOSTFN_LPU0_READ_STAT},
{ CT2_HOSTFN_LPU1_MBOX0, CT2_LPU1_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
- CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT },
+ CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT,
+ CT2_HOSTFN_LPU1_READ_STAT},
};
static void
@@ -271,6 +274,7 @@ bfa_ioc_ct2_reg_init(struct bfa_ioc_s *ioc)
ioc->ioc_regs.host_page_num_fn = rb + ct2_reg[port].hfn_pgn;
ioc->ioc_regs.hfn_mbox_cmd = rb + ct2_reg[port].hfn;
ioc->ioc_regs.lpu_mbox_cmd = rb + ct2_reg[port].lpu;
+ ioc->ioc_regs.lpu_read_stat = rb + ct2_reg[port].lpu_read;
if (port == 0) {
ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC0_HBEAT_REG;
@@ -379,6 +383,20 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
writel(r32, rb + FNC_PERS_REG);
}
+bfa_boolean_t
+bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc_s *ioc)
+{
+ u32 r32;
+
+ r32 = readl(ioc->ioc_regs.lpu_read_stat);
+ if (r32) {
+ writel(1, ioc->ioc_regs.lpu_read_stat);
+ return BFA_TRUE;
+ }
+
+ return BFA_FALSE;
+}
+
/*
* Cleanup hw semaphore and usecnt registers
*/
@@ -540,6 +558,7 @@ bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc)
hwif_ct2.ioc_pll_init = bfa_ioc_ct2_pll_init;
hwif_ct2.ioc_reg_init = bfa_ioc_ct2_reg_init;
hwif_ct2.ioc_map_port = bfa_ioc_ct2_map_port;
+ hwif_ct2.ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat;
hwif_ct2.ioc_isr_mode_set = NULL;
ioc->ioc_hwif = &hwif_ct2;
}
@@ -791,15 +810,26 @@ bfa_ioc_ct2_mem_init(void __iomem *rb, enum bfi_asic_mode mode)
bfa_status_t
bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
{
+ u32 r32;
+
+ /*
+ * Initialize PLL if not already done by NFC
+ */
+ r32 = readl((rb + CT2_WGN_STATUS));
+
+ writel(__HALT_NFC_CONTROLLER, (rb + CT2_NFC_CSR_SET_REG));
+
bfa_ioc_ct2_sclk_init(rb, mode);
bfa_ioc_ct2_lclk_init(rb, mode);
bfa_ioc_ct2_mem_init(rb, mode);
/*
- * Disable flash presence to NFC by clearing GPIO 0
+ * Announce flash device presence, if flash was corrupted.
*/
- writel(0, (rb + PSS_GPIO_OUT_REG));
- writel(1, (rb + PSS_GPIO_OE_REG));
+ if (r32 == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
+ writel(0, (rb + PSS_GPIO_OUT_REG));
+ writel(1, (rb + PSS_GPIO_OE_REG));
+ }
writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG));
writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG));
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 8ddae0d85fa8..57cc50eacb0f 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -1348,8 +1348,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
int error = -ENODEV, retval;
/* For single port cards - only claim function 0 */
- if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P ||
- pdev->device == BFA_PCI_DEVICE_ID_CT2) &&
+ if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) &&
(PCI_FUNC(pdev->devfn) != 0))
return -ENODEV;
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index a94ea4235433..3127df2951e6 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -218,6 +218,9 @@ bfad_im_get_host_speed(struct Scsi_Host *shost)
case BFA_PORT_SPEED_10GBPS:
fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
break;
+ case BFA_PORT_SPEED_16GBPS:
+ fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
+ break;
case BFA_PORT_SPEED_8GBPS:
fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
break;
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index d6d89fbfa65d..451ff556625d 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -925,7 +925,10 @@ bfad_im_supported_speeds(struct bfa_s *bfa)
return 0;
bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
- if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
+ if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_16GBPS)
+ supported_speed |= FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT |
+ FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT;
+ else if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
if (ioc_attr->adapter_attr.is_mezz) {
supported_speed |= FC_PORTSPEED_8GBIT |
FC_PORTSPEED_4GBIT |
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index e6383f23e065..35af1d11ab2f 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -251,7 +251,7 @@ struct bfi_ioc_attr_s {
u32 adapter_prop; /* adapter properties */
u16 maxfrsize; /* max receive frame size */
char asic_rev;
- u8 rsvd_d;
+ u8 ic; /* initial capability */
char fw_version[BFA_VERSION_LEN];
char optrom_version[BFA_VERSION_LEN];
struct bfa_mfg_vpd_s vpd;
diff --git a/drivers/scsi/bfa/bfi_reg.h b/drivers/scsi/bfa/bfi_reg.h
index de4db72b39e9..d20d2b30ed30 100644
--- a/drivers/scsi/bfa/bfi_reg.h
+++ b/drivers/scsi/bfa/bfi_reg.h
@@ -275,6 +275,8 @@ enum {
#define CT2_HOSTFN_LPU1_CMD_STAT (CT2_PCI_CPQ_BASE + 0x84)
#define CT2_LPU0_HOSTFN_CMD_STAT (CT2_PCI_CPQ_BASE + 0x88)
#define CT2_LPU1_HOSTFN_CMD_STAT (CT2_PCI_CPQ_BASE + 0x8c)
+#define CT2_HOSTFN_LPU0_READ_STAT (CT2_PCI_CPQ_BASE + 0x90)
+#define CT2_HOSTFN_LPU1_READ_STAT (CT2_PCI_CPQ_BASE + 0x94)
#define CT2_HOST_SEM0_REG 0x000148f0
#define CT2_HOST_SEM1_REG 0x000148f4
#define CT2_HOST_SEM2_REG 0x000148f8
@@ -330,6 +332,11 @@ enum {
#define CT2_PMM_1T_CONTROL_REG_P0 0x0002381c
#define __PMM_1T_PNDB_P 0x00000002
#define CT2_PMM_1T_CONTROL_REG_P1 0x00023c1c
+#define CT2_WGN_STATUS 0x00014990
+#define __WGN_READY 0x00000400
+#define __GLBL_PF_VF_CFG_RDY 0x00000200
+#define CT2_NFC_CSR_SET_REG 0x00027424
+#define __HALT_NFC_CONTROLLER 0x00000002
/*
* Name semaphore registers based on usage