aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/bfa
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r--drivers/scsi/bfa/bfa_core.c96
-rw-r--r--drivers/scsi/bfa/bfa_defs.h143
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h188
-rw-r--r--drivers/scsi/bfa/bfa_fc.h22
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c4
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c125
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h13
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c126
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h58
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c393
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c299
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c1290
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h77
-rw-r--r--drivers/scsi/bfa/bfa_ioc_cb.c109
-rw-r--r--drivers/scsi/bfa/bfa_ioc_ct.c282
-rw-r--r--drivers/scsi/bfa/bfa_modules.h1
-rw-r--r--drivers/scsi/bfa/bfa_port.c32
-rw-r--r--drivers/scsi/bfa/bfa_port.h3
-rw-r--r--drivers/scsi/bfa/bfa_svc.c1350
-rw-r--r--drivers/scsi/bfa/bfa_svc.h54
-rw-r--r--drivers/scsi/bfa/bfad.c165
-rw-r--r--drivers/scsi/bfa/bfad_attr.c40
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c485
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h98
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c28
-rw-r--r--drivers/scsi/bfa/bfad_drv.h6
-rw-r--r--drivers/scsi/bfa/bfad_im.c34
-rw-r--r--drivers/scsi/bfa/bfi.h178
-rw-r--r--drivers/scsi/bfa/bfi_ms.h19
-rw-r--r--drivers/scsi/bfa/bfi_reg.h3
30 files changed, 5045 insertions, 676 deletions
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index b7c326f7a6d..e3f67b097a5 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -165,6 +165,16 @@ bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg);
}
+static void
+bfa_com_fru_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+ struct bfa_fru_s *fru = BFA_FRU(bfa);
+ struct bfa_mem_dma_s *fru_dma = BFA_MEM_FRU_DMA(bfa);
+
+ bfa_fru_attach(fru, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+ bfa_fru_memclaim(fru, fru_dma->kva_curp, fru_dma->dma_curp, mincfg);
+}
+
/*
* BFA IOC FC related definitions
*/
@@ -274,6 +284,15 @@ bfa_iocfc_sm_initing(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
case IOCFC_E_IOC_ENABLED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_read);
break;
+
+ case IOCFC_E_DISABLE:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+ break;
+
+ case IOCFC_E_STOP:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping);
+ break;
+
case IOCFC_E_IOC_FAILED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed);
break;
@@ -298,6 +317,15 @@ bfa_iocfc_sm_dconf_read(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
case IOCFC_E_DCONF_DONE:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_cfg_wait);
break;
+
+ case IOCFC_E_DISABLE:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+ break;
+
+ case IOCFC_E_STOP:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping);
+ break;
+
case IOCFC_E_IOC_FAILED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed);
break;
@@ -322,6 +350,15 @@ bfa_iocfc_sm_init_cfg_wait(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
case IOCFC_E_CFG_DONE:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_cfg_done);
break;
+
+ case IOCFC_E_DISABLE:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+ break;
+
+ case IOCFC_E_STOP:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping);
+ break;
+
case IOCFC_E_IOC_FAILED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed);
break;
@@ -433,6 +470,12 @@ bfa_iocfc_sm_stopping(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.stop_hcb_qe,
bfa_iocfc_stop_cb, iocfc->bfa);
break;
+
+ case IOCFC_E_IOC_ENABLED:
+ case IOCFC_E_DCONF_DONE:
+ case IOCFC_E_CFG_DONE:
+ break;
+
default:
bfa_sm_fault(iocfc->bfa, event);
break;
@@ -454,6 +497,15 @@ bfa_iocfc_sm_enabling(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
case IOCFC_E_IOC_ENABLED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_cfg_wait);
break;
+
+ case IOCFC_E_DISABLE:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+ break;
+
+ case IOCFC_E_STOP:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write);
+ break;
+
case IOCFC_E_IOC_FAILED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed);
@@ -493,6 +545,13 @@ bfa_iocfc_sm_cfg_wait(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
bfa_iocfc_enable_cb, iocfc->bfa);
iocfc->bfa->iocfc.cb_reqd = BFA_FALSE;
break;
+ case IOCFC_E_DISABLE:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling);
+ break;
+
+ case IOCFC_E_STOP:
+ bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write);
+ break;
case IOCFC_E_IOC_FAILED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed);
if (iocfc->bfa->iocfc.cb_reqd == BFA_FALSE)
@@ -524,6 +583,10 @@ bfa_iocfc_sm_disabling(struct bfa_iocfc_s *iocfc, enum iocfc_event event)
case IOCFC_E_IOC_DISABLED:
bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabled);
break;
+ case IOCFC_E_IOC_ENABLED:
+ case IOCFC_E_DCONF_DONE:
+ case IOCFC_E_CFG_DONE:
+ break;
default:
bfa_sm_fault(iocfc->bfa, event);
break;
@@ -785,19 +848,20 @@ void
bfa_isr_enable(struct bfa_s *bfa)
{
u32 umsk;
- int pci_func = bfa_ioc_pcifn(&bfa->ioc);
+ int port_id = bfa_ioc_portid(&bfa->ioc);
- bfa_trc(bfa, pci_func);
+ bfa_trc(bfa, bfa_ioc_pcifn(&bfa->ioc));
+ bfa_trc(bfa, port_id);
bfa_msix_ctrl_install(bfa);
if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
umsk = __HFN_INT_ERR_MASK_CT2;
- umsk |= pci_func == 0 ?
+ umsk |= port_id == 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;
+ umsk |= port_id == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK;
}
writel(umsk, bfa->iocfc.bfa_regs.intr_status);
@@ -930,7 +994,8 @@ bfa_iocfc_send_cfg(void *bfa_arg)
cfg_info->single_msix_vec = 1;
cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
cfg_info->num_cqs = cfg->fwcfg.num_cqs;
- cfg_info->num_ioim_reqs = cpu_to_be16(cfg->fwcfg.num_ioim_reqs);
+ cfg_info->num_ioim_reqs = cpu_to_be16(bfa_fcpim_get_throttle_cfg(bfa,
+ cfg->fwcfg.num_ioim_reqs));
cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);
bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
@@ -1192,10 +1257,14 @@ bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg)
static void
bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg)
{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
+
bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs);
bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs);
bfa_rport_res_recfg(bfa, fwcfg->num_rports);
- bfa_fcp_res_recfg(bfa, fwcfg->num_ioim_reqs);
+ bfa_fcp_res_recfg(bfa, cpu_to_be16(cfg_info->num_ioim_reqs),
+ fwcfg->num_ioim_reqs);
bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs);
}
@@ -1298,10 +1367,6 @@ bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
bfa_status_t status;
- iocfc->faa_args.faa_attr = attr;
- iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
- iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
-
status = bfa_faa_validate_request(bfa);
if (status != BFA_STATUS_OK)
return status;
@@ -1309,6 +1374,10 @@ bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
if (iocfc->faa_args.busy == BFA_TRUE)
return BFA_STATUS_DEVBUSY;
+ iocfc->faa_args.faa_attr = attr;
+ iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+ iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
iocfc->faa_args.busy = BFA_TRUE;
memset(&faa_attr_req, 0, sizeof(struct bfi_faa_query_s));
bfi_h2i_set(faa_attr_req.mh, BFI_MC_IOCFC,
@@ -1363,6 +1432,7 @@ bfa_iocfc_disable_cbfn(void *bfa_arg)
{
struct bfa_s *bfa = bfa_arg;
+ bfa->queue_process = BFA_FALSE;
bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_IOC_DISABLED);
}
@@ -1498,7 +1568,6 @@ bfa_iocfc_start(struct bfa_s *bfa)
void
bfa_iocfc_stop(struct bfa_s *bfa)
{
- bfa->queue_process = BFA_FALSE;
bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_STOP);
}
@@ -1605,7 +1674,6 @@ bfa_iocfc_disable(struct bfa_s *bfa)
bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
"IOC Disable");
- bfa->queue_process = BFA_FALSE;
bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DISABLE);
}
@@ -1693,6 +1761,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa);
+ struct bfa_mem_dma_s *fru_dma = BFA_MEM_FRU_DMA(bfa);
WARN_ON((cfg == NULL) || (meminfo == NULL));
@@ -1717,6 +1786,8 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo());
bfa_mem_dma_setup(meminfo, phy_dma,
bfa_phy_meminfo(cfg->drvcfg.min_cfg));
+ bfa_mem_dma_setup(meminfo, fru_dma,
+ bfa_fru_meminfo(cfg->drvcfg.min_cfg));
}
/*
@@ -1789,6 +1860,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
bfa_com_diag_attach(bfa);
bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg);
+ bfa_com_fru_attach(bfa, cfg->drvcfg.min_cfg);
}
/*
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index b5a1595cc0a..877b86dd283 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -45,6 +45,7 @@ enum {
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_CHINOOK2 = 1869, /*!< Chinook2 cards */
BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */
};
@@ -59,7 +60,8 @@ enum {
(type) == BFA_MFG_TYPE_ASTRA || \
(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
(type) == BFA_MFG_TYPE_LIGHTNING || \
- (type) == BFA_MFG_TYPE_CHINOOK))
+ (type) == BFA_MFG_TYPE_CHINOOK || \
+ (type) == BFA_MFG_TYPE_CHINOOK2))
/*
* Check if the card having old wwn/mac handling
@@ -130,6 +132,7 @@ enum bfa_status {
BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists,
* contact support */
BFA_STATUS_EPROTOCOL = 6, /* Protocol error */
+ BFA_STATUS_BADFLASH = 9, /* Flash is bad */
BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */
BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */
BFA_STATUS_DATACORRUPTED = 12, /* Diag returned data corrupted */
@@ -159,10 +162,13 @@ enum bfa_status {
BFA_STATUS_BEACON_ON = 72, /* Port Beacon already on */
BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */
BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */
+ BFA_STATUS_ERROR_TRL_ENABLED = 87, /* TRL is enabled */
+ BFA_STATUS_ERROR_QOS_ENABLED = 88, /* QoS is enabled */
BFA_STATUS_NO_SFP_DEV = 89, /* No SFP device check or replace SFP */
BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */
+ BFA_STATUS_CMD_NOTSUPP_CNA = 146, /* Command not supported for CNA */
BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot
* configuration */
BFA_STATUS_BAD_FWCFG = 156, /* Bad firmware configuration */
@@ -182,8 +188,48 @@ enum bfa_status {
BFA_STATUS_FAA_DISABLED = 198, /* FAA is already disabled */
BFA_STATUS_FAA_ACQUIRED = 199, /* FAA is already acquired */
BFA_STATUS_FAA_ACQ_ADDR = 200, /* Acquiring addr */
+ BFA_STATUS_BBCR_FC_ONLY = 201, /*!< BBCredit Recovery is supported for *
+ * FC mode only */
BFA_STATUS_ERROR_TRUNK_ENABLED = 203, /* Trunk enabled on adapter */
BFA_STATUS_MAX_ENTRY_REACHED = 212, /* MAX entry reached */
+ BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */
+ BFA_STATUS_LOOP_UNSUPP_MEZZ = 231, /* Loop topology is not supported
+ * on mezz cards */
+ BFA_STATUS_INVALID_BW = 233, /* Invalid bandwidth value */
+ BFA_STATUS_QOS_BW_INVALID = 234, /* Invalid QOS bandwidth
+ * configuration */
+ BFA_STATUS_DPORT_ENABLED = 235, /* D-port mode is already enabled */
+ BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */
+ BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */
+ BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */
+ BFA_STATUS_DPORT_NO_SFP = 243, /* SFP is not present.\n D-port will be
+ * enabled but it will be operational
+ * only after inserting a valid SFP. */
+ BFA_STATUS_DPORT_ERR = 245, /* D-port mode is enabled */
+ BFA_STATUS_DPORT_ENOSYS = 254, /* Switch has no D_Port functionality */
+ BFA_STATUS_DPORT_CANT_PERF = 255, /* Switch port is not D_Port capable
+ * or D_Port is disabled */
+ BFA_STATUS_DPORT_LOGICALERR = 256, /* Switch D_Port fail */
+ BFA_STATUS_DPORT_SWBUSY = 257, /* Switch port busy */
+ BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT = 258, /*!< BB credit recovery is
+ * supported at max port speed alone */
+ BFA_STATUS_ERROR_BBCR_ENABLED = 259, /*!< BB credit recovery
+ * is enabled */
+ BFA_STATUS_INVALID_BBSCN = 260, /*!< Invalid BBSCN value.
+ * Valid range is [1-15] */
+ BFA_STATUS_DDPORT_ERR = 261, /* Dynamic D_Port mode is active.\n To
+ * exit dynamic mode, disable D_Port on
+ * the remote port */
+ BFA_STATUS_DPORT_SFPWRAP_ERR = 262, /* Clear e/o_wrap fail, check or
+ * replace SFP */
+ BFA_STATUS_BBCR_CFG_NO_CHANGE = 265, /*!< BBCR is operational.
+ * Disable BBCR and try this operation again. */
+ BFA_STATUS_DPORT_SW_NOTREADY = 268, /* Remote port is not ready to
+ * start dport test. Check remote
+ * port status. */
+ BFA_STATUS_DPORT_INV_SFP = 271, /* Invalid SFP for D-PORT mode. */
+ BFA_STATUS_DPORT_CMD_NOTSUPP = 273, /* Dport is not supported by
+ * remote port */
BFA_STATUS_MAX_VAL /* Unknown error code */
};
#define bfa_status_t enum bfa_status
@@ -220,6 +266,7 @@ enum {
BFA_ADAPTER_MFG_NAME_LEN = 8, /* manufacturer name length */
BFA_ADAPTER_SYM_NAME_LEN = 64, /* adapter symbolic name length */
BFA_ADAPTER_OS_TYPE_LEN = 64, /* adapter os type length */
+ BFA_ADAPTER_UUID_LEN = 16, /* adapter uuid length */
};
struct bfa_adapter_attr_s {
@@ -249,6 +296,11 @@ struct bfa_adapter_attr_s {
u8 is_mezz;
u8 trunk_capable;
+ u8 mfg_day; /* manufacturing day */
+ u8 mfg_month; /* manufacturing month */
+ u16 mfg_year; /* manufacturing year */
+ u16 rsvd;
+ u8 uuid[BFA_ADAPTER_UUID_LEN];
};
/*
@@ -362,7 +414,8 @@ struct bfa_ioc_attr_s {
u8 port_mode; /* bfa_mode_s */
u8 cap_bm; /* capability */
u8 port_mode_cfg; /* bfa_mode_s */
- u8 rsvd[4]; /* 64bit align */
+ u8 def_fn; /* 1 if default fn */
+ u8 rsvd[3]; /* 64bit align */
};
/*
@@ -585,6 +638,7 @@ enum {
BFA_PCI_DEVICE_ID_CT = 0x14,
BFA_PCI_DEVICE_ID_CT_FC = 0x21,
BFA_PCI_DEVICE_ID_CT2 = 0x22,
+ BFA_PCI_DEVICE_ID_CT2_QUAD = 0x23,
};
#define bfa_asic_id_cb(__d) \
@@ -593,7 +647,9 @@ enum {
#define bfa_asic_id_ct(__d) \
((__d) == BFA_PCI_DEVICE_ID_CT || \
(__d) == BFA_PCI_DEVICE_ID_CT_FC)
-#define bfa_asic_id_ct2(__d) ((__d) == BFA_PCI_DEVICE_ID_CT2)
+#define bfa_asic_id_ct2(__d) \
+ ((__d) == BFA_PCI_DEVICE_ID_CT2 || \
+ (__d) == BFA_PCI_DEVICE_ID_CT2_QUAD)
#define bfa_asic_id_ctc(__d) \
(bfa_asic_id_ct(__d) || bfa_asic_id_ct2(__d))
@@ -722,7 +778,8 @@ struct bfa_ablk_cfg_pf_s {
u8 rsvd[1];
u16 num_qpairs;
u16 num_vectors;
- u32 bw;
+ u16 bw_min;
+ u16 bw_max;
};
struct bfa_ablk_cfg_port_s {
@@ -889,11 +946,40 @@ struct sfp_diag_ext_s {
u8 ext_status_ctl[2];
};
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * General Use Fields: User Writable Table - Features's Control Registers
+ * Total 32 bytes
+ */
+struct sfp_usr_eeprom_s {
+ u8 rsvd1[2]; /* 128-129 */
+ u8 ewrap; /* 130 */
+ u8 rsvd2[2]; /* */
+ u8 owrap; /* 133 */
+ u8 rsvd3[2]; /* */
+ u8 prbs; /* 136: PRBS 7 generator */
+ u8 rsvd4[2]; /* */
+ u8 tx_eqz_16; /* 139: TX Equalizer (16xFC) */
+ u8 tx_eqz_8; /* 140: TX Equalizer (8xFC) */
+ u8 rsvd5[2]; /* */
+ u8 rx_emp_16; /* 143: RX Emphasis (16xFC) */
+ u8 rx_emp_8; /* 144: RX Emphasis (8xFC) */
+ u8 rsvd6[2]; /* */
+ u8 tx_eye_adj; /* 147: TX eye Threshold Adjust */
+ u8 rsvd7[3]; /* */
+ u8 tx_eye_qctl; /* 151: TX eye Quality Control */
+ u8 tx_eye_qres; /* 152: TX eye Quality Result */
+ u8 rsvd8[2]; /* */
+ u8 poh[3]; /* 155-157: Power On Hours */
+ u8 rsvd9[2]; /* */
+};
+
struct sfp_mem_s {
struct sfp_srlid_base_s srlid_base;
struct sfp_srlid_ext_s srlid_ext;
struct sfp_diag_base_s diag_base;
struct sfp_diag_ext_s diag_ext;
+ struct sfp_usr_eeprom_s usr_eeprom;
};
/*
@@ -1067,6 +1153,7 @@ struct bfa_flash_attr_s {
#define LB_PATTERN_DEFAULT 0xB5B5B5B5
#define QTEST_CNT_DEFAULT 10
#define QTEST_PAT_DEFAULT LB_PATTERN_DEFAULT
+#define DPORT_ENABLE_LOOPCNT_DEFAULT (1024 * 1024)
struct bfa_diag_memtest_s {
u8 algo;
@@ -1095,6 +1182,54 @@ struct bfa_diag_loopback_result_s {
u8 rsvd[3];
};
+enum bfa_diag_dport_test_status {
+ DPORT_TEST_ST_IDLE = 0, /* the test has not started yet. */
+ DPORT_TEST_ST_FINAL = 1, /* the test done successfully */
+ DPORT_TEST_ST_SKIP = 2, /* the test skipped */
+ DPORT_TEST_ST_FAIL = 3, /* the test failed */
+ DPORT_TEST_ST_INPRG = 4, /* the testing is in progress */
+ DPORT_TEST_ST_RESPONDER = 5, /* test triggered from remote port */
+ DPORT_TEST_ST_STOPPED = 6, /* the test stopped by user. */
+ DPORT_TEST_ST_MAX
+};
+
+enum bfa_diag_dport_test_type {
+ DPORT_TEST_ELOOP = 0,
+ DPORT_TEST_OLOOP = 1,
+ DPORT_TEST_ROLOOP = 2,
+ DPORT_TEST_LINK = 3,
+ DPORT_TEST_MAX
+};
+
+enum bfa_diag_dport_test_opmode {
+ BFA_DPORT_OPMODE_AUTO = 0,
+ BFA_DPORT_OPMODE_MANU = 1,
+};
+
+struct bfa_diag_dport_subtest_result_s {
+ u8 status; /* bfa_diag_dport_test_status */
+ u8 rsvd[7]; /* 64bit align */
+ u64 start_time; /* timestamp */
+};
+
+struct bfa_diag_dport_result_s {
+ wwn_t rp_pwwn; /* switch port wwn */
+ wwn_t rp_nwwn; /* switch node wwn */
+ u64 start_time; /* user/sw start time */
+ u64 end_time; /* timestamp */
+ u8 status; /* bfa_diag_dport_test_status */
+ u8 mode; /* bfa_diag_dport_test_opmode */
+ u8 rsvd; /* 64bit align */
+ u8 speed; /* link speed for buf_reqd */
+ u16 buffer_required;
+ u16 frmsz; /* frame size for buf_reqd */
+ u32 lpcnt; /* Frame count */
+ u32 pat; /* Pattern */
+ u32 roundtrip_latency; /* in nano sec */
+ u32 est_cable_distance; /* in meter */
+ struct bfa_diag_dport_subtest_result_s subtest[DPORT_TEST_MAX];
+};
+
struct bfa_diag_ledtest_s {
u32 cmd; /* bfa_led_op_t */
u32 color; /* bfa_led_color_t */
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index 36756ce0e58..638f441ffc3 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -105,6 +105,9 @@ struct bfa_fw_ioim_stats_s {
* an error condition*/
u32 wait_for_si; /* FW wait for SI */
u32 rec_rsp_inval; /* REC rsp invalid */
+ u32 rec_rsp_xchg_comp; /* REC rsp xchg complete */
+ u32 rec_rsp_rd_si_ownd; /* REC rsp read si owned */
+
u32 seqr_io_abort; /* target does not know cmd so abort */
u32 seqr_io_retry; /* SEQR failed so retry IO */
@@ -257,7 +260,6 @@ struct bfa_fw_port_lksm_stats_s {
u32 nos_tx; /* No. of times NOS tx started */
u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */
u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */
- u32 bbsc_lr; /* LKSM LR tx for credit recovery */
};
struct bfa_fw_port_snsm_stats_s {
@@ -270,6 +272,9 @@ struct bfa_fw_port_snsm_stats_s {
u32 sync_lost; /* Sync loss count */
u32 sig_lost; /* Signal loss count */
u32 asn8g_attempts; /* SNSM HWSM at 8Gbps attempts */
+ u32 adapt_success; /* SNSM adaptation success */
+ u32 adapt_fails; /* SNSM adaptation failures */
+ u32 adapt_ign_fails; /* SNSM adaptation failures ignored */
};
struct bfa_fw_port_physm_stats_s {
@@ -324,12 +329,46 @@ struct bfa_fw_fcoe_port_stats_s {
struct bfa_fw_fip_stats_s fip_stats;
};
+/**
+ * @brief LPSM statistics
+ */
+struct bfa_fw_lpsm_stats_s {
+ u32 cls_rx; /* LPSM cls_rx */
+ u32 cls_tx; /* LPSM cls_tx */
+ u32 arbf0_rx; /* LPSM abrf0 rcvd */
+ u32 arbf0_tx; /* LPSM abrf0 xmit */
+ u32 init_rx; /* LPSM loop init start */
+ u32 unexp_hwst; /* LPSM unknown hw state */
+ u32 unexp_frame; /* LPSM unknown_frame */
+ u32 unexp_prim; /* LPSM unexpected primitive */
+ u32 prev_alpa_unavail; /* LPSM prev alpa unavailable */
+ u32 alpa_unavail; /* LPSM alpa not available */
+ u32 lip_rx; /* LPSM lip rcvd */
+ u32 lip_f7f7_rx; /* LPSM lip f7f7 rcvd */
+ u32 lip_f8_rx; /* LPSM lip f8 rcvd */
+ u32 lip_f8f7_rx; /* LPSM lip f8f7 rcvd */
+ u32 lip_other_rx; /* LPSM lip other rcvd */
+ u32 lip_tx; /* LPSM lip xmit */
+ u32 retry_tov; /* LPSM retry TOV */
+ u32 lip_tov; /* LPSM LIP wait TOV */
+ u32 idle_tov; /* LPSM idle wait TOV */
+ u32 arbf0_tov; /* LPSM arbfo wait TOV */
+ u32 stop_loop_tov; /* LPSM stop loop wait TOV */
+ u32 lixa_tov; /* LPSM lisa wait TOV */
+ u32 lixx_tov; /* LPSM lilp/lirp wait TOV */
+ u32 cls_tov; /* LPSM cls wait TOV */
+ u32 sler; /* LPSM SLER recvd */
+ u32 failed; /* LPSM failed */
+ u32 success; /* LPSM online */
+};
+
/*
* IOC firmware FC uport stats
*/
struct bfa_fw_fc_uport_stats_s {
struct bfa_fw_port_snsm_stats_s snsm_stats;
struct bfa_fw_port_lksm_stats_s lksm_stats;
+ struct bfa_fw_lpsm_stats_s lpsm_stats;
};
/*
@@ -357,11 +396,6 @@ struct bfa_fw_fcxchg_stats_s {
u32 ua_state_inv;
};
-struct bfa_fw_lpsm_stats_s {
- u32 cls_rx;
- u32 cls_tx;
-};
-
/*
* Trunk statistics
*/
@@ -376,7 +410,7 @@ struct bfa_fw_trunk_stats_s {
u32 rsvd; /* padding for 64 bit alignment */
};
-struct bfa_fw_advsm_stats_s {
+struct bfa_fw_aport_stats_s {
u32 flogi_sent; /* Flogi sent */
u32 flogi_acc_recvd; /* Flogi Acc received */
u32 flogi_rjt_recvd; /* Flogi rejects received */
@@ -386,6 +420,12 @@ struct bfa_fw_advsm_stats_s {
u32 elp_accepted; /* ELP Accepted */
u32 elp_rejected; /* ELP rejected */
u32 elp_dropped; /* ELP dropped */
+
+ u32 bbcr_lr_count; /*!< BBCR Link Resets */
+ u32 frame_lost_intrs; /*!< BBCR Frame loss intrs */
+ u32 rrdy_lost_intrs; /*!< BBCR Rrdy loss intrs */
+
+ u32 rsvd;
};
/*
@@ -446,6 +486,14 @@ struct bfa_fw_ct_mod_stats_s {
};
/*
+ * RDS mod stats
+ */
+struct bfa_fw_rds_stats_s {
+ u32 no_fid_drop_err; /* RDS no fid drop error */
+ u32 rsvd; /* 64bit align */
+};
+
+/*
* IOC firmware stats
*/
struct bfa_fw_stats_s {
@@ -454,13 +502,13 @@ struct bfa_fw_stats_s {
struct bfa_fw_io_stats_s io_stats;
struct bfa_fw_port_stats_s port_stats;
struct bfa_fw_fcxchg_stats_s fcxchg_stats;
- struct bfa_fw_lpsm_stats_s lpsm_stats;
struct bfa_fw_lps_stats_s lps_stats;
struct bfa_fw_trunk_stats_s trunk_stats;
- struct bfa_fw_advsm_stats_s advsm_stats;
+ struct bfa_fw_aport_stats_s aport_stats;
struct bfa_fw_mac_mod_stats_s macmod_stats;
struct bfa_fw_ct_mod_stats_s ctmod_stats;
struct bfa_fw_eth_sndrcv_stats_s ethsndrcv_stats;
+ struct bfa_fw_rds_stats_s rds_stats;
};
#define BFA_IOCFC_PATHTOV_MAX 60
@@ -494,13 +542,44 @@ enum bfa_qos_bw_alloc {
BFA_QOS_BW_LOW = 10, /* bandwidth allocation for Low */
};
#pragma pack(1)
+
+struct bfa_qos_bw_s {
+ u8 qos_bw_set;
+ u8 high;
+ u8 med;
+ u8 low;
+};
+
/*
* QoS attribute returned in QoS Query
*/
struct bfa_qos_attr_s {
- u8 state; /* QoS current state */
- u8 rsvd[3];
- u32 total_bb_cr; /* Total BB Credits */
+ u8 state; /* QoS current state */
+ u8 rsvd1[3];
+ u32 total_bb_cr; /* Total BB Credits */
+ struct bfa_qos_bw_s qos_bw; /* QOS bw cfg */
+ struct bfa_qos_bw_s qos_bw_op; /* QOS bw operational */
+};
+
+enum bfa_bbcr_state {
+ BFA_BBCR_DISABLED, /*!< BBCR is disable */
+ BFA_BBCR_ONLINE, /*!< BBCR is online */
+ BFA_BBCR_OFFLINE, /*!< BBCR is offline */
+};
+
+enum bfa_bbcr_err_reason {
+ BFA_BBCR_ERR_REASON_NONE, /*!< Unknown */
+ BFA_BBCR_ERR_REASON_SPEED_UNSUP, /*!< Port speed < max sup_speed */
+ BFA_BBCR_ERR_REASON_PEER_UNSUP, /*!< BBCR is disable on peer port */
+ BFA_BBCR_ERR_REASON_NON_BRCD_SW, /*!< Connected to non BRCD switch */
+ BFA_BBCR_ERR_REASON_FLOGI_RJT, /*!< Login rejected by the switch */
+};
+
+struct bfa_bbcr_attr_s {
+ u8 state;
+ u8 peer_bb_scn;
+ u8 reason;
+ u8 rsvd;
};
/*
@@ -692,7 +771,9 @@ enum bfa_port_states {
BFA_PORT_ST_FWMISMATCH = 12,
BFA_PORT_ST_PREBOOT_DISABLED = 13,
BFA_PORT_ST_TOGGLING_QWAIT = 14,
- BFA_PORT_ST_ACQ_ADDR = 15,
+ BFA_PORT_ST_FAA_MISCONFIG = 15,
+ BFA_PORT_ST_DPORT = 16,
+ BFA_PORT_ST_DDPORT = 17,
BFA_PORT_ST_MAX_STATE,
};
@@ -714,9 +795,11 @@ enum bfa_port_type {
*/
enum bfa_port_topology {
BFA_PORT_TOPOLOGY_NONE = 0, /* No valid topology */
- BFA_PORT_TOPOLOGY_P2P = 1, /* P2P only */
- BFA_PORT_TOPOLOGY_LOOP = 2, /* LOOP topology */
- BFA_PORT_TOPOLOGY_AUTO = 3, /* auto topology selection */
+ BFA_PORT_TOPOLOGY_P2P_OLD_VER = 1, /* P2P def for older ver */
+ BFA_PORT_TOPOLOGY_LOOP = 2, /* LOOP topology */
+ BFA_PORT_TOPOLOGY_AUTO_OLD_VER = 3, /* auto def for older ver */
+ BFA_PORT_TOPOLOGY_AUTO = 4, /* auto topology selection */
+ BFA_PORT_TOPOLOGY_P2P = 5, /* P2P only */
};
/*
@@ -760,6 +843,7 @@ enum bfa_port_linkstate_rsn {
BFA_PORT_LINKSTATE_RSN_LOCAL_FAULT = 9,
BFA_PORT_LINKSTATE_RSN_REMOTE_FAULT = 10,
BFA_PORT_LINKSTATE_RSN_TIMEOUT = 11,
+ BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG = 12,
@@ -811,6 +895,15 @@ enum bfa_lunmask_state_s {
BFA_LUNMASK_UNINITIALIZED = 0xff,
};
+/**
+ * FEC states
+ */
+enum bfa_fec_state_s {
+ BFA_FEC_ONLINE = 1, /*!< FEC is online */
+ BFA_FEC_OFFLINE = 2, /*!< FEC is offline */
+ BFA_FEC_OFFLINE_NOT_16G = 3, /*!< FEC is offline (speed not 16Gig) */
+};
+
#pragma pack(1)
/*
* LUN mask configuration
@@ -833,6 +926,22 @@ struct bfa_lunmask_cfg_s {
struct bfa_lun_mask_s lun_list[MAX_LUN_MASK_CFG];
};
+struct bfa_throttle_cfg_s {
+ u16 is_valid;
+ u16 value;
+ u32 rsvd;
+};
+
+struct bfa_defs_fcpim_throttle_s {
+ u16 max_value;
+ u16 cur_value;
+ u16 cfg_value;
+ u16 rsvd;
+};
+
+#define BFA_BB_SCN_DEF 3
+#define BFA_BB_SCN_MAX 0x0F
+
/*
* Physical port configuration
*/
@@ -848,12 +957,13 @@ struct bfa_port_cfg_s {
u8 tx_bbcredit; /* transmit buffer credits */
u8 ratelimit; /* ratelimit enabled or not */
u8 trl_def_speed; /* ratelimit default speed */
- u8 bb_scn; /* BB_SCN value from FLOGI Exchg */
- u8 bb_scn_state; /* Config state of BB_SCN */
+ u8 bb_cr_enabled; /*!< Config state of BB_SCN */
+ u8 bb_scn; /*!< BB_SCN value for FLOGI Exchg */
u8 faa_state; /* FAA enabled/disabled */
- u8 rsvd[1];
+ u8 rsvd1;
u16 path_tov; /* device path timeout */
u16 q_depth; /* SCSI Queue depth */
+ struct bfa_qos_bw_s qos_bw; /* QOS bandwidth */
};
#pragma pack()
@@ -890,6 +1000,7 @@ struct bfa_port_attr_s {
bfa_boolean_t link_e2e_beacon; /* link beacon is on */
bfa_boolean_t bbsc_op_status; /* fc credit recovery oper
* state */
+ enum bfa_fec_state_s fec_state; /*!< current FEC state */
/*
* Dynamic field - info from FCS
@@ -971,6 +1082,13 @@ struct bfa_trunk_vc_attr_s {
u16 vc_credits[8];
};
+struct bfa_fcport_loop_info_s {
+ u8 myalpa; /* alpa claimed */
+ u8 alpabm_val; /* alpa bitmap valid or not (1 or 0) */
+ u8 resvd[6];
+ struct fc_alpabm_s alpabm; /* alpa bitmap */
+};
+
/*
* Link state information
*/
@@ -981,13 +1099,20 @@ struct bfa_port_link_s {
u8 speed; /* Link speed (1/2/4/8 G) */
u32 linkstate_opt; /* Linkstate optional data (debug) */
u8 trunked; /* Trunked or not (1 or 0) */
- u8 resvd[3];
+ u8 fec_state; /*!< State of FEC */
+ u8 resvd[6];
struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
union {
- struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */
- struct bfa_trunk_vc_attr_s trunk_vc_attr;
- struct bfa_fcport_fcf_s fcf; /* FCF information (for FCoE) */
- } vc_fcf;
+ struct bfa_fcport_loop_info_s loop_info;
+ struct bfa_bbcr_attr_s bbcr_attr;
+ union {
+ struct bfa_qos_vc_attr_s qos_vc_attr;
+ /* VC info from ELP */
+ struct bfa_trunk_vc_attr_s trunk_vc_attr;
+ struct bfa_fcport_fcf_s fcf;
+ /* FCF information (for FCoE) */
+ } vc_fcf;
+ } attr;
};
#pragma pack()
@@ -1112,6 +1237,9 @@ struct bfa_port_fc_stats_s {
u64 tx_frames; /* Tx frames */
u64 tx_words; /* Tx words */
u64 tx_lip; /* Tx LIP */
+ u64 tx_lip_f7f7; /* Tx LIP_F7F7 */
+ u64 tx_lip_f8f7; /* Tx LIP_F8F7 */
+ u64 tx_arbf0; /* Tx ARB F0 */
u64 tx_nos; /* Tx NOS */
u64 tx_ols; /* Tx OLS */
u64 tx_lr; /* Tx LR */
@@ -1119,6 +1247,9 @@ struct bfa_port_fc_stats_s {
u64 rx_frames; /* Rx frames */
u64 rx_words; /* Rx words */
u64 lip_count; /* Rx LIP */
+ u64 rx_lip_f7f7; /* Rx LIP_F7F7 */
+ u64 rx_lip_f8f7; /* Rx LIP_F8F7 */
+ u64 rx_arbf0; /* Rx ARB F0 */
u64 nos_count; /* Rx NOS */
u64 ols_count; /* Rx OLS */
u64 lr_count; /* Rx LR */
@@ -1137,9 +1268,12 @@ struct bfa_port_fc_stats_s {
u64 bad_os_count; /* Invalid ordered sets */
u64 err_enc_out; /* Encoding err nonframe_8b10b */
u64 err_enc; /* Encoding err frame_8b10b */
- u64 bbsc_frames_lost; /* Credit Recovery-Frames Lost */
- u64 bbsc_credits_lost; /* Credit Recovery-Credits Lost */
- u64 bbsc_link_resets; /* Credit Recovery-Link Resets */
+ u64 bbcr_frames_lost; /*!< BBCR Frames Lost */
+ u64 bbcr_rrdys_lost; /*!< BBCR RRDYs Lost */
+ u64 bbcr_link_resets; /*!< BBCR Link Resets */
+ u64 bbcr_frame_lost_intrs; /*!< BBCR Frame loss intrs */
+ u64 bbcr_rrdy_lost_intrs; /*!< BBCR Rrdy loss intrs */
+ u64 loop_timeouts; /* Loop timeouts */
};
/*
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index e0beb4d7e26..64069a0a3d0 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -24,6 +24,7 @@ typedef u64 wwn_t;
#define WWN_NULL (0)
#define FC_SYMNAME_MAX 256 /* max name server symbolic name size */
+#define FC_ALPA_MAX 128
#pragma pack(1)
@@ -1015,13 +1016,17 @@ struct fc_symname_s {
u8 symname[FC_SYMNAME_MAX];
};
+struct fc_alpabm_s {
+ u8 alpa_bm[FC_ALPA_MAX / 8];
+};
+
/*
* protocol default timeout values
*/
#define FC_ED_TOV 2
#define FC_REC_TOV (FC_ED_TOV + 1)
#define FC_RA_TOV 10
-#define FC_ELS_TOV ((2 * FC_RA_TOV) + 1)
+#define FC_ELS_TOV (2 * FC_RA_TOV)
#define FC_FCCT_TOV (3 * FC_RA_TOV)
/*
@@ -1526,6 +1531,12 @@ enum fdmi_hba_attribute_type {
FDMI_HBA_ATTRIB_FW_VERSION, /* 0x0009 */
FDMI_HBA_ATTRIB_OS_NAME, /* 0x000A */
FDMI_HBA_ATTRIB_MAX_CT, /* 0x000B */
+ FDMI_HBA_ATTRIB_NODE_SYM_NAME, /* 0x000C */
+ FDMI_HBA_ATTRIB_VENDOR_INFO, /* 0x000D */
+ FDMI_HBA_ATTRIB_NUM_PORTS, /* 0x000E */
+ FDMI_HBA_ATTRIB_FABRIC_NAME, /* 0x000F */
+ FDMI_HBA_ATTRIB_BIOS_VER, /* 0x0010 */
+ FDMI_HBA_ATTRIB_VENDOR_ID = 0x00E0,
FDMI_HBA_ATTRIB_MAX_TYPE
};
@@ -1540,6 +1551,15 @@ enum fdmi_port_attribute_type {
FDMI_PORT_ATTRIB_FRAME_SIZE, /* 0x0004 */
FDMI_PORT_ATTRIB_DEV_NAME, /* 0x0005 */
FDMI_PORT_ATTRIB_HOST_NAME, /* 0x0006 */
+ FDMI_PORT_ATTRIB_NODE_NAME, /* 0x0007 */
+ FDMI_PORT_ATTRIB_PORT_NAME, /* 0x0008 */
+ FDMI_PORT_ATTRIB_PORT_SYM_NAME, /* 0x0009 */
+ FDMI_PORT_ATTRIB_PORT_TYPE, /* 0x000A */
+ FDMI_PORT_ATTRIB_SUPP_COS, /* 0x000B */
+ FDMI_PORT_ATTRIB_PORT_FAB_NAME, /* 0x000C */
+ FDMI_PORT_ATTRIB_PORT_FC4_TYPE, /* 0x000D */
+ FDMI_PORT_ATTRIB_PORT_STATE = 0x101, /* 0x0101 */
+ FDMI_PORT_ATTRIB_PORT_NUM_RPRT = 0x102, /* 0x0102 */
FDMI_PORT_ATTR_MAX_TYPE
};
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index 273cee90b3b..dce787f6cca 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -228,6 +228,10 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+ /* For FC AL bb_cr is 0 and altbbcred is 1 */
+ if (!bb_cr)
+ plogi->csp.altbbcred = 1;
+
plogi->els_cmd.els_code = els_code;
if (els_code == FC_ELS_PLOGI)
fc_els_req_build(fchs, d_id, s_id, ox_id);
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 1633963c66c..d7385d1d9c5 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -158,6 +158,7 @@ enum bfa_tskim_event {
BFA_TSKIM_SM_IOS_DONE = 7, /* IO and sub TM completions */
BFA_TSKIM_SM_CLEANUP = 8, /* TM cleanup on ITN offline */
BFA_TSKIM_SM_CLEANUP_DONE = 9, /* TM abort completion */
+ BFA_TSKIM_SM_UTAG = 10, /* TM completion unknown tag */
};
/*
@@ -2881,7 +2882,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
iotag = be16_to_cpu(rsp->io_tag);
ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
- WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag);
+ WARN_ON(ioim->iotag != iotag);
bfa_ioim_cb_profile_comp(fcpim, ioim);
@@ -3036,7 +3037,7 @@ bfa_ioim_abort(struct bfa_ioim_s *ioim)
static void
bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
{
- bfa_trc(tskim->bfa, event);
+ bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
switch (event) {
case BFA_TSKIM_SM_START:
@@ -3074,7 +3075,7 @@ bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
static void
bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
{
- bfa_trc(tskim->bfa, event);
+ bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
switch (event) {
case BFA_TSKIM_SM_DONE:
@@ -3110,7 +3111,7 @@ bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
static void
bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
{
- bfa_trc(tskim->bfa, event);
+ bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
switch (event) {
case BFA_TSKIM_SM_DONE:
@@ -3119,6 +3120,7 @@ bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
*/
break;
+ case BFA_TSKIM_SM_UTAG:
case BFA_TSKIM_SM_CLEANUP_DONE:
bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
bfa_tskim_cleanup_ios(tskim);
@@ -3138,7 +3140,7 @@ bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
static void
bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
{
- bfa_trc(tskim->bfa, event);
+ bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
switch (event) {
case BFA_TSKIM_SM_IOS_DONE:
@@ -3170,7 +3172,7 @@ bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
static void
bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
{
- bfa_trc(tskim->bfa, event);
+ bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
switch (event) {
case BFA_TSKIM_SM_QRESUME:
@@ -3207,7 +3209,7 @@ static void
bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
enum bfa_tskim_event event)
{
- bfa_trc(tskim->bfa, event);
+ bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
switch (event) {
case BFA_TSKIM_SM_DONE:
@@ -3238,7 +3240,7 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
static void
bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
{
- bfa_trc(tskim->bfa, event);
+ bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);
switch (event) {
case BFA_TSKIM_SM_HCB:
@@ -3560,6 +3562,8 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
bfa_stats(tskim->itnim, tm_cleanup_comps);
bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
+ } else if (rsp->tsk_status == BFI_TSKIM_STS_UTAG) {
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_UTAG);
} else {
bfa_stats(tskim->itnim, tm_fw_rsps);
bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
@@ -3699,6 +3703,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_mem_dma_s *seg_ptr;
u16 idx, nsegs, num_io_req;
+ fcp->max_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
fcp->num_fwtio_reqs = cfg->fwcfg.num_fwtio_reqs;
fcp->num_itns = cfg->fwcfg.num_rports;
@@ -3721,6 +3726,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
}
+ fcp->throttle_update_required = 1;
bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
bfa_iotag_attach(fcp);
@@ -3759,23 +3765,33 @@ bfa_fcp_iocdisable(struct bfa_s *bfa)
{
struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
- /* Enqueue unused ioim resources to free_q */
- list_splice_tail_init(&fcp->iotag_unused_q, &fcp->iotag_ioim_free_q);
-
bfa_fcpim_iocdisable(fcp);
}
void
-bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw)
+bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw)
{
struct bfa_fcp_mod_s *mod = BFA_FCP_MOD(bfa);
struct list_head *qe;
int i;
+ /* Update io throttle value only once during driver load time */
+ if (!mod->throttle_update_required)
+ return;
+
for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
list_add_tail(qe, &mod->iotag_unused_q);
}
+
+ if (mod->num_ioim_reqs != num_ioim_fw) {
+ bfa_trc(bfa, mod->num_ioim_reqs);
+ bfa_trc(bfa, num_ioim_fw);
+ }
+
+ mod->max_ioim_reqs = max_ioim_fw;
+ mod->num_ioim_reqs = num_ioim_fw;
+ mod->throttle_update_required = 0;
}
void
@@ -3833,3 +3849,88 @@ bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
bfa_mem_kva_curp(fcp) = (u8 *) iotag;
}
+
+
+/**
+ * To send config req, first try to use throttle value from flash
+ * If 0, then use driver parameter
+ * We need to use min(flash_val, drv_val) because
+ * memory allocation was done based on this cfg'd value
+ */
+u16
+bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param)
+{
+ u16 tmp;
+ struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+
+ /*
+ * If throttle value from flash is already in effect after driver is
+ * loaded then until next load, always return current value instead
+ * of actual flash value
+ */
+ if (!fcp->throttle_update_required)
+ return (u16)fcp->num_ioim_reqs;
+
+ tmp = bfa_dconf_read_data_valid(bfa) ? bfa_fcpim_read_throttle(bfa) : 0;
+ if (!tmp || (tmp > drv_cfg_param))
+ tmp = drv_cfg_param;
+
+ return tmp;
+}
+
+bfa_status_t
+bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value)
+{
+ if (!bfa_dconf_get_min_cfg(bfa)) {
+ BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.value = value;
+ BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.is_valid = 1;
+ return BFA_STATUS_OK;
+ }
+
+ return BFA_STATUS_FAILED;
+}
+
+u16
+bfa_fcpim_read_throttle(struct bfa_s *bfa)
+{
+ struct bfa_throttle_cfg_s *throttle_cfg =
+ &(BFA_DCONF_MOD(bfa)->dconf->throttle_cfg);
+
+ return ((!bfa_dconf_get_min_cfg(bfa)) ?
+ ((throttle_cfg->is_valid == 1) ? (throttle_cfg->value) : 0) : 0);
+}
+
+bfa_status_t
+bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value)
+{
+ /* in min cfg no commands should run. */
+ if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
+ (!bfa_dconf_read_data_valid(bfa)))
+ return BFA_STATUS_FAILED;
+
+ bfa_fcpim_write_throttle(bfa, value);
+
+ return bfa_dconf_update(bfa);
+}
+
+bfa_status_t
+bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf)
+{
+ struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+ struct bfa_defs_fcpim_throttle_s throttle;
+
+ if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) ||
+ (!bfa_dconf_read_data_valid(bfa)))
+ return BFA_STATUS_FAILED;
+
+ memset(&throttle, 0, sizeof(struct bfa_defs_fcpim_throttle_s));
+
+ throttle.cur_value = (u16)(fcpim->fcp->num_ioim_reqs);
+ throttle.cfg_value = bfa_fcpim_read_throttle(bfa);
+ if (!throttle.cfg_value)
+ throttle.cfg_value = throttle.cur_value;
+ throttle.max_value = (u16)(fcpim->fcp->max_ioim_reqs);
+ memcpy(buf, &throttle, sizeof(struct bfa_defs_fcpim_throttle_s));
+
+ return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index 36f26da80f7..e693af6e593 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -42,7 +42,7 @@ void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m));
void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m);
void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp);
-void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw);
+void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw);
#define BFA_FCP_MOD(_hal) (&(_hal)->modules.fcp_mod)
#define BFA_MEM_FCP_KVA(__bfa) (&(BFA_FCP_MOD(__bfa)->kva_seg))
@@ -51,7 +51,9 @@ void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw);
#define BFA_ITN_FROM_TAG(_fcp, _tag) \
((_fcp)->itn_arr + ((_tag) & ((_fcp)->num_itns - 1)))
#define BFA_SNSINFO_FROM_TAG(_fcp, _tag) \
- bfa_mem_get_dmabuf_kva(_fcp, _tag, BFI_IOIM_SNSLEN)
+ bfa_mem_get_dmabuf_kva(_fcp, (_tag & BFA_IOIM_IOTAG_MASK), \
+ BFI_IOIM_SNSLEN)
+
#define BFA_ITNIM_MIN 32
#define BFA_ITNIM_MAX 1024
@@ -148,6 +150,7 @@ struct bfa_fcp_mod_s {
struct list_head iotag_unused_q; /* unused IO resources*/
struct bfa_iotag_s *iotag_arr;
struct bfa_itn_s *itn_arr;
+ int max_ioim_reqs;
int num_ioim_reqs;
int num_fwtio_reqs;
int num_itns;
@@ -155,6 +158,7 @@ struct bfa_fcp_mod_s {
struct bfa_fcpim_s fcpim;
struct bfa_mem_dma_s dma_seg[BFA_FCP_DMA_SEGS];
struct bfa_mem_kva_s kva_seg;
+ int throttle_update_required;
};
/*
@@ -416,5 +420,10 @@ bfa_status_t bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id,
bfa_status_t bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id,
wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun);
bfa_status_t bfa_fcpim_lunmask_clear(struct bfa_s *bfa);
+u16 bfa_fcpim_read_throttle(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value);
+bfa_status_t bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value);
+bfa_status_t bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf);
+u16 bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param);
#endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index fd3e84d32bd..a3ab5cce420 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -240,9 +240,6 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
u32 rsp_len,
u32 resid_len,
struct fchs_s *rspfchs);
-static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
-static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
- struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
@@ -303,16 +300,30 @@ static void
bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event)
{
+ struct bfa_s *bfa = fabric->fcs->bfa;
+
bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
bfa_trc(fabric->fcs, event);
switch (event) {
case BFA_FCS_FABRIC_SM_START:
- if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+ if (!bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ break;
+ }
+ if (bfa_fcport_get_topology(bfa) ==
+ BFA_PORT_TOPOLOGY_LOOP) {
+ fabric->fab_type = BFA_FCS_FABRIC_LOOP;
+ fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
+ fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
+ bfa_sm_set_state(fabric,
+ bfa_fcs_fabric_sm_online);
+ bfa_fcs_fabric_set_opertype(fabric);
+ bfa_fcs_lport_online(&fabric->bport);
+ } else {
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
bfa_fcs_fabric_login(fabric);
- } else
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ }
break;
case BFA_FCS_FABRIC_SM_LINK_UP:
@@ -337,16 +348,28 @@ static void
bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event)
{
+ struct bfa_s *bfa = fabric->fcs->bfa;
+
bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
bfa_trc(fabric->fcs, event);
switch (event) {
case BFA_FCS_FABRIC_SM_LINK_UP:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
- bfa_fcs_fabric_login(fabric);
+ if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) {
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+ bfa_fcs_fabric_login(fabric);
+ break;
+ }
+ fabric->fab_type = BFA_FCS_FABRIC_LOOP;
+ fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
+ fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+ bfa_fcs_fabric_set_opertype(fabric);
+ bfa_fcs_lport_online(&fabric->bport);
break;
case BFA_FCS_FABRIC_SM_RETRY_OP:
+ case BFA_FCS_FABRIC_SM_LOOPBACK:
break;
case BFA_FCS_FABRIC_SM_DELETE:
@@ -378,8 +401,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_CONT_OP:
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit,
- bfa_fcs_fabric_oper_bbscn(fabric));
+ fabric->bb_credit);
fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
if (fabric->auth_reqd && fabric->is_auth) {
@@ -407,8 +429,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_NO_FABRIC:
fabric->fab_type = BFA_FCS_FABRIC_N2N;
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit,
- bfa_fcs_fabric_oper_bbscn(fabric));
+ fabric->bb_credit);
bfa_fcs_fabric_notify_online(fabric);
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
break;
@@ -576,8 +597,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
case BFA_FCS_FABRIC_SM_NO_FABRIC:
bfa_trc(fabric->fcs, fabric->bb_credit);
bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
- fabric->bb_credit,
- bfa_fcs_fabric_oper_bbscn(fabric));
+ fabric->bb_credit);
break;
case BFA_FCS_FABRIC_SM_RETRY_OP:
@@ -595,14 +615,20 @@ void
bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event)
{
+ struct bfa_s *bfa = fabric->fcs->bfa;
+
bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
bfa_trc(fabric->fcs, event);
switch (event) {
case BFA_FCS_FABRIC_SM_LINK_DOWN:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
- bfa_fcs_fabric_notify_offline(fabric);
+ if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
+ bfa_fcs_lport_offline(&fabric->bport);
+ } else {
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
+ bfa_fcs_fabric_notify_offline(fabric);
+ }
break;
case BFA_FCS_FABRIC_SM_DELETE:
@@ -719,20 +745,29 @@ static void
bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event)
{
+ struct bfa_s *bfa = fabric->fcs->bfa;
+
bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
bfa_trc(fabric->fcs, event);
switch (event) {
case BFA_FCS_FABRIC_SM_STOPCOMP:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
- bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
+ if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+ } else {
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
+ bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
+ }
break;
case BFA_FCS_FABRIC_SM_LINK_UP:
break;
case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
+ if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+ else
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
break;
default:
@@ -924,10 +959,6 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
case BFA_STATUS_FABRIC_RJT:
fabric->stats.flogi_rejects++;
- if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
- fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
- fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;
-
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
return;
@@ -973,17 +1004,11 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
{
struct bfa_s *bfa = fabric->fcs->bfa;
struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
- u8 alpa = 0, bb_scn = 0;
-
- if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
- alpa = bfa_fcport_get_myalpa(bfa);
+ u8 alpa = 0;
- if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
- (!fabric->fcs->bbscn_flogi_rjt))
- bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
- pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);
+ pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
fabric->stats.flogi_sent++;
}
@@ -1064,40 +1089,6 @@ bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric)
}
/*
- * Computes operating BB_SCN value
- */
-static u8
-bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
-{
- u8 pr_bbscn = fabric->lps->pr_bbscn;
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
-
- if (!(fcport->cfg.bb_scn_state && pr_bbscn))
- return 0;
-
- /* return max of local/remote bb_scn values */
- return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
- pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
-}
-
-/*
- * Check if BB_SCN can be enabled.
- */
-static bfa_boolean_t
-bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
-
- if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
- fcport->cfg.bb_scn_state &&
- !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
- !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
- return BFA_TRUE;
- else
- return BFA_FALSE;
-}
-
-/*
* Delete all vports and wait for vport delete completions.
*/
static void
@@ -1235,7 +1226,6 @@ void
bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
{
bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
}
@@ -1442,7 +1432,6 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
}
fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
- fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
@@ -1475,8 +1464,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
n2n_port->reply_oxid, pcfg->pwwn,
pcfg->nwwn,
bfa_fcport_get_maxfrsize(bfa),
- bfa_fcport_get_rx_bbcredit(bfa),
- bfa_fcs_fabric_oper_bbscn(fabric));
+ bfa_fcport_get_rx_bbcredit(bfa), 0);
bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,
BFA_FALSE, FC_CLASS_3,
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index 6c4377cb287..42bcb970445 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -118,9 +118,9 @@ struct bfa_fcs_lport_fab_s {
#define MAX_ALPA_COUNT 127
struct bfa_fcs_lport_loop_s {
- u8 num_alpa; /* Num of ALPA entries in the map */
- u8 alpa_pos_map[MAX_ALPA_COUNT]; /* ALPA Positional
- *Map */
+ u8 num_alpa; /* Num of ALPA entries in the map */
+ u8 alpabm_valid; /* alpa bitmap valid or not (1 or 0) */
+ u8 alpa_pos_map[MAX_ALPA_COUNT]; /* ALPA Positional Map */
struct bfa_fcs_lport_s *port; /* parent port */
};
@@ -175,6 +175,7 @@ enum bfa_fcs_fabric_type {
BFA_FCS_FABRIC_UNKNOWN = 0,
BFA_FCS_FABRIC_SWITCHED = 1,
BFA_FCS_FABRIC_N2N = 2,
+ BFA_FCS_FABRIC_LOOP = 3,
};
@@ -242,24 +243,21 @@ struct bfa_fcs_fabric_s;
* Symbolic Name.
*
* Physical Port's symbolic name Format : (Total 128 bytes)
- * Adapter Model number/name : 12 bytes
+ * Adapter Model number/name : 16 bytes
* Driver Version : 10 bytes
* Host Machine Name : 30 bytes
- * Host OS Info : 48 bytes
+ * Host OS Info : 44 bytes
* Host OS PATCH Info : 16 bytes
* ( remaining 12 bytes reserved to be used for separator)
*/
#define BFA_FCS_PORT_SYMBNAME_SEPARATOR " | "
-#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 12
+#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 16
#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 10
#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 30
-#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48
+#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 44
#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16
-/* bb_scn value in 2^bb_scn */
-#define BFA_FCS_PORT_DEF_BB_SCN 3
-
/*
* Get FC port ID for a logical port.
*/
@@ -298,6 +296,7 @@ wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
u16 vf_id, wwn_t lpwwn);
+void bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, char *symname);
void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
struct bfa_lport_info_s *port_info);
void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port,
@@ -350,9 +349,10 @@ void bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg,
struct bfa_fcxp_s *fcxp_alloced);
void bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);
void bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport);
-void bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport);
+void bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *vport);
void bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
struct fchs_s *rx_frame, u32 len);
+void bfa_fcs_lport_lip_scn_online(bfa_fcs_lport_t *port);
struct bfa_fcs_vport_s {
struct list_head qe; /* queue elem */
@@ -453,6 +453,7 @@ struct bfa_fcs_rport_s {
struct bfa_rport_stats_s stats; /* rport stats */
enum bfa_rport_function scsi_function; /* Initiator/Target */
struct bfa_fcs_rpf_s rpf; /* Rport features module */
+ bfa_boolean_t scn_online; /* SCN online flag */
};
static inline struct bfa_rport_s *
@@ -627,6 +628,9 @@ void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
#define BFA_FCS_FDMI_SUPP_SPEEDS_10G FDMI_TRANS_SPEED_10G
+#define BFA_FCS_FDMI_VENDOR_INFO_LEN 8
+#define BFA_FCS_FDMI_FC4_TYPE_LEN 32
+
/*
* HBA Attribute Block : BFA internal representation. Note : Some variable
* sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
@@ -637,25 +641,39 @@ struct bfa_fcs_fdmi_hba_attr_s {
u8 manufacturer[64];
u8 serial_num[64];
u8 model[16];
- u8 model_desc[256];
+ u8 model_desc[128];
u8 hw_version[8];
- u8 driver_version[8];
+ u8 driver_version[BFA_VERSION_LEN];
u8 option_rom_ver[BFA_VERSION_LEN];
- u8 fw_version[8];
+ u8 fw_version[BFA_VERSION_LEN];
u8 os_name[256];
__be32 max_ct_pyld;
+ struct bfa_lport_symname_s node_sym_name;
+ u8 vendor_info[BFA_FCS_FDMI_VENDOR_INFO_LEN];
+ __be32 num_ports;
+ wwn_t fabric_name;
+ u8 bios_ver[BFA_VERSION_LEN];
};
/*
* Port Attribute Block
*/
struct bfa_fcs_fdmi_port_attr_s {
- u8 supp_fc4_types[32]; /* supported FC4 types */
+ u8 supp_fc4_types[BFA_FCS_FDMI_FC4_TYPE_LEN];
__be32 supp_speed; /* supported speed */
__be32 curr_speed; /* current Speed */
__be32 max_frm_size; /* max frame size */
u8 os_device_name[256]; /* OS device Name */
u8 host_name[256]; /* host name */
+ wwn_t port_name;
+ wwn_t node_name;
+ struct bfa_lport_symname_s port_sym_name;
+ __be32 port_type;
+ enum fc_cos scos;
+ wwn_t port_fabric_name;
+ u8 port_act_fc4_type[BFA_FCS_FDMI_FC4_TYPE_LEN];
+ __be32 port_state;
+ __be32 num_ports;
};
struct bfa_fcs_stats_s {
@@ -680,8 +698,6 @@ struct bfa_fcs_s {
struct bfa_trc_mod_s *trcmod; /* tracing module */
bfa_boolean_t vf_enabled; /* VF mode is enabled */
bfa_boolean_t fdmi_enabled; /* FDMI is enabled */
- bfa_boolean_t bbscn_enabled; /* Driver Config Parameter */
- bfa_boolean_t bbscn_flogi_rjt;/* FLOGI reject due to BB_SCN */
bfa_boolean_t min_cfg; /* min cfg enabled/disabled */
u16 port_vfid; /* port default VF ID */
struct bfa_fcs_driver_info_s driver_info;
@@ -733,7 +749,7 @@ enum rport_event {
RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
RPSM_EVENT_DELETE = 7, /* RPORT delete request */
- RPSM_EVENT_SCN = 8, /* state change notification */
+ RPSM_EVENT_FAB_SCN = 8, /* state change notification */
RPSM_EVENT_ACCEPTED = 9, /* Good response from remote device */
RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
@@ -744,7 +760,9 @@ enum rport_event {
RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */
RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */
RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continuously */
- RPSM_EVENT_FC4_FCS_ONLINE = 19, /*!< FC-4 FCS online complete */
+ RPSM_EVENT_SCN_OFFLINE = 19, /* loop scn offline */
+ RPSM_EVENT_SCN_ONLINE = 20, /* loop scn online */
+ RPSM_EVENT_FC4_FCS_ONLINE = 21, /* FC-4 FCS online complete */
};
/*
@@ -763,7 +781,7 @@ enum bfa_fcs_itnim_event {
BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */
BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */
BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
- BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /*!< bfa rport online event */
+ BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /* bfa rport online event */
};
/*
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 3b75f6fb2de..ff75ef89175 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -23,6 +23,34 @@
BFA_TRC_FILE(FCS, PORT);
+/*
+ * ALPA to LIXA bitmap mapping
+ *
+ * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
+ * is for L_bit (login required) and is filled as ALPA 0x00 here.
+ */
+static const u8 loop_alpa_map[] = {
+ 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */
+ 0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */
+ 0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */
+
+ 0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */
+ 0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */
+ 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */
+ 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */
+
+ 0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */
+ 0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */
+ 0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */
+ 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */
+
+ 0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */
+ 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */
+ 0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */
+ 0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */
+};
+
static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
struct fchs_s *rx_fchs, u8 reason_code,
u8 reason_code_expl);
@@ -51,6 +79,10 @@ static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port);
+
static struct {
void (*init) (struct bfa_fcs_lport_s *port);
void (*online) (struct bfa_fcs_lport_s *port);
@@ -62,7 +94,9 @@ static struct {
bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
bfa_fcs_lport_fab_offline}, {
bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
- bfa_fcs_lport_n2n_offline},
+ bfa_fcs_lport_n2n_offline}, {
+ bfa_fcs_lport_loop_init, bfa_fcs_lport_loop_online,
+ bfa_fcs_lport_loop_offline},
};
/*
@@ -739,7 +773,20 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
bfa_trc(lport->fcs, fchs->type);
if (!bfa_fcs_lport_is_online(lport)) {
- bfa_stats(lport, uf_recv_drops);
+ /*
+ * In direct attach topology, it is possible to get a PLOGI
+ * before the lport is online due to port feature
+ * (QoS/Trunk/FEC/CR), so send a rjt
+ */
+ if ((fchs->type == FC_TYPE_ELS) &&
+ (els_cmd->els_code == FC_ELS_PLOGI)) {
+ bfa_fcs_lport_send_ls_rjt(lport, fchs,
+ FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
+ FC_LS_RJT_EXP_NO_ADDL_INFO);
+ bfa_stats(lport, plogi_rcvd);
+ } else
+ bfa_stats(lport, uf_recv_drops);
+
return;
}
@@ -1063,6 +1110,17 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
}
+void
+bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port,
+ char *symname)
+{
+ strcpy(port->port_cfg.sym_name.symname, symname);
+
+ if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
+ bfa_fcs_lport_ns_util_send_rspn_id(
+ BFA_FCS_GET_NS_FROM_PORT(port), NULL);
+}
+
/*
* fcs_lport_api
*/
@@ -1127,7 +1185,7 @@ static void
bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
{
bfa_fcs_lport_ns_online(port);
- bfa_fcs_lport_scn_online(port);
+ bfa_fcs_lport_fab_scn_online(port);
}
/*
@@ -1221,6 +1279,98 @@ bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
n2n_port->reply_oxid = 0;
}
+void
+bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port)
+{
+ int i = 0, j = 0, bit = 0, alpa_bit = 0;
+ u8 k = 0;
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa);
+
+ port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid;
+ port->pid = fcport->myalpa;
+ port->pid = bfa_hton3b(port->pid);
+
+ for (i = 0; i < (FC_ALPA_MAX / 8); i++) {
+ for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) {
+ bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]);
+ bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j)));
+ if (bit) {
+ port->port_topo.ploop.alpa_pos_map[k] =
+ loop_alpa_map[(i * 8) + alpa_bit];
+ k++;
+ bfa_trc(port->fcs->bfa, k);
+ bfa_trc(port->fcs->bfa,
+ port->port_topo.ploop.alpa_pos_map[k]);
+ }
+ }
+ }
+ port->port_topo.ploop.num_alpa = k;
+}
+
+/*
+ * Called by fcs/port to initialize Loop topology.
+ */
+static void
+bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port)
+{
+}
+
+/*
+ * Called by fcs/port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port)
+{
+ u8 num_alpa = 0, alpabm_valid = 0;
+ struct bfa_fcs_rport_s *rport;
+ u8 *alpa_map = NULL;
+ int i = 0;
+ u32 pid;
+
+ bfa_fcport_get_loop_attr(port);
+
+ num_alpa = port->port_topo.ploop.num_alpa;
+ alpabm_valid = port->port_topo.ploop.alpabm_valid;
+ alpa_map = port->port_topo.ploop.alpa_pos_map;
+
+ bfa_trc(port->fcs->bfa, port->pid);
+ bfa_trc(port->fcs->bfa, num_alpa);
+ if (alpabm_valid == 1) {
+ for (i = 0; i < num_alpa; i++) {
+ bfa_trc(port->fcs->bfa, alpa_map[i]);
+ if (alpa_map[i] != bfa_hton3b(port->pid)) {
+ pid = alpa_map[i];
+ bfa_trc(port->fcs->bfa, pid);
+ rport = bfa_fcs_lport_get_rport_by_pid(port,
+ bfa_hton3b(pid));
+ if (!rport)
+ rport = bfa_fcs_rport_create(port,
+ bfa_hton3b(pid));
+ }
+ }
+ } else {
+ for (i = 0; i < MAX_ALPA_COUNT; i++) {
+ if (alpa_map[i] != port->pid) {
+ pid = loop_alpa_map[i];
+ bfa_trc(port->fcs->bfa, pid);
+ rport = bfa_fcs_lport_get_rport_by_pid(port,
+ bfa_hton3b(pid));
+ if (!rport)
+ rport = bfa_fcs_rport_create(port,
+ bfa_hton3b(pid));
+ }
+ }
+ }
+}
+
+/*
+ * Called by fcs/port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port)
+{
+}
+
#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
/*
@@ -1888,13 +2038,10 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
sizeof(templen));
}
- /*
- * f/w Version = driver version
- */
attr = (struct fdmi_attr_s *) curr_ptr;
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
- templen = (u16) strlen(fcs_hba_attr->driver_version);
- memcpy(attr->value, fcs_hba_attr->driver_version, templen);
+ templen = (u16) strlen(fcs_hba_attr->fw_version);
+ memcpy(attr->value, fcs_hba_attr->fw_version, templen);
templen = fc_roundup(templen, sizeof(u32));
curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
len += templen;
@@ -1925,10 +2072,71 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
templen = sizeof(fcs_hba_attr->max_ct_pyld);
memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
len += templen;
count++;
attr->len = cpu_to_be16(templen + sizeof(attr->type) +
sizeof(templen));
+ /*
+ * Send extended attributes ( FOS 7.1 support )
+ */
+ if (fdmi->retry_cnt == 0) {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME);
+ templen = sizeof(fcs_hba_attr->node_sym_name);
+ memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID);
+ templen = sizeof(fcs_hba_attr->vendor_info);
+ memcpy(attr->value, &fcs_hba_attr->vendor_info, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS);
+ templen = sizeof(fcs_hba_attr->num_ports);
+ memcpy(attr->value, &fcs_hba_attr->num_ports, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME);
+ templen = sizeof(fcs_hba_attr->fabric_name);
+ memcpy(attr->value, &fcs_hba_attr->fabric_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER);
+ templen = sizeof(fcs_hba_attr->bios_ver);
+ memcpy(attr->value, &fcs_hba_attr->bios_ver, templen);
+ templen = fc_roundup(attr->len, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ count++;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+ }
/*
* Update size of payload
@@ -2129,6 +2337,113 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
sizeof(templen));
}
+ if (fdmi->retry_cnt == 0) {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME);
+ templen = sizeof(fcs_port_attr.node_name);
+ memcpy(attr->value, &fcs_port_attr.node_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME);
+ templen = sizeof(fcs_port_attr.port_name);
+ memcpy(attr->value, &fcs_port_attr.port_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ if (fcs_port_attr.port_sym_name.symname[0] != '\0') {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type =
+ cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME);
+ templen = sizeof(fcs_port_attr.port_sym_name);
+ memcpy(attr->value,
+ &fcs_port_attr.port_sym_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) +
+ sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen +
+ sizeof(attr->type) + sizeof(templen));
+ }
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE);
+ templen = sizeof(fcs_port_attr.port_type);
+ memcpy(attr->value, &fcs_port_attr.port_type, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS);
+ templen = sizeof(fcs_port_attr.scos);
+ memcpy(attr->value, &fcs_port_attr.scos, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME);
+ templen = sizeof(fcs_port_attr.port_fabric_name);
+ memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE);
+ templen = sizeof(fcs_port_attr.port_act_fc4_type);
+ memcpy(attr->value, fcs_port_attr.port_act_fc4_type,
+ templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE);
+ templen = sizeof(fcs_port_attr.port_state);
+ memcpy(attr->value, &fcs_port_attr.port_state, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT);
+ templen = sizeof(fcs_port_attr.num_ports);
+ memcpy(attr->value, &fcs_port_attr.num_ports, templen);
+ templen = fc_roundup(templen, sizeof(u32));
+ curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+ len += templen;
+ ++count;
+ attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+ sizeof(templen));
+ }
+
/*
* Update size of payload
*/
@@ -2296,6 +2611,7 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
{
struct bfa_fcs_lport_s *port = fdmi->ms->port;
struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
+ struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
@@ -2331,7 +2647,18 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
sizeof(driver_info->host_os_patch));
}
- hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
+ /* Retrieve the max frame size from the port attr */
+ bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
+ hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size;
+
+ strncpy(hba_attr->node_sym_name.symname,
+ port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN);
+ strcpy(hba_attr->vendor_info, "BROCADE");
+ hba_attr->num_ports =
+ cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc));
+ hba_attr->fabric_name = port->fabric->lps->pr_nwwn;
+ strncpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN);
+
}
static void
@@ -2341,6 +2668,7 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
struct bfa_fcs_lport_s *port = fdmi->ms->port;
struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
struct bfa_port_attr_s pport_attr;
+ struct bfa_lport_attr_s lport_attr;
memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
@@ -2391,7 +2719,7 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
/*
* Max PDU Size.
*/
- port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
+ port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize);
/*
* OS device Name
@@ -2405,6 +2733,18 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
sizeof(port_attr->host_name));
+ port_attr->node_name = bfa_fcs_lport_get_nwwn(port);
+ port_attr->port_name = bfa_fcs_lport_get_pwwn(port);
+
+ strncpy(port_attr->port_sym_name.symname,
+ (char *)&bfa_fcs_lport_get_psym_name(port), BFA_SYMNAME_MAXLEN);
+ bfa_fcs_lport_get_attr(port, &lport_attr);
+ port_attr->port_type = cpu_to_be32(lport_attr.port_type);
+ port_attr->scos = pport_attr.cos_supported;
+ port_attr->port_fabric_name = port->fabric->lps->pr_nwwn;
+ fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type);
+ port_attr->port_state = cpu_to_be32(pport_attr.port_state);
+ port_attr->num_ports = cpu_to_be32(port->num_rports);
}
/*
@@ -4824,9 +5164,6 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
u8 *psymbl = &symbl[0];
int len;
- if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
- return;
-
/* Avoid sending RSPN in the following states. */
if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
@@ -5199,7 +5536,7 @@ bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
}
void
-bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
+bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)
{
struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
@@ -5621,6 +5958,15 @@ bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
}
/*
+ * Let new loop map create missing rports
+ */
+void
+bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port)
+{
+ bfa_fcs_lport_loop_online(port);
+}
+
+/*
* FCS virtual port state machine
*/
@@ -5663,6 +6009,7 @@ enum bfa_fcs_vport_event {
BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
+ BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */
};
static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
@@ -5848,6 +6195,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
break;
case BFA_FCS_VPORT_SM_RSP_FAILED:
+ case BFA_FCS_VPORT_SM_FABRIC_MAX:
bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
break;
@@ -5918,6 +6266,7 @@ bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
case BFA_FCS_VPORT_SM_OFFLINE:
case BFA_FCS_VPORT_SM_RSP_ERROR:
case BFA_FCS_VPORT_SM_RSP_FAILED:
+ case BFA_FCS_VPORT_SM_FABRIC_MAX:
case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
@@ -6203,7 +6552,7 @@ bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
else {
bfa_fcs_vport_aen_post(&vport->lport,
BFA_LPORT_AEN_NPIV_FABRIC_MAX);
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX);
}
break;
@@ -6589,7 +6938,19 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
break;
}
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ else
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+
+ break;
+
+ case BFA_STATUS_ETIMER:
+ vport->vport_stats.fdisc_timeouts++;
+ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ else
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
break;
case BFA_STATUS_FABRIC_RJT:
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index cc43b2a58ce..2035b0d6435 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -106,9 +106,13 @@ static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
enum rport_event event);
static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_adisc_online_sending(
+ struct bfa_fcs_rport_s *rport, enum rport_event event);
+static void bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s
+ *rport, enum rport_event event);
+static void bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
enum rport_event event);
static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
enum rport_event event);
@@ -150,8 +154,10 @@ static struct bfa_sm_table_s rport_sm_table[] = {
{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
- {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
- {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
+ {BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},
+ {BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},
+ {BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},
+ {BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},
{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
@@ -183,8 +189,8 @@ bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
break;
case RPSM_EVENT_PLOGI_RCVD:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
- bfa_fcs_rport_fcs_online_action(rport);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+ bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
case RPSM_EVENT_PLOGI_COMP:
@@ -231,10 +237,19 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
+ case RPSM_EVENT_SCN_OFFLINE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ break;
case RPSM_EVENT_ADDRESS_CHANGE:
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
/* query the NS */
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+ WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+ BFA_PORT_TOPOLOGY_LOOP));
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -280,12 +295,20 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_PLOGI_RCVD:
case RPSM_EVENT_PLOGI_COMP:
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
/*
* Ignore, SCN is possibly online notification.
*/
break;
+ case RPSM_EVENT_SCN_OFFLINE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ break;
+
case RPSM_EVENT_ADDRESS_CHANGE:
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
@@ -346,9 +369,19 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
+ case RPSM_EVENT_SCN_OFFLINE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_timer_stop(&rport->timer);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ break;
+
case RPSM_EVENT_ADDRESS_CHANGE:
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
bfa_timer_stop(&rport->timer);
+ WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+ BFA_PORT_TOPOLOGY_LOOP));
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -422,7 +455,18 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
break;
- case RPSM_EVENT_PLOGI_RETRY:
+ case RPSM_EVENT_SCN_ONLINE:
+ break;
+
+ case RPSM_EVENT_SCN_OFFLINE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_fcxp_discard(rport->fcxp);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ break;
+
+ case RPSM_EVENT_PLOGI_RETRY:
rport->plogi_retries = 0;
bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -440,8 +484,10 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
break;
case RPSM_EVENT_ADDRESS_CHANGE:
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
bfa_fcxp_discard(rport->fcxp);
+ WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+ BFA_PORT_TOPOLOGY_LOOP));
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -512,7 +558,8 @@ bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_PLOGI_COMP:
case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
+ case RPSM_EVENT_SCN_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcs_rport_fcs_offline_action(rport);
break;
@@ -561,9 +608,10 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_fcs_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
+ case RPSM_EVENT_SCN_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcs_rport_fcs_offline_action(rport);
break;
@@ -595,14 +643,15 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_trc(rport->fcs, event);
switch (event) {
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
bfa_sm_set_state(rport,
bfa_fcs_rport_sm_nsquery_sending);
rport->ns_retries = 0;
bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+ bfa_sm_set_state(rport,
+ bfa_fcs_rport_sm_adisc_online_sending);
bfa_fcs_rport_send_adisc(rport, NULL);
}
break;
@@ -610,6 +659,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
case RPSM_EVENT_PLOGI_RCVD:
case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
+ case RPSM_EVENT_SCN_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcs_rport_hal_offline_action(rport);
break;
@@ -625,6 +675,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_fcs_rport_hal_offline_action(rport);
break;
+ case RPSM_EVENT_SCN_ONLINE:
case RPSM_EVENT_PLOGI_COMP:
break;
@@ -656,7 +707,7 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_hal_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
/*
* ignore SCN, wait for response to query itself
*/
@@ -696,7 +747,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
switch (event) {
case RPSM_EVENT_ACCEPTED:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);
bfa_fcs_rport_send_adisc(rport, NULL);
break;
@@ -718,7 +769,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_fcs_rport_hal_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
break;
case RPSM_EVENT_LOGO_RCVD:
@@ -747,7 +798,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
* authenticating with rport. FC-4s are paused.
*/
static void
-bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,
enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
@@ -756,7 +807,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FCXP_SENT:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);
break;
case RPSM_EVENT_DELETE:
@@ -779,7 +830,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_hal_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
break;
case RPSM_EVENT_PLOGI_RCVD:
@@ -798,7 +849,8 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
* FC-4s are paused.
*/
static void
-bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
+bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -831,7 +883,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_fcs_rport_hal_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
/*
* already processing RSCN
*/
@@ -856,7 +908,96 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
/*
- * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ * ADISC is being sent for authenticating with rport
+ * Already did offline actions.
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,
+ enum rport_event event)
+{
+ bfa_trc(rport->fcs, rport->pwwn);
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPSM_EVENT_FCXP_SENT:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);
+ break;
+
+ case RPSM_EVENT_DELETE:
+ case RPSM_EVENT_SCN_OFFLINE:
+ case RPSM_EVENT_LOGO_IMP:
+ case RPSM_EVENT_LOGO_RCVD:
+ case RPSM_EVENT_PRLO_RCVD:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_fcxp_walloc_cancel(rport->fcs->bfa,
+ &rport->fcxp_wqe);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ break;
+
+ case RPSM_EVENT_PLOGI_RCVD:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+ bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+ bfa_fcs_rport_send_plogiacc(rport, NULL);
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+/*
+ * ADISC to rport
+ * Already did offline actions
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
+ enum rport_event event)
+{
+ bfa_trc(rport->fcs, rport->pwwn);
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPSM_EVENT_ACCEPTED:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_fcs_rport_hal_online(rport);
+ break;
+
+ case RPSM_EVENT_PLOGI_RCVD:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+ bfa_fcxp_discard(rport->fcxp);
+ bfa_fcs_rport_send_plogiacc(rport, NULL);
+ break;
+
+ case RPSM_EVENT_FAILED:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ break;
+
+ case RPSM_EVENT_DELETE:
+ case RPSM_EVENT_SCN_OFFLINE:
+ case RPSM_EVENT_LOGO_IMP:
+ case RPSM_EVENT_LOGO_RCVD:
+ case RPSM_EVENT_PRLO_RCVD:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_fcxp_discard(rport->fcxp);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+/*
+ * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
*/
static void
bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
@@ -881,6 +1022,8 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
break;
+ case RPSM_EVENT_SCN_ONLINE:
+ case RPSM_EVENT_SCN_OFFLINE:
case RPSM_EVENT_HCB_ONLINE:
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
@@ -945,6 +1088,8 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_hal_offline(rport);
break;
+ case RPSM_EVENT_SCN_ONLINE:
+ break;
case RPSM_EVENT_LOGO_RCVD:
/*
* Rport is going offline. Just ack the logo
@@ -956,8 +1101,9 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_send_prlo_acc(rport);
break;
+ case RPSM_EVENT_SCN_OFFLINE:
case RPSM_EVENT_HCB_ONLINE:
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
/*
@@ -1015,6 +1161,19 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
bfa_fcs_rport_send_nsdisc(rport, NULL);
+ } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==
+ BFA_PORT_TOPOLOGY_LOOP) {
+ if (rport->scn_online) {
+ bfa_sm_set_state(rport,
+ bfa_fcs_rport_sm_adisc_offline_sending);
+ bfa_fcs_rport_send_adisc(rport, NULL);
+ } else {
+ bfa_sm_set_state(rport,
+ bfa_fcs_rport_sm_offline);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ }
} else {
bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
rport->plogi_retries = 0;
@@ -1027,7 +1186,9 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_free(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_SCN_ONLINE:
+ case RPSM_EVENT_SCN_OFFLINE:
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
case RPSM_EVENT_PLOGI_RCVD:
@@ -1106,6 +1267,8 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
break;
+ case RPSM_EVENT_SCN_ONLINE:
+ case RPSM_EVENT_SCN_OFFLINE:
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
/*
@@ -1146,6 +1309,8 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
break;
+ case RPSM_EVENT_SCN_ONLINE:
+ case RPSM_EVENT_SCN_OFFLINE:
case RPSM_EVENT_ADDRESS_CHANGE:
break;
@@ -1172,7 +1337,9 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_free(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_SCN_ONLINE:
+ case RPSM_EVENT_SCN_OFFLINE:
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_ADDRESS_CHANGE:
break;
@@ -1209,10 +1376,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_fcs_rport_free(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_ADDRESS_CHANGE:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
bfa_timer_stop(&rport->timer);
+ WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+ BFA_PORT_TOPOLOGY_LOOP));
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
@@ -1232,6 +1401,7 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
case RPSM_EVENT_LOGO_IMP:
+ case RPSM_EVENT_SCN_OFFLINE:
break;
case RPSM_EVENT_PLOGI_COMP:
@@ -1240,6 +1410,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_fcs_rport_fcs_online_action(rport);
break;
+ case RPSM_EVENT_SCN_ONLINE:
+ bfa_timer_stop(&rport->timer);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+ bfa_fcs_rport_send_plogi(rport, NULL);
+ break;
+
case RPSM_EVENT_PLOGI_SEND:
bfa_timer_stop(&rport->timer);
bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
@@ -1280,7 +1456,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
case RPSM_EVENT_PLOGI_SEND:
@@ -1326,7 +1502,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_ADDRESS_CHANGE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
bfa_timer_stop(&rport->timer);
@@ -1439,7 +1615,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_PRLO_RCVD:
bfa_fcs_rport_send_prlo_acc(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
/*
* ignore, wait for NS query response
*/
@@ -2401,7 +2577,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
- port->fabric->bb_credit, 0);
+ port->fabric->bb_credit);
}
}
@@ -2546,7 +2722,7 @@ void
bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
{
rport->stats.rscns++;
- bfa_sm_send_event(rport, RPSM_EVENT_SCN);
+ bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);
}
/*
@@ -2621,6 +2797,48 @@ bfa_cb_rport_qos_scn_flowid(void *cbarg,
bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
}
+void
+bfa_cb_rport_scn_online(struct bfa_s *bfa)
+{
+ struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+ struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+ struct bfa_fcs_rport_s *rp;
+ struct list_head *qe;
+
+ list_for_each(qe, &port->rport_q) {
+ rp = (struct bfa_fcs_rport_s *) qe;
+ bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);
+ rp->scn_online = BFA_TRUE;
+ }
+
+ if (bfa_fcs_lport_is_online(port))
+ bfa_fcs_lport_lip_scn_online(port);
+}
+
+void
+bfa_cb_rport_scn_no_dev(void *rport)
+{
+ struct bfa_fcs_rport_s *rp = rport;
+
+ bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+ rp->scn_online = BFA_FALSE;
+}
+
+void
+bfa_cb_rport_scn_offline(struct bfa_s *bfa)
+{
+ struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+ struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+ struct bfa_fcs_rport_s *rp;
+ struct list_head *qe;
+
+ list_for_each(qe, &port->rport_q) {
+ rp = (struct bfa_fcs_rport_s *) qe;
+ bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+ rp->scn_online = BFA_FALSE;
+ }
+}
+
/*
* brief
* This routine is a static BFA callback when there is a QoS priority
@@ -2808,6 +3026,9 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
struct bfa_rport_qos_attr_s qos_attr;
struct bfa_fcs_lport_s *port = rport->port;
bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+ struct bfa_port_attr_s port_attr;
+
+ bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
@@ -2838,7 +3059,8 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
rport_speed =
bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
- if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+ if ((bfa_fcs_lport_get_rport_max_speed(port) !=
+ BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
rport_attr->trl_enforced = BFA_TRUE;
}
}
@@ -3208,9 +3430,10 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
num_ents = be16_to_cpu(rpsc2_acc->num_pids);
bfa_trc(rport->fcs, num_ents);
if (num_ents > 0) {
- WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid);
+ WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) !=
+ bfa_ntoh3b(rport->pid));
bfa_trc(rport->fcs,
- be16_to_cpu(rpsc2_acc->port_info[0].pid));
+ be32_to_cpu(rpsc2_acc->port_info[0].pid));
bfa_trc(rport->fcs,
be16_to_cpu(rpsc2_acc->port_info[0].speed));
bfa_trc(rport->fcs,
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 75ca8752b9f..315d6d6dcfc 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -21,6 +21,7 @@
#include "bfi_reg.h"
#include "bfa_defs.h"
#include "bfa_defs_svc.h"
+#include "bfi.h"
BFA_TRC_FILE(CNA, IOC);
@@ -45,6 +46,14 @@ BFA_TRC_FILE(CNA, IOC);
#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
+#define bfa_ioc_state_disabled(__sm) \
+ (((__sm) == BFI_IOC_UNINIT) || \
+ ((__sm) == BFI_IOC_INITING) || \
+ ((__sm) == BFI_IOC_HWINIT) || \
+ ((__sm) == BFI_IOC_DISABLED) || \
+ ((__sm) == BFI_IOC_FAIL) || \
+ ((__sm) == BFI_IOC_CFG_DISABLED))
+
/*
* Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
*/
@@ -67,6 +76,14 @@ BFA_TRC_FILE(CNA, IOC);
((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
#define bfa_ioc_sync_complete(__ioc) \
((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
+#define bfa_ioc_set_cur_ioc_fwstate(__ioc, __fwstate) \
+ ((__ioc)->ioc_hwif->ioc_set_fwstate(__ioc, __fwstate))
+#define bfa_ioc_get_cur_ioc_fwstate(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_get_fwstate(__ioc))
+#define bfa_ioc_set_alt_ioc_fwstate(__ioc, __fwstate) \
+ ((__ioc)->ioc_hwif->ioc_set_alt_fwstate(__ioc, __fwstate))
+#define bfa_ioc_get_alt_ioc_fwstate(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_get_alt_fwstate(__ioc))
#define bfa_ioc_mbox_cmd_pending(__ioc) \
(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
@@ -94,6 +111,12 @@ static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
+static enum bfi_ioc_img_ver_cmp_e bfa_ioc_fw_ver_patch_cmp(
+ struct bfi_ioc_image_hdr_s *base_fwhdr,
+ struct bfi_ioc_image_hdr_s *fwhdr_to_cmp);
+static enum bfi_ioc_img_ver_cmp_e bfa_ioc_flash_fwver_cmp(
+ struct bfa_ioc_s *ioc,
+ struct bfi_ioc_image_hdr_s *base_fwhdr);
/*
* IOC state machine definitions/declarations
@@ -698,7 +721,7 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
}
/* h/w sem init */
- fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate);
+ fwstate = bfa_ioc_get_cur_ioc_fwstate(iocpf->ioc);
if (fwstate == BFI_IOC_UNINIT) {
writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
goto sem_get;
@@ -725,14 +748,13 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
bfa_trc(iocpf->ioc, fwstate);
bfa_trc(iocpf->ioc, swab32(fwhdr.exec));
- writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT);
+ bfa_ioc_set_alt_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT);
/*
* Unlock the hw semaphore. Should be here only once per boot.
*/
- readl(iocpf->ioc->ioc_regs.ioc_sem_reg);
- writel(1, iocpf->ioc->ioc_regs.ioc_sem_reg);
+ bfa_ioc_ownership_reset(iocpf->ioc);
/*
* unlock init semaphore.
@@ -1038,7 +1060,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
*/
case IOCPF_E_TIMEOUT:
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
break;
@@ -1139,7 +1161,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
case IOCPF_E_SEMLOCKED:
bfa_ioc_notify_fail(ioc);
bfa_ioc_sync_leave(ioc);
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
break;
@@ -1228,7 +1250,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
bfa_ioc_notify_fail(ioc);
if (!iocpf->auto_recover) {
bfa_ioc_sync_leave(ioc);
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
writel(1, ioc->ioc_regs.ioc_sem_reg);
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
} else {
@@ -1447,28 +1469,42 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
}
/*
- * Returns TRUE if same.
+ * Returns TRUE if driver is willing to work with current smem f/w version.
*/
bfa_boolean_t
-bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
+bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
+ struct bfi_ioc_image_hdr_s *smem_fwhdr)
{
struct bfi_ioc_image_hdr_s *drv_fwhdr;
- int i;
+ enum bfi_ioc_img_ver_cmp_e smem_flash_cmp, drv_smem_cmp;
drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
- for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
- if (fwhdr->md5sum[i] != cpu_to_le32(drv_fwhdr->md5sum[i])) {
- bfa_trc(ioc, i);
- bfa_trc(ioc, fwhdr->md5sum[i]);
- bfa_trc(ioc, drv_fwhdr->md5sum[i]);
- return BFA_FALSE;
- }
+ /*
+ * If smem is incompatible or old, driver should not work with it.
+ */
+ drv_smem_cmp = bfa_ioc_fw_ver_patch_cmp(drv_fwhdr, smem_fwhdr);
+ if (drv_smem_cmp == BFI_IOC_IMG_VER_INCOMP ||
+ drv_smem_cmp == BFI_IOC_IMG_VER_OLD) {
+ return BFA_FALSE;
}
- bfa_trc(ioc, fwhdr->md5sum[0]);
- return BFA_TRUE;
+ /*
+ * IF Flash has a better F/W than smem do not work with smem.
+ * If smem f/w == flash f/w, as smem f/w not old | incmp, work with it.
+ * If Flash is old or incomp work with smem iff smem f/w == drv f/w.
+ */
+ smem_flash_cmp = bfa_ioc_flash_fwver_cmp(ioc, smem_fwhdr);
+
+ if (smem_flash_cmp == BFI_IOC_IMG_VER_BETTER) {
+ return BFA_FALSE;
+ } else if (smem_flash_cmp == BFI_IOC_IMG_VER_SAME) {
+ return BFA_TRUE;
+ } else {
+ return (drv_smem_cmp == BFI_IOC_IMG_VER_SAME) ?
+ BFA_TRUE : BFA_FALSE;
+ }
}
/*
@@ -1478,17 +1514,9 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
static bfa_boolean_t
bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
{
- struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
+ struct bfi_ioc_image_hdr_s fwhdr;
bfa_ioc_fwver_get(ioc, &fwhdr);
- drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
- bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
-
- if (fwhdr.signature != cpu_to_le32(drv_fwhdr->signature)) {
- bfa_trc(ioc, fwhdr.signature);
- bfa_trc(ioc, drv_fwhdr->signature);
- return BFA_FALSE;
- }
if (swab32(fwhdr.bootenv) != boot_env) {
bfa_trc(ioc, fwhdr.bootenv);
@@ -1499,6 +1527,168 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
return bfa_ioc_fwver_cmp(ioc, &fwhdr);
}
+static bfa_boolean_t
+bfa_ioc_fwver_md5_check(struct bfi_ioc_image_hdr_s *fwhdr_1,
+ struct bfi_ioc_image_hdr_s *fwhdr_2)
+{
+ int i;
+
+ for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++)
+ if (fwhdr_1->md5sum[i] != fwhdr_2->md5sum[i])
+ return BFA_FALSE;
+
+ return BFA_TRUE;
+}
+
+/*
+ * Returns TRUE if major minor and maintainence are same.
+ * If patch versions are same, check for MD5 Checksum to be same.
+ */
+static bfa_boolean_t
+bfa_ioc_fw_ver_compatible(struct bfi_ioc_image_hdr_s *drv_fwhdr,
+ struct bfi_ioc_image_hdr_s *fwhdr_to_cmp)
+{
+ if (drv_fwhdr->signature != fwhdr_to_cmp->signature)
+ return BFA_FALSE;
+
+ if (drv_fwhdr->fwver.major != fwhdr_to_cmp->fwver.major)
+ return BFA_FALSE;
+
+ if (drv_fwhdr->fwver.minor != fwhdr_to_cmp->fwver.minor)
+ return BFA_FALSE;
+
+ if (drv_fwhdr->fwver.maint != fwhdr_to_cmp->fwver.maint)
+ return BFA_FALSE;
+
+ if (drv_fwhdr->fwver.patch == fwhdr_to_cmp->fwver.patch &&
+ drv_fwhdr->fwver.phase == fwhdr_to_cmp->fwver.phase &&
+ drv_fwhdr->fwver.build == fwhdr_to_cmp->fwver.build) {
+ return bfa_ioc_fwver_md5_check(drv_fwhdr, fwhdr_to_cmp);
+ }
+
+ return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_ioc_flash_fwver_valid(struct bfi_ioc_image_hdr_s *flash_fwhdr)
+{
+ if (flash_fwhdr->fwver.major == 0 || flash_fwhdr->fwver.major == 0xFF)
+ return BFA_FALSE;
+
+ return BFA_TRUE;
+}
+
+static bfa_boolean_t fwhdr_is_ga(struct bfi_ioc_image_hdr_s *fwhdr)
+{
+ if (fwhdr->fwver.phase == 0 &&
+ fwhdr->fwver.build == 0)
+ return BFA_TRUE;
+
+ return BFA_FALSE;
+}
+
+/*
+ * Returns TRUE if both are compatible and patch of fwhdr_to_cmp is better.
+ */
+static enum bfi_ioc_img_ver_cmp_e
+bfa_ioc_fw_ver_patch_cmp(struct bfi_ioc_image_hdr_s *base_fwhdr,
+ struct bfi_ioc_image_hdr_s *fwhdr_to_cmp)
+{
+ if (bfa_ioc_fw_ver_compatible(base_fwhdr, fwhdr_to_cmp) == BFA_FALSE)
+ return BFI_IOC_IMG_VER_INCOMP;
+
+ if (fwhdr_to_cmp->fwver.patch > base_fwhdr->fwver.patch)
+ return BFI_IOC_IMG_VER_BETTER;
+
+ else if (fwhdr_to_cmp->fwver.patch < base_fwhdr->fwver.patch)
+ return BFI_IOC_IMG_VER_OLD;
+
+ /*
+ * GA takes priority over internal builds of the same patch stream.
+ * At this point major minor maint and patch numbers are same.
+ */
+
+ if (fwhdr_is_ga(base_fwhdr) == BFA_TRUE) {
+ if (fwhdr_is_ga(fwhdr_to_cmp))
+ return BFI_IOC_IMG_VER_SAME;
+ else
+ return BFI_IOC_IMG_VER_OLD;
+ } else {
+ if (fwhdr_is_ga(fwhdr_to_cmp))
+ return BFI_IOC_IMG_VER_BETTER;
+ }
+
+ if (fwhdr_to_cmp->fwver.phase > base_fwhdr->fwver.phase)
+ return BFI_IOC_IMG_VER_BETTER;
+ else if (fwhdr_to_cmp->fwver.phase < base_fwhdr->fwver.phase)
+ return BFI_IOC_IMG_VER_OLD;
+
+ if (fwhdr_to_cmp->fwver.build > base_fwhdr->fwver.build)
+ return BFI_IOC_IMG_VER_BETTER;
+ else if (fwhdr_to_cmp->fwver.build < base_fwhdr->fwver.build)
+ return BFI_IOC_IMG_VER_OLD;
+
+ /*
+ * All Version Numbers are equal.
+ * Md5 check to be done as a part of compatibility check.
+ */
+ return BFI_IOC_IMG_VER_SAME;
+}
+
+#define BFA_FLASH_PART_FWIMG_ADDR 0x100000 /* fw image address */
+
+bfa_status_t
+bfa_ioc_flash_img_get_chnk(struct bfa_ioc_s *ioc, u32 off,
+ u32 *fwimg)
+{
+ return bfa_flash_raw_read(ioc->pcidev.pci_bar_kva,
+ BFA_FLASH_PART_FWIMG_ADDR + (off * sizeof(u32)),
+ (char *)fwimg, BFI_FLASH_CHUNK_SZ);
+}
+
+static enum bfi_ioc_img_ver_cmp_e
+bfa_ioc_flash_fwver_cmp(struct bfa_ioc_s *ioc,
+ struct bfi_ioc_image_hdr_s *base_fwhdr)
+{
+ struct bfi_ioc_image_hdr_s *flash_fwhdr;
+ bfa_status_t status;
+ u32 fwimg[BFI_FLASH_CHUNK_SZ_WORDS];
+
+ status = bfa_ioc_flash_img_get_chnk(ioc, 0, fwimg);
+ if (status != BFA_STATUS_OK)
+ return BFI_IOC_IMG_VER_INCOMP;
+
+ flash_fwhdr = (struct bfi_ioc_image_hdr_s *) fwimg;
+ if (bfa_ioc_flash_fwver_valid(flash_fwhdr) == BFA_TRUE)
+ return bfa_ioc_fw_ver_patch_cmp(base_fwhdr, flash_fwhdr);
+ else
+ return BFI_IOC_IMG_VER_INCOMP;
+}
+
+
+/*
+ * Invalidate fwver signature
+ */
+bfa_status_t
+bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc)
+{
+
+ u32 pgnum, pgoff;
+ u32 loff = 0;
+ enum bfi_ioc_state ioc_fwstate;
+
+ ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);
+ if (!bfa_ioc_state_disabled(ioc_fwstate))
+ return BFA_STATUS_ADAPTER_ENABLED;
+
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+ pgoff = PSS_SMEM_PGOFF(loff);
+ writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+ bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, BFA_IOC_FW_INV_SIGN);
+
+ return BFA_STATUS_OK;
+}
+
/*
* Conditionally flush any pending message from firmware at start.
*/
@@ -1520,7 +1710,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
u32 boot_type;
u32 boot_env;
- ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);
if (force)
ioc_fwstate = BFI_IOC_UNINIT;
@@ -1537,8 +1727,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
if (!fwvalid) {
- bfa_ioc_boot(ioc, boot_type, boot_env);
- bfa_ioc_poll_fwinit(ioc);
+ if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK)
+ bfa_ioc_poll_fwinit(ioc);
return;
}
@@ -1573,8 +1763,8 @@ 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);
+ if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK)
+ bfa_ioc_poll_fwinit(ioc);
}
static void
@@ -1677,7 +1867,7 @@ bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
/*
* Initiate a full firmware download.
*/
-static void
+static bfa_status_t
bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
u32 boot_env)
{
@@ -1687,28 +1877,60 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
u32 chunkno = 0;
u32 i;
u32 asicmode;
+ u32 fwimg_size;
+ u32 fwimg_buf[BFI_FLASH_CHUNK_SZ_WORDS];
+ bfa_status_t status;
+
+ if (boot_env == BFI_FWBOOT_ENV_OS &&
+ boot_type == BFI_FWBOOT_TYPE_FLASH) {
+ fwimg_size = BFI_FLASH_IMAGE_SZ/sizeof(u32);
+
+ status = bfa_ioc_flash_img_get_chnk(ioc,
+ BFA_IOC_FLASH_CHUNK_ADDR(chunkno), fwimg_buf);
+ if (status != BFA_STATUS_OK)
+ return status;
+
+ fwimg = fwimg_buf;
+ } else {
+ fwimg_size = bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc));
+ fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
+ BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
+ }
+
+ bfa_trc(ioc, fwimg_size);
- bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
- fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
pgoff = PSS_SMEM_PGOFF(loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
- for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
+ for (i = 0; i < fwimg_size; i++) {
if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
- fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
+
+ if (boot_env == BFI_FWBOOT_ENV_OS &&
+ boot_type == BFI_FWBOOT_TYPE_FLASH) {
+ status = bfa_ioc_flash_img_get_chnk(ioc,
+ BFA_IOC_FLASH_CHUNK_ADDR(chunkno),
+ fwimg_buf);
+ if (status != BFA_STATUS_OK)
+ return status;
+
+ fwimg = fwimg_buf;
+ } else {
+ fwimg = bfa_cb_image_get_chunk(
+ bfa_ioc_asic_gen(ioc),
BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
+ }
}
/*
* write smem
*/
bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
- cpu_to_le32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]));
+ fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
loff += sizeof(u32);
@@ -1726,8 +1948,12 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
ioc->ioc_regs.host_page_num_fn);
/*
- * Set boot type and device mode at the end.
+ * Set boot type, env and device mode at the end.
*/
+ if (boot_env == BFI_FWBOOT_ENV_OS &&
+ boot_type == BFI_FWBOOT_TYPE_FLASH) {
+ boot_type = BFI_FWBOOT_TYPE_NORMAL;
+ }
asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
ioc->port0_mode, ioc->port1_mode);
bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
@@ -1736,6 +1962,7 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
swab32(boot_type));
bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
swab32(boot_env));
+ return BFA_STATUS_OK;
}
@@ -1751,6 +1978,7 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
attr->card_type = be32_to_cpu(attr->card_type);
attr->maxfrsize = be16_to_cpu(attr->maxfrsize);
ioc->fcmode = (attr->port_mode == BFI_PORT_MODE_FC);
+ attr->mfg_year = be16_to_cpu(attr->mfg_year);
bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
}
@@ -1850,7 +2078,7 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
bfa_trc(ioc, len);
for (i = 0; i < len; i++) {
r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
- buf[i] = be32_to_cpu(r32);
+ buf[i] = swab32(r32);
loff += sizeof(u32);
/*
@@ -1994,28 +2222,51 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
* Interface used by diag module to do firmware boot with memory test
* as the entry vector.
*/
-void
+bfa_status_t
bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
{
+ struct bfi_ioc_image_hdr_s *drv_fwhdr;
+ bfa_status_t status;
bfa_ioc_stats(ioc, ioc_boots);
if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
- return;
+ return BFA_STATUS_FAILED;
+
+ if (boot_env == BFI_FWBOOT_ENV_OS &&
+ boot_type == BFI_FWBOOT_TYPE_NORMAL) {
+
+ drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
+ bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
+
+ /*
+ * Work with Flash iff flash f/w is better than driver f/w.
+ * Otherwise push drivers firmware.
+ */
+ if (bfa_ioc_flash_fwver_cmp(ioc, drv_fwhdr) ==
+ BFI_IOC_IMG_VER_BETTER)
+ boot_type = BFI_FWBOOT_TYPE_FLASH;
+ }
/*
* Initialize IOC state of all functions on a chip reset.
*/
if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
- writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_MEMTEST);
+ bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_MEMTEST);
} else {
- writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_INITING);
+ bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_INITING);
}
bfa_ioc_msgflush(ioc);
- bfa_ioc_download_fw(ioc, boot_type, boot_env);
- bfa_ioc_lpu_start(ioc);
+ status = bfa_ioc_download_fw(ioc, boot_type, boot_env);
+ if (status == BFA_STATUS_OK)
+ bfa_ioc_lpu_start(ioc);
+ else {
+ WARN_ON(boot_type == BFI_FWBOOT_TYPE_MEMTEST);
+ bfa_iocpf_timeout(ioc);
+ }
+ return status;
}
/*
@@ -2038,7 +2289,7 @@ bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
bfa_boolean_t
bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
{
- u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 r32 = bfa_ioc_get_cur_ioc_fwstate(ioc);
return ((r32 != BFI_IOC_UNINIT) &&
(r32 != BFI_IOC_INITING) &&
@@ -2188,6 +2439,7 @@ bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
break;
case BFA_PCI_DEVICE_ID_CT2:
+ case BFA_PCI_DEVICE_ID_CT2_QUAD:
ioc->asic_gen = BFI_ASIC_GEN_CT2;
if (clscode == BFI_PCIFN_CLASS_FC &&
pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
@@ -2410,14 +2662,6 @@ bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
}
-#define bfa_ioc_state_disabled(__sm) \
- (((__sm) == BFI_IOC_UNINIT) || \
- ((__sm) == BFI_IOC_INITING) || \
- ((__sm) == BFI_IOC_HWINIT) || \
- ((__sm) == BFI_IOC_DISABLED) || \
- ((__sm) == BFI_IOC_FAIL) || \
- ((__sm) == BFI_IOC_CFG_DISABLED))
-
/*
* Check if adapter is disabled -- both IOCs should be in a disabled
* state.
@@ -2430,12 +2674,12 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
return BFA_FALSE;
- ioc_state = readl(ioc->ioc_regs.ioc_fwstate);
+ ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);
if (!bfa_ioc_state_disabled(ioc_state))
return BFA_FALSE;
if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
- ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate);
+ ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);
if (!bfa_ioc_state_disabled(ioc_state))
return BFA_FALSE;
}
@@ -2449,8 +2693,8 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
void
bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)
{
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
- writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+ bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_UNINIT);
+ bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_UNINIT);
}
#define BFA_MFG_NAME "Brocade"
@@ -2497,6 +2741,10 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
ad_attr->trunk_capable = (ad_attr->nports > 1) &&
!bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
+ ad_attr->mfg_day = ioc_attr->mfg_day;
+ ad_attr->mfg_month = ioc_attr->mfg_month;
+ ad_attr->mfg_year = ioc_attr->mfg_year;
+ memcpy(ad_attr->uuid, ioc_attr->uuid, BFA_ADAPTER_UUID_LEN);
}
enum bfa_ioc_type_e
@@ -2561,13 +2809,19 @@ void
bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
{
struct bfi_ioc_attr_s *ioc_attr;
+ u8 nports = bfa_ioc_get_nports(ioc);
WARN_ON(!model);
memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
ioc_attr = ioc->attr;
- snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+ if (bfa_asic_id_ct2(ioc->pcidev.device_id) &&
+ (!bfa_mfg_is_mezz(ioc_attr->card_type)))
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u-%u%s",
+ BFA_MFG_NAME, ioc_attr->card_type, nports, "p");
+ else
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
BFA_MFG_NAME, ioc_attr->card_type);
}
@@ -2617,7 +2871,7 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
ioc_attr->state = bfa_ioc_get_state(ioc);
- ioc_attr->port_id = ioc->port_id;
+ ioc_attr->port_id = bfa_ioc_portid(ioc);
ioc_attr->port_mode = ioc->port_mode;
ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
ioc_attr->cap_bm = ioc->ad_cap_bm;
@@ -2626,8 +2880,9 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
- ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
- ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
+ ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc);
+ ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc);
+ ioc_attr->def_fn = (bfa_ioc_pcifn(ioc) == bfa_ioc_portid(ioc));
bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
}
@@ -2914,7 +3169,7 @@ bfa_iocpf_sem_timeout(void *ioc_arg)
static void
bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
{
- u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);
bfa_trc(ioc, fwstate);
@@ -2923,7 +3178,7 @@ bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
return;
}
- if (ioc->iocpf.poll_time >= BFA_IOC_TOV)
+ if (ioc->iocpf.poll_time >= (3 * BFA_IOC_TOV))
bfa_iocpf_timeout(ioc);
else {
ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
@@ -3016,7 +3271,6 @@ bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
struct bfa_ablk_cfg_inst_s *cfg_inst;
int i, j;
u16 be16;
- u32 be32;
for (i = 0; i < BFA_ABLK_MAX; i++) {
cfg_inst = &cfg->inst[i];
@@ -3027,8 +3281,10 @@ bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);
be16 = cfg_inst->pf_cfg[j].num_vectors;
cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);
- be32 = cfg_inst->pf_cfg[j].bw;
- cfg_inst->pf_cfg[j].bw = be16_to_cpu(be32);
+ be16 = cfg_inst->pf_cfg[j].bw_min;
+ cfg_inst->pf_cfg[j].bw_min = be16_to_cpu(be16);
+ be16 = cfg_inst->pf_cfg[j].bw_max;
+ cfg_inst->pf_cfg[j].bw_max = be16_to_cpu(be16);
}
}
}
@@ -3170,7 +3426,8 @@ bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,
bfa_status_t
bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
- u8 port, enum bfi_pcifn_class personality, int bw,
+ u8 port, enum bfi_pcifn_class personality,
+ u16 bw_min, u16 bw_max,
bfa_ablk_cbfn_t cbfn, void *cbarg)
{
struct bfi_ablk_h2i_pf_req_s *m;
@@ -3194,7 +3451,8 @@ bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,
bfa_ioc_portid(ablk->ioc));
m->pers = cpu_to_be16((u16)personality);
- m->bw = cpu_to_be32(bw);
+ m->bw_min = cpu_to_be16(bw_min);
+ m->bw_max = cpu_to_be16(bw_max);
m->port = port;
bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
@@ -3294,8 +3552,8 @@ bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,
}
bfa_status_t
-bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
- bfa_ablk_cbfn_t cbfn, void *cbarg)
+bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, u16 bw_min,
+ u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg)
{
struct bfi_ablk_h2i_pf_req_s *m;
@@ -3317,7 +3575,8 @@ bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,
bfa_ioc_portid(ablk->ioc));
m->pcifn = (u8)pcifn;
- m->bw = cpu_to_be32(bw);
+ m->bw_min = cpu_to_be16(bw_min);
+ m->bw_max = cpu_to_be16(bw_max);
bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
return BFA_STATUS_OK;
@@ -3619,7 +3878,7 @@ bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
bfa_trc(sfp, sfp->data_valid);
if (sfp->data_valid) {
u32 size = sizeof(struct sfp_mem_s);
- u8 *des = (u8 *) &(sfp->sfpmem->srlid_base);
+ u8 *des = (u8 *) &(sfp->sfpmem);
memcpy(des, sfp->dbuf_kva, size);
}
/*
@@ -4680,22 +4939,25 @@ diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
diag->tsensor.temp->ts_junc = rsp->ts_junc;
diag->tsensor.temp->ts_brd = rsp->ts_brd;
- diag->tsensor.temp->status = BFA_STATUS_OK;
if (rsp->ts_brd) {
+ /* tsensor.temp->status is brd_temp status */
+ diag->tsensor.temp->status = rsp->status;
if (rsp->status == BFA_STATUS_OK) {
diag->tsensor.temp->brd_temp =
be16_to_cpu(rsp->brd_temp);
- } else {
- bfa_trc(diag, rsp->status);
+ } else
diag->tsensor.temp->brd_temp = 0;
- diag->tsensor.temp->status = BFA_STATUS_DEVBUSY;
- }
}
+
+ bfa_trc(diag, rsp->status);
bfa_trc(diag, rsp->ts_junc);
bfa_trc(diag, rsp->temp);
bfa_trc(diag, rsp->ts_brd);
bfa_trc(diag, rsp->brd_temp);
+
+ /* tsensor status is always good bcos we always have junction temp */
+ diag->tsensor.status = BFA_STATUS_OK;
diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
diag->tsensor.lock = 0;
}
@@ -4924,6 +5186,7 @@ bfa_diag_tsensor_query(struct bfa_diag_s *diag,
diag->tsensor.temp = result;
diag->tsensor.cbfn = cbfn;
diag->tsensor.cbarg = cbarg;
+ diag->tsensor.status = BFA_STATUS_OK;
/* Send msg to fw */
diag_tempsensor_send(diag);
@@ -5615,7 +5878,7 @@ bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
}
bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read);
bfa_timer_start(dconf->bfa, &dconf->timer,
- bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
+ bfa_dconf_timer, dconf, 2 * BFA_DCONF_UPDATE_TOV);
bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa),
BFA_FLASH_PART_DRV, dconf->instance,
dconf->dconf,
@@ -5655,7 +5918,7 @@ bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
break;
case BFA_DCONF_SM_TIMEOUT:
bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
- bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_IOC_FAILED);
+ bfa_ioc_suspend(&dconf->bfa->ioc);
break;
case BFA_DCONF_SM_EXIT:
bfa_timer_stop(&dconf->timer);
@@ -5853,7 +6116,6 @@ bfa_dconf_init_cb(void *arg, bfa_status_t status)
struct bfa_s *bfa = arg;
struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
- bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
if (status == BFA_STATUS_OK) {
bfa_dconf_read_data_valid(bfa) = BFA_TRUE;
if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE)
@@ -5861,6 +6123,7 @@ bfa_dconf_init_cb(void *arg, bfa_status_t status)
if (dconf->dconf->hdr.version != BFI_DCONF_VERSION)
dconf->dconf->hdr.version = BFI_DCONF_VERSION;
}
+ bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE);
}
@@ -5945,3 +6208,858 @@ bfa_dconf_modexit(struct bfa_s *bfa)
struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);
}
+
+/*
+ * FRU specific functions
+ */
+
+#define BFA_FRU_DMA_BUF_SZ 0x02000 /* 8k dma buffer */
+#define BFA_FRU_CHINOOK_MAX_SIZE 0x10000
+#define BFA_FRU_LIGHTNING_MAX_SIZE 0x200
+
+static void
+bfa_fru_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+ struct bfa_fru_s *fru = cbarg;
+
+ bfa_trc(fru, event);
+
+ switch (event) {
+ case BFA_IOC_E_DISABLED:
+ case BFA_IOC_E_FAILED:
+ if (fru->op_busy) {
+ fru->status = BFA_STATUS_IOC_FAILURE;
+ fru->cbfn(fru->cbarg, fru->status);
+ fru->op_busy = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * Send fru write request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
+{
+ struct bfa_fru_s *fru = cbarg;
+ struct bfi_fru_write_req_s *msg =
+ (struct bfi_fru_write_req_s *) fru->mb.msg;
+ u32 len;
+
+ msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
+ len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
+ fru->residue : BFA_FRU_DMA_BUF_SZ;
+ msg->length = cpu_to_be32(len);
+
+ /*
+ * indicate if it's the last msg of the whole write operation
+ */
+ msg->last = (len == fru->residue) ? 1 : 0;
+
+ msg->trfr_cmpl = (len == fru->residue) ? fru->trfr_cmpl : 0;
+ bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
+ bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
+
+ memcpy(fru->dbuf_kva, fru->ubuf + fru->offset, len);
+ bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
+
+ fru->residue -= len;
+ fru->offset += len;
+}
+
+/*
+ * Send fru read request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_fru_read_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
+{
+ struct bfa_fru_s *fru = cbarg;
+ struct bfi_fru_read_req_s *msg =
+ (struct bfi_fru_read_req_s *) fru->mb.msg;
+ u32 len;
+
+ msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
+ len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
+ fru->residue : BFA_FRU_DMA_BUF_SZ;
+ msg->length = cpu_to_be32(len);
+ bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
+ bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
+ bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
+}
+
+/*
+ * Flash memory info API.
+ *
+ * @param[in] mincfg - minimal cfg variable
+ */
+u32
+bfa_fru_meminfo(bfa_boolean_t mincfg)
+{
+ /* min driver doesn't need fru */
+ if (mincfg)
+ return 0;
+
+ return BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Flash attach API.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] ioc - ioc structure
+ * @param[in] dev - device structure
+ * @param[in] trcmod - trace module
+ * @param[in] logmod - log module
+ */
+void
+bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, void *dev,
+ struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
+{
+ fru->ioc = ioc;
+ fru->trcmod = trcmod;
+ fru->cbfn = NULL;
+ fru->cbarg = NULL;
+ fru->op_busy = 0;
+
+ bfa_ioc_mbox_regisr(fru->ioc, BFI_MC_FRU, bfa_fru_intr, fru);
+ bfa_q_qe_init(&fru->ioc_notify);
+ bfa_ioc_notify_init(&fru->ioc_notify, bfa_fru_notify, fru);
+ list_add_tail(&fru->ioc_notify.qe, &fru->ioc->notify_q);
+
+ /* min driver doesn't need fru */
+ if (mincfg) {
+ fru->dbuf_kva = NULL;
+ fru->dbuf_pa = 0;
+ }
+}
+
+/*
+ * Claim memory for fru
+ *
+ * @param[in] fru - fru structure
+ * @param[in] dm_kva - pointer to virtual memory address
+ * @param[in] dm_pa - frusical memory address
+ * @param[in] mincfg - minimal cfg variable
+ */
+void
+bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa,
+ bfa_boolean_t mincfg)
+{
+ if (mincfg)
+ return;
+
+ fru->dbuf_kva = dm_kva;
+ fru->dbuf_pa = dm_pa;
+ memset(fru->dbuf_kva, 0, BFA_FRU_DMA_BUF_SZ);
+ dm_kva += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+ dm_pa += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Update fru vpd image.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl)
+{
+ bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ);
+ bfa_trc(fru, len);
+ bfa_trc(fru, offset);
+
+ if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2 &&
+ fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2)
+ return BFA_STATUS_FRU_NOT_PRESENT;
+
+ if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
+ return BFA_STATUS_CMD_NOTSUPP;
+
+ if (!bfa_ioc_is_operational(fru->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (fru->op_busy) {
+ bfa_trc(fru, fru->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ fru->op_busy = 1;
+
+ fru->cbfn = cbfn;
+ fru->cbarg = cbarg;
+ fru->residue = len;
+ fru->offset = 0;
+ fru->addr_off = offset;
+ fru->ubuf = buf;
+ fru->trfr_cmpl = trfr_cmpl;
+
+ bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Read fru vpd image.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg)
+{
+ bfa_trc(fru, BFI_FRUVPD_H2I_READ_REQ);
+ bfa_trc(fru, len);
+ bfa_trc(fru, offset);
+
+ if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+ return BFA_STATUS_FRU_NOT_PRESENT;
+
+ if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK &&
+ fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2)
+ return BFA_STATUS_CMD_NOTSUPP;
+
+ if (!bfa_ioc_is_operational(fru->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (fru->op_busy) {
+ bfa_trc(fru, fru->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ fru->op_busy = 1;
+
+ fru->cbfn = cbfn;
+ fru->cbarg = cbarg;
+ fru->residue = len;
+ fru->offset = 0;
+ fru->addr_off = offset;
+ fru->ubuf = buf;
+ bfa_fru_read_send(fru, BFI_FRUVPD_H2I_READ_REQ);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Get maximum size fru vpd image.
+ *
+ * @param[in] fru - fru structure
+ * @param[out] size - maximum size of fru vpd data
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size)
+{
+ if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+ return BFA_STATUS_FRU_NOT_PRESENT;
+
+ if (!bfa_ioc_is_operational(fru->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK ||
+ fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK2)
+ *max_size = BFA_FRU_CHINOOK_MAX_SIZE;
+ else
+ return BFA_STATUS_CMD_NOTSUPP;
+ return BFA_STATUS_OK;
+}
+/*
+ * tfru write.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_tfru_write(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg)
+{
+ bfa_trc(fru, BFI_TFRU_H2I_WRITE_REQ);
+ bfa_trc(fru, len);
+ bfa_trc(fru, offset);
+ bfa_trc(fru, *((u8 *) buf));
+
+ if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+ return BFA_STATUS_FRU_NOT_PRESENT;
+
+ if (!bfa_ioc_is_operational(fru->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (fru->op_busy) {
+ bfa_trc(fru, fru->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ fru->op_busy = 1;
+
+ fru->cbfn = cbfn;
+ fru->cbarg = cbarg;
+ fru->residue = len;
+ fru->offset = 0;
+ fru->addr_off = offset;
+ fru->ubuf = buf;
+
+ bfa_fru_write_send(fru, BFI_TFRU_H2I_WRITE_REQ);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * tfru read.
+ *
+ * @param[in] fru - fru structure
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_tfru_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg)
+{
+ bfa_trc(fru, BFI_TFRU_H2I_READ_REQ);
+ bfa_trc(fru, len);
+ bfa_trc(fru, offset);
+
+ if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
+ return BFA_STATUS_FRU_NOT_PRESENT;
+
+ if (!bfa_ioc_is_operational(fru->ioc))
+ return BFA_STATUS_IOC_NON_OP;
+
+ if (fru->op_busy) {
+ bfa_trc(fru, fru->op_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ fru->op_busy = 1;
+
+ fru->cbfn = cbfn;
+ fru->cbarg = cbarg;
+ fru->residue = len;
+ fru->offset = 0;
+ fru->addr_off = offset;
+ fru->ubuf = buf;
+ bfa_fru_read_send(fru, BFI_TFRU_H2I_READ_REQ);
+
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Process fru response messages upon receiving interrupts.
+ *
+ * @param[in] fruarg - fru structure
+ * @param[in] msg - message structure
+ */
+void
+bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg)
+{
+ struct bfa_fru_s *fru = fruarg;
+ struct bfi_fru_rsp_s *rsp = (struct bfi_fru_rsp_s *)msg;
+ u32 status;
+
+ bfa_trc(fru, msg->mh.msg_id);
+
+ if (!fru->op_busy) {
+ /*
+ * receiving response after ioc failure
+ */
+ bfa_trc(fru, 0x9999);
+ return;
+ }
+
+ switch (msg->mh.msg_id) {
+ case BFI_FRUVPD_I2H_WRITE_RSP:
+ case BFI_TFRU_I2H_WRITE_RSP:
+ status = be32_to_cpu(rsp->status);
+ bfa_trc(fru, status);
+
+ if (status != BFA_STATUS_OK || fru->residue == 0) {
+ fru->status = status;
+ fru->op_busy = 0;
+ if (fru->cbfn)
+ fru->cbfn(fru->cbarg, fru->status);
+ } else {
+ bfa_trc(fru, fru->offset);
+ if (msg->mh.msg_id == BFI_FRUVPD_I2H_WRITE_RSP)
+ bfa_fru_write_send(fru,
+ BFI_FRUVPD_H2I_WRITE_REQ);
+ else
+ bfa_fru_write_send(fru,
+ BFI_TFRU_H2I_WRITE_REQ);
+ }
+ break;
+ case BFI_FRUVPD_I2H_READ_RSP:
+ case BFI_TFRU_I2H_READ_RSP:
+ status = be32_to_cpu(rsp->status);
+ bfa_trc(fru, status);
+
+ if (status != BFA_STATUS_OK) {
+ fru->status = status;
+ fru->op_busy = 0;
+ if (fru->cbfn)
+ fru->cbfn(fru->cbarg, fru->status);
+ } else {
+ u32 len = be32_to_cpu(rsp->length);
+
+ bfa_trc(fru, fru->offset);
+ bfa_trc(fru, len);
+
+ memcpy(fru->ubuf + fru->offset, fru->dbuf_kva, len);
+ fru->residue -= len;
+ fru->offset += len;
+
+ if (fru->residue == 0) {
+ fru->status = status;
+ fru->op_busy = 0;
+ if (fru->cbfn)
+ fru->cbfn(fru->cbarg, fru->status);
+ } else {
+ if (msg->mh.msg_id == BFI_FRUVPD_I2H_READ_RSP)
+ bfa_fru_read_send(fru,
+ BFI_FRUVPD_H2I_READ_REQ);
+ else
+ bfa_fru_read_send(fru,
+ BFI_TFRU_H2I_READ_REQ);
+ }
+ }
+ break;
+ default:
+ WARN_ON(1);
+ }
+}
+
+/*
+ * register definitions
+ */
+#define FLI_CMD_REG 0x0001d000
+#define FLI_RDDATA_REG 0x0001d010
+#define FLI_ADDR_REG 0x0001d004
+#define FLI_DEV_STATUS_REG 0x0001d014
+
+#define BFA_FLASH_FIFO_SIZE 128 /* fifo size */
+#define BFA_FLASH_CHECK_MAX 10000 /* max # of status check */
+#define BFA_FLASH_BLOCKING_OP_MAX 1000000 /* max # of blocking op check */
+#define BFA_FLASH_WIP_MASK 0x01 /* write in progress bit mask */
+
+enum bfa_flash_cmd {
+ BFA_FLASH_FAST_READ = 0x0b, /* fast read */
+ BFA_FLASH_READ_STATUS = 0x05, /* read status */
+};
+
+/**
+ * @brief hardware error definition
+ */
+enum bfa_flash_err {
+ BFA_FLASH_NOT_PRESENT = -1, /*!< flash not present */
+ BFA_FLASH_UNINIT = -2, /*!< flash not initialized */
+ BFA_FLASH_BAD = -3, /*!< flash bad */
+ BFA_FLASH_BUSY = -4, /*!< flash busy */
+ BFA_FLASH_ERR_CMD_ACT = -5, /*!< command active never cleared */
+ BFA_FLASH_ERR_FIFO_CNT = -6, /*!< fifo count never cleared */
+ BFA_FLASH_ERR_WIP = -7, /*!< write-in-progress never cleared */
+ BFA_FLASH_ERR_TIMEOUT = -8, /*!< fli timeout */
+ BFA_FLASH_ERR_LEN = -9, /*!< invalid length */
+};
+
+/**
+ * @brief flash command register data structure
+ */
+union bfa_flash_cmd_reg_u {
+ struct {
+#ifdef __BIG_ENDIAN
+ u32 act:1;
+ u32 rsv:1;
+ u32 write_cnt:9;
+ u32 read_cnt:9;
+ u32 addr_cnt:4;
+ u32 cmd:8;
+#else
+ u32 cmd:8;
+ u32 addr_cnt:4;
+ u32 read_cnt:9;
+ u32 write_cnt:9;
+ u32 rsv:1;
+ u32 act:1;
+#endif
+ } r;
+ u32 i;
+};
+
+/**
+ * @brief flash device status register data structure
+ */
+union bfa_flash_dev_status_reg_u {
+ struct {
+#ifdef __BIG_ENDIAN
+ u32 rsv:21;
+ u32 fifo_cnt:6;
+ u32 busy:1;
+ u32 init_status:1;
+ u32 present:1;
+ u32 bad:1;
+ u32 good:1;
+#else
+ u32 good:1;
+ u32 bad:1;
+ u32 present:1;
+ u32 init_status:1;
+ u32 busy:1;
+ u32 fifo_cnt:6;
+ u32 rsv:21;
+#endif
+ } r;
+ u32 i;
+};
+
+/**
+ * @brief flash address register data structure
+ */
+union bfa_flash_addr_reg_u {
+ struct {
+#ifdef __BIG_ENDIAN
+ u32 addr:24;
+ u32 dummy:8;
+#else
+ u32 dummy:8;
+ u32 addr:24;
+#endif
+ } r;
+ u32 i;
+};
+
+/**
+ * dg flash_raw_private Flash raw private functions
+ */
+static void
+bfa_flash_set_cmd(void __iomem *pci_bar, u8 wr_cnt,
+ u8 rd_cnt, u8 ad_cnt, u8 op)
+{
+ union bfa_flash_cmd_reg_u cmd;
+
+ cmd.i = 0;
+ cmd.r.act = 1;
+ cmd.r.write_cnt = wr_cnt;
+ cmd.r.read_cnt = rd_cnt;
+ cmd.r.addr_cnt = ad_cnt;
+ cmd.r.cmd = op;
+ writel(cmd.i, (pci_bar + FLI_CMD_REG));
+}
+
+static void
+bfa_flash_set_addr(void __iomem *pci_bar, u32 address)
+{
+ union bfa_flash_addr_reg_u addr;
+
+ addr.r.addr = address & 0x00ffffff;
+ addr.r.dummy = 0;
+ writel(addr.i, (pci_bar + FLI_ADDR_REG));
+}
+
+static int
+bfa_flash_cmd_act_check(void __iomem *pci_bar)
+{
+ union bfa_flash_cmd_reg_u cmd;
+
+ cmd.i = readl(pci_bar + FLI_CMD_REG);
+
+ if (cmd.r.act)
+ return BFA_FLASH_ERR_CMD_ACT;
+
+ return 0;
+}
+
+/**
+ * @brief
+ * Flush FLI data fifo.
+ *
+ * @param[in] pci_bar - pci bar address
+ * @param[in] dev_status - device status
+ *
+ * Return 0 on success, negative error number on error.
+ */
+static u32
+bfa_flash_fifo_flush(void __iomem *pci_bar)
+{
+ u32 i;
+ u32 t;
+ union bfa_flash_dev_status_reg_u dev_status;
+
+ dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
+
+ if (!dev_status.r.fifo_cnt)
+ return 0;
+
+ /* fifo counter in terms of words */
+ for (i = 0; i < dev_status.r.fifo_cnt; i++)
+ t = readl(pci_bar + FLI_RDDATA_REG);
+
+ /*
+ * Check the device status. It may take some time.
+ */
+ for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {
+ dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
+ if (!dev_status.r.fifo_cnt)
+ break;
+ }
+
+ if (dev_status.r.fifo_cnt)
+ return BFA_FLASH_ERR_FIFO_CNT;
+
+ return 0;
+}
+
+/**
+ * @brief
+ * Read flash status.
+ *
+ * @param[in] pci_bar - pci bar address
+ *
+ * Return 0 on success, negative error number on error.
+*/
+static u32
+bfa_flash_status_read(void __iomem *pci_bar)
+{
+ union bfa_flash_dev_status_reg_u dev_status;
+ int status;
+ u32 ret_status;
+ int i;
+
+ status = bfa_flash_fifo_flush(pci_bar);
+ if (status < 0)
+ return status;
+
+ bfa_flash_set_cmd(pci_bar, 0, 4, 0, BFA_FLASH_READ_STATUS);
+
+ for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {
+ status = bfa_flash_cmd_act_check(pci_bar);
+ if (!status)
+ break;
+ }
+
+ if (status)
+ return status;
+
+ dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
+ if (!dev_status.r.fifo_cnt)
+ return BFA_FLASH_BUSY;
+
+ ret_status = readl(pci_bar + FLI_RDDATA_REG);
+ ret_status >>= 24;
+
+ status = bfa_flash_fifo_flush(pci_bar);
+ if (status < 0)
+ return status;
+
+ return ret_status;
+}
+
+/**
+ * @brief
+ * Start flash read operation.
+ *
+ * @param[in] pci_bar - pci bar address
+ * @param[in] offset - flash address offset
+ * @param[in] len - read data length
+ * @param[in] buf - read data buffer
+ *
+ * Return 0 on success, negative error number on error.
+ */
+static u32
+bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len,
+ char *buf)
+{
+ int status;
+
+ /*
+ * len must be mutiple of 4 and not exceeding fifo size
+ */
+ if (len == 0 || len > BFA_FLASH_FIFO_SIZE || (len & 0x03) != 0)
+ return BFA_FLASH_ERR_LEN;
+
+ /*
+ * check status
+ */
+ status = bfa_flash_status_read(pci_bar);
+ if (status == BFA_FLASH_BUSY)
+ status = bfa_flash_status_read(pci_bar);
+
+ if (status < 0)
+ return status;
+
+ /*
+ * check if write-in-progress bit is cleared
+ */
+ if (status & BFA_FLASH_WIP_MASK)
+ return BFA_FLASH_ERR_WIP;
+
+ bfa_flash_set_addr(pci_bar, offset);
+
+ bfa_flash_set_cmd(pci_bar, 0, (u8)len, 4, BFA_FLASH_FAST_READ);
+
+ return 0;
+}
+
+/**
+ * @brief
+ * Check flash read operation.
+ *
+ * @param[in] pci_bar - pci bar address
+ *
+ * Return flash device status, 1 if busy, 0 if not.
+ */
+static u32
+bfa_flash_read_check(void __iomem *pci_bar)
+{
+ if (bfa_flash_cmd_act_check(pci_bar))
+ return 1;
+
+ return 0;
+}
+/**
+ * @brief
+ * End flash read operation.
+ *
+ * @param[in] pci_bar - pci bar address
+ * @param[in] len - read data length
+ * @param[in] buf - read data buffer
+ *
+ */
+static void
+bfa_flash_read_end(void __iomem *pci_bar, u32 len, char *buf)
+{
+
+ u32 i;
+
+ /*
+ * read data fifo up to 32 words
+ */
+ for (i = 0; i < len; i += 4) {
+ u32 w = readl(pci_bar + FLI_RDDATA_REG);
+ *((u32 *) (buf + i)) = swab32(w);
+ }
+
+ bfa_flash_fifo_flush(pci_bar);
+}
+
+/**
+ * @brief
+ * Perform flash raw read.
+ *
+ * @param[in] pci_bar - pci bar address
+ * @param[in] offset - flash partition address offset
+ * @param[in] buf - read data buffer
+ * @param[in] len - read data length
+ *
+ * Return status.
+ */
+
+
+#define FLASH_BLOCKING_OP_MAX 500
+#define FLASH_SEM_LOCK_REG 0x18820
+
+static int
+bfa_raw_sem_get(void __iomem *bar)
+{
+ int locked;
+
+ locked = readl((bar + FLASH_SEM_LOCK_REG));
+ return !locked;
+
+}
+
+bfa_status_t
+bfa_flash_sem_get(void __iomem *bar)
+{
+ u32 n = FLASH_BLOCKING_OP_MAX;
+
+ while (!bfa_raw_sem_get(bar)) {
+ if (--n <= 0)
+ return BFA_STATUS_BADFLASH;
+ mdelay(10);
+ }
+ return BFA_STATUS_OK;
+}
+
+void
+bfa_flash_sem_put(void __iomem *bar)
+{
+ writel(0, (bar + FLASH_SEM_LOCK_REG));
+}
+
+bfa_status_t
+bfa_flash_raw_read(void __iomem *pci_bar, u32 offset, char *buf,
+ u32 len)
+{
+ u32 n;
+ int status;
+ u32 off, l, s, residue, fifo_sz;
+
+ residue = len;
+ off = 0;
+ fifo_sz = BFA_FLASH_FIFO_SIZE;
+ status = bfa_flash_sem_get(pci_bar);
+ if (status != BFA_STATUS_OK)
+ return status;
+
+ while (residue) {
+ s = offset + off;
+ n = s / fifo_sz;
+ l = (n + 1) * fifo_sz - s;
+ if (l > residue)
+ l = residue;
+
+ status = bfa_flash_read_start(pci_bar, offset + off, l,
+ &buf[off]);
+ if (status < 0) {
+ bfa_flash_sem_put(pci_bar);
+ return BFA_STATUS_FAILED;
+ }
+
+ n = BFA_FLASH_BLOCKING_OP_MAX;
+ while (bfa_flash_read_check(pci_bar)) {
+ if (--n <= 0) {
+ bfa_flash_sem_put(pci_bar);
+ return BFA_STATUS_FAILED;
+ }
+ }
+
+ bfa_flash_read_end(pci_bar, l, &buf[off]);
+
+ residue -= l;
+ off += l;
+ }
+ bfa_flash_sem_put(pci_bar);
+
+ return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index b2856f96567..2e28392c2fb 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -346,6 +346,12 @@ struct bfa_ioc_hwif_s {
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);
+ void (*ioc_set_fwstate) (struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate);
+ enum bfi_ioc_state (*ioc_get_fwstate) (struct bfa_ioc_s *ioc);
+ void (*ioc_set_alt_fwstate) (struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate);
+ enum bfi_ioc_state (*ioc_get_alt_fwstate) (struct bfa_ioc_s *ioc);
};
/*
@@ -509,6 +515,8 @@ void bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc,
void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
void bfa_flash_memclaim(struct bfa_flash_s *flash,
u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
+bfa_status_t bfa_flash_raw_read(void __iomem *pci_bar_kva,
+ u32 offset, char *buf, u32 len);
/*
* DIAG module specific
@@ -702,6 +710,56 @@ void bfa_phy_memclaim(struct bfa_phy_s *phy,
void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg);
/*
+ * FRU module specific
+ */
+typedef void (*bfa_cb_fru_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_fru_s {
+ struct bfa_ioc_s *ioc; /* back pointer to ioc */
+ struct bfa_trc_mod_s *trcmod; /* trace module */
+ u8 op_busy; /* operation busy flag */
+ u8 rsv[3];
+ u32 residue; /* residual length */
+ u32 offset; /* offset */
+ bfa_status_t status; /* status */
+ u8 *dbuf_kva; /* dma buf virtual address */
+ u64 dbuf_pa; /* dma buf physical address */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ bfa_cb_fru_t cbfn; /* user callback function */
+ void *cbarg; /* user callback arg */
+ u8 *ubuf; /* user supplied buffer */
+ struct bfa_cb_qe_s hcb_qe; /* comp: BFA callback qelem */
+ u32 addr_off; /* fru address offset */
+ struct bfa_mbox_cmd_s mb; /* mailbox */
+ struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */
+ struct bfa_mem_dma_s fru_dma;
+ u8 trfr_cmpl;
+};
+
+#define BFA_FRU(__bfa) (&(__bfa)->modules.fru)
+#define BFA_MEM_FRU_DMA(__bfa) (&(BFA_FRU(__bfa)->fru_dma))
+
+bfa_status_t bfa_fruvpd_update(struct bfa_fru_s *fru,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl);
+bfa_status_t bfa_fruvpd_read(struct bfa_fru_s *fru,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg);
+bfa_status_t bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size);
+bfa_status_t bfa_tfru_write(struct bfa_fru_s *fru,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg);
+bfa_status_t bfa_tfru_read(struct bfa_fru_s *fru,
+ void *buf, u32 len, u32 offset,
+ bfa_cb_fru_t cbfn, void *cbarg);
+u32 bfa_fru_meminfo(bfa_boolean_t mincfg);
+void bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc,
+ void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
+void bfa_fru_memclaim(struct bfa_fru_s *fru,
+ u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
+void bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg);
+
+/*
* Driver Config( dconf) specific
*/
#define BFI_DCONF_SIGNATURE 0xabcdabcd
@@ -716,6 +774,7 @@ struct bfa_dconf_hdr_s {
struct bfa_dconf_s {
struct bfa_dconf_hdr_s hdr;
struct bfa_lunmask_cfg_s lun_mask;
+ struct bfa_throttle_cfg_s throttle_cfg;
};
#pragma pack()
@@ -738,6 +797,8 @@ struct bfa_dconf_mod_s {
#define bfa_dconf_read_data_valid(__bfa) \
(BFA_DCONF_MOD(__bfa)->read_data_valid)
#define BFA_DCONF_UPDATE_TOV 5000 /* memtest timeout in msec */
+#define bfa_dconf_get_min_cfg(__bfa) \
+ (BFA_DCONF_MOD(__bfa)->min_cfg)
void bfa_dconf_modinit(struct bfa_s *bfa);
void bfa_dconf_modexit(struct bfa_s *bfa);
@@ -761,7 +822,8 @@ bfa_status_t bfa_dconf_update(struct bfa_s *bfa);
#define bfa_ioc_maxfrsize(__ioc) ((__ioc)->attr->maxfrsize)
#define bfa_ioc_rx_bbcredit(__ioc) ((__ioc)->attr->rx_bbcredit)
#define bfa_ioc_speed_sup(__ioc) \
- BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
+ ((bfa_ioc_is_cna(__ioc)) ? BFA_PORT_SPEED_10GBPS : \
+ BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop))
#define bfa_ioc_get_nports(__ioc) \
BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
@@ -828,7 +890,7 @@ void bfa_ioc_enable(struct bfa_ioc_s *ioc);
void bfa_ioc_disable(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
-void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
+bfa_status_t bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
u32 boot_env);
void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
@@ -859,6 +921,7 @@ bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
int *trclen);
bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
u32 *offset, int *buflen);
+bfa_status_t bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg);
void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,
struct bfi_ioc_image_hdr_s *fwhdr);
@@ -885,17 +948,19 @@ bfa_status_t bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port,
enum bfa_mode_s mode, int max_pf, int max_vf,
bfa_ablk_cbfn_t cbfn, void *cbarg);
bfa_status_t bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
- u8 port, enum bfi_pcifn_class personality, int bw,
- bfa_ablk_cbfn_t cbfn, void *cbarg);
+ u8 port, enum bfi_pcifn_class personality,
+ u16 bw_min, u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg);
bfa_status_t bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
bfa_ablk_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
- bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn,
+ u16 bw_min, u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg);
bfa_status_t bfa_ablk_optrom_en(struct bfa_ablk_s *ablk,
bfa_ablk_cbfn_t cbfn, void *cbarg);
bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk,
bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ioc_flash_img_get_chnk(struct bfa_ioc_s *ioc, u32 off,
+ u32 *fwimg);
/*
* bfa mfg wwn API functions
*/
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 30df8a28471..453c2f5b556 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -22,6 +22,8 @@
BFA_TRC_FILE(CNA, IOC_CB);
+#define bfa_ioc_cb_join_pos(__ioc) ((u32) (1 << BFA_IOC_CB_JOIN_SH))
+
/*
* forward declarations
*/
@@ -37,6 +39,12 @@ static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_set_cur_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_set_alt_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc);
static struct bfa_ioc_hwif_s hwif_cb;
@@ -59,6 +67,10 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave;
hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack;
hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete;
+ hwif_cb.ioc_set_fwstate = bfa_ioc_cb_set_cur_ioc_fwstate;
+ hwif_cb.ioc_get_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate;
+ hwif_cb.ioc_set_alt_fwstate = bfa_ioc_cb_set_alt_ioc_fwstate;
+ hwif_cb.ioc_get_alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate;
ioc->ioc_hwif = &hwif_cb;
}
@@ -69,6 +81,29 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
static bfa_boolean_t
bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
{
+ enum bfi_ioc_state alt_fwstate, cur_fwstate;
+ struct bfi_ioc_image_hdr_s fwhdr;
+
+ cur_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc);
+ bfa_trc(ioc, cur_fwstate);
+ alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc);
+ bfa_trc(ioc, alt_fwstate);
+
+ /*
+ * Uninit implies this is the only driver as of now.
+ */
+ if (cur_fwstate == BFI_IOC_UNINIT)
+ return BFA_TRUE;
+ /*
+ * Check if another driver with a different firmware is active
+ */
+ bfa_ioc_fwver_get(ioc, &fwhdr);
+ if (!bfa_ioc_fwver_cmp(ioc, &fwhdr) &&
+ alt_fwstate != BFI_IOC_DISABLED) {
+ bfa_trc(ioc, alt_fwstate);
+ return BFA_FALSE;
+ }
+
return BFA_TRUE;
}
@@ -187,6 +222,20 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
static bfa_boolean_t
bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc)
{
+ u32 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ /**
+ * Driver load time. If the join bit is set,
+ * it is due to an unclean exit by the driver for this
+ * PCI fn in the previous incarnation. Whoever comes here first
+ * should clean it up, no matter which PCI fn.
+ */
+ if (ioc_fwstate & BFA_IOC_CB_JOIN_MASK) {
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+ return BFA_TRUE;
+ }
+
return bfa_ioc_cb_sync_complete(ioc);
}
@@ -212,24 +261,66 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
static void
bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc)
{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 join_pos = bfa_ioc_cb_join_pos(ioc);
+
+ writel((r32 | join_pos), ioc->ioc_regs.ioc_fwstate);
}
static void
bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc)
{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 join_pos = bfa_ioc_cb_join_pos(ioc);
+
+ writel((r32 & ~join_pos), ioc->ioc_regs.ioc_fwstate);
+}
+
+static void
+bfa_ioc_cb_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
+
+ writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)),
+ ioc->ioc_regs.ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state)(readl(ioc->ioc_regs.ioc_fwstate) &
+ BFA_IOC_CB_FWSTATE_MASK);
+}
+
+static void
+bfa_ioc_cb_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ u32 r32 = readl(ioc->ioc_regs.alt_ioc_fwstate);
+
+ writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)),
+ ioc->ioc_regs.alt_ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state)(readl(ioc->ioc_regs.alt_ioc_fwstate) &
+ BFA_IOC_CB_FWSTATE_MASK);
}
static void
bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc)
{
- writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_ioc_cb_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
}
static bfa_boolean_t
bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
{
- uint32_t fwstate, alt_fwstate;
- fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 fwstate, alt_fwstate;
+ fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc);
/*
* At this point, this IOC is hoding the hw sem in the
@@ -257,7 +348,7 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
fwstate == BFI_IOC_OP)
return BFA_TRUE;
else {
- alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate);
+ alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc);
if (alt_fwstate == BFI_IOC_FAIL ||
alt_fwstate == BFI_IOC_DISABLED ||
alt_fwstate == BFI_IOC_UNINIT ||
@@ -272,7 +363,7 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
bfa_status_t
bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
{
- u32 pll_sclk, pll_fclk;
+ u32 pll_sclk, pll_fclk, join_bits;
pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN |
__APP_PLL_SCLK_P0_1(3U) |
@@ -282,8 +373,12 @@ bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
__APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
__APP_PLL_LCLK_JITLMT0_1(3U) |
__APP_PLL_LCLK_CNTLMT0_1(3U);
- writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
- writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
+ join_bits = readl(rb + BFA_IOC0_STATE_REG) &
+ BFA_IOC_CB_JOIN_MASK;
+ writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC0_STATE_REG));
+ join_bits = readl(rb + BFA_IOC1_STATE_REG) &
+ BFA_IOC_CB_JOIN_MASK;
+ writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC1_STATE_REG));
writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 2eb0c6a2938..bd53150e4ee 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -43,6 +43,12 @@ static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_set_cur_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_set_alt_ioc_fwstate(
+ struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate);
+static enum bfi_ioc_state bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc);
static struct bfa_ioc_hwif_s hwif_ct;
static struct bfa_ioc_hwif_s hwif_ct2;
@@ -57,13 +63,6 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
u32 usecnt;
struct bfi_ioc_image_hdr_s fwhdr;
- /*
- * If bios boot (flash based) -- do not increment usage count
- */
- if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
- BFA_IOC_FWIMG_MINSZ)
- return BFA_TRUE;
-
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
@@ -115,13 +114,6 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
u32 usecnt;
/*
- * If bios boot (flash based) -- do not decrement usage count
- */
- if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
- BFA_IOC_FWIMG_MINSZ)
- return;
-
- /*
* decrement usage count
*/
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
@@ -400,13 +392,12 @@ static void
bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
{
- if (bfa_ioc_is_cna(ioc)) {
- bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
- writel(0, ioc->ioc_regs.ioc_usage_reg);
- readl(ioc->ioc_regs.ioc_usage_sem_reg);
- writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
- }
+ bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(0, ioc->ioc_regs.ioc_usage_reg);
+ readl(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(0, ioc->ioc_regs.ioc_fail_sync);
/*
* Read the hw sem reg to make sure that it is locked
* before we clear it. If it is not locked, writing 1
@@ -527,6 +518,10 @@ bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif)
hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave;
hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack;
hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete;
+ hwif->ioc_set_fwstate = bfa_ioc_ct_set_cur_ioc_fwstate;
+ hwif->ioc_get_fwstate = bfa_ioc_ct_get_cur_ioc_fwstate;
+ hwif->ioc_set_alt_fwstate = bfa_ioc_ct_set_alt_ioc_fwstate;
+ hwif->ioc_get_alt_fwstate = bfa_ioc_ct_get_alt_ioc_fwstate;
}
/**
@@ -759,25 +754,6 @@ bfa_ioc_ct2_mem_init(void __iomem *rb)
void
bfa_ioc_ct2_mac_reset(void __iomem *rb)
{
- u32 r32;
-
- bfa_ioc_ct2_sclk_init(rb);
- bfa_ioc_ct2_lclk_init(rb);
-
- /*
- * release soft reset on s_clk & l_clk
- */
- r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
- writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
- (rb + CT2_APP_PLL_SCLK_CTL_REG));
-
- /*
- * release soft reset on s_clk & l_clk
- */
- r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
- writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
- (rb + CT2_APP_PLL_LCLK_CTL_REG));
-
/* put port0, port1 MAC & AHB in reset */
writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
rb + CT2_CSI_MAC_CONTROL_REG(0));
@@ -785,8 +761,21 @@ bfa_ioc_ct2_mac_reset(void __iomem *rb)
rb + CT2_CSI_MAC_CONTROL_REG(1));
}
+static void
+bfa_ioc_ct2_enable_flash(void __iomem *rb)
+{
+ u32 r32;
+
+ r32 = readl((rb + PSS_GPIO_OUT_REG));
+ writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG));
+ r32 = readl((rb + PSS_GPIO_OE_REG));
+ writel(r32 | 1, (rb + PSS_GPIO_OE_REG));
+}
+
#define CT2_NFC_MAX_DELAY 1000
-#define CT2_NFC_VER_VALID 0x143
+#define CT2_NFC_PAUSE_MAX_DELAY 4000
+#define CT2_NFC_VER_VALID 0x147
+#define CT2_NFC_STATE_RUNNING 0x20000001
#define BFA_IOC_PLL_POLL 1000000
static bfa_boolean_t
@@ -802,6 +791,20 @@ bfa_ioc_ct2_nfc_halted(void __iomem *rb)
}
static void
+bfa_ioc_ct2_nfc_halt(void __iomem *rb)
+{
+ int i;
+
+ writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG);
+ for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
+ if (bfa_ioc_ct2_nfc_halted(rb))
+ break;
+ udelay(1000);
+ }
+ WARN_ON(!bfa_ioc_ct2_nfc_halted(rb));
+}
+
+static void
bfa_ioc_ct2_nfc_resume(void __iomem *rb)
{
u32 r32;
@@ -817,105 +820,178 @@ bfa_ioc_ct2_nfc_resume(void __iomem *rb)
WARN_ON(1);
}
-bfa_status_t
-bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
+static void
+bfa_ioc_ct2_clk_reset(void __iomem *rb)
{
- u32 wgn, r32, nfc_ver, i;
+ u32 r32;
- wgn = readl(rb + CT2_WGN_STATUS);
- nfc_ver = readl(rb + CT2_RSC_GPR15_REG);
+ bfa_ioc_ct2_sclk_init(rb);
+ bfa_ioc_ct2_lclk_init(rb);
- if ((wgn == (__A2T_AHB_LOAD | __WGN_READY)) &&
- (nfc_ver >= CT2_NFC_VER_VALID)) {
- if (bfa_ioc_ct2_nfc_halted(rb))
- bfa_ioc_ct2_nfc_resume(rb);
+ /*
+ * release soft reset on s_clk & l_clk
+ */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
+ (rb + CT2_APP_PLL_SCLK_CTL_REG));
- writel(__RESET_AND_START_SCLK_LCLK_PLLS,
- rb + CT2_CSI_FW_CTL_SET_REG);
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
+ (rb + CT2_APP_PLL_LCLK_CTL_REG));
- for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
- r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
- if (r32 & __RESET_AND_START_SCLK_LCLK_PLLS)
- break;
- }
+}
- WARN_ON(!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS));
+static void
+bfa_ioc_ct2_nfc_clk_reset(void __iomem *rb)
+{
+ u32 r32, i;
- for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
- r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
- if (!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS))
- break;
- }
+ r32 = readl((rb + PSS_CTL_REG));
+ r32 |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
+ writel(r32, (rb + PSS_CTL_REG));
+
+ writel(__RESET_AND_START_SCLK_LCLK_PLLS, rb + CT2_CSI_FW_CTL_SET_REG);
+
+ for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+ r32 = readl(rb + CT2_NFC_FLASH_STS_REG);
+
+ if ((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS))
+ break;
+ }
+ WARN_ON(!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS));
+
+ for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+ r32 = readl(rb + CT2_NFC_FLASH_STS_REG);
+
+ if (!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS))
+ break;
+ }
+ WARN_ON((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS));
+
+ r32 = readl(rb + CT2_CSI_FW_CTL_REG);
+ WARN_ON((r32 & __RESET_AND_START_SCLK_LCLK_PLLS));
+}
+
+static void
+bfa_ioc_ct2_wait_till_nfc_running(void __iomem *rb)
+{
+ u32 r32;
+ int i;
- WARN_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
+ if (bfa_ioc_ct2_nfc_halted(rb))
+ bfa_ioc_ct2_nfc_resume(rb);
+ for (i = 0; i < CT2_NFC_PAUSE_MAX_DELAY; i++) {
+ r32 = readl(rb + CT2_NFC_STS_REG);
+ if (r32 == CT2_NFC_STATE_RUNNING)
+ return;
udelay(1000);
+ }
- r32 = readl(rb + CT2_CSI_FW_CTL_REG);
- WARN_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
- } else {
- writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG);
- for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
- r32 = readl(rb + CT2_NFC_CSR_SET_REG);
- if (r32 & __NFC_CONTROLLER_HALTED)
- break;
- udelay(1000);
- }
+ r32 = readl(rb + CT2_NFC_STS_REG);
+ WARN_ON(!(r32 == CT2_NFC_STATE_RUNNING));
+}
- bfa_ioc_ct2_mac_reset(rb);
- bfa_ioc_ct2_sclk_init(rb);
- bfa_ioc_ct2_lclk_init(rb);
+bfa_status_t
+bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
+{
+ u32 wgn, r32, nfc_ver;
- /*
- * release soft reset on s_clk & l_clk
- */
- r32 = readl(rb + CT2_APP_PLL_SCLK_CTL_REG);
- writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
- (rb + CT2_APP_PLL_SCLK_CTL_REG));
+ wgn = readl(rb + CT2_WGN_STATUS);
+ if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
/*
- * release soft reset on s_clk & l_clk
+ * If flash is corrupted, enable flash explicitly
*/
- r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
- writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
- (rb + CT2_APP_PLL_LCLK_CTL_REG));
- }
+ bfa_ioc_ct2_clk_reset(rb);
+ bfa_ioc_ct2_enable_flash(rb);
- /*
- * Announce flash device presence, if flash was corrupted.
- */
- if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
- r32 = readl(rb + PSS_GPIO_OUT_REG);
- writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG));
- r32 = readl(rb + PSS_GPIO_OE_REG);
- writel(r32 | 1, (rb + PSS_GPIO_OE_REG));
+ bfa_ioc_ct2_mac_reset(rb);
+
+ bfa_ioc_ct2_clk_reset(rb);
+ bfa_ioc_ct2_enable_flash(rb);
+
+ } else {
+ nfc_ver = readl(rb + CT2_RSC_GPR15_REG);
+
+ if ((nfc_ver >= CT2_NFC_VER_VALID) &&
+ (wgn == (__A2T_AHB_LOAD | __WGN_READY))) {
+
+ bfa_ioc_ct2_wait_till_nfc_running(rb);
+
+ bfa_ioc_ct2_nfc_clk_reset(rb);
+ } else {
+ bfa_ioc_ct2_nfc_halt(rb);
+
+ bfa_ioc_ct2_clk_reset(rb);
+ bfa_ioc_ct2_mac_reset(rb);
+ bfa_ioc_ct2_clk_reset(rb);
+
+ }
}
+ /*
+ * The very first PCIe DMA Read done by LPU fails with a fatal error,
+ * when Address Translation Cache (ATC) has been enabled by system BIOS.
+ *
+ * Workaround:
+ * Disable Invalidated Tag Match Enable capability by setting the bit 26
+ * of CHIP_MISC_PRG to 0, by default it is set to 1.
+ */
+ r32 = readl(rb + CT2_CHIP_MISC_PRG);
+ writel((r32 & 0xfbffffff), (rb + CT2_CHIP_MISC_PRG));
/*
* Mask the interrupts and clear any
- * pending interrupts.
+ * pending interrupts left by BIOS/EFI
*/
+
writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
/* For first time initialization, no need to clear interrupts */
r32 = readl(rb + HOST_SEM5_REG);
if (r32 & 0x1) {
- r32 = readl(rb + CT2_LPU0_HOSTFN_CMD_STAT);
+ r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
if (r32 == 1) {
- writel(1, rb + CT2_LPU0_HOSTFN_CMD_STAT);
+ writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
}
- r32 = readl(rb + CT2_LPU1_HOSTFN_CMD_STAT);
+ r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
if (r32 == 1) {
- writel(1, rb + CT2_LPU1_HOSTFN_CMD_STAT);
- readl(rb + CT2_LPU1_HOSTFN_CMD_STAT);
+ writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
}
}
bfa_ioc_ct2_mem_init(rb);
- writel(BFI_IOC_UNINIT, rb + CT2_BFA_IOC0_STATE_REG);
- writel(BFI_IOC_UNINIT, rb + CT2_BFA_IOC1_STATE_REG);
+ writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG));
+ writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG));
return BFA_STATUS_OK;
}
+
+static void
+bfa_ioc_ct_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ writel(fwstate, ioc->ioc_regs.ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state)readl(ioc->ioc_regs.ioc_fwstate);
+}
+
+static void
+bfa_ioc_ct_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc,
+ enum bfi_ioc_state fwstate)
+{
+ writel(fwstate, ioc->ioc_regs.alt_ioc_fwstate);
+}
+
+static enum bfi_ioc_state
+bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc)
+{
+ return (enum bfi_ioc_state) readl(ioc->ioc_regs.alt_ioc_fwstate);
+}
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index 189fff71e3c..a14c784ff3f 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -45,6 +45,7 @@ struct bfa_modules_s {
struct bfa_diag_s diag_mod; /* diagnostics module */
struct bfa_phy_s phy; /* phy module */
struct bfa_dconf_mod_s dconf_mod; /* DCONF common module */
+ struct bfa_fru_s fru; /* fru module */
};
/*
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index 95e4ad8759a..8ea7697deb9 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -250,6 +250,12 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
return BFA_STATUS_IOC_FAILURE;
}
+ /* if port is d-port enabled, return error */
+ if (port->dport_enabled) {
+ bfa_trc(port, BFA_STATUS_DPORT_ERR);
+ return BFA_STATUS_DPORT_ERR;
+ }
+
if (port->endis_pending) {
bfa_trc(port, BFA_STATUS_DEVBUSY);
return BFA_STATUS_DEVBUSY;
@@ -300,6 +306,12 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
return BFA_STATUS_IOC_FAILURE;
}
+ /* if port is d-port enabled, return error */
+ if (port->dport_enabled) {
+ bfa_trc(port, BFA_STATUS_DPORT_ERR);
+ return BFA_STATUS_DPORT_ERR;
+ }
+
if (port->endis_pending) {
bfa_trc(port, BFA_STATUS_DEVBUSY);
return BFA_STATUS_DEVBUSY;
@@ -431,6 +443,10 @@ bfa_port_notify(void *arg, enum bfa_ioc_event_e event)
port->endis_cbfn = NULL;
port->endis_pending = BFA_FALSE;
}
+
+ /* clear D-port mode */
+ if (port->dport_enabled)
+ bfa_port_set_dportenabled(port, BFA_FALSE);
break;
default:
break;
@@ -467,6 +483,7 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
port->stats_cbfn = NULL;
port->endis_cbfn = NULL;
port->pbc_disabled = BFA_FALSE;
+ port->dport_enabled = BFA_FALSE;
bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
bfa_q_qe_init(&port->ioc_notify);
@@ -483,6 +500,21 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
}
/*
+ * bfa_port_set_dportenabled();
+ *
+ * Port module- set pbc disabled flag
+ *
+ * @param[in] port - Pointer to the Port module data structure
+ *
+ * @return void
+ */
+void
+bfa_port_set_dportenabled(struct bfa_port_s *port, bfa_boolean_t enabled)
+{
+ port->dport_enabled = enabled;
+}
+
+/*
* CEE module specific definitions
*/
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
index 947f897328d..2fcab6bc628 100644
--- a/drivers/scsi/bfa/bfa_port.h
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -45,6 +45,7 @@ struct bfa_port_s {
bfa_status_t endis_status;
struct bfa_ioc_notify_s ioc_notify;
bfa_boolean_t pbc_disabled;
+ bfa_boolean_t dport_enabled;
struct bfa_mem_dma_s port_dma;
};
@@ -66,6 +67,8 @@ bfa_status_t bfa_port_disable(struct bfa_port_s *port,
u32 bfa_port_meminfo(void);
void bfa_port_mem_claim(struct bfa_port_s *port,
u8 *dma_kva, u64 dma_pa);
+void bfa_port_set_dportenabled(struct bfa_port_s *port,
+ bfa_boolean_t enabled);
/*
* CEE declaration
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index b2538d60db3..625225f3108 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -67,6 +67,11 @@ enum bfa_fcport_sm_event {
BFA_FCPORT_SM_LINKDOWN = 7, /* firmware linkup down */
BFA_FCPORT_SM_QRESUME = 8, /* CQ space available */
BFA_FCPORT_SM_HWFAIL = 9, /* IOC h/w failure */
+ BFA_FCPORT_SM_DPORTENABLE = 10, /* enable dport */
+ BFA_FCPORT_SM_DPORTDISABLE = 11,/* disable dport */
+ BFA_FCPORT_SM_FAA_MISCONFIG = 12, /* FAA misconfiguratin */
+ BFA_FCPORT_SM_DDPORTENABLE = 13, /* enable ddport */
+ BFA_FCPORT_SM_DDPORTDISABLE = 14, /* disable ddport */
};
/*
@@ -197,6 +202,12 @@ static void bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event);
static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
static void bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
enum bfa_fcport_ln_sm_event event);
@@ -226,6 +237,9 @@ static struct bfa_sm_table_s hal_port_sm_table[] = {
{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
+ {BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
+ {BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},
+ {BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
};
@@ -1244,6 +1258,12 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
* Just ignore
*/
break;
+ case BFA_LPS_SM_SET_N2N_PID:
+ /*
+ * When topology is set to loop, bfa_lps_set_n2n_pid() sends
+ * this event. Ignore this event.
+ */
+ break;
default:
bfa_sm_fault(lps->bfa, event);
@@ -1599,7 +1619,6 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
lps->lp_mac = rsp->lp_mac;
lps->brcd_switch = rsp->brcd_switch;
lps->fcf_mac = rsp->fcf_mac;
- lps->pr_bbscn = rsp->bb_scn;
break;
@@ -1729,7 +1748,6 @@ bfa_lps_send_login(struct bfa_lps_s *lps)
m->nwwn = lps->nwwn;
m->fdisc = lps->fdisc;
m->auth_en = lps->auth_en;
- m->bb_scn = lps->bb_scn;
bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
list_del(&lps->qe);
@@ -1925,7 +1943,7 @@ bfa_lps_delete(struct bfa_lps_s *lps)
*/
void
bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
- wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en, uint8_t bb_scn)
+ wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
{
lps->uarg = uarg;
lps->alpa = alpa;
@@ -1934,7 +1952,6 @@ bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
lps->nwwn = nwwn;
lps->fdisc = BFA_FALSE;
lps->auth_en = auth_en;
- lps->bb_scn = bb_scn;
bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
}
@@ -2169,6 +2186,12 @@ bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
break;
+ case BFA_FCPORT_SM_FAA_MISCONFIG:
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+ break;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2225,6 +2248,12 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
break;
+ case BFA_FCPORT_SM_FAA_MISCONFIG:
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+ break;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2250,11 +2279,11 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
bfa_trc(fcport->bfa,
- pevent->link_state.vc_fcf.fcf.fipenabled);
+ pevent->link_state.attr.vc_fcf.fcf.fipenabled);
bfa_trc(fcport->bfa,
- pevent->link_state.vc_fcf.fcf.fipfailed);
+ pevent->link_state.attr.vc_fcf.fcf.fipfailed);
- if (pevent->link_state.vc_fcf.fcf.fipfailed)
+ if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
BFA_PL_EID_FIP_FCF_DISC, 0,
"FIP FCF Discovery Failed");
@@ -2311,6 +2340,12 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
break;
+ case BFA_FCPORT_SM_FAA_MISCONFIG:
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+ break;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2404,6 +2439,12 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
}
break;
+ case BFA_FCPORT_SM_FAA_MISCONFIG:
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+ break;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2449,6 +2490,12 @@ bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
bfa_reqq_wcancel(&fcport->reqq_wait);
break;
+ case BFA_FCPORT_SM_FAA_MISCONFIG:
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
+ break;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2600,6 +2647,14 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
break;
+ case BFA_FCPORT_SM_DPORTENABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
+ break;
+
+ case BFA_FCPORT_SM_DDPORTENABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
+ break;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2680,6 +2735,115 @@ bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
}
}
+static void
+bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_DPORTENABLE:
+ case BFA_FCPORT_SM_DISABLE:
+ case BFA_FCPORT_SM_ENABLE:
+ case BFA_FCPORT_SM_START:
+ /*
+ * Ignore event for a port that is dport
+ */
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+ break;
+
+ case BFA_FCPORT_SM_DPORTDISABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_DISABLE:
+ case BFA_FCPORT_SM_DDPORTDISABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+ break;
+
+ case BFA_FCPORT_SM_DPORTENABLE:
+ case BFA_FCPORT_SM_DPORTDISABLE:
+ case BFA_FCPORT_SM_ENABLE:
+ case BFA_FCPORT_SM_START:
+ /**
+ * Ignore event for a port that is ddport
+ */
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_DPORTENABLE:
+ case BFA_FCPORT_SM_ENABLE:
+ case BFA_FCPORT_SM_START:
+ /*
+ * Ignore event for a port as there is FAA misconfig
+ */
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ if (bfa_fcport_send_disable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+ else
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
+
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+ bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
/*
* Link state is down
*/
@@ -2943,6 +3107,7 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
*/
do_gettimeofday(&tv);
fcport->stats_reset_time = tv.tv_sec;
+ fcport->stats_dma_ready = BFA_FALSE;
/*
* initialize and set default configuration
@@ -2953,6 +3118,11 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
port_cfg->maxfrsize = 0;
port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
+ port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
+ port_cfg->qos_bw.med = BFA_QOS_BW_MED;
+ port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
+
+ fcport->fec_state = BFA_FEC_OFFLINE;
INIT_LIST_HEAD(&fcport->stats_pending_q);
INIT_LIST_HEAD(&fcport->statsclr_pending_q);
@@ -2996,6 +3166,21 @@ bfa_fcport_iocdisable(struct bfa_s *bfa)
bfa_trunk_iocdisable(bfa);
}
+/*
+ * Update loop info in fcport for SCN online
+ */
+static void
+bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
+ struct bfa_fcport_loop_info_s *loop_info)
+{
+ fcport->myalpa = loop_info->myalpa;
+ fcport->alpabm_valid =
+ loop_info->alpabm_val;
+ memcpy(fcport->alpabm.alpa_bm,
+ loop_info->alpabm.alpa_bm,
+ sizeof(struct fc_alpabm_s));
+}
+
static void
bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
{
@@ -3005,12 +3190,20 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
fcport->speed = pevent->link_state.speed;
fcport->topology = pevent->link_state.topology;
- if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
- fcport->myalpa = 0;
+ if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
+ bfa_fcport_update_loop_info(fcport,
+ &pevent->link_state.attr.loop_info);
+ return;
+ }
/* QoS Details */
fcport->qos_attr = pevent->link_state.qos_attr;
- fcport->qos_vc_attr = pevent->link_state.vc_fcf.qos_vc_attr;
+ fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
+
+ if (fcport->cfg.bb_cr_enabled)
+ fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
+
+ fcport->fec_state = pevent->link_state.fec_state;
/*
* update trunk state if applicable
@@ -3019,7 +3212,8 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
trunk->attr.state = BFA_TRUNK_DISABLED;
/* update FCoE specific */
- fcport->fcoe_vlan = be16_to_cpu(pevent->link_state.vc_fcf.fcf.vlan);
+ fcport->fcoe_vlan =
+ be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
bfa_trc(fcport->bfa, fcport->speed);
bfa_trc(fcport->bfa, fcport->topology);
@@ -3030,7 +3224,7 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
{
fcport->speed = BFA_PORT_SPEED_UNKNOWN;
fcport->topology = BFA_PORT_TOPOLOGY_NONE;
- fcport->bbsc_op_state = BFA_FALSE;
+ fcport->fec_state = BFA_FEC_OFFLINE;
}
/*
@@ -3453,6 +3647,7 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
case BFI_FCPORT_I2H_ENABLE_RSP:
if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
+ fcport->stats_dma_ready = BFA_TRUE;
if (fcport->use_flash_cfg) {
fcport->cfg = i2hmsg.penable_rsp->port_cfg;
fcport->cfg.maxfrsize =
@@ -3468,6 +3663,8 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
else
fcport->trunk.attr.state =
BFA_TRUNK_DISABLED;
+ fcport->qos_attr.qos_bw =
+ i2hmsg.penable_rsp->port_cfg.qos_bw;
fcport->use_flash_cfg = BFA_FALSE;
}
@@ -3476,6 +3673,14 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
else
fcport->qos_attr.state = BFA_QOS_DISABLED;
+ fcport->qos_attr.qos_bw_op =
+ i2hmsg.penable_rsp->port_cfg.qos_bw;
+
+ if (fcport->cfg.bb_cr_enabled)
+ fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
+ else
+ fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
+
bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
}
break;
@@ -3486,10 +3691,24 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
break;
case BFI_FCPORT_I2H_EVENT:
+ if (fcport->cfg.bb_cr_enabled)
+ fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
+ else
+ fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
+
if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
- else
- bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
+ else {
+ if (i2hmsg.event->link_state.linkstate_rsn ==
+ BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
+ bfa_sm_send_event(fcport,
+ BFA_FCPORT_SM_FAA_MISCONFIG);
+ else
+ bfa_sm_send_event(fcport,
+ BFA_FCPORT_SM_LINKDOWN);
+ }
+ fcport->qos_attr.qos_bw_op =
+ i2hmsg.event->link_state.qos_attr.qos_bw_op;
break;
case BFI_FCPORT_I2H_TRUNK_SCN:
@@ -3609,6 +3828,9 @@ bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
if (fcport->cfg.trunked == BFA_TRUE)
return BFA_STATUS_TRUNK_ENABLED;
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (speed == BFA_PORT_SPEED_16GBPS))
+ return BFA_STATUS_UNSUPP_SPEED;
if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
bfa_trc(bfa, fcport->speed_sup);
return BFA_STATUS_UNSUPP_SPEED;
@@ -3663,7 +3885,28 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
switch (topology) {
case BFA_PORT_TOPOLOGY_P2P:
+ break;
+
case BFA_PORT_TOPOLOGY_LOOP:
+ if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
+ (fcport->qos_attr.state != BFA_QOS_DISABLED))
+ return BFA_STATUS_ERROR_QOS_ENABLED;
+ if (fcport->cfg.ratelimit != BFA_FALSE)
+ return BFA_STATUS_ERROR_TRL_ENABLED;
+ if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
+ (fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
+ return BFA_STATUS_ERROR_TRUNK_ENABLED;
+ if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
+ (fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
+ return BFA_STATUS_UNSUPP_SPEED;
+ if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
+ return BFA_STATUS_LOOP_UNSUPP_MEZZ;
+ if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
+ return BFA_STATUS_DPORT_ERR;
+ if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
+ return BFA_STATUS_DPORT_ERR;
+ break;
+
case BFA_PORT_TOPOLOGY_AUTO:
break;
@@ -3686,6 +3929,17 @@ bfa_fcport_get_topology(struct bfa_s *bfa)
return fcport->topology;
}
+/**
+ * Get config topology.
+ */
+enum bfa_port_topology
+bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->cfg.topology;
+}
+
bfa_status_t
bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
{
@@ -3761,20 +4015,19 @@ bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
u8
bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
+ return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
- return fcport->cfg.rx_bbcredit;
+ else
+ return 0;
}
void
-bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn)
+bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
- fcport->cfg.bb_scn = bb_scn;
- if (bb_scn)
- fcport->bbsc_op_state = BFA_TRUE;
}
/*
@@ -3824,7 +4077,8 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
- attr->bbsc_op_status = fcport->bbsc_op_state;
+
+ attr->fec_state = fcport->fec_state;
/* PBC Disabled State */
if (bfa_fcport_is_pbcdisabled(bfa))
@@ -3850,8 +4104,9 @@ bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- if (bfa_ioc_is_disabled(&bfa->ioc))
- return BFA_STATUS_IOC_DISABLED;
+ if (!bfa_iocfc_is_operational(bfa) ||
+ !fcport->stats_dma_ready)
+ return BFA_STATUS_IOC_NON_OP;
if (!list_empty(&fcport->statsclr_pending_q))
return BFA_STATUS_DEVBUSY;
@@ -3876,6 +4131,10 @@ bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ if (!bfa_iocfc_is_operational(bfa) ||
+ !fcport->stats_dma_ready)
+ return BFA_STATUS_IOC_NON_OP;
+
if (!list_empty(&fcport->stats_pending_q))
return BFA_STATUS_DEVBUSY;
@@ -3905,6 +4164,49 @@ bfa_fcport_is_disabled(struct bfa_s *bfa)
}
bfa_boolean_t
+bfa_fcport_is_dport(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
+ BFA_PORT_ST_DPORT);
+}
+
+bfa_boolean_t
+bfa_fcport_is_ddport(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
+ BFA_PORT_ST_DDPORT);
+}
+
+bfa_status_t
+bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
+
+ bfa_trc(bfa, ioc_type);
+
+ if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
+ return BFA_STATUS_QOS_BW_INVALID;
+
+ if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
+ return BFA_STATUS_QOS_BW_INVALID;
+
+ if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
+ (qos_bw->low > qos_bw->high))
+ return BFA_STATUS_QOS_BW_INVALID;
+
+ if ((ioc_type == BFA_IOC_TYPE_FC) &&
+ (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
+ fcport->cfg.qos_bw = *qos_bw;
+
+ return BFA_STATUS_OK;
+}
+
+bfa_boolean_t
bfa_fcport_is_ratelim(struct bfa_s *bfa)
{
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
@@ -3981,6 +4283,115 @@ bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
return fcport->cfg.trunked;
}
+bfa_status_t
+bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, on_off);
+
+ if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
+ return BFA_STATUS_BBCR_FC_ONLY;
+
+ if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
+ (bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
+ return BFA_STATUS_CMD_NOTSUPP_MEZZ;
+
+ if (on_off) {
+ if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
+ return BFA_STATUS_TOPOLOGY_LOOP;
+
+ if (fcport->cfg.qos_enabled)
+ return BFA_STATUS_ERROR_QOS_ENABLED;
+
+ if (fcport->cfg.trunked)
+ return BFA_STATUS_TRUNK_ENABLED;
+
+ if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
+ (fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
+ return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
+
+ if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
+ return BFA_STATUS_FEATURE_NOT_SUPPORTED;
+
+ if (fcport->cfg.bb_cr_enabled) {
+ if (bb_scn != fcport->cfg.bb_scn)
+ return BFA_STATUS_BBCR_CFG_NO_CHANGE;
+ else
+ return BFA_STATUS_NO_CHANGE;
+ }
+
+ if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
+ bb_scn = BFA_BB_SCN_DEF;
+
+ fcport->cfg.bb_cr_enabled = on_off;
+ fcport->cfg.bb_scn = bb_scn;
+ } else {
+ if (!fcport->cfg.bb_cr_enabled)
+ return BFA_STATUS_NO_CHANGE;
+
+ fcport->cfg.bb_cr_enabled = on_off;
+ fcport->cfg.bb_scn = 0;
+ }
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
+ struct bfa_bbcr_attr_s *bbcr_attr)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
+ return BFA_STATUS_BBCR_FC_ONLY;
+
+ if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
+ return BFA_STATUS_TOPOLOGY_LOOP;
+
+ *bbcr_attr = fcport->bbcr_attr;
+
+ return BFA_STATUS_OK;
+}
+
+void
+bfa_fcport_dportenable(struct bfa_s *bfa)
+{
+ /*
+ * Assume caller check for port is in disable state
+ */
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
+ bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
+}
+
+void
+bfa_fcport_dportdisable(struct bfa_s *bfa)
+{
+ /*
+ * Assume caller check for port is in disable state
+ */
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
+ bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
+}
+
+void
+bfa_fcport_ddportenable(struct bfa_s *bfa)
+{
+ /*
+ * Assume caller check for port is in disable state
+ */
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
+}
+
+void
+bfa_fcport_ddportdisable(struct bfa_s *bfa)
+{
+ /*
+ * Assume caller check for port is in disable state
+ */
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
+}
+
/*
* Rport State machine functions
*/
@@ -4707,6 +5118,21 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
break;
+ case BFI_RPORT_I2H_LIP_SCN_ONLINE:
+ bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
+ &msg.lip_scn->loop_info);
+ bfa_cb_rport_scn_online(bfa);
+ break;
+
+ case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
+ bfa_cb_rport_scn_offline(bfa);
+ break;
+
+ case BFI_RPORT_I2H_NO_DEV:
+ rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
+ bfa_cb_rport_scn_no_dev(rp->rport_drv);
+ break;
+
default:
bfa_trc(bfa, m->mhdr.msg_id);
WARN_ON(1);
@@ -5348,6 +5774,58 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
}
/*
+ * Dport forward declaration
+ */
+
+enum bfa_dport_test_state_e {
+ BFA_DPORT_ST_DISABLED = 0, /*!< dport is disabled */
+ BFA_DPORT_ST_INP = 1, /*!< test in progress */
+ BFA_DPORT_ST_COMP = 2, /*!< test complete successfully */
+ BFA_DPORT_ST_NO_SFP = 3, /*!< sfp is not present */
+ BFA_DPORT_ST_NOTSTART = 4, /*!< test not start dport is enabled */
+};
+
+/*
+ * BFA DPORT state machine events
+ */
+enum bfa_dport_sm_event {
+ BFA_DPORT_SM_ENABLE = 1, /* dport enable event */
+ BFA_DPORT_SM_DISABLE = 2, /* dport disable event */
+ BFA_DPORT_SM_FWRSP = 3, /* fw enable/disable rsp */
+ BFA_DPORT_SM_QRESUME = 4, /* CQ space available */
+ BFA_DPORT_SM_HWFAIL = 5, /* IOC h/w failure */
+ BFA_DPORT_SM_START = 6, /* re-start dport test */
+ BFA_DPORT_SM_REQFAIL = 7, /* request failure */
+ BFA_DPORT_SM_SCN = 8, /* state change notify frm fw */
+};
+
+static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event);
+static void bfa_dport_qresume(void *cbarg);
+static void bfa_dport_req_comp(struct bfa_dport_s *dport,
+ struct bfi_diag_dport_rsp_s *msg);
+static void bfa_dport_scn(struct bfa_dport_s *dport,
+ struct bfi_diag_dport_scn_s *msg);
+
+/*
* BFA fcdiag module
*/
#define BFA_DIAG_QTEST_TOV 1000 /* msec */
@@ -5377,15 +5855,26 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_pcidev_s *pcidev)
{
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
fcdiag->bfa = bfa;
fcdiag->trcmod = bfa->trcmod;
/* The common DIAG attach bfa_diag_attach() will do all memory claim */
+ dport->bfa = bfa;
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
+ dport->cbfn = NULL;
+ dport->cbarg = NULL;
+ dport->test_state = BFA_DPORT_ST_DISABLED;
+ memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
}
static void
bfa_fcdiag_iocdisable(struct bfa_s *bfa)
{
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
bfa_trc(fcdiag, fcdiag->lb.lock);
if (fcdiag->lb.lock) {
fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
@@ -5393,6 +5882,8 @@ bfa_fcdiag_iocdisable(struct bfa_s *bfa)
fcdiag->lb.lock = 0;
bfa_fcdiag_set_busy_status(fcdiag);
}
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
}
static void
@@ -5577,6 +6068,14 @@ bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
case BFI_DIAG_I2H_QTEST:
bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
break;
+ case BFI_DIAG_I2H_DPORT:
+ bfa_dport_req_comp(&fcdiag->dport,
+ (struct bfi_diag_dport_rsp_s *)msg);
+ break;
+ case BFI_DIAG_I2H_DPORT_SCN:
+ bfa_dport_scn(&fcdiag->dport,
+ (struct bfi_diag_dport_scn_s *)msg);
+ break;
default:
bfa_trc(fcdiag, msg->mhdr.msg_id);
WARN_ON(1);
@@ -5646,12 +6145,18 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
}
}
+ /*
+ * For CT2, 1G is not supported
+ */
+ if ((speed == BFA_PORT_SPEED_1GBPS) &&
+ (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
+ bfa_trc(fcdiag, speed);
+ return BFA_STATUS_UNSUPP_SPEED;
+ }
+
/* For Mezz card, port speed entered needs to be checked */
if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
- if ((speed == BFA_PORT_SPEED_1GBPS) &&
- (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
- return BFA_STATUS_UNSUPP_SPEED;
if (!(speed == BFA_PORT_SPEED_1GBPS ||
speed == BFA_PORT_SPEED_2GBPS ||
speed == BFA_PORT_SPEED_4GBPS ||
@@ -5664,7 +6169,11 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
return BFA_STATUS_UNSUPP_SPEED;
}
}
-
+ /* check to see if fcport is dport */
+ if (bfa_fcport_is_dport(bfa)) {
+ bfa_trc(fcdiag, fcdiag->lb.lock);
+ return BFA_STATUS_DPORT_ENABLED;
+ }
/* check to see if there is another destructive diag cmd running */
if (fcdiag->lb.lock) {
bfa_trc(fcdiag, fcdiag->lb.lock);
@@ -5764,3 +6273,790 @@ bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
return fcdiag->lb.lock ? BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
}
+
+/*
+ * D-port
+ */
+#define bfa_dport_result_start(__dport, __mode) do { \
+ (__dport)->result.start_time = bfa_get_log_time(); \
+ (__dport)->result.status = DPORT_TEST_ST_INPRG; \
+ (__dport)->result.mode = (__mode); \
+ (__dport)->result.rp_pwwn = (__dport)->rp_pwwn; \
+ (__dport)->result.rp_nwwn = (__dport)->rp_nwwn; \
+ (__dport)->result.lpcnt = (__dport)->lpcnt; \
+} while (0)
+
+static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
+ enum bfi_dport_req req);
+static void
+bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
+{
+ if (dport->cbfn != NULL) {
+ dport->cbfn(dport->cbarg, bfa_status);
+ dport->cbfn = NULL;
+ dport->cbarg = NULL;
+ }
+}
+
+static void
+bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_ENABLE:
+ bfa_fcport_dportenable(dport->bfa);
+ if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
+ bfa_sm_set_state(dport, bfa_dport_sm_enabling);
+ else
+ bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
+ break;
+
+ case BFA_DPORT_SM_DISABLE:
+ /* Already disabled */
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ /* ignore */
+ break;
+
+ case BFA_DPORT_SM_SCN:
+ if (dport->i2hmsg.scn.state == BFI_DPORT_SCN_DDPORT_ENABLE) {
+ bfa_fcport_ddportenable(dport->bfa);
+ dport->dynamic = BFA_TRUE;
+ dport->test_state = BFA_DPORT_ST_NOTSTART;
+ bfa_sm_set_state(dport, bfa_dport_sm_enabled);
+ } else {
+ bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
+ WARN_ON(1);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_QRESUME:
+ bfa_sm_set_state(dport, bfa_dport_sm_enabling);
+ bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_reqq_wcancel(&dport->reqq_wait);
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_FWRSP:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
+ dport->test_state = BFA_DPORT_ST_NO_SFP;
+ } else {
+ dport->test_state = BFA_DPORT_ST_INP;
+ bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
+ }
+ bfa_sm_set_state(dport, bfa_dport_sm_enabled);
+ break;
+
+ case BFA_DPORT_SM_REQFAIL:
+ dport->test_state = BFA_DPORT_ST_DISABLED;
+ bfa_fcport_dportdisable(dport->bfa);
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_START:
+ if (bfa_dport_send_req(dport, BFI_DPORT_START))
+ bfa_sm_set_state(dport, bfa_dport_sm_starting);
+ else
+ bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
+ break;
+
+ case BFA_DPORT_SM_DISABLE:
+ bfa_fcport_dportdisable(dport->bfa);
+ if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
+ bfa_sm_set_state(dport, bfa_dport_sm_disabling);
+ else
+ bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ break;
+
+ case BFA_DPORT_SM_SCN:
+ switch (dport->i2hmsg.scn.state) {
+ case BFI_DPORT_SCN_TESTCOMP:
+ dport->test_state = BFA_DPORT_ST_COMP;
+ break;
+
+ case BFI_DPORT_SCN_TESTSTART:
+ dport->test_state = BFA_DPORT_ST_INP;
+ break;
+
+ case BFI_DPORT_SCN_TESTSKIP:
+ case BFI_DPORT_SCN_SUBTESTSTART:
+ /* no state change */
+ break;
+
+ case BFI_DPORT_SCN_SFP_REMOVED:
+ dport->test_state = BFA_DPORT_ST_NO_SFP;
+ break;
+
+ case BFI_DPORT_SCN_DDPORT_DISABLE:
+ bfa_fcport_ddportdisable(dport->bfa);
+
+ if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
+ bfa_sm_set_state(dport,
+ bfa_dport_sm_dynamic_disabling);
+ else
+ bfa_sm_set_state(dport,
+ bfa_dport_sm_dynamic_disabling_qwait);
+ break;
+
+ case BFI_DPORT_SCN_FCPORT_DISABLE:
+ bfa_fcport_ddportdisable(dport->bfa);
+
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ dport->dynamic = BFA_FALSE;
+ break;
+
+ default:
+ bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
+ bfa_sm_fault(dport->bfa, event);
+ }
+ break;
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_QRESUME:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabling);
+ bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_reqq_wcancel(&dport->reqq_wait);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+ break;
+
+ case BFA_DPORT_SM_SCN:
+ /* ignore */
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_FWRSP:
+ dport->test_state = BFA_DPORT_ST_DISABLED;
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+ break;
+
+ case BFA_DPORT_SM_SCN:
+ /* no state change */
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_QRESUME:
+ bfa_sm_set_state(dport, bfa_dport_sm_starting);
+ bfa_dport_send_req(dport, BFI_DPORT_START);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_reqq_wcancel(&dport->reqq_wait);
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_FWRSP:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
+ dport->test_state = BFA_DPORT_ST_NO_SFP;
+ } else {
+ dport->test_state = BFA_DPORT_ST_INP;
+ bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
+ }
+ /* fall thru */
+
+ case BFA_DPORT_SM_REQFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_enabled);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_SCN:
+ switch (dport->i2hmsg.scn.state) {
+ case BFI_DPORT_SCN_DDPORT_DISABLED:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ dport->dynamic = BFA_FALSE;
+ bfa_fcport_enable(dport->bfa);
+ break;
+
+ default:
+ bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
+ bfa_sm_fault(dport->bfa, event);
+
+ }
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static void
+bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
+ enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_QRESUME:
+ bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);
+ bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);
+ break;
+
+ case BFA_DPORT_SM_HWFAIL:
+ bfa_sm_set_state(dport, bfa_dport_sm_disabled);
+ bfa_reqq_wcancel(&dport->reqq_wait);
+ bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
+ break;
+
+ case BFA_DPORT_SM_SCN:
+ /* ignore */
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, event);
+ }
+}
+
+static bfa_boolean_t
+bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
+{
+ struct bfi_diag_dport_req_s *m;
+
+ /*
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
+ if (!m) {
+ bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
+ bfa_fn_lpu(dport->bfa));
+ m->req = req;
+ if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
+ m->lpcnt = cpu_to_be32(dport->lpcnt);
+ m->payload = cpu_to_be32(dport->payload);
+ }
+
+ /*
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);
+
+ return BFA_TRUE;
+}
+
+static void
+bfa_dport_qresume(void *cbarg)
+{
+ struct bfa_dport_s *dport = cbarg;
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
+}
+
+static void
+bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
+{
+ msg->status = cpu_to_be32(msg->status);
+ dport->i2hmsg.rsp.status = msg->status;
+ dport->rp_pwwn = msg->pwwn;
+ dport->rp_nwwn = msg->nwwn;
+
+ if ((msg->status == BFA_STATUS_OK) ||
+ (msg->status == BFA_STATUS_DPORT_NO_SFP)) {
+ bfa_trc(dport->bfa, msg->status);
+ bfa_trc(dport->bfa, dport->rp_pwwn);
+ bfa_trc(dport->bfa, dport->rp_nwwn);
+ bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
+
+ } else {
+ bfa_trc(dport->bfa, msg->status);
+ bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
+ }
+ bfa_cb_fcdiag_dport(dport, msg->status);
+}
+
+static bfa_boolean_t
+bfa_dport_is_sending_req(struct bfa_dport_s *dport)
+{
+ if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_starting) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
+ return BFA_TRUE;
+ } else {
+ return BFA_FALSE;
+ }
+}
+
+static void
+bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
+{
+ int i;
+ uint8_t subtesttype;
+
+ bfa_trc(dport->bfa, msg->state);
+ dport->i2hmsg.scn.state = msg->state;
+
+ switch (dport->i2hmsg.scn.state) {
+ case BFI_DPORT_SCN_TESTCOMP:
+ dport->result.end_time = bfa_get_log_time();
+ bfa_trc(dport->bfa, dport->result.end_time);
+
+ dport->result.status = msg->info.testcomp.status;
+ bfa_trc(dport->bfa, dport->result.status);
+
+ dport->result.roundtrip_latency =
+ cpu_to_be32(msg->info.testcomp.latency);
+ dport->result.est_cable_distance =
+ cpu_to_be32(msg->info.testcomp.distance);
+ dport->result.buffer_required =
+ be16_to_cpu(msg->info.testcomp.numbuffer);
+
+ dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
+ dport->result.speed = msg->info.testcomp.speed;
+
+ bfa_trc(dport->bfa, dport->result.roundtrip_latency);
+ bfa_trc(dport->bfa, dport->result.est_cable_distance);
+ bfa_trc(dport->bfa, dport->result.buffer_required);
+ bfa_trc(dport->bfa, dport->result.frmsz);
+ bfa_trc(dport->bfa, dport->result.speed);
+
+ for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
+ dport->result.subtest[i].status =
+ msg->info.testcomp.subtest_status[i];
+ bfa_trc(dport->bfa, dport->result.subtest[i].status);
+ }
+ break;
+
+ case BFI_DPORT_SCN_TESTSKIP:
+ case BFI_DPORT_SCN_DDPORT_ENABLE:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ break;
+
+ case BFI_DPORT_SCN_TESTSTART:
+ memset(&dport->result, 0,
+ sizeof(struct bfa_diag_dport_result_s));
+ dport->rp_pwwn = msg->info.teststart.pwwn;
+ dport->rp_nwwn = msg->info.teststart.nwwn;
+ dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
+ bfa_dport_result_start(dport, msg->info.teststart.mode);
+ break;
+
+ case BFI_DPORT_SCN_SUBTESTSTART:
+ subtesttype = msg->info.teststart.type;
+ dport->result.subtest[subtesttype].start_time =
+ bfa_get_log_time();
+ dport->result.subtest[subtesttype].status =
+ DPORT_TEST_ST_INPRG;
+
+ bfa_trc(dport->bfa, subtesttype);
+ bfa_trc(dport->bfa,
+ dport->result.subtest[subtesttype].start_time);
+ break;
+
+ case BFI_DPORT_SCN_SFP_REMOVED:
+ case BFI_DPORT_SCN_DDPORT_DISABLED:
+ case BFI_DPORT_SCN_DDPORT_DISABLE:
+ case BFI_DPORT_SCN_FCPORT_DISABLE:
+ dport->result.status = DPORT_TEST_ST_IDLE;
+ break;
+
+ default:
+ bfa_sm_fault(dport->bfa, msg->state);
+ }
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
+}
+
+/*
+ * Dport enable
+ *
+ * @param[in] *bfa - bfa data struct
+ */
+bfa_status_t
+bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
+ /*
+ * Dport is not support in MEZZ card
+ */
+ if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
+ bfa_trc(dport->bfa, BFA_STATUS_PBC);
+ return BFA_STATUS_CMD_NOTSUPP_MEZZ;
+ }
+
+ /*
+ * Dport is supported in CT2 or above
+ */
+ if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
+ bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
+ return BFA_STATUS_FEATURE_NOT_SUPPORTED;
+ }
+
+ /*
+ * Check to see if IOC is down
+ */
+ if (!bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /* if port is PBC disabled, return error */
+ if (bfa_fcport_is_pbcdisabled(bfa)) {
+ bfa_trc(dport->bfa, BFA_STATUS_PBC);
+ return BFA_STATUS_PBC;
+ }
+
+ /*
+ * Check if port mode is FC port
+ */
+ if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
+ bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
+ return BFA_STATUS_CMD_NOTSUPP_CNA;
+ }
+
+ /*
+ * Check if port is in LOOP mode
+ */
+ if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
+ (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_TOPOLOGY_LOOP;
+ }
+
+ /*
+ * Check if port is TRUNK mode
+ */
+ if (bfa_fcport_is_trunk_enabled(bfa)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_ERROR_TRUNK_ENABLED;
+ }
+
+ /*
+ * Check if diag loopback is running
+ */
+ if (bfa_fcdiag_lb_is_running(bfa)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DIAG_BUSY;
+ }
+
+ /*
+ * Check to see if port is disable or in dport state
+ */
+ if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
+ (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_PORT_NOT_DISABLED;
+ }
+
+ /*
+ * Check if dport is in dynamic mode
+ */
+ if (dport->dynamic)
+ return BFA_STATUS_DDPORT_ERR;
+
+ /*
+ * Check if dport is busy
+ */
+ if (bfa_dport_is_sending_req(dport))
+ return BFA_STATUS_DEVBUSY;
+
+ /*
+ * Check if dport is already enabled
+ */
+ if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DPORT_ENABLED;
+ }
+
+ bfa_trc(dport->bfa, lpcnt);
+ bfa_trc(dport->bfa, pat);
+ dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
+ dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
+ dport->cbfn = cbfn;
+ dport->cbarg = cbarg;
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Dport disable
+ *
+ * @param[in] *bfa - bfa data struct
+ */
+bfa_status_t
+bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
+ if (bfa_ioc_is_disabled(&bfa->ioc))
+ return BFA_STATUS_IOC_DISABLED;
+
+ /* if port is PBC disabled, return error */
+ if (bfa_fcport_is_pbcdisabled(bfa)) {
+ bfa_trc(dport->bfa, BFA_STATUS_PBC);
+ return BFA_STATUS_PBC;
+ }
+
+ /*
+ * Check if dport is in dynamic mode
+ */
+ if (dport->dynamic) {
+ return BFA_STATUS_DDPORT_ERR;
+ }
+
+ /*
+ * Check to see if port is disable or in dport state
+ */
+ if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
+ (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_PORT_NOT_DISABLED;
+ }
+
+ /*
+ * Check if dport is busy
+ */
+ if (bfa_dport_is_sending_req(dport))
+ return BFA_STATUS_DEVBUSY;
+
+ /*
+ * Check if dport is already disabled
+ */
+ if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DPORT_DISABLED;
+ }
+
+ dport->cbfn = cbfn;
+ dport->cbarg = cbarg;
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Dport start -- restart dport test
+ *
+ * @param[in] *bfa - bfa data struct
+ */
+bfa_status_t
+bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
+ /*
+ * Check to see if IOC is down
+ */
+ if (!bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /*
+ * Check if dport is in dynamic mode
+ */
+ if (dport->dynamic)
+ return BFA_STATUS_DDPORT_ERR;
+
+ /*
+ * Check if dport is busy
+ */
+ if (bfa_dport_is_sending_req(dport))
+ return BFA_STATUS_DEVBUSY;
+
+ /*
+ * Check if dport is in enabled state.
+ * Test can only be restart when previous test has completed
+ */
+ if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DPORT_DISABLED;
+
+ } else {
+ if (dport->test_state == BFA_DPORT_ST_NO_SFP)
+ return BFA_STATUS_DPORT_INV_SFP;
+
+ if (dport->test_state == BFA_DPORT_ST_INP)
+ return BFA_STATUS_DEVBUSY;
+
+ WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
+ }
+
+ bfa_trc(dport->bfa, lpcnt);
+ bfa_trc(dport->bfa, pat);
+
+ dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
+ dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
+
+ dport->cbfn = cbfn;
+ dport->cbarg = cbarg;
+
+ bfa_sm_send_event(dport, BFA_DPORT_SM_START);
+ return BFA_STATUS_OK;
+}
+
+/*
+ * Dport show -- return dport test result
+ *
+ * @param[in] *bfa - bfa data struct
+ */
+bfa_status_t
+bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
+ /*
+ * Check to see if IOC is down
+ */
+ if (!bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_IOC_NON_OP;
+
+ /*
+ * Check if dport is busy
+ */
+ if (bfa_dport_is_sending_req(dport))
+ return BFA_STATUS_DEVBUSY;
+
+ /*
+ * Check if dport is in enabled state.
+ */
+ if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
+ bfa_trc(dport->bfa, 0);
+ return BFA_STATUS_DPORT_DISABLED;
+
+ }
+
+ /*
+ * Check if there is SFP
+ */
+ if (dport->test_state == BFA_DPORT_ST_NO_SFP)
+ return BFA_STATUS_DPORT_INV_SFP;
+
+ memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
+
+ return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index 1abcf7c5166..ef07365991e 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -405,8 +405,6 @@ struct bfa_lps_s {
bfa_status_t status; /* login status */
u16 pdusz; /* max receive PDU size */
u16 pr_bbcred; /* BB_CREDIT from peer */
- u8 pr_bbscn; /* BB_SCN from peer */
- u8 bb_scn; /* local BB_SCN */
u8 lsrjt_rsn; /* LSRJT reason */
u8 lsrjt_expl; /* LSRJT explanation */
u8 lun_mask; /* LUN mask flag */
@@ -474,8 +472,10 @@ struct bfa_fcport_s {
/* supported speeds */
enum bfa_port_speed speed; /* current speed */
enum bfa_port_topology topology; /* current topology */
- u8 myalpa; /* my ALPA in LOOP topology */
u8 rsvd[3];
+ u8 myalpa; /* my ALPA in LOOP topology */
+ u8 alpabm_valid; /* alpa bitmap valid or not */
+ struct fc_alpabm_s alpabm; /* alpa bitmap */
struct bfa_port_cfg_s cfg; /* current port configuration */
bfa_boolean_t use_flash_cfg; /* get port cfg from flash */
struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
@@ -508,10 +508,12 @@ struct bfa_fcport_s {
bfa_boolean_t diag_busy; /* diag busy status */
bfa_boolean_t beacon; /* port beacon status */
bfa_boolean_t link_e2e_beacon; /* link beacon status */
- bfa_boolean_t bbsc_op_state; /* Cred recov Oper State */
struct bfa_fcport_trunk_s trunk;
u16 fcoe_vlan;
struct bfa_mem_dma_s fcport_dma;
+ bfa_boolean_t stats_dma_ready;
+ struct bfa_bbcr_attr_s bbcr_attr;
+ enum bfa_fec_state_s fec_state;
};
#define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport)
@@ -534,6 +536,7 @@ enum bfa_port_speed bfa_fcport_get_speed(struct bfa_s *bfa);
bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
enum bfa_port_topology topo);
enum bfa_port_topology bfa_fcport_get_topology(struct bfa_s *bfa);
+enum bfa_port_topology bfa_fcport_get_cfg_topology(struct bfa_s *bfa);
bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
@@ -547,9 +550,13 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
void (*event_cbfn) (void *cbarg,
enum bfa_port_linkstate event), void *event_cbarg);
bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
+bfa_boolean_t bfa_fcport_is_dport(struct bfa_s *bfa);
+bfa_boolean_t bfa_fcport_is_ddport(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa,
+ struct bfa_qos_bw_s *qos_bw);
enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
-void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn);
+void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
bfa_boolean_t link_e2e_beacon);
@@ -560,8 +567,14 @@ bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa,
struct bfa_cb_pending_q_s *cb);
bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
+void bfa_fcport_dportenable(struct bfa_s *bfa);
+void bfa_fcport_dportdisable(struct bfa_s *bfa);
bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
void bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state);
+bfa_status_t bfa_fcport_cfg_bbcr(struct bfa_s *bfa,
+ bfa_boolean_t on_off, u8 bb_scn);
+bfa_status_t bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
+ struct bfa_bbcr_attr_s *bbcr_attr);
/*
* bfa rport API functions
@@ -575,6 +588,9 @@ void bfa_cb_rport_offline(void *rport);
void bfa_cb_rport_qos_scn_flowid(void *rport,
struct bfa_rport_qos_attr_s old_qos_attr,
struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_cb_rport_scn_online(struct bfa_s *bfa);
+void bfa_cb_rport_scn_offline(struct bfa_s *bfa);
+void bfa_cb_rport_scn_no_dev(void *rp);
void bfa_cb_rport_qos_scn_prio(void *rport,
struct bfa_rport_qos_attr_s old_qos_attr,
struct bfa_rport_qos_attr_s new_qos_attr);
@@ -655,7 +671,7 @@ struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
void bfa_lps_delete(struct bfa_lps_s *lps);
void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
u16 pdusz, wwn_t pwwn, wwn_t nwwn,
- bfa_boolean_t auth_en, u8 bb_scn);
+ bfa_boolean_t auth_en);
void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
wwn_t pwwn, wwn_t nwwn);
void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
@@ -697,11 +713,29 @@ struct bfa_fcdiag_lb_s {
u32 status;
};
+struct bfa_dport_s {
+ struct bfa_s *bfa; /* Back pointer to BFA */
+ bfa_sm_t sm; /* finite state machine */
+ struct bfa_reqq_wait_s reqq_wait;
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+ union bfi_diag_dport_msg_u i2hmsg;
+ u8 test_state; /* enum dport_test_state */
+ u8 dynamic; /* boolean_t */
+ u8 rsvd[2];
+ u32 lpcnt;
+ u32 payload; /* user defined payload pattern */
+ wwn_t rp_pwwn;
+ wwn_t rp_nwwn;
+ struct bfa_diag_dport_result_s result;
+};
+
struct bfa_fcdiag_s {
struct bfa_s *bfa; /* Back pointer to BFA */
struct bfa_trc_mod_s *trcmod;
struct bfa_fcdiag_lb_s lb;
struct bfa_fcdiag_qtest_s qtest;
+ struct bfa_dport_s dport;
};
#define BFA_FCDIAG_MOD(__bfa) (&(__bfa)->modules.fcdiag)
@@ -717,5 +751,13 @@ bfa_status_t bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore,
u32 queue, struct bfa_diag_qtest_result_s *result,
bfa_cb_diag_t cbfn, void *cbarg);
bfa_status_t bfa_fcdiag_lb_is_running(struct bfa_s *bfa);
+bfa_status_t bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn,
+ void *cbarg);
+bfa_status_t bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
+ bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t bfa_dport_show(struct bfa_s *bfa,
+ struct bfa_diag_dport_result_s *result);
#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index c37494916a1..7593b7c1d33 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -63,9 +63,9 @@ int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
u32 *bfi_image_cb, *bfi_image_ct, *bfi_image_ct2;
-#define BFAD_FW_FILE_CB "cbfw.bin"
-#define BFAD_FW_FILE_CT "ctfw.bin"
-#define BFAD_FW_FILE_CT2 "ct2fw.bin"
+#define BFAD_FW_FILE_CB "cbfw-3.2.3.0.bin"
+#define BFAD_FW_FILE_CT "ctfw-3.2.3.0.bin"
+#define BFAD_FW_FILE_CT2 "ct2fw-3.2.3.0.bin"
static u32 *bfad_load_fwimg(struct pci_dev *pdev);
static void bfad_free_fwimg(void);
@@ -204,6 +204,7 @@ static void
bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
{
unsigned long flags;
+ bfa_status_t ret;
bfa_trc(bfad, event);
@@ -217,7 +218,7 @@ bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
if (bfad_setup_intr(bfad)) {
printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
bfad->inst_no);
- bfa_sm_send_event(bfad, BFAD_E_INTR_INIT_FAILED);
+ bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
break;
}
@@ -242,8 +243,26 @@ bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
printk(KERN_WARNING
"bfa %s: bfa init failed\n",
bfad->pci_name);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_fcs_init(&bfad->bfa_fcs);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ ret = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
+ if (ret != BFA_STATUS_OK) {
+ init_completion(&bfad->comp);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfad->pport.flags |= BFAD_PORT_DELETE;
+ bfa_fcs_exit(&bfad->bfa_fcs);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ wait_for_completion(&bfad->comp);
+
+ bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
+ break;
+ }
bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
- bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
+ bfa_sm_send_event(bfad, BFAD_E_HAL_INIT_FAILED);
}
break;
@@ -273,12 +292,14 @@ bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
retval = bfad_start_ops(bfad);
- if (retval != BFA_STATUS_OK)
+ if (retval != BFA_STATUS_OK) {
+ bfa_sm_set_state(bfad, bfad_sm_failed);
break;
+ }
bfa_sm_set_state(bfad, bfad_sm_operational);
break;
- case BFAD_E_INTR_INIT_FAILED:
+ case BFAD_E_INIT_FAILED:
bfa_sm_set_state(bfad, bfad_sm_uninit);
kthread_stop(bfad->bfad_tsk);
spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -286,7 +307,7 @@ bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
break;
- case BFAD_E_INIT_FAILED:
+ case BFAD_E_HAL_INIT_FAILED:
bfa_sm_set_state(bfad, bfad_sm_failed);
break;
default:
@@ -310,13 +331,8 @@ bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event)
break;
case BFAD_E_STOP:
- if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
- bfad_uncfg_pport(bfad);
- if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE) {
- bfad_im_probe_undo(bfad);
- bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
- }
- bfad_stop(bfad);
+ bfa_sm_set_state(bfad, bfad_sm_fcs_exit);
+ bfa_sm_send_event(bfad, BFAD_E_FCS_EXIT_COMP);
break;
case BFAD_E_EXIT_COMP:
@@ -491,7 +507,7 @@ bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
struct bfad_vport_s *vport;
int rc;
- vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
+ vport = kzalloc(sizeof(struct bfad_vport_s), GFP_ATOMIC);
if (!vport) {
bfa_trc(bfad, 0);
return;
@@ -766,49 +782,20 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
bfad->pcidev = pdev;
/* Adjust PCIe Maximum Read Request Size */
- if (pcie_max_read_reqsz > 0) {
- int pcie_cap_reg;
- u16 pcie_dev_ctl;
- u16 mask = 0xffff;
-
- switch (pcie_max_read_reqsz) {
- case 128:
- mask = 0x0;
- break;
- case 256:
- mask = 0x1000;
- break;
- case 512:
- mask = 0x2000;
- break;
- case 1024:
- mask = 0x3000;
- break;
- case 2048:
- mask = 0x4000;
- break;
- case 4096:
- mask = 0x5000;
- break;
- default:
- break;
- }
-
- pcie_cap_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (mask != 0xffff && pcie_cap_reg) {
- pcie_cap_reg += 0x08;
- pci_read_config_word(pdev, pcie_cap_reg, &pcie_dev_ctl);
- if ((pcie_dev_ctl & 0x7000) != mask) {
- printk(KERN_WARNING "BFA[%s]: "
+ if (pci_is_pcie(pdev) && pcie_max_read_reqsz) {
+ if (pcie_max_read_reqsz >= 128 &&
+ pcie_max_read_reqsz <= 4096 &&
+ is_power_of_2(pcie_max_read_reqsz)) {
+ int max_rq = pcie_get_readrq(pdev);
+ printk(KERN_WARNING "BFA[%s]: "
"pcie_max_read_request_size is %d, "
- "reset to %d\n", bfad->pci_name,
- (1 << ((pcie_dev_ctl & 0x7000) >> 12)) << 7,
+ "reset to %d\n", bfad->pci_name, max_rq,
pcie_max_read_reqsz);
-
- pcie_dev_ctl &= ~0x7000;
- pci_write_config_word(pdev, pcie_cap_reg,
- pcie_dev_ctl | mask);
- }
+ pcie_set_readrq(pdev, pcie_max_read_reqsz);
+ } else {
+ printk(KERN_WARNING "BFA[%s]: invalid "
+ "pcie_max_read_request_size %d ignored\n",
+ bfad->pci_name, pcie_max_read_reqsz);
}
}
@@ -833,7 +820,6 @@ bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
/* Disable PCIE Advanced Error Recovery (AER) */
pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
}
bfa_status_t
@@ -854,7 +840,7 @@ bfad_drv_init(struct bfad_s *bfad)
printk(KERN_WARNING
"Not enough memory to attach all Brocade HBA ports, %s",
"System may need more memory.\n");
- goto out_hal_mem_alloc_failure;
+ return BFA_STATUS_FAILED;
}
bfad->bfa.trcmod = bfad->trcmod;
@@ -871,31 +857,11 @@ bfad_drv_init(struct bfad_s *bfad)
bfad->bfa_fcs.trcmod = bfad->trcmod;
bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
bfad->bfa_fcs.fdmi_enabled = fdmi_enable;
- bfa_fcs_init(&bfad->bfa_fcs);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
- /* configure base port */
- rc = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
- if (rc != BFA_STATUS_OK)
- goto out_cfg_pport_fail;
-
return BFA_STATUS_OK;
-
-out_cfg_pport_fail:
- /* fcs exit - on cfg pport failure */
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- init_completion(&bfad->comp);
- bfad->pport.flags |= BFAD_PORT_DELETE;
- bfa_fcs_exit(&bfad->bfa_fcs);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- wait_for_completion(&bfad->comp);
- /* bfa detach - free hal memory */
- bfa_detach(&bfad->bfa);
- bfad_hal_mem_release(bfad);
-out_hal_mem_alloc_failure:
- return BFA_STATUS_FAILED;
}
void
@@ -1034,18 +1000,24 @@ bfad_start_ops(struct bfad_s *bfad) {
sizeof(driver_info.host_os_patch) - 1);
strncpy(driver_info.os_device_name, bfad->pci_name,
- sizeof(driver_info.os_device_name - 1));
+ sizeof(driver_info.os_device_name) - 1);
/* FCS driver info init */
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
+
+ if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
+ bfa_fcs_update_cfg(&bfad->bfa_fcs);
+ else
+ bfa_fcs_init(&bfad->bfa_fcs);
+
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- /*
- * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
- * with values learned during bfa_init firmware GETATTR REQ.
- */
- bfa_fcs_update_cfg(&bfad->bfa_fcs);
+ if (!(bfad->bfad_flags & BFAD_CFG_PPORT_DONE)) {
+ retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
+ if (retval != BFA_STATUS_OK)
+ return BFA_STATUS_FAILED;
+ }
/* Setup fc host fixed attribute if the lk supports */
bfad_fc_host_init(bfad->pport.im_port);
@@ -1056,10 +1028,6 @@ bfad_start_ops(struct bfad_s *bfad) {
printk(KERN_WARNING "bfad_im_probe failed\n");
if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
bfa_sm_set_state(bfad, bfad_sm_failed);
- bfad_im_probe_undo(bfad);
- bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
- bfad_uncfg_pport(bfad);
- bfad_stop(bfad);
return BFA_STATUS_FAILED;
} else
bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
@@ -1429,7 +1397,6 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
return 0;
out_bfad_sm_failure:
- bfa_detach(&bfad->bfa);
bfad_hal_mem_release(bfad);
out_drv_init_failure:
/* Remove the debugfs node for this bfad */
@@ -1564,7 +1531,7 @@ restart_bfa(struct bfad_s *bfad)
if (bfad_setup_intr(bfad)) {
dev_printk(KERN_WARNING, &pdev->dev,
"%s: bfad_setup_intr failed\n", bfad->pci_name);
- bfa_sm_send_event(bfad, BFAD_E_INTR_INIT_FAILED);
+ bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
return -1;
}
@@ -1720,6 +1687,14 @@ struct pci_device_id bfad_id_table[] = {
.class_mask = ~0,
},
+ {
+ .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+ .device = BFA_PCI_DEVICE_ID_CT2_QUAD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_SERIAL_FIBER << 8),
+ .class_mask = ~0,
+ },
{0, 0},
};
@@ -1739,7 +1714,7 @@ static struct pci_driver bfad_pci_driver = {
.name = BFAD_DRIVER_NAME,
.id_table = bfad_id_table,
.probe = bfad_pci_probe,
- .remove = __devexit_p(bfad_pci_remove),
+ .remove = bfad_pci_remove,
.err_handler = &bfad_err_handler,
};
@@ -1824,7 +1799,7 @@ out:
static u32 *
bfad_load_fwimg(struct pci_dev *pdev)
{
- if (pdev->device == BFA_PCI_DEVICE_ID_CT2) {
+ if (bfa_asic_id_ct2(pdev->device)) {
if (bfi_image_ct2_size == 0)
bfad_read_firmware(pdev, &bfi_image_ct2,
&bfi_image_ct2_size, BFAD_FW_FILE_CT2);
@@ -1834,12 +1809,14 @@ bfad_load_fwimg(struct pci_dev *pdev)
bfad_read_firmware(pdev, &bfi_image_ct,
&bfi_image_ct_size, BFAD_FW_FILE_CT);
return bfi_image_ct;
- } else {
+ } else if (bfa_asic_id_cb(pdev->device)) {
if (bfi_image_cb_size == 0)
bfad_read_firmware(pdev, &bfi_image_cb,
&bfi_image_cb_size, BFAD_FW_FILE_CB);
return bfi_image_cb;
}
+
+ return NULL;
}
static void
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 72f5dc32cc1..40be670a1cb 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -335,23 +335,10 @@ bfad_im_reset_stats(struct Scsi_Host *shost)
}
/*
- * FC transport template entry, get rport loss timeout.
- */
-static void
-bfad_im_get_rport_loss_tmo(struct fc_rport *rport)
-{
- struct bfad_itnim_data_s *itnim_data = rport->dd_data;
- struct bfad_itnim_s *itnim = itnim_data->itnim;
- struct bfad_s *bfad = itnim->im->bfad;
- unsigned long flags;
-
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-}
-
-/*
* FC transport template entry, set rport loss timeout.
+ * Update dev_loss_tmo based on the value pushed down by the stack
+ * In case it is lesser than path_tov of driver, set it to path_tov + 1
+ * to ensure that the driver times out before the application
*/
static void
bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
@@ -359,15 +346,11 @@ bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
struct bfad_itnim_data_s *itnim_data = rport->dd_data;
struct bfad_itnim_s *itnim = itnim_data->itnim;
struct bfad_s *bfad = itnim->im->bfad;
- unsigned long flags;
-
- if (timeout > 0) {
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_fcpim_path_tov_set(&bfad->bfa, timeout);
- rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- }
+ uint16_t path_tov = bfa_fcpim_path_tov_get(&bfad->bfa);
+ rport->dev_loss_tmo = timeout;
+ if (timeout < path_tov)
+ rport->dev_loss_tmo = path_tov + 1;
}
static int
@@ -610,11 +593,8 @@ bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
return;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (strlen(sym_name) > 0) {
- strcpy(fcs_vport->lport.port_cfg.sym_name.symname, sym_name);
- bfa_fcs_lport_ns_util_send_rspn_id(
- BFA_FCS_GET_NS_FROM_PORT((&fcs_vport->lport)), NULL);
- }
+ if (strlen(sym_name) > 0)
+ bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}
@@ -665,7 +645,6 @@ struct fc_function_template bfad_im_fc_function_template = {
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.show_rport_dev_loss_tmo = 1,
- .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
.issue_fc_host_lip = bfad_im_issue_fc_host_lip,
.vport_create = bfad_im_vport_create,
@@ -723,7 +702,6 @@ struct fc_function_template bfad_im_vport_fc_function_template = {
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.show_rport_dev_loss_tmo = 1,
- .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
};
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 0afa39076ce..8994fb857ee 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -33,7 +33,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
/* If IOC is not in disabled state - return */
if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_IOC_FAILURE;
+ iocmd->status = BFA_STATUS_OK;
return rc;
}
@@ -54,6 +54,12 @@ bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
+ if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ iocmd->status = BFA_STATUS_OK;
+ return rc;
+ }
+
if (bfad->disable_active) {
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return -EBUSY;
@@ -101,9 +107,10 @@ bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
/* set adapter hw path */
strcpy(iocmd->adapter_hwpath, bfad->pci_name);
- i = strlen(iocmd->adapter_hwpath) - 1;
- while (iocmd->adapter_hwpath[i] != '.')
- i--;
+ for (i = 0; iocmd->adapter_hwpath[i] != ':' && i < BFA_STRING_32; i++)
+ ;
+ for (; iocmd->adapter_hwpath[++i] != ':' && i < BFA_STRING_32; )
+ ;
iocmd->adapter_hwpath[i] = '\0';
iocmd->status = BFA_STATUS_OK;
return 0;
@@ -222,6 +229,18 @@ bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd)
}
int
+bfad_iocmd_ioc_fw_sig_inv(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_ioc_fwsig_invalidate(&bfad->bfa.ioc);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return 0;
+}
+
+int
bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd;
@@ -395,25 +414,43 @@ bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd)
}
int
-bfad_iocmd_port_cfg_bbsc(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
+bfad_iocmd_port_cfg_bbcr(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
- struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
- unsigned long flags;
+ struct bfa_bsg_bbcr_enable_s *iocmd =
+ (struct bfa_bsg_bbcr_enable_s *)pcmd;
+ unsigned long flags;
+ int rc;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
- if (v_cmd == IOCMD_PORT_BBSC_ENABLE)
- fcport->cfg.bb_scn_state = BFA_TRUE;
- else if (v_cmd == IOCMD_PORT_BBSC_DISABLE)
- fcport->cfg.bb_scn_state = BFA_FALSE;
+ if (cmd == IOCMD_PORT_BBCR_ENABLE)
+ rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_TRUE, iocmd->bb_scn);
+ else if (cmd == IOCMD_PORT_BBCR_DISABLE)
+ rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_FALSE, 0);
+ else {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return -EINVAL;
}
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_OK;
+ iocmd->status = rc;
+ return 0;
+}
+
+int
+bfad_iocmd_port_get_bbcr_attr(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_bbcr_attr_s *iocmd = (struct bfa_bsg_bbcr_attr_s *) pcmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status =
+ bfa_fcport_get_bbcr_attr(&bfad->bfa, &iocmd->attr);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
return 0;
}
+
static int
bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd)
{
@@ -880,6 +917,19 @@ out:
}
int
+bfad_iocmd_qos_set_bw(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_qos_bw_s *iocmd = (struct bfa_bsg_qos_bw_s *)pcmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcport_set_qos_bw(&bfad->bfa, &iocmd->qos_bw);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
+int
bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
@@ -888,16 +938,22 @@ bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (cmd == IOCMD_RATELIM_ENABLE)
- fcport->cfg.ratelimit = BFA_TRUE;
- else if (cmd == IOCMD_RATELIM_DISABLE)
- fcport->cfg.ratelimit = BFA_FALSE;
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else {
+ if (cmd == IOCMD_RATELIM_ENABLE)
+ fcport->cfg.ratelimit = BFA_TRUE;
+ else if (cmd == IOCMD_RATELIM_DISABLE)
+ fcport->cfg.ratelimit = BFA_FALSE;
+
+ if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
+ fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
- if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
- fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+ iocmd->status = BFA_STATUS_OK;
+ }
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_OK;
return 0;
}
@@ -919,8 +975,13 @@ bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
return 0;
}
- fcport->cfg.trl_def_speed = iocmd->speed;
- iocmd->status = BFA_STATUS_OK;
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else {
+ fcport->cfg.trl_def_speed = iocmd->speed;
+ iocmd->status = BFA_STATUS_OK;
+ }
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return 0;
@@ -1167,8 +1228,8 @@ bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_ablk_pf_create(&bfad->bfa.modules.ablk,
&iocmd->pcifn_id, iocmd->port,
- iocmd->pcifn_class, iocmd->bandwidth,
- bfad_hcb_comp, &fcomp);
+ iocmd->pcifn_class, iocmd->bw_min,
+ iocmd->bw_max, bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK)
goto out;
@@ -1211,8 +1272,8 @@ bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd)
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_ablk_pf_update(&bfad->bfa.modules.ablk,
- iocmd->pcifn_id, iocmd->bandwidth,
- bfad_hcb_comp, &fcomp);
+ iocmd->pcifn_id, iocmd->bw_min,
+ iocmd->bw_max, bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
bfa_trc(bfad, iocmd->status);
if (iocmd->status != BFA_STATUS_OK)
@@ -1736,6 +1797,88 @@ bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
}
int
+bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_dport_enable_s *iocmd =
+ (struct bfa_bsg_dport_enable_s *)pcmd;
+ unsigned long flags;
+ struct bfad_hal_comp fcomp;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_dport_enable(&bfad->bfa, iocmd->lpcnt,
+ iocmd->pat, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ bfa_trc(bfad, iocmd->status);
+ else {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
+ return 0;
+}
+
+int
+bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+ unsigned long flags;
+ struct bfad_hal_comp fcomp;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_dport_disable(&bfad->bfa, bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status != BFA_STATUS_OK)
+ bfa_trc(bfad, iocmd->status);
+ else {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
+ return 0;
+}
+
+int
+bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_dport_enable_s *iocmd =
+ (struct bfa_bsg_dport_enable_s *)pcmd;
+ unsigned long flags;
+ struct bfad_hal_comp fcomp;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_dport_start(&bfad->bfa, iocmd->lpcnt,
+ iocmd->pat, bfad_hcb_comp,
+ &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (iocmd->status != BFA_STATUS_OK) {
+ bfa_trc(bfad, iocmd->status);
+ } else {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
+
+ return 0;
+}
+
+int
+bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_diag_dport_show_s *iocmd =
+ (struct bfa_bsg_diag_dport_show_s *)pcmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_dport_show(&bfad->bfa, &iocmd->result);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
+
+int
bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_phy_attr_s *iocmd =
@@ -2052,7 +2195,7 @@ bfad_iocmd_boot_cfg(struct bfad_s *bfad, void *cmd)
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa),
- BFA_FLASH_PART_BOOT, PCI_FUNC(bfad->pcidev->devfn),
+ BFA_FLASH_PART_BOOT, bfad->bfa.ioc.port_id,
&iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0,
bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -2074,7 +2217,7 @@ bfad_iocmd_boot_query(struct bfad_s *bfad, void *cmd)
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa),
- BFA_FLASH_PART_BOOT, PCI_FUNC(bfad->pcidev->devfn),
+ BFA_FLASH_PART_BOOT, bfad->bfa.ioc.port_id,
&iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0,
bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -2161,22 +2304,33 @@ bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (v_cmd == IOCMD_TRUNK_ENABLE) {
- trunk->attr.state = BFA_TRUNK_OFFLINE;
- bfa_fcport_disable(&bfad->bfa);
- fcport->cfg.trunked = BFA_TRUE;
- } else if (v_cmd == IOCMD_TRUNK_DISABLE) {
- trunk->attr.state = BFA_TRUNK_DISABLED;
- bfa_fcport_disable(&bfad->bfa);
- fcport->cfg.trunked = BFA_FALSE;
+ if (bfa_fcport_is_dport(&bfad->bfa)) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return BFA_STATUS_DPORT_ERR;
}
- if (!bfa_fcport_is_disabled(&bfad->bfa))
- bfa_fcport_enable(&bfad->bfa);
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) ||
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else {
+ if (v_cmd == IOCMD_TRUNK_ENABLE) {
+ trunk->attr.state = BFA_TRUNK_OFFLINE;
+ bfa_fcport_disable(&bfad->bfa);
+ fcport->cfg.trunked = BFA_TRUE;
+ } else if (v_cmd == IOCMD_TRUNK_DISABLE) {
+ trunk->attr.state = BFA_TRUNK_DISABLED;
+ bfa_fcport_disable(&bfad->bfa);
+ fcport->cfg.trunked = BFA_FALSE;
+ }
+
+ if (!bfa_fcport_is_disabled(&bfad->bfa))
+ bfa_fcport_enable(&bfad->bfa);
+
+ iocmd->status = BFA_STATUS_OK;
+ }
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_OK;
return 0;
}
@@ -2189,12 +2343,17 @@ bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd)
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- memcpy((void *)&iocmd->attr, (void *)&trunk->attr,
- sizeof(struct bfa_trunk_attr_s));
- iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa);
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) ||
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else {
+ memcpy((void *)&iocmd->attr, (void *)&trunk->attr,
+ sizeof(struct bfa_trunk_attr_s));
+ iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa);
+ iocmd->status = BFA_STATUS_OK;
+ }
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_OK;
return 0;
}
@@ -2207,14 +2366,22 @@ bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
- if (v_cmd == IOCMD_QOS_ENABLE)
- fcport->cfg.qos_enabled = BFA_TRUE;
- else if (v_cmd == IOCMD_QOS_DISABLE)
- fcport->cfg.qos_enabled = BFA_FALSE;
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else {
+ if (v_cmd == IOCMD_QOS_ENABLE)
+ fcport->cfg.qos_enabled = BFA_TRUE;
+ else if (v_cmd == IOCMD_QOS_DISABLE) {
+ fcport->cfg.qos_enabled = BFA_FALSE;
+ fcport->cfg.qos_bw.high = BFA_QOS_BW_HIGH;
+ fcport->cfg.qos_bw.med = BFA_QOS_BW_MED;
+ fcport->cfg.qos_bw.low = BFA_QOS_BW_LOW;
+ }
+ }
}
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_OK;
return 0;
}
@@ -2226,11 +2393,21 @@ bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd)
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- iocmd->attr.state = fcport->qos_attr.state;
- iocmd->attr.total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr);
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else {
+ iocmd->attr.state = fcport->qos_attr.state;
+ iocmd->attr.total_bb_cr =
+ be32_to_cpu(fcport->qos_attr.total_bb_cr);
+ iocmd->attr.qos_bw.high = fcport->cfg.qos_bw.high;
+ iocmd->attr.qos_bw.med = fcport->cfg.qos_bw.med;
+ iocmd->attr.qos_bw.low = fcport->cfg.qos_bw.low;
+ iocmd->attr.qos_bw_op = fcport->qos_attr.qos_bw_op;
+ iocmd->status = BFA_STATUS_OK;
+ }
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- iocmd->status = BFA_STATUS_OK;
return 0;
}
@@ -2274,6 +2451,7 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
struct bfad_hal_comp fcomp;
unsigned long flags;
struct bfa_cb_pending_q_s cb_qe;
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
init_completion(&fcomp.comp);
bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
@@ -2281,7 +2459,11 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
- iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else
+ iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK) {
bfa_trc(bfad, iocmd->status);
@@ -2300,6 +2482,7 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
struct bfad_hal_comp fcomp;
unsigned long flags;
struct bfa_cb_pending_q_s cb_qe;
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
init_completion(&fcomp.comp);
bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
@@ -2307,7 +2490,11 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
- iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
+ if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+ (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+ iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+ else
+ iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (iocmd->status != BFA_STATUS_OK) {
bfa_trc(bfad, iocmd->status);
@@ -2435,6 +2622,139 @@ bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
return 0;
}
+int
+bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_fcpim_throttle_s *iocmd =
+ (struct bfa_bsg_fcpim_throttle_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcpim_throttle_get(&bfad->bfa,
+ (void *)&iocmd->throttle);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
+int
+bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_fcpim_throttle_s *iocmd =
+ (struct bfa_bsg_fcpim_throttle_s *)cmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcpim_throttle_set(&bfad->bfa,
+ iocmd->throttle.cfg_value);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
+int
+bfad_iocmd_tfru_read(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_tfru_s *iocmd =
+ (struct bfa_bsg_tfru_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags = 0;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_tfru_read(BFA_FRU(&bfad->bfa),
+ &iocmd->data, iocmd->len, iocmd->offset,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status == BFA_STATUS_OK) {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
+
+ return 0;
+}
+
+int
+bfad_iocmd_tfru_write(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_tfru_s *iocmd =
+ (struct bfa_bsg_tfru_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags = 0;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_tfru_write(BFA_FRU(&bfad->bfa),
+ &iocmd->data, iocmd->len, iocmd->offset,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status == BFA_STATUS_OK) {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
+
+ return 0;
+}
+
+int
+bfad_iocmd_fruvpd_read(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_fruvpd_s *iocmd =
+ (struct bfa_bsg_fruvpd_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags = 0;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fruvpd_read(BFA_FRU(&bfad->bfa),
+ &iocmd->data, iocmd->len, iocmd->offset,
+ bfad_hcb_comp, &fcomp);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status == BFA_STATUS_OK) {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
+
+ return 0;
+}
+
+int
+bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_fruvpd_s *iocmd =
+ (struct bfa_bsg_fruvpd_s *)cmd;
+ struct bfad_hal_comp fcomp;
+ unsigned long flags = 0;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fruvpd_update(BFA_FRU(&bfad->bfa),
+ &iocmd->data, iocmd->len, iocmd->offset,
+ bfad_hcb_comp, &fcomp, iocmd->trfr_cmpl);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ if (iocmd->status == BFA_STATUS_OK) {
+ wait_for_completion(&fcomp.comp);
+ iocmd->status = fcomp.status;
+ }
+
+ return 0;
+}
+
+int
+bfad_iocmd_fruvpd_get_max_size(struct bfad_s *bfad, void *cmd)
+{
+ struct bfa_bsg_fruvpd_max_size_s *iocmd =
+ (struct bfa_bsg_fruvpd_max_size_s *)cmd;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fruvpd_get_max_size(BFA_FRU(&bfad->bfa),
+ &iocmd->max_size);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ return 0;
+}
+
static int
bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
unsigned int payload_len)
@@ -2498,9 +2818,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_PORT_CFG_MAXFRSZ:
rc = bfad_iocmd_port_cfg_maxfrsize(bfad, iocmd);
break;
- case IOCMD_PORT_BBSC_ENABLE:
- case IOCMD_PORT_BBSC_DISABLE:
- rc = bfad_iocmd_port_cfg_bbsc(bfad, iocmd, cmd);
+ case IOCMD_PORT_BBCR_ENABLE:
+ case IOCMD_PORT_BBCR_DISABLE:
+ rc = bfad_iocmd_port_cfg_bbcr(bfad, cmd, iocmd);
+ break;
+ case IOCMD_PORT_BBCR_GET_ATTR:
+ rc = bfad_iocmd_port_get_bbcr_attr(bfad, iocmd);
break;
case IOCMD_LPORT_GET_ATTR:
rc = bfad_iocmd_lport_get_attr(bfad, iocmd);
@@ -2584,6 +2907,9 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_IOC_PCIFN_CFG:
rc = bfad_iocmd_ioc_get_pcifn_cfg(bfad, iocmd);
break;
+ case IOCMD_IOC_FW_SIG_INV:
+ rc = bfad_iocmd_ioc_fw_sig_inv(bfad, iocmd);
+ break;
case IOCMD_PCIFN_CREATE:
rc = bfad_iocmd_pcifn_create(bfad, iocmd);
break;
@@ -2660,6 +2986,18 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_DIAG_LB_STAT:
rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
break;
+ case IOCMD_DIAG_DPORT_ENABLE:
+ rc = bfad_iocmd_diag_dport_enable(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_DPORT_DISABLE:
+ rc = bfad_iocmd_diag_dport_disable(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_DPORT_SHOW:
+ rc = bfad_iocmd_diag_dport_show(bfad, iocmd);
+ break;
+ case IOCMD_DIAG_DPORT_START:
+ rc = bfad_iocmd_diag_dport_start(bfad, iocmd);
+ break;
case IOCMD_PHY_GET_ATTR:
rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
break;
@@ -2741,6 +3079,9 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_QOS_RESET_STATS:
rc = bfad_iocmd_qos_reset_stats(bfad, iocmd);
break;
+ case IOCMD_QOS_SET_BW:
+ rc = bfad_iocmd_qos_set_bw(bfad, iocmd);
+ break;
case IOCMD_VF_GET_STATS:
rc = bfad_iocmd_vf_get_stats(bfad, iocmd);
break;
@@ -2759,6 +3100,29 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
case IOCMD_FCPIM_LUNMASK_DELETE:
rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd);
break;
+ case IOCMD_FCPIM_THROTTLE_QUERY:
+ rc = bfad_iocmd_fcpim_throttle_query(bfad, iocmd);
+ break;
+ case IOCMD_FCPIM_THROTTLE_SET:
+ rc = bfad_iocmd_fcpim_throttle_set(bfad, iocmd);
+ break;
+ /* TFRU */
+ case IOCMD_TFRU_READ:
+ rc = bfad_iocmd_tfru_read(bfad, iocmd);
+ break;
+ case IOCMD_TFRU_WRITE:
+ rc = bfad_iocmd_tfru_write(bfad, iocmd);
+ break;
+ /* FRU */
+ case IOCMD_FRUVPD_READ:
+ rc = bfad_iocmd_fruvpd_read(bfad, iocmd);
+ break;
+ case IOCMD_FRUVPD_UPDATE:
+ rc = bfad_iocmd_fruvpd_update(bfad, iocmd);
+ break;
+ case IOCMD_FRUVPD_GET_MAX_SIZE:
+ rc = bfad_iocmd_fruvpd_get_max_size(bfad, iocmd);
+ break;
default:
rc = -EINVAL;
break;
@@ -3024,7 +3388,8 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
goto out;
}
- if (copy_from_user((uint8_t *)bsg_fcpt, bsg_data->payload,
+ if (copy_from_user((uint8_t *)bsg_fcpt,
+ (void *)(unsigned long)bsg_data->payload,
bsg_data->payload_len)) {
kfree(bsg_fcpt);
rc = -EIO;
@@ -3178,8 +3543,8 @@ out_free_mem:
kfree(rsp_kbuf);
/* Need a copy to user op */
- if (copy_to_user(bsg_data->payload, (void *) bsg_fcpt,
- bsg_data->payload_len))
+ if (copy_to_user((void *)(unsigned long)bsg_data->payload,
+ (void *)bsg_fcpt, bsg_data->payload_len))
rc = -EIO;
kfree(bsg_fcpt);
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index 8c569ddb750..90abef69158 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -34,6 +34,7 @@ enum {
IOCMD_IOC_RESET_FWSTATS,
IOCMD_IOC_SET_ADAPTER_NAME,
IOCMD_IOC_SET_PORT_NAME,
+ IOCMD_IOC_FW_SIG_INV,
IOCMD_IOCFC_GET_ATTR,
IOCMD_IOCFC_SET_INTR,
IOCMD_PORT_ENABLE,
@@ -46,8 +47,9 @@ enum {
IOCMD_PORT_CFG_ALPA,
IOCMD_PORT_CFG_MAXFRSZ,
IOCMD_PORT_CLR_ALPA,
- IOCMD_PORT_BBSC_ENABLE,
- IOCMD_PORT_BBSC_DISABLE,
+ IOCMD_PORT_BBCR_ENABLE,
+ IOCMD_PORT_BBCR_DISABLE,
+ IOCMD_PORT_BBCR_GET_ATTR,
IOCMD_LPORT_GET_ATTR,
IOCMD_LPORT_GET_RPORTS,
IOCMD_LPORT_GET_STATS,
@@ -141,6 +143,18 @@ enum {
IOCMD_FCPIM_LUNMASK_QUERY,
IOCMD_FCPIM_LUNMASK_ADD,
IOCMD_FCPIM_LUNMASK_DELETE,
+ IOCMD_DIAG_DPORT_ENABLE,
+ IOCMD_DIAG_DPORT_DISABLE,
+ IOCMD_QOS_SET_BW,
+ IOCMD_FCPIM_THROTTLE_QUERY,
+ IOCMD_FCPIM_THROTTLE_SET,
+ IOCMD_TFRU_READ,
+ IOCMD_TFRU_WRITE,
+ IOCMD_FRUVPD_READ,
+ IOCMD_FRUVPD_UPDATE,
+ IOCMD_FRUVPD_GET_MAX_SIZE,
+ IOCMD_DIAG_DPORT_SHOW,
+ IOCMD_DIAG_DPORT_START,
};
struct bfa_bsg_gen_s {
@@ -463,7 +477,8 @@ struct bfa_bsg_pcifn_s {
bfa_status_t status;
u16 bfad_num;
u16 pcifn_id;
- u32 bandwidth;
+ u16 bw_min;
+ u16 bw_max;
u8 port;
enum bfi_pcifn_class pcifn_class;
u8 rsvd[1];
@@ -483,6 +498,20 @@ struct bfa_bsg_port_cfg_mode_s {
struct bfa_port_cfg_mode_s cfg;
};
+struct bfa_bsg_bbcr_enable_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u8 bb_scn;
+ u8 rsvd;
+};
+
+struct bfa_bsg_bbcr_attr_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_bbcr_attr_s attr;
+};
+
struct bfa_bsg_faa_attr_s {
bfa_status_t status;
u16 bfad_num;
@@ -566,6 +595,21 @@ struct bfa_bsg_diag_loopback_s {
struct bfa_diag_loopback_result_s result;
};
+struct bfa_bsg_diag_dport_show_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_diag_dport_result_s result;
+};
+
+struct bfa_bsg_dport_enable_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u16 lpcnt;
+ u16 pat;
+};
+
struct bfa_bsg_diag_fwping_s {
bfa_status_t status;
u16 bfad_num;
@@ -694,6 +738,13 @@ struct bfa_bsg_qos_vc_attr_s {
struct bfa_qos_vc_attr_s attr;
};
+struct bfa_bsg_qos_bw_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ struct bfa_qos_bw_s qos_bw;
+};
+
struct bfa_bsg_vf_stats_s {
bfa_status_t status;
u16 bfad_num;
@@ -722,6 +773,43 @@ struct bfa_bsg_fcpim_lunmask_s {
struct scsi_lun lun;
};
+struct bfa_bsg_fcpim_throttle_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 vf_id;
+ struct bfa_defs_fcpim_throttle_s throttle;
+};
+
+#define BFA_TFRU_DATA_SIZE 64
+#define BFA_MAX_FRUVPD_TRANSFER_SIZE 0x1000
+
+struct bfa_bsg_tfru_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 offset;
+ u32 len;
+ u8 data[BFA_TFRU_DATA_SIZE];
+};
+
+struct bfa_bsg_fruvpd_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd1;
+ u32 offset;
+ u32 len;
+ u8 data[BFA_MAX_FRUVPD_TRANSFER_SIZE];
+ u8 trfr_cmpl;
+ u8 rsvd2[3];
+};
+
+struct bfa_bsg_fruvpd_max_size_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ u32 max_size;
+};
+
struct bfa_bsg_fcpt_s {
bfa_status_t status;
u16 vf_id;
@@ -734,10 +822,12 @@ struct bfa_bsg_fcpt_s {
};
#define bfa_bsg_fcpt_t struct bfa_bsg_fcpt_s
+#pragma pack(1)
struct bfa_bsg_data {
int payload_len;
- void *payload;
+ u64 payload;
};
+#pragma pack()
#define bfad_chk_iocmd_sz(__payload_len, __hdrsz, __bufsz) \
(((__payload_len) != ((__hdrsz) + (__bufsz))) ? \
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 439c012be76..8e83d0474fe 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -173,31 +173,9 @@ bfad_debugfs_open_reg(struct inode *inode, struct file *file)
static loff_t
bfad_debugfs_lseek(struct file *file, loff_t offset, int orig)
{
- struct bfad_debug_info *debug;
- loff_t pos = file->f_pos;
-
- debug = file->private_data;
-
- switch (orig) {
- case 0:
- file->f_pos = offset;
- break;
- case 1:
- file->f_pos += offset;
- break;
- case 2:
- file->f_pos = debug->buffer_len - offset;
- break;
- default:
- return -EINVAL;
- }
-
- if (file->f_pos < 0 || file->f_pos > debug->buffer_len) {
- file->f_pos = pos;
- return -EINVAL;
- }
-
- return file->f_pos;
+ struct bfad_debug_info *debug = file->private_data;
+ return fixed_size_llseek(file, offset, orig,
+ debug->buffer_len);
}
static ssize_t
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 1840651ce1d..8b97877d42c 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -57,7 +57,7 @@
#ifdef BFA_DRIVER_VERSION
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
#else
-#define BFAD_DRIVER_VERSION "3.1.2.0"
+#define BFAD_DRIVER_VERSION "3.2.23.0"
#endif
#define BFAD_PROTO_NAME FCPI_NAME
@@ -240,8 +240,8 @@ enum bfad_sm_event {
BFAD_E_KTHREAD_CREATE_FAILED = 2,
BFAD_E_INIT = 3,
BFAD_E_INIT_SUCCESS = 4,
- BFAD_E_INIT_FAILED = 5,
- BFAD_E_INTR_INIT_FAILED = 6,
+ BFAD_E_HAL_INIT_FAILED = 5,
+ BFAD_E_INIT_FAILED = 6,
BFAD_E_FCS_EXIT_COMP = 7,
BFAD_E_EXIT_COMP = 8,
BFAD_E_STOP = 9
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 8f92732655c..f067332bf76 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -73,9 +73,14 @@ bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
break;
- case BFI_IOIM_STS_ABORTED:
case BFI_IOIM_STS_TIMEDOUT:
+ host_status = DID_TIME_OUT;
+ cmnd->result = ScsiResult(host_status, 0);
+ break;
case BFI_IOIM_STS_PATHTOV:
+ host_status = DID_TRANSPORT_DISRUPTED;
+ cmnd->result = ScsiResult(host_status, 0);
+ break;
default:
host_status = DID_ERROR;
cmnd->result = ScsiResult(host_status, 0);
@@ -206,7 +211,7 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)
spin_lock_irqsave(&bfad->bfad_lock, flags);
hal_io = (struct bfa_ioim_s *) cmnd->host_scribble;
if (!hal_io) {
- /* IO has been completed, retrun success */
+ /* IO has been completed, return success */
rc = SUCCESS;
goto out;
}
@@ -523,20 +528,13 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
int error = 1;
mutex_lock(&bfad_mutex);
- if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) {
+ error = idr_alloc(&bfad_im_port_index, im_port, 0, 0, GFP_KERNEL);
+ if (error < 0) {
mutex_unlock(&bfad_mutex);
- printk(KERN_WARNING "idr_pre_get failure\n");
+ printk(KERN_WARNING "idr_alloc failure\n");
goto out;
}
-
- error = idr_get_new(&bfad_im_port_index, im_port,
- &im_port->idr_id);
- if (error) {
- mutex_unlock(&bfad_mutex);
- printk(KERN_WARNING "idr_get_new failure\n");
- goto out;
- }
-
+ im_port->idr_id = error;
mutex_unlock(&bfad_mutex);
im_port->shost = bfad_scsi_host_alloc(im_port, bfad);
@@ -951,13 +949,15 @@ static int
bfad_im_slave_alloc(struct scsi_device *sdev)
{
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
- struct bfad_itnim_data_s *itnim_data =
- (struct bfad_itnim_data_s *) rport->dd_data;
- struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
+ struct bfad_itnim_data_s *itnim_data;
+ struct bfa_s *bfa;
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
+ itnim_data = (struct bfad_itnim_data_s *) rport->dd_data;
+ bfa = itnim_data->itnim->bfa_itnim->bfa;
+
if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) {
/*
* We should not mask LUN 0 - since this will translate
@@ -1042,7 +1042,7 @@ bfad_fc_host_init(struct bfad_im_port_s *im_port)
/* For fibre channel services type 0x20 */
fc_host_supported_fc4s(host)[7] = 1;
- strncpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,
+ strlcpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,
BFA_SYMNAME_MAXLEN);
sprintf(fc_host_symbolic_name(host), "%s", symname);
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index b2ba0b2e91b..9ef91f907de 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -46,6 +46,7 @@
*/
#define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */
#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
+#define BFI_FLASH_IMAGE_SZ 0x100000
/*
* Msg header common to all msgs
@@ -210,7 +211,8 @@ enum bfi_mclass {
BFI_MC_PORT = 21, /* Physical port */
BFI_MC_SFP = 22, /* SFP module */
BFI_MC_PHY = 25, /* External PHY message class */
- BFI_MC_MAX = 32
+ BFI_MC_FRU = 34,
+ BFI_MC_MAX = 35
};
#define BFI_IOC_MAX_CQS 4
@@ -263,6 +265,7 @@ struct bfi_ioc_getattr_req_s {
union bfi_addr_u attr_addr;
};
+#define BFI_IOC_ATTR_UUID_SZ 16
struct bfi_ioc_attr_s {
wwn_t mfg_pwwn; /* Mfg port wwn */
wwn_t mfg_nwwn; /* Mfg node wwn */
@@ -288,6 +291,10 @@ struct bfi_ioc_attr_s {
char optrom_version[BFA_VERSION_LEN];
struct bfa_mfg_vpd_s vpd;
u32 card_type; /* card type */
+ u8 mfg_day; /* manufacturing day */
+ u8 mfg_month; /* manufacturing month */
+ u16 mfg_year; /* manufacturing year */
+ u8 uuid[BFI_IOC_ATTR_UUID_SZ]; /*!< chinook uuid */
};
/*
@@ -318,7 +325,29 @@ struct bfi_ioc_getattr_reply_s {
#define BFI_IOC_TRC_ENTS 256
#define BFI_IOC_FW_SIGNATURE (0xbfadbfad)
+#define BFA_IOC_FW_INV_SIGN (0xdeaddead)
#define BFI_IOC_MD5SUM_SZ 4
+
+struct bfi_ioc_fwver_s {
+#ifdef __BIG_ENDIAN
+ uint8_t patch;
+ uint8_t maint;
+ uint8_t minor;
+ uint8_t major;
+ uint8_t rsvd[2];
+ uint8_t build;
+ uint8_t phase;
+#else
+ uint8_t major;
+ uint8_t minor;
+ uint8_t maint;
+ uint8_t patch;
+ uint8_t phase;
+ uint8_t build;
+ uint8_t rsvd[2];
+#endif
+};
+
struct bfi_ioc_image_hdr_s {
u32 signature; /* constant signature */
u8 asic_gen; /* asic generation */
@@ -327,10 +356,18 @@ struct bfi_ioc_image_hdr_s {
u8 port1_mode; /* device mode for port 1 */
u32 exec; /* exec vector */
u32 bootenv; /* fimware boot env */
- u32 rsvd_b[4];
+ u32 rsvd_b[2];
+ struct bfi_ioc_fwver_s fwver;
u32 md5sum[BFI_IOC_MD5SUM_SZ];
};
+enum bfi_ioc_img_ver_cmp_e {
+ BFI_IOC_IMG_VER_INCOMP,
+ BFI_IOC_IMG_VER_OLD,
+ BFI_IOC_IMG_VER_SAME,
+ BFI_IOC_IMG_VER_BETTER
+};
+
#define BFI_FWBOOT_DEVMODE_OFF 4
#define BFI_FWBOOT_TYPE_OFF 8
#define BFI_FWBOOT_ENV_OFF 12
@@ -340,6 +377,12 @@ struct bfi_ioc_image_hdr_s {
((u32)(__p0_mode)) << 8 | \
((u32)(__p1_mode)))
+enum bfi_fwboot_type {
+ BFI_FWBOOT_TYPE_NORMAL = 0,
+ BFI_FWBOOT_TYPE_FLASH = 1,
+ BFI_FWBOOT_TYPE_MEMTEST = 2,
+};
+
#define BFI_FWBOOT_TYPE_NORMAL 0
#define BFI_FWBOOT_TYPE_MEMTEST 2
#define BFI_FWBOOT_ENV_OS 0
@@ -370,6 +413,10 @@ enum bfi_ioc_state {
BFI_IOC_MEMTEST = 9, /* IOC is doing memtest */
};
+#define BFA_IOC_CB_JOIN_SH 16
+#define BFA_IOC_CB_FWSTATE_MASK 0x0000ffff
+#define BFA_IOC_CB_JOIN_MASK 0xffff0000
+
#define BFI_IOC_ENDIAN_SIG 0x12345678
enum {
@@ -687,7 +734,8 @@ struct bfi_ablk_h2i_pf_req_s {
u8 pcifn;
u8 port;
u16 pers;
- u32 bw;
+ u16 bw_min; /* percent BW @ max speed */
+ u16 bw_max; /* percent BW @ max speed */
};
/* BFI_ABLK_H2I_OPTROM_ENABLE, BFI_ABLK_H2I_OPTROM_DISABLE */
@@ -957,6 +1005,7 @@ enum bfi_diag_h2i {
BFI_DIAG_H2I_TEMPSENSOR = 4,
BFI_DIAG_H2I_LEDTEST = 5,
BFI_DIAG_H2I_QTEST = 6,
+ BFI_DIAG_H2I_DPORT = 7,
};
enum bfi_diag_i2h {
@@ -966,6 +1015,8 @@ enum bfi_diag_i2h {
BFI_DIAG_I2H_TEMPSENSOR = BFA_I2HM(BFI_DIAG_H2I_TEMPSENSOR),
BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST),
BFI_DIAG_I2H_QTEST = BFA_I2HM(BFI_DIAG_H2I_QTEST),
+ BFI_DIAG_I2H_DPORT = BFA_I2HM(BFI_DIAG_H2I_DPORT),
+ BFI_DIAG_I2H_DPORT_SCN = BFA_I2HM(8),
};
#define BFI_DIAG_MAX_SGES 2
@@ -1052,6 +1103,81 @@ struct bfi_diag_qtest_req_s {
#define bfi_diag_qtest_rsp_t struct bfi_diag_qtest_req_s
/*
+ * D-port test
+ */
+enum bfi_dport_req {
+ BFI_DPORT_DISABLE = 0, /* disable dport request */
+ BFI_DPORT_ENABLE = 1, /* enable dport request */
+ BFI_DPORT_START = 2, /* start dport request */
+ BFI_DPORT_SHOW = 3, /* show dport request */
+ BFI_DPORT_DYN_DISABLE = 4, /* disable dynamic dport request */
+};
+
+enum bfi_dport_scn {
+ BFI_DPORT_SCN_TESTSTART = 1,
+ BFI_DPORT_SCN_TESTCOMP = 2,
+ BFI_DPORT_SCN_SFP_REMOVED = 3,
+ BFI_DPORT_SCN_DDPORT_ENABLE = 4,
+ BFI_DPORT_SCN_DDPORT_DISABLE = 5,
+ BFI_DPORT_SCN_FCPORT_DISABLE = 6,
+ BFI_DPORT_SCN_SUBTESTSTART = 7,
+ BFI_DPORT_SCN_TESTSKIP = 8,
+ BFI_DPORT_SCN_DDPORT_DISABLED = 9,
+};
+
+struct bfi_diag_dport_req_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ u8 req; /* request 1: enable 0: disable */
+ u8 rsvd[3];
+ u32 lpcnt;
+ u32 payload;
+};
+
+struct bfi_diag_dport_rsp_s {
+ struct bfi_mhdr_s mh; /* header 4 bytes */
+ bfa_status_t status; /* reply status */
+ wwn_t pwwn; /* switch port wwn. 8 bytes */
+ wwn_t nwwn; /* switch node wwn. 8 bytes */
+};
+
+struct bfi_diag_dport_scn_teststart_s {
+ wwn_t pwwn; /* switch port wwn. 8 bytes */
+ wwn_t nwwn; /* switch node wwn. 8 bytes */
+ u8 type; /* bfa_diag_dport_test_type_e */
+ u8 mode; /* bfa_diag_dport_test_opmode */
+ u8 rsvd[2];
+ u32 numfrm; /* from switch uint in 1M */
+};
+
+struct bfi_diag_dport_scn_testcomp_s {
+ u8 status; /* bfa_diag_dport_test_status_e */
+ u8 speed; /* bfa_port_speed_t */
+ u16 numbuffer; /* from switch */
+ u8 subtest_status[DPORT_TEST_MAX]; /* 4 bytes */
+ u32 latency; /* from switch */
+ u32 distance; /* from swtich unit in meters */
+ /* Buffers required to saturate the link */
+ u16 frm_sz; /* from switch for buf_reqd */
+ u8 rsvd[2];
+};
+
+struct bfi_diag_dport_scn_s { /* max size == RDS_RMESZ */
+ struct bfi_mhdr_s mh; /* header 4 bytes */
+ u8 state; /* new state */
+ u8 rsvd[3];
+ union {
+ struct bfi_diag_dport_scn_teststart_s teststart;
+ struct bfi_diag_dport_scn_testcomp_s testcomp;
+ } info;
+};
+
+union bfi_diag_dport_msg_u {
+ struct bfi_diag_dport_req_s req;
+ struct bfi_diag_dport_rsp_s rsp;
+ struct bfi_diag_dport_scn_s scn;
+};
+
+/*
* PHY module specific
*/
enum bfi_phy_h2i_msgs_e {
@@ -1147,6 +1273,52 @@ struct bfi_phy_write_rsp_s {
u32 length;
};
+enum bfi_fru_h2i_msgs {
+ BFI_FRUVPD_H2I_WRITE_REQ = 1,
+ BFI_FRUVPD_H2I_READ_REQ = 2,
+ BFI_TFRU_H2I_WRITE_REQ = 3,
+ BFI_TFRU_H2I_READ_REQ = 4,
+};
+
+enum bfi_fru_i2h_msgs {
+ BFI_FRUVPD_I2H_WRITE_RSP = BFA_I2HM(1),
+ BFI_FRUVPD_I2H_READ_RSP = BFA_I2HM(2),
+ BFI_TFRU_I2H_WRITE_RSP = BFA_I2HM(3),
+ BFI_TFRU_I2H_READ_RSP = BFA_I2HM(4),
+};
+
+/*
+ * FRU write request
+ */
+struct bfi_fru_write_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 last;
+ u8 rsv_1[3];
+ u8 trfr_cmpl;
+ u8 rsv_2[3];
+ u32 offset;
+ u32 length;
+ struct bfi_alen_s alen;
+};
+
+/*
+ * FRU read request
+ */
+struct bfi_fru_read_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 offset;
+ u32 length;
+ struct bfi_alen_s alen;
+};
+
+/*
+ * FRU response
+ */
+struct bfi_fru_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u32 status;
+ u32 length;
+};
#pragma pack()
#endif /* __BFI_H__ */
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index d4220e13caf..1a3fe5ad58f 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -276,8 +276,7 @@ struct bfi_fcport_enable_req_s {
struct bfi_fcport_set_svc_params_req_s {
struct bfi_mhdr_s mh; /* msg header */
__be16 tx_bbcredit; /* Tx credits */
- u8 bb_scn; /* BB_SC FC credit recovery */
- u8 rsvd;
+ u8 rsvd[2];
};
/*
@@ -426,6 +425,7 @@ struct bfi_lps_login_req_s {
u8 auth_en;
u8 lps_role;
u8 bb_scn;
+ u32 vvl_flag;
};
struct bfi_lps_login_rsp_s {
@@ -445,8 +445,8 @@ struct bfi_lps_login_rsp_s {
mac_t fcf_mac;
u8 ext_status;
u8 brcd_switch; /* attached peer is brcd switch */
- u8 bb_scn; /* atatched port's bb_scn */
u8 bfa_tag;
+ u8 rsvd;
};
struct bfi_lps_logout_req_s {
@@ -499,6 +499,9 @@ enum bfi_rport_i2h_msgs {
BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
BFI_RPORT_I2H_QOS_SCN = BFA_I2HM(3),
+ BFI_RPORT_I2H_LIP_SCN_ONLINE = BFA_I2HM(4),
+ BFI_RPORT_I2H_LIP_SCN_OFFLINE = BFA_I2HM(5),
+ BFI_RPORT_I2H_NO_DEV = BFA_I2HM(6),
};
struct bfi_rport_create_req_s {
@@ -551,6 +554,14 @@ struct bfi_rport_qos_scn_s {
struct bfa_rport_qos_attr_s new_qos_attr; /* New QoS Attributes */
};
+struct bfi_rport_lip_scn_s {
+ struct bfi_mhdr_s mh; /*!< common msg header */
+ u16 bfa_handle; /*!< host rport handle */
+ u8 status; /*!< scn online status */
+ u8 rsvd;
+ struct bfa_fcport_loop_info_s loop_info;
+};
+
union bfi_rport_h2i_msg_u {
struct bfi_msg_s *msg;
struct bfi_rport_create_req_s *create_req;
@@ -563,6 +574,7 @@ union bfi_rport_i2h_msg_u {
struct bfi_rport_create_rsp_s *create_rsp;
struct bfi_rport_delete_rsp_s *delete_rsp;
struct bfi_rport_qos_scn_s *qos_scn_evt;
+ struct bfi_rport_lip_scn_s *lip_scn;
};
/*
@@ -828,6 +840,7 @@ enum bfi_tskim_status {
*/
BFI_TSKIM_STS_TIMEOUT = 10, /* TM request timedout */
BFI_TSKIM_STS_ABORTED = 11, /* Aborted on host request */
+ BFI_TSKIM_STS_UTAG = 12, /* unknown tag for request */
};
struct bfi_tskim_rsp_s {
diff --git a/drivers/scsi/bfa/bfi_reg.h b/drivers/scsi/bfa/bfi_reg.h
index ed5f159e186..99133bcf53f 100644
--- a/drivers/scsi/bfa/bfi_reg.h
+++ b/drivers/scsi/bfa/bfi_reg.h
@@ -338,6 +338,7 @@ enum {
#define __A2T_AHB_LOAD 0x00000800
#define __WGN_READY 0x00000400
#define __GLBL_PF_VF_CFG_RDY 0x00000200
+#define CT2_NFC_STS_REG 0x00027410
#define CT2_NFC_CSR_CLR_REG 0x00027420
#define CT2_NFC_CSR_SET_REG 0x00027424
#define __HALT_NFC_CONTROLLER 0x00000002
@@ -355,6 +356,8 @@ enum {
(CT2_CSI_MAC0_CONTROL_REG + \
(__n) * (CT2_CSI_MAC1_CONTROL_REG - CT2_CSI_MAC0_CONTROL_REG))
+#define CT2_NFC_FLASH_STS_REG 0x00014834
+#define __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS 0x00000020
/*
* Name semaphore registers based on usage
*/