From 8b070b4a022f86dd5098308e36426ce29b6b8960 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Mon, 13 Jun 2011 15:52:40 -0700 Subject: [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 Signed-off-by: James Bottomley diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index be1ba54..7dbf362 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 ece51ec..24c4cfb 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 9c6e493..b9413c2 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 8c9bbdf..527e613 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 6710a80..5b55794 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 8ddae0d..57cc50e 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 a94ea42..3127df2 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 d6d89fb..451ff55 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 e6383f2..35af1d1 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 de4db72..d20d2b3 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 -- cgit v0.10.2