aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r--drivers/scsi/bfa/bfa_core.c106
-rw-r--r--drivers/scsi/bfa/bfa_cs.h4
-rw-r--r--drivers/scsi/bfa/bfa_defs.h61
-rw-r--r--drivers/scsi/bfa/bfa_defs_fcs.h18
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h119
-rw-r--r--drivers/scsi/bfa/bfa_fc.h15
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c25
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h2
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c135
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h13
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c240
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h85
-rw-r--r--drivers/scsi/bfa/bfa_fcs_fcpim.c129
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c787
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c748
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c518
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h65
-rw-r--r--drivers/scsi/bfa/bfa_ioc_ct.c236
-rw-r--r--drivers/scsi/bfa/bfa_modules.h2
-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.c827
-rw-r--r--drivers/scsi/bfa/bfa_svc.h53
-rw-r--r--drivers/scsi/bfa/bfad.c242
-rw-r--r--drivers/scsi/bfa/bfad_attr.c46
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c414
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h65
-rw-r--r--drivers/scsi/bfa/bfad_drv.h5
-rw-r--r--drivers/scsi/bfa/bfad_im.c9
-rw-r--r--drivers/scsi/bfa/bfi.h72
-rw-r--r--drivers/scsi/bfa/bfi_ms.h14
-rw-r--r--drivers/scsi/bfa/bfi_reg.h3
32 files changed, 4491 insertions, 602 deletions
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 456e5762977d..342d7d9c0997 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;
@@ -775,7 +838,8 @@ bfa_intx(struct bfa_s *bfa)
if (!intr)
return BFA_TRUE;
- bfa_msix_lpu_err(bfa, intr);
+ if (bfa->intr_enabled)
+ bfa_msix_lpu_err(bfa, intr);
return BFA_TRUE;
}
@@ -784,30 +848,37 @@ 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);
writel(~umsk, bfa->iocfc.bfa_regs.intr_mask);
bfa->iocfc.intr_mask = ~umsk;
bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
+
+ /*
+ * Set the flag indicating successful enabling of interrupts
+ */
+ bfa->intr_enabled = BFA_TRUE;
}
void
bfa_isr_disable(struct bfa_s *bfa)
{
+ bfa->intr_enabled = BFA_FALSE;
bfa_isr_mode_set(bfa, BFA_FALSE);
writel(-1L, bfa->iocfc.bfa_regs.intr_mask);
bfa_msix_uninstall(bfa);
@@ -923,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);
@@ -1022,7 +1094,7 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
{
u8 *dm_kva = NULL;
u64 dm_pa = 0;
- int i, per_reqq_sz, per_rspq_sz, dbgsz;
+ int i, per_reqq_sz, per_rspq_sz;
struct bfa_iocfc_s *iocfc = &bfa->iocfc;
struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
@@ -1083,11 +1155,8 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
BFA_CACHELINE_SZ);
/* Claim IOCFC kva memory */
- dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
- if (dbgsz > 0) {
- bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
- bfa_mem_kva_curp(iocfc) += dbgsz;
- }
+ bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
+ bfa_mem_kva_curp(iocfc) += BFA_DBG_FWTRC_LEN;
}
/*
@@ -1188,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);
}
@@ -1429,8 +1502,7 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len);
/* kva memory setup for IOCFC */
- bfa_mem_kva_setup(meminfo, iocfc_kva,
- ((bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0));
+ bfa_mem_kva_setup(meminfo, iocfc_kva, BFA_DBG_FWTRC_LEN);
}
/*
@@ -1690,6 +1762,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));
@@ -1714,6 +1787,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));
}
/*
@@ -1786,6 +1861,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_cs.h b/drivers/scsi/bfa/bfa_cs.h
index 12bfeed268eb..91a8aa394db5 100644
--- a/drivers/scsi/bfa/bfa_cs.h
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -168,7 +168,7 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
/*
* bfa_q_deq - dequeue an element from head of the queue
*/
-#define bfa_q_deq(_q, _qe) { \
+#define bfa_q_deq(_q, _qe) do { \
if (!list_empty(_q)) { \
(*((struct list_head **) (_qe))) = bfa_q_next(_q); \
bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \
@@ -177,7 +177,7 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
} \
-}
+} while (0)
/*
* bfa_q_deq_tail - dequeue an element from tail of the queue
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index b5a1595cc0a5..0efdf312b42c 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -159,10 +159,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 */
@@ -184,6 +187,17 @@ enum bfa_status {
BFA_STATUS_FAA_ACQ_ADDR = 200, /* Acquiring addr */
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_ERR = 245, /* D-port mode is enabled */
BFA_STATUS_MAX_VAL /* Unknown error code */
};
#define bfa_status_t enum bfa_status
@@ -249,6 +263,10 @@ 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;
};
/*
@@ -499,6 +517,17 @@ struct bfa_ioc_aen_data_s {
};
/*
+ * D-port states
+ *
+*/
+enum bfa_dport_state {
+ BFA_DPORT_ST_DISABLED = 0, /* D-port is Disabled */
+ BFA_DPORT_ST_DISABLING = 1, /* D-port is Disabling */
+ BFA_DPORT_ST_ENABLING = 2, /* D-port is Enabling */
+ BFA_DPORT_ST_ENABLED = 3, /* D-port is Enabled */
+};
+
+/*
* ---------------------- mfg definitions ------------
*/
@@ -722,7 +751,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 +919,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;
};
/*
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h
index 3bbc583f65cf..06f0a163ca35 100644
--- a/drivers/scsi/bfa/bfa_defs_fcs.h
+++ b/drivers/scsi/bfa/bfa_defs_fcs.h
@@ -93,6 +93,7 @@ struct bfa_lport_cfg_s {
wwn_t pwwn; /* port wwn */
wwn_t nwwn; /* node wwn */
struct bfa_lport_symname_s sym_name; /* vm port symbolic name */
+ struct bfa_lport_symname_s node_sym_name; /* Node symbolic name */
enum bfa_lport_role roles; /* FCS port roles */
u32 rsvd;
bfa_boolean_t preboot_vp; /* vport created from PBC */
@@ -192,6 +193,18 @@ struct bfa_lport_stats_s {
u32 ns_gidft_unknown_rsp;
u32 ns_gidft_alloc_wait;
+ u32 ns_rnnid_sent;
+ u32 ns_rnnid_accepts;
+ u32 ns_rnnid_rsp_err;
+ u32 ns_rnnid_rejects;
+ u32 ns_rnnid_alloc_wait;
+
+ u32 ns_rsnn_nn_sent;
+ u32 ns_rsnn_nn_accepts;
+ u32 ns_rsnn_nn_rsp_err;
+ u32 ns_rsnn_nn_rejects;
+ u32 ns_rsnn_nn_alloc_wait;
+
/*
* Mgmt Server stats
*/
@@ -410,6 +423,11 @@ struct bfa_rport_remote_link_stats_s {
u32 icc; /* Invalid CRC Count */
};
+struct bfa_rport_qualifier_s {
+ wwn_t pwwn; /* Port WWN */
+ u32 pid; /* port ID */
+ u32 rsvd;
+};
#define BFA_MAX_IO_INDEX 7
#define BFA_NO_IO_INDEX 9
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index 36756ce0e58f..ec03c8cd8dac 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -258,6 +258,7 @@ struct bfa_fw_port_lksm_stats_s {
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 */
+ u32 rsvd;
};
struct bfa_fw_port_snsm_stats_s {
@@ -270,6 +271,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 +328,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 +395,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
*/
@@ -454,7 +487,6 @@ 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;
@@ -494,13 +526,23 @@ 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 */
};
/*
@@ -692,7 +734,8 @@ 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_MAX_STATE,
};
@@ -714,9 +757,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 +805,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,
@@ -833,6 +879,19 @@ 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;
+};
+
/*
* Physical port configuration
*/
@@ -851,9 +910,10 @@ struct bfa_port_cfg_s {
u8 bb_scn; /* BB_SCN value from FLOGI Exchg */
u8 bb_scn_state; /* Config state of BB_SCN */
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()
@@ -901,7 +961,7 @@ struct bfa_port_attr_s {
/* FCoE specific */
u16 fcoe_vlan;
- u8 rsvd1[2];
+ u8 rsvd1[6];
};
/*
@@ -971,6 +1031,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 +1048,18 @@ 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 resvd[7];
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;
+ 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 +1184,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 +1194,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 */
@@ -1140,6 +1218,7 @@ struct bfa_port_fc_stats_s {
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 loop_timeouts; /* Loop timeouts */
};
/*
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index 8d0b88f67a38..bea821b98030 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,6 +1016,10 @@ struct fc_symname_s {
u8 symname[FC_SYMNAME_MAX];
};
+struct fc_alpabm_s {
+ u8 alpa_bm[FC_ALPA_MAX / 8];
+};
+
/*
* protocol default timeout values
*/
@@ -1279,6 +1284,7 @@ enum {
GS_GSPN_ID = 0x0118, /* Get symbolic PN on ID */
GS_RFT_ID = 0x0217, /* Register fc4type on ID */
GS_RSPN_ID = 0x0218, /* Register symbolic PN on ID */
+ GS_RSNN_NN = 0x0239, /* Register symbolic NN on NN */
GS_RPN_ID = 0x0212, /* Register port name */
GS_RNN_ID = 0x0213, /* Register node name */
GS_RCS_ID = 0x0214, /* Register class of service */
@@ -1357,6 +1363,15 @@ struct fcgs_rspnid_req_s {
};
/*
+ * RSNN_NN
+ */
+struct fcgs_rsnn_nn_req_s {
+ wwn_t node_name; /* Node name */
+ u8 snn_len; /* symbolic node name length */
+ u8 snn[256]; /* symbolic node name */
+};
+
+/*
* RPN_ID
*/
struct fcgs_rpnid_req_s {
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index 17b59b8b5644..dce787f6cca2 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);
@@ -1252,6 +1256,27 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
}
u16
+fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ wwn_t node_name, u8 *name)
+{
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_rsnn_nn_req_s *rsnn_nn =
+ (struct fcgs_rsnn_nn_req_s *) (cthdr + 1);
+ u32 d_id = bfa_hton3b(FC_NAME_SERVER);
+
+ fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+ fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN);
+
+ memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s));
+
+ rsnn_nn->node_name = node_name;
+ rsnn_nn->snn_len = (u8) strlen((char *)name);
+ strncpy((char *)rsnn_nn->snn, (char *)name, rsnn_nn->snn_len);
+
+ return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
{
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index 42cd9d4da697..03c753d1e548 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -166,6 +166,8 @@ enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
u16 ox_id, u8 *name);
+u16 fc_rsnn_nn_build(struct fchs_s *fchs, void *pld, u32 s_id,
+ wwn_t node_name, u8 *name);
u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
u16 ox_id, enum bfa_lport_role role);
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index f0f80e282e39..27b560962357 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 */
};
/*
@@ -1466,7 +1467,13 @@ bfa_status_t
bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
struct bfa_itnim_ioprofile_s *ioprofile)
{
- struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);
+ struct bfa_fcpim_s *fcpim;
+
+ if (!itnim)
+ return BFA_STATUS_NO_FCPIM_NEXUS;
+
+ fcpim = BFA_FCPIM(itnim->bfa);
+
if (!fcpim->io_profile)
return BFA_STATUS_IOPROFILE_OFF;
@@ -1484,6 +1491,10 @@ void
bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
{
int j;
+
+ if (!itnim)
+ return;
+
memset(&itnim->stats, 0, sizeof(itnim->stats));
memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));
for (j = 0; j < BFA_IOBUCKET_MAX; j++)
@@ -3026,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:
@@ -3064,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:
@@ -3100,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:
@@ -3109,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);
@@ -3128,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:
@@ -3160,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:
@@ -3197,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:
@@ -3228,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:
@@ -3550,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);
@@ -3689,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;
@@ -3711,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);
@@ -3749,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
@@ -3823,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 36f26da80f76..e693af6e5930 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 eaac57e1ddec..d428808fb37e 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -76,6 +76,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
fcs->bfa = bfa;
fcs->bfad = bfad;
fcs->min_cfg = min_cfg;
+ fcs->num_rport_logins = 0;
bfa->fcs = BFA_TRUE;
fcbuild_init();
@@ -119,6 +120,18 @@ bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)
}
/*
+ * Stop FCS operations.
+ */
+void
+bfa_fcs_stop(struct bfa_fcs_s *fcs)
+{
+ bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
+ bfa_wc_up(&fcs->wc);
+ bfa_fcs_fabric_modstop(fcs);
+ bfa_wc_wait(&fcs->wc);
+}
+
+/*
* fcs pbc vport initialization
*/
void
@@ -153,6 +166,7 @@ bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
fcs->driver_info = *driver_info;
bfa_fcs_fabric_psymb_init(&fcs->fabric);
+ bfa_fcs_fabric_nsymb_init(&fcs->fabric);
}
/*
@@ -213,6 +227,8 @@ static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_delay(void *cbarg);
static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
static void bfa_fcs_fabric_delete_comp(void *cbarg);
+static void bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_stop_comp(void *cbarg);
static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
struct fchs_s *fchs, u16 len);
static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
@@ -250,6 +266,10 @@ static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
/*
* Beginning state before fabric creation.
*/
@@ -283,16 +303,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:
@@ -317,16 +351,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:
@@ -334,6 +380,11 @@ bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
bfa_fcs_fabric_delete(fabric);
break;
+ case BFA_FCS_FABRIC_SM_STOP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
+ bfa_fcs_fabric_stop(fabric);
+ break;
+
default:
bfa_sm_fault(fabric->fcs, event);
}
@@ -570,14 +621,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:
@@ -585,6 +642,11 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
bfa_fcs_fabric_delete(fabric);
break;
+ case BFA_FCS_FABRIC_SM_STOP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_stopping);
+ bfa_fcs_fabric_stop(fabric);
+ break;
+
case BFA_FCS_FABRIC_SM_AUTH_FAILED:
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
@@ -682,7 +744,71 @@ bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
}
}
+/*
+ * Fabric is being stopped, awaiting vport stop completions.
+ */
+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:
+ 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:
+ 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:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/*
+ * Fabric is being stopped, cleanup without FLOGO
+ */
+static void
+bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_STOPCOMP:
+ case BFA_FCS_FABRIC_SM_LOGOCOMP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+ bfa_wc_down(&(fabric->fcs)->wc);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ /*
+ * Ignore - can get this event if we get notified about IOC down
+ * before the fabric completion callbk is done.
+ */
+ break;
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
/*
* fcs_fabric_private fabric private functions
@@ -760,6 +886,44 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
}
/*
+ * Node Symbolic Name Creation for base port and all vports
+ */
+void
+bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+ char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
+ struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
+
+ bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
+
+ /* Model name/number */
+ strncpy((char *)&port_cfg->node_sym_name, model,
+ BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
+ strncat((char *)&port_cfg->node_sym_name,
+ BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+ /* Driver Version */
+ strncat((char *)&port_cfg->node_sym_name, (char *)driver_info->version,
+ BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
+ strncat((char *)&port_cfg->node_sym_name,
+ BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+ /* Host machine name */
+ strncat((char *)&port_cfg->node_sym_name,
+ (char *)driver_info->host_machine_name,
+ BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
+ strncat((char *)&port_cfg->node_sym_name,
+ BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+ /* null terminate */
+ port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
+}
+
+/*
* bfa lps login completion callback
*/
void
@@ -852,9 +1016,6 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
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);
-
if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
(!fabric->fcs->bbscn_flogi_rjt))
bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
@@ -919,6 +1080,28 @@ bfa_fcs_fabric_delay(void *cbarg)
}
/*
+ * Stop all vports and wait for vport stop completions.
+ */
+static void
+bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe, *qen;
+
+ bfa_wc_init(&fabric->stop_wc, bfa_fcs_fabric_stop_comp, fabric);
+
+ list_for_each_safe(qe, qen, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ bfa_wc_up(&fabric->stop_wc);
+ bfa_fcs_vport_fcs_stop(vport);
+ }
+
+ bfa_wc_up(&fabric->stop_wc);
+ bfa_fcs_lport_stop(&fabric->bport);
+ bfa_wc_wait(&fabric->stop_wc);
+}
+
+/*
* Computes operating BB_SCN value
*/
static u8
@@ -978,6 +1161,14 @@ bfa_fcs_fabric_delete_comp(void *cbarg)
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
}
+static void
+bfa_fcs_fabric_stop_comp(void *cbarg)
+{
+ struct bfa_fcs_fabric_s *fabric = cbarg;
+
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOPCOMP);
+}
+
/*
* fcs_fabric_public fabric public functions
*/
@@ -1039,6 +1230,19 @@ bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
}
/*
+ * Fabric module stop -- stop FCS actions
+ */
+void
+bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs)
+{
+ struct bfa_fcs_fabric_s *fabric;
+
+ bfa_trc(fcs, 0);
+ fabric = &fcs->fabric;
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOP);
+}
+
+/*
* Fabric module start -- kick starts FCS actions
*/
void
@@ -1219,8 +1423,11 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
return;
}
}
- bfa_trc(fabric->fcs, els_cmd->els_code);
- bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+
+ if (!bfa_fcs_fabric_is_switched(fabric))
+ bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+
+ bfa_trc(fabric->fcs, fchs->type);
}
/*
@@ -1294,7 +1501,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
u16 reqlen;
struct fchs_s fchs;
- fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(fabric->fcs, BFA_FALSE);
/*
* Do not expect this failure -- expect remote node to retry
*/
@@ -1387,6 +1594,13 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
}
}
+void
+bfa_cb_lps_flogo_comp(void *bfad, void *uarg)
+{
+ struct bfa_fcs_fabric_s *fabric = uarg;
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOGOCOMP);
+}
+
/*
* Returns FCS vf structure for a given vf_id.
*
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index 51c9e1345719..a449706c6bc0 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -62,9 +62,9 @@ struct bfa_fcs_s;
#define N2N_LOCAL_PID 0x010000
#define N2N_REMOTE_PID 0x020000
#define BFA_FCS_RETRY_TIMEOUT 2000
+#define BFA_FCS_MAX_NS_RETRIES 5
#define BFA_FCS_PID_IS_WKA(pid) ((bfa_ntoh3b(pid) > 0xFFF000) ? 1 : 0)
-
-
+#define BFA_FCS_MAX_RPORT_LOGINS 1024
struct bfa_fcs_lport_ns_s {
bfa_sm_t sm; /* state machine */
@@ -72,6 +72,8 @@ struct bfa_fcs_lport_ns_s {
struct bfa_fcs_lport_s *port; /* parent port */
struct bfa_fcxp_s *fcxp;
struct bfa_fcxp_wqe_s fcxp_wqe;
+ u8 num_rnnid_retries;
+ u8 num_rsnn_nn_retries;
};
@@ -116,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 */
};
@@ -173,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,
};
@@ -205,6 +208,7 @@ struct bfa_fcs_fabric_s {
struct bfa_lps_s *lps; /* lport login services */
u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];
/* attached fabric's ip addr */
+ struct bfa_wc_s stop_wc; /* wait counter for stop */
};
#define bfa_fcs_fabric_npiv_capable(__f) ((__f)->is_npiv)
@@ -264,6 +268,7 @@ struct bfa_fcs_fabric_s;
#define bfa_fcs_lport_get_pwwn(_lport) ((_lport)->port_cfg.pwwn)
#define bfa_fcs_lport_get_nwwn(_lport) ((_lport)->port_cfg.nwwn)
#define bfa_fcs_lport_get_psym_name(_lport) ((_lport)->port_cfg.sym_name)
+#define bfa_fcs_lport_get_nsym_name(_lport) ((_lport)->port_cfg.node_sym_name)
#define bfa_fcs_lport_is_initiator(_lport) \
((_lport)->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
#define bfa_fcs_lport_get_nrports(_lport) \
@@ -286,9 +291,8 @@ bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)
bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);
struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
-void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
- wwn_t rport_wwns[], int *nrports);
-
+void bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
+ struct bfa_rport_qualifier_s rport[], int *nrports);
wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
int index, int nrports, bfa_boolean_t bwwn);
@@ -324,12 +328,17 @@ void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
void bfa_fcs_lport_online(struct bfa_fcs_lport_s *port);
void bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);
void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port);
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
struct bfa_fcs_lport_s *port, u32 pid);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_old_pid(
+ struct bfa_fcs_lport_s *port, u32 pid);
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(
struct bfa_fcs_lport_s *port, wwn_t pwwn);
struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(
struct bfa_fcs_lport_s *port, wwn_t nwwn);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_qualifier(
+ struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 pid);
void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
struct bfa_fcs_rport_s *rport);
void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
@@ -338,11 +347,14 @@ void bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);
void bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);
void bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);
void bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port);
+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 */
@@ -382,6 +394,7 @@ void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport);
void bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport);
#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 90 /* in secs */
@@ -419,6 +432,7 @@ struct bfa_fcs_rport_s {
struct bfa_fcs_s *fcs; /* fcs instance */
struct bfad_rport_s *rp_drv; /* driver peer instance */
u32 pid; /* port ID of rport */
+ u32 old_pid; /* PID before rport goes offline */
u16 maxfrsize; /* maximum frame size */
__be16 reply_oxid; /* OX_ID of inbound requests */
enum fc_cos fc_cos; /* FC classes of service supp */
@@ -441,6 +455,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 *
@@ -459,7 +474,7 @@ struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
struct bfa_fcs_lport_s *port, wwn_t rnwwn);
void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
-
+void bfa_fcs_rport_set_max_logins(u32 max_logins);
void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
struct fchs_s *fchs, u16 len);
void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
@@ -505,12 +520,13 @@ struct bfa_fcs_itnim_s {
struct bfa_fcxp_s *fcxp; /* FCXP in use */
struct bfa_itnim_stats_s stats; /* itn statistics */
};
-#define bfa_fcs_fcxp_alloc(__fcs) \
- bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
-
-#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg) \
- bfa_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg, \
- NULL, 0, 0, NULL, NULL, NULL, NULL)
+#define bfa_fcs_fcxp_alloc(__fcs, __req) \
+ bfa_fcxp_req_rsp_alloc(NULL, (__fcs)->bfa, 0, 0, \
+ NULL, NULL, NULL, NULL, __req)
+#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, \
+ __alloc_cbarg, __req) \
+ bfa_fcxp_req_rsp_alloc_wait(__bfa, __wqe, __alloc_cbfn, \
+ __alloc_cbarg, NULL, 0, 0, NULL, NULL, NULL, NULL, __req)
static inline struct bfad_port_s *
bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
@@ -592,7 +608,7 @@ bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port,
struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim);
bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
@@ -626,9 +642,9 @@ struct bfa_fcs_fdmi_hba_attr_s {
u8 model[16];
u8 model_desc[256];
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;
};
@@ -676,6 +692,7 @@ struct bfa_fcs_s {
struct bfa_fcs_stats_s stats; /* FCS statistics */
struct bfa_wc_s wc; /* waiting counter */
int fcs_aen_seq;
+ u32 num_rport_logins;
};
/*
@@ -702,6 +719,9 @@ enum bfa_fcs_fabric_event {
BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */
BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */
BFA_FCS_FABRIC_SM_START = 16, /* from driver */
+ BFA_FCS_FABRIC_SM_STOP = 17, /* Stop from driver */
+ BFA_FCS_FABRIC_SM_STOPCOMP = 18, /* Stop completion */
+ BFA_FCS_FABRIC_SM_LOGOCOMP = 19, /* FLOGO completion */
};
/*
@@ -716,7 +736,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 */
@@ -727,6 +747,28 @@ 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_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 */
+};
+
+/*
+ * fcs_itnim_sm FCS itnim state machine events
+ */
+enum bfa_fcs_itnim_event {
+ BFA_FCS_ITNIM_SM_FCS_ONLINE = 1, /* rport online event */
+ BFA_FCS_ITNIM_SM_OFFLINE = 2, /* rport offline */
+ BFA_FCS_ITNIM_SM_FRMSENT = 3, /* prli frame is sent */
+ BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */
+ BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */
+ BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */
+ BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
+ BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
+ BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
+ 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 */
};
/*
@@ -741,6 +783,7 @@ void bfa_fcs_update_cfg(struct bfa_fcs_s *fcs);
void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
struct bfa_fcs_driver_info_s *driver_info);
void bfa_fcs_exit(struct bfa_fcs_s *fcs);
+void bfa_fcs_stop(struct bfa_fcs_s *fcs);
/*
* bfa fcs vf public functions
@@ -766,11 +809,13 @@ void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
struct fchs_s *fchs, u16 len);
void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
wwn_t fabric_name);
u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event);
void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index 9272840a2409..6dc7926a3edd 100644
--- a/drivers/scsi/bfa/bfa_fcs_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -40,25 +40,6 @@ static void bfa_fcs_itnim_prli_response(void *fcsarg,
static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
enum bfa_itnim_aen_event event);
-/*
- * fcs_itnim_sm FCS itnim state machine events
- */
-
-enum bfa_fcs_itnim_event {
- BFA_FCS_ITNIM_SM_ONLINE = 1, /* rport online event */
- BFA_FCS_ITNIM_SM_OFFLINE = 2, /* rport offline */
- BFA_FCS_ITNIM_SM_FRMSENT = 3, /* prli frame is sent */
- BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */
- BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */
- BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */
- BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
- BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
- BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
- 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 */
-};
-
static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
@@ -69,6 +50,8 @@ static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
+static void bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
+ enum bfa_fcs_itnim_event event);
static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
@@ -99,7 +82,7 @@ bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
bfa_trc(itnim->fcs, event);
switch (event) {
- case BFA_FCS_ITNIM_SM_ONLINE:
+ case BFA_FCS_ITNIM_SM_FCS_ONLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
itnim->prli_retries = 0;
bfa_fcs_itnim_send_prli(itnim, NULL);
@@ -138,6 +121,7 @@ bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_INITIATOR:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
break;
case BFA_FCS_ITNIM_SM_OFFLINE:
@@ -166,12 +150,13 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
switch (event) {
case BFA_FCS_ITNIM_SM_RSP_OK:
- if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) {
+ if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR)
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
- } else {
- bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
- bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
- }
+ else
+ bfa_sm_set_state(itnim,
+ bfa_fcs_itnim_sm_hal_rport_online);
+
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
break;
case BFA_FCS_ITNIM_SM_RSP_ERROR:
@@ -194,6 +179,7 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_INITIATOR:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
bfa_fcxp_discard(itnim->fcxp);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
break;
case BFA_FCS_ITNIM_SM_DELETE:
@@ -208,6 +194,44 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
}
static void
+bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
+ enum bfa_fcs_itnim_event event)
+{
+ bfa_trc(itnim->fcs, itnim->rport->pwwn);
+ bfa_trc(itnim->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_ITNIM_SM_HAL_ONLINE:
+ if (!itnim->bfa_itnim)
+ itnim->bfa_itnim = bfa_itnim_create(itnim->fcs->bfa,
+ itnim->rport->bfa_rport, itnim);
+
+ if (itnim->bfa_itnim) {
+ bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
+ bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
+ } else {
+ bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_DELETE);
+ }
+
+ break;
+
+ case BFA_FCS_ITNIM_SM_OFFLINE:
+ bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
+ break;
+
+ case BFA_FCS_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+ bfa_fcs_itnim_free(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->fcs, event);
+ }
+}
+
+static void
bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event)
{
@@ -238,6 +262,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_INITIATOR:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
bfa_timer_stop(&itnim->timer);
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
break;
case BFA_FCS_ITNIM_SM_DELETE:
@@ -275,9 +300,8 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
break;
case BFA_FCS_ITNIM_SM_OFFLINE:
- bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+ bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
bfa_itnim_offline(itnim->bfa_itnim);
- bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
case BFA_FCS_ITNIM_SM_DELETE:
@@ -372,8 +396,14 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
break;
+ /*
+ * fcs_online is expected here for well known initiator ports
+ */
+ case BFA_FCS_ITNIM_SM_FCS_ONLINE:
+ bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
+ break;
+
case BFA_FCS_ITNIM_SM_RSP_ERROR:
- case BFA_FCS_ITNIM_SM_ONLINE:
case BFA_FCS_ITNIM_SM_INITIATOR:
break;
@@ -426,11 +456,12 @@ bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(itnim->fcs, itnim->rport->pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
itnim->stats.fcxp_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
- bfa_fcs_itnim_send_prli, itnim);
+ bfa_fcs_itnim_send_prli, itnim, BFA_TRUE);
return;
}
itnim->fcxp = fcxp;
@@ -483,7 +514,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
if (prli_resp->parampage.servparams.initiator) {
bfa_trc(itnim->fcs, prli_resp->parampage.type);
itnim->rport->scsi_function =
- BFA_RPORT_INITIATOR;
+ BFA_RPORT_INITIATOR;
itnim->stats.prli_rsp_acc++;
itnim->stats.initiator++;
bfa_sm_send_event(itnim,
@@ -531,7 +562,11 @@ bfa_fcs_itnim_timeout(void *arg)
static void
bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
{
- bfa_itnim_delete(itnim->bfa_itnim);
+ if (itnim->bfa_itnim) {
+ bfa_itnim_delete(itnim->bfa_itnim);
+ itnim->bfa_itnim = NULL;
+ }
+
bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
}
@@ -552,7 +587,6 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
struct bfa_fcs_lport_s *port = rport->port;
struct bfa_fcs_itnim_s *itnim;
struct bfad_itnim_s *itnim_drv;
- struct bfa_itnim_s *bfa_itnim;
/*
* call bfad to allocate the itnim
@@ -570,20 +604,7 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
itnim->fcs = rport->fcs;
itnim->itnim_drv = itnim_drv;
- /*
- * call BFA to create the itnim
- */
- bfa_itnim =
- bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
-
- if (bfa_itnim == NULL) {
- bfa_trc(port->fcs, rport->pwwn);
- bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
- WARN_ON(1);
- return NULL;
- }
-
- itnim->bfa_itnim = bfa_itnim;
+ itnim->bfa_itnim = NULL;
itnim->seq_rec = BFA_FALSE;
itnim->rec_support = BFA_FALSE;
itnim->conf_comp = BFA_FALSE;
@@ -613,20 +634,12 @@ bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
* Notification from rport that PLOGI is complete to initiate FC-4 session.
*/
void
-bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
+bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim)
{
itnim->stats.onlines++;
- if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
- bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
- } else {
- /*
- * For well known addresses, we set the itnim to initiator
- * state
- */
- itnim->stats.initiator++;
- bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
- }
+ if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid))
+ bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HAL_ONLINE);
}
/*
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index bcc4966e8ba4..1224d0462a49 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},
};
/*
@@ -131,6 +165,8 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
/* If vport - send completion call back */
if (port->vport)
bfa_fcs_vport_stop_comp(port->vport);
+ else
+ bfa_wc_down(&(port->fabric->stop_wc));
break;
case BFA_FCS_PORT_SM_OFFLINE:
@@ -166,6 +202,8 @@ bfa_fcs_lport_sm_online(
/* If vport - send completion call back */
if (port->vport)
bfa_fcs_vport_stop_comp(port->vport);
+ else
+ bfa_wc_down(&(port->fabric->stop_wc));
} else {
bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
list_for_each_safe(qe, qen, &port->rport_q) {
@@ -222,6 +260,8 @@ bfa_fcs_lport_sm_offline(
/* If vport - send completion call back */
if (port->vport)
bfa_fcs_vport_stop_comp(port->vport);
+ else
+ bfa_wc_down(&(port->fabric->stop_wc));
} else {
bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
list_for_each_safe(qe, qen, &port->rport_q) {
@@ -267,6 +307,8 @@ bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
/* If vport - send completion call back */
if (port->vport)
bfa_fcs_vport_stop_comp(port->vport);
+ else
+ bfa_wc_down(&(port->fabric->stop_wc));
}
break;
@@ -340,7 +382,7 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
bfa_trc(port->fcs, rx_fchs->d_id);
bfa_trc(port->fcs, rx_fchs->s_id);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -370,7 +412,7 @@ bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
bfa_trc(port->fcs, rx_fchs->d_id);
bfa_trc(port->fcs, rx_fchs->s_id);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -507,7 +549,7 @@ bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
bfa_trc(port->fcs, rx_fchs->s_id);
bfa_trc(port->fcs, rx_fchs->d_id);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -552,7 +594,7 @@ bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
bfa_trc(port->fcs, rx_fchs->d_id);
bfa_trc(port->fcs, rx_len);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -684,7 +726,7 @@ bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
bfa_trc(port->fcs, rx_fchs->d_id);
bfa_trc(port->fcs, rx_fchs->s_id);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -854,6 +896,25 @@ bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
}
/*
+ * OLD_PID based Lookup for a R-Port in the Port R-Port Queue
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid)
+{
+ struct bfa_fcs_rport_s *rport;
+ struct list_head *qe;
+
+ list_for_each(qe, &port->rport_q) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ if (rport->old_pid == pid)
+ return rport;
+ }
+
+ bfa_trc(port->fcs, pid);
+ return NULL;
+}
+
+/*
* PWWN based Lookup for a R-Port in the Port R-Port Queue
*/
struct bfa_fcs_rport_s *
@@ -892,6 +953,26 @@ bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
}
/*
+ * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port,
+ wwn_t pwwn, u32 pid)
+{
+ struct bfa_fcs_rport_s *rport;
+ struct list_head *qe;
+
+ list_for_each(qe, &port->rport_q) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid)
+ return rport;
+ }
+
+ bfa_trc(port->fcs, pwwn);
+ return NULL;
+}
+
+/*
* Called by rport module when new rports are discovered.
*/
void
@@ -939,6 +1020,16 @@ bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
}
/*
+ * Called by fabric for base port and by vport for virtual ports
+ * when target mode driver is unloaded.
+ */
+void
+bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port)
+{
+ bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP);
+}
+
+/*
* Called by fabric to delete base lport and associated resources.
*
* Called by vport to delete lport and associated resources. Should call
@@ -1070,7 +1161,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);
}
/*
@@ -1164,6 +1255,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
/*
@@ -1657,10 +1840,11 @@ bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->port_cfg.pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
- bfa_fcs_lport_fdmi_send_rhba, fdmi);
+ bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE);
return;
}
fdmi->fcxp = fcxp;
@@ -1830,13 +2014,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;
@@ -1931,10 +2112,11 @@ bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->port_cfg.pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
- bfa_fcs_lport_fdmi_send_rprt, fdmi);
+ bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
return;
}
fdmi->fcxp = fcxp;
@@ -2146,10 +2328,11 @@ bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->port_cfg.pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
- bfa_fcs_lport_fdmi_send_rpa, fdmi);
+ bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
return;
}
fdmi->fcxp = fcxp;
@@ -2236,6 +2419,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));
@@ -2271,7 +2455,9 @@ 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;
}
static void
@@ -2331,7 +2517,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
@@ -2736,10 +2922,11 @@ bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->pid);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
- bfa_fcs_lport_ms_send_gmal, ms);
+ bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
return;
}
ms->fcxp = fcxp;
@@ -2936,10 +3123,11 @@ bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->pid);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
- bfa_fcs_lport_ms_send_gfn, ms);
+ bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
return;
}
ms->fcxp = fcxp;
@@ -3012,11 +3200,12 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->pid);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
port->stats.ms_plogi_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
- bfa_fcs_lport_ms_send_plogi, ms);
+ bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
return;
}
ms->fcxp = fcxp;
@@ -3166,6 +3355,10 @@ static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
static void bfa_fcs_lport_ns_timeout(void *arg);
static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
struct bfa_fcxp_s *fcxp,
@@ -3202,6 +3395,20 @@ static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
u32 rsp_len,
u32 resid_len,
struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ns_rnn_id_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
static void bfa_fcs_lport_ns_process_gidft_pids(
struct bfa_fcs_lport_s *port,
u32 *pid_buf, u32 n_pids);
@@ -3226,6 +3433,8 @@ enum vport_ns_event {
NSSM_EVENT_RFTID_SENT = 9,
NSSM_EVENT_RFFID_SENT = 10,
NSSM_EVENT_GIDFT_SENT = 11,
+ NSSM_EVENT_RNNID_SENT = 12,
+ NSSM_EVENT_RSNN_NN_SENT = 13,
};
static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
@@ -3266,6 +3475,21 @@ static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
enum vport_ns_event event);
static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_sending_rnn_id(
+ struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_sending_rsnn_nn(
+ struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rsnn_nn_retry(
+ struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
/*
* Start in offline state - awaiting linkup
*/
@@ -3333,8 +3557,9 @@ bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
break;
case NSSM_EVENT_RSP_OK:
- bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
- bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
+ ns->num_rnnid_retries = 0;
+ bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
break;
case NSSM_EVENT_PORT_OFFLINE:
@@ -3374,6 +3599,176 @@ bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
}
static void
+bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RNNID_SENT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->fcxp_wqe);
+ break;
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSP_OK:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
+ ns->num_rnnid_retries = 0;
+ ns->num_rsnn_nn_retries = 0;
+ bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
+ break;
+
+ case NSSM_EVENT_RSP_ERROR:
+ if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) {
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry);
+ ns->port->stats.ns_retries++;
+ ns->num_rnnid_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+ BFA_FCS_RETRY_TIMEOUT);
+ } else {
+ bfa_sm_set_state(ns,
+ bfa_fcs_lport_ns_sm_sending_rspn_id);
+ bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+ }
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_fcxp_discard(ns->fcxp);
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_TIMEOUT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
+ bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_timer_stop(&ns->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSNN_NN_SENT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSP_OK:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+ ns->num_rsnn_nn_retries = 0;
+ bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_RSP_ERROR:
+ if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) {
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry);
+ ns->port->stats.ns_retries++;
+ ns->num_rsnn_nn_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->timer, bfa_fcs_lport_ns_timeout,
+ ns, BFA_FCS_RETRY_TIMEOUT);
+ } else {
+ bfa_sm_set_state(ns,
+ bfa_fcs_lport_ns_sm_sending_rspn_id);
+ bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+ }
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_discard(ns->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_TIMEOUT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
+ bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_timer_stop(&ns->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
enum vport_ns_event event)
{
@@ -3770,11 +4165,12 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->pid);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
port->stats.ns_plogi_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_lport_ns_send_plogi, ns);
+ bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
return;
}
ns->fcxp = fcxp;
@@ -3853,6 +4249,162 @@ bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
}
/*
+ * Register node name for port_id
+ */
+static void
+bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
+ if (!fcxp) {
+ port->stats.ns_rnnid_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE);
+ return;
+ }
+
+ ns->fcxp = fcxp;
+
+ len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port),
+ bfa_fcs_lport_get_fcid(port),
+ bfa_fcs_lport_get_nwwn(port));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ns_rnn_id_response, (void *)ns,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ port->stats.ns_rnnid_sent++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ port->stats.ns_rnnid_rsp_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ port->stats.ns_rnnid_accepts++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ return;
+ }
+
+ port->stats.ns_rnnid_rejects++;
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/*
+ * Register the symbolic node name for a given node name.
+ */
+static void
+bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+ u8 *nsymbl;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
+ if (!fcxp) {
+ port->stats.ns_rsnn_nn_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE);
+ return;
+ }
+ ns->fcxp = fcxp;
+
+ nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name(
+ bfa_fcs_get_base_port(port->fcs)));
+
+ len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port),
+ bfa_fcs_lport_get_nwwn(port), nsymbl);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ port->stats.ns_rsnn_nn_sent++;
+
+ bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ port->stats.ns_rsnn_nn_rsp_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ port->stats.ns_rsnn_nn_accepts++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ return;
+ }
+
+ port->stats.ns_rsnn_nn_rejects++;
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/*
* Register the symbolic port name.
*/
static void
@@ -3870,11 +4422,12 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->port_cfg.pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
port->stats.ns_rspnid_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_lport_ns_send_rspn_id, ns);
+ bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
return;
}
ns->fcxp = fcxp;
@@ -3971,11 +4524,12 @@ bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->port_cfg.pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
port->stats.ns_rftid_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_lport_ns_send_rft_id, ns);
+ bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
return;
}
ns->fcxp = fcxp;
@@ -4044,11 +4598,12 @@ bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->port_cfg.pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
port->stats.ns_rffid_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_lport_ns_send_rff_id, ns);
+ bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
return;
}
ns->fcxp = fcxp;
@@ -4127,11 +4682,12 @@ bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->pid);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
port->stats.ns_gidft_alloc_wait++;
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_lport_ns_send_gid_ft, ns);
+ bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
return;
}
ns->fcxp = fcxp;
@@ -4261,6 +4817,10 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
struct fcgs_gidft_resp_s *gidft_entry;
struct bfa_fcs_rport_s *rport;
u32 ii;
+ struct bfa_fcs_fabric_s *fabric = port->fabric;
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe;
+ u8 found = 0;
for (ii = 0; ii < n_pids; ii++) {
gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
@@ -4269,6 +4829,29 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
continue;
/*
+ * Ignore PID if it is of base port
+ * (Avoid vports discovering base port as remote port)
+ */
+ if (gidft_entry->pid == fabric->bport.pid)
+ continue;
+
+ /*
+ * Ignore PID if it is of vport created on the same base port
+ * (Avoid vport discovering every other vport created on the
+ * same port as remote port)
+ */
+ list_for_each(qe, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ if (vport->lport.pid == gidft_entry->pid)
+ found = 1;
+ }
+
+ if (found) {
+ found = 0;
+ continue;
+ }
+
+ /*
* Check if this rport already exists
*/
rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
@@ -4335,7 +4918,8 @@ bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
bfa_trc(port->fcs, port->pid);
- bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
+ if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online))
+ bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
}
static void
@@ -4355,6 +4939,70 @@ bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
}
}
+void
+bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ struct bfa_fcxp_s *fcxp;
+ u8 symbl[256];
+ 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) ||
+ bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) ||
+ bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) ||
+ bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry))
+ return;
+
+ memset(symbl, 0, sizeof(symbl));
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
+ if (!fcxp) {
+ port->stats.ns_rspnid_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
+ return;
+ }
+
+ ns->fcxp = fcxp;
+
+ if (port->vport) {
+ /*
+ * For Vports, we append the vport's port symbolic name
+ * to that of the base port.
+ */
+ strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name
+ (bfa_fcs_get_base_port(port->fcs))),
+ strlen((char *)&bfa_fcs_lport_get_psym_name(
+ bfa_fcs_get_base_port(port->fcs))));
+
+ /* Ensure we have a null terminating string. */
+ ((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name(
+ bfa_fcs_get_base_port(port->fcs)))] = 0;
+
+ strncat((char *)psymbl,
+ (char *)&(bfa_fcs_lport_get_psym_name(port)),
+ strlen((char *)&bfa_fcs_lport_get_psym_name(port)));
+ }
+
+ len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port), 0, psymbl);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+
+ port->stats.ns_rspnid_sent++;
+}
+
/*
* FCS SCN
*/
@@ -4529,10 +5177,11 @@ bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(port->fcs, port->pid);
bfa_trc(port->fcs, port->port_cfg.pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
- bfa_fcs_lport_scn_send_scr, scn);
+ bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
return;
}
scn->fcxp = fcxp;
@@ -4614,7 +5263,7 @@ bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
bfa_trc(port->fcs, rx_fchs->s_id);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -4676,7 +5325,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);
@@ -4688,14 +5337,33 @@ static void
bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
{
struct bfa_fcs_rport_s *rport;
+ struct bfa_fcs_fabric_s *fabric = port->fabric;
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe;
bfa_trc(port->fcs, rpid);
/*
+ * Ignore PID if it is of base port or of vports created on the
+ * same base port. It is to avoid vports discovering base port or
+ * other vports created on same base port as remote port
+ */
+ if (rpid == fabric->bport.pid)
+ return;
+
+ list_for_each(qe, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ if (vport->lport.pid == rpid)
+ return;
+ }
+ /*
* If this is an unknown device, then it just came online.
* Otherwise let rport handle the RSCN event.
*/
rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
+ if (!rport)
+ rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
+
if (rport == NULL) {
/*
* If min cfg mode is enabled, we donot need to
@@ -4888,15 +5556,15 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
}
void
-bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
- wwn_t rport_wwns[], int *nrports)
+bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
+ struct bfa_rport_qualifier_s rports[], int *nrports)
{
struct list_head *qh, *qe;
struct bfa_fcs_rport_s *rport = NULL;
int i;
struct bfa_fcs_s *fcs;
- if (port == NULL || rport_wwns == NULL || *nrports == 0)
+ if (port == NULL || rports == NULL || *nrports == 0)
return;
fcs = port->fcs;
@@ -4916,7 +5584,13 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
continue;
}
- rport_wwns[i] = rport->pwwn;
+ if (!rport->pwwn && !rport->pid) {
+ qe = bfa_q_next(qe);
+ continue;
+ }
+
+ rports[i].pwwn = rport->pwwn;
+ rports[i].pid = rport->pid;
i++;
qe = bfa_q_next(qe);
@@ -5073,6 +5747,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
*/
@@ -5760,6 +6443,16 @@ bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
{
vport->vport_stats.fab_cleanup++;
}
+
+/*
+ * Stop notification from fabric SM. To be invoked from within FCS.
+ */
+void
+bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
+{
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
+}
+
/*
* delete notification from fabric SM. To be invoked from within FCS.
*/
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index fe0463a1db04..58ac643ba9f3 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -30,14 +30,22 @@ static u32
bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
/* In millisecs */
/*
+ * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports
+ * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports
+ */
+static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;
+
+/*
* forward declarations
*/
static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);
static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
struct fc_logi_s *plogi);
static void bfa_fcs_rport_timeout(void *arg);
@@ -76,6 +84,7 @@ static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
struct fchs_s *rx_fchs, u16 len);
static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);
static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
enum rport_event event);
@@ -87,6 +96,8 @@ static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
enum rport_event event);
static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
enum rport_event event);
+static void bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
enum rport_event event);
static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
@@ -95,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);
@@ -123,6 +138,10 @@ static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
enum rport_event event);
static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
enum rport_event event);
+static void bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
static struct bfa_sm_table_s rport_sm_table[] = {
{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
@@ -130,12 +149,15 @@ static struct bfa_sm_table_s rport_sm_table[] = {
{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
+ {BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},
{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
{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},
@@ -167,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_plogiacc_sending);
- bfa_fcs_rport_send_plogiacc(rport, NULL);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
case RPSM_EVENT_PLOGI_COMP:
@@ -215,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);
@@ -252,8 +283,8 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FCXP_SENT:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
- bfa_fcs_rport_hal_online(rport);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
case RPSM_EVENT_DELETE:
@@ -264,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);
@@ -330,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);
@@ -348,9 +397,9 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_PLOGI_COMP:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
bfa_timer_stop(&rport->timer);
- bfa_fcs_rport_hal_online(rport);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
default:
@@ -370,9 +419,9 @@ bfa_fcs_rport_sm_plogi(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_hal_online);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
rport->plogi_retries = 0;
- bfa_fcs_rport_hal_online(rport);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
case RPSM_EVENT_LOGO_RCVD:
@@ -397,6 +446,7 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
BFA_FCS_RETRY_TIMEOUT);
} else {
bfa_stats(rport->port, rport_del_max_plogi_retry);
+ rport->old_pid = rport->pid;
rport->pid = 0;
bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -405,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,
@@ -423,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);
@@ -443,9 +506,9 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
break;
case RPSM_EVENT_PLOGI_COMP:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_hal_online(rport);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
default:
@@ -454,6 +517,71 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
/*
+ * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function
+ */
+static void
+bfa_fcs_rport_sm_fc4_fcs_online(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_FC4_FCS_ONLINE:
+ if (rport->scsi_function == BFA_RPORT_INITIATOR) {
+ if (!BFA_FCS_PID_IS_WKA(rport->pid))
+ bfa_fcs_rpf_rport_online(rport);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+ break;
+ }
+
+ if (!rport->bfa_rport)
+ rport->bfa_rport =
+ bfa_rport_create(rport->fcs->bfa, rport);
+
+ if (rport->bfa_rport) {
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_fcs_rport_hal_online(rport);
+ } else {
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+ bfa_fcs_rport_fcs_offline_action(rport);
+ }
+ break;
+
+ case RPSM_EVENT_PLOGI_RCVD:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+ rport->plogi_pending = BFA_TRUE;
+ bfa_fcs_rport_fcs_offline_action(rport);
+ break;
+
+ case RPSM_EVENT_PLOGI_COMP:
+ case RPSM_EVENT_LOGO_IMP:
+ case RPSM_EVENT_ADDRESS_CHANGE:
+ 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;
+
+ case RPSM_EVENT_LOGO_RCVD:
+ case RPSM_EVENT_PRLO_RCVD:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+ bfa_fcs_rport_fcs_offline_action(rport);
+ break;
+
+ case RPSM_EVENT_DELETE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+ bfa_fcs_rport_fcs_offline_action(rport);
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ break;
+ }
+}
+
+/*
* PLOGI is complete. Awaiting BFA rport online callback. FC-4s
* are offline.
*/
@@ -468,41 +596,35 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_HCB_ONLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
- bfa_fcs_rport_online_action(rport);
+ bfa_fcs_rport_hal_online_action(rport);
break;
- case RPSM_EVENT_PRLO_RCVD:
case RPSM_EVENT_PLOGI_COMP:
break;
+ case RPSM_EVENT_PRLO_RCVD:
case RPSM_EVENT_LOGO_RCVD:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+ bfa_fcs_rport_fcs_offline_action(rport);
break;
+ case RPSM_EVENT_FAB_SCN:
case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+ case RPSM_EVENT_SCN_OFFLINE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+ bfa_fcs_rport_fcs_offline_action(rport);
break;
case RPSM_EVENT_PLOGI_RCVD:
rport->plogi_pending = BFA_TRUE;
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+ bfa_fcs_rport_fcs_offline_action(rport);
break;
case RPSM_EVENT_DELETE:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
- break;
-
- case RPSM_EVENT_SCN:
- /*
- * @todo
- * Ignore SCN - PLOGI just completed, FC-4 login should detect
- * device failures.
- */
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+ bfa_fcs_rport_fcs_offline_action(rport);
break;
default:
@@ -521,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;
@@ -536,21 +659,23 @@ 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_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_DELETE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
+ case RPSM_EVENT_SCN_ONLINE:
case RPSM_EVENT_PLOGI_COMP:
break;
@@ -579,10 +704,10 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_DELETE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_offline_action(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
*/
@@ -592,24 +717,16 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_PRLO_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_LOGO_IMP:
- rport->pid = 0;
- 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:
case RPSM_EVENT_ADDRESS_CHANGE:
case RPSM_EVENT_PLOGI_COMP:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
default:
@@ -630,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;
@@ -642,24 +759,24 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
}
break;
case RPSM_EVENT_DELETE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
break;
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_PLOGI_COMP:
@@ -668,7 +785,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
case RPSM_EVENT_LOGO_IMP:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
default:
@@ -681,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);
@@ -690,36 +807,36 @@ 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:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
break;
case RPSM_EVENT_PLOGI_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
default:
@@ -732,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);
@@ -756,16 +874,16 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
case RPSM_EVENT_FAILED:
case RPSM_EVENT_ADDRESS_CHANGE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_DELETE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
- case RPSM_EVENT_SCN:
+ case RPSM_EVENT_FAB_SCN:
/*
* already processing RSCN
*/
@@ -774,14 +892,103 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
case RPSM_EVENT_LOGO_IMP:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
break;
case RPSM_EVENT_LOGO_RCVD:
case RPSM_EVENT_PRLO_RCVD:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_offline_action(rport);
+ bfa_fcs_rport_hal_offline_action(rport);
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+/*
+ * 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:
@@ -790,7 +997,7 @@ 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.
+ * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
*/
static void
bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
@@ -803,13 +1010,21 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FC4_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+ bfa_fcs_rport_hal_offline(rport);
break;
case RPSM_EVENT_DELETE:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+ if (rport->pid && (rport->prlo == BFA_TRUE))
+ bfa_fcs_rport_send_prlo_acc(rport);
+ if (rport->pid && (rport->prlo == BFA_FALSE))
+ bfa_fcs_rport_send_logo_acc(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:
case RPSM_EVENT_ADDRESS_CHANGE:
@@ -835,7 +1050,20 @@ bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FC4_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+ bfa_fcs_rport_hal_offline(rport);
+ break;
+
+ case RPSM_EVENT_LOGO_RCVD:
+ bfa_fcs_rport_send_logo_acc(rport);
+ case RPSM_EVENT_PRLO_RCVD:
+ if (rport->prlo == BFA_TRUE)
+ bfa_fcs_rport_send_prlo_acc(rport);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
+ break;
+
+ case RPSM_EVENT_HCB_ONLINE:
+ case RPSM_EVENT_DELETE:
+ /* Rport is being deleted */
break;
default:
@@ -857,13 +1085,26 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FC4_OFFLINE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+ bfa_fcs_rport_hal_offline(rport);
break;
- case RPSM_EVENT_SCN:
- case RPSM_EVENT_LOGO_IMP:
+ case RPSM_EVENT_SCN_ONLINE:
+ break;
case RPSM_EVENT_LOGO_RCVD:
+ /*
+ * Rport is going offline. Just ack the logo
+ */
+ bfa_fcs_rport_send_logo_acc(rport);
+ break;
+
case RPSM_EVENT_PRLO_RCVD:
+ bfa_fcs_rport_send_prlo_acc(rport);
+ break;
+
+ case RPSM_EVENT_SCN_OFFLINE:
+ case RPSM_EVENT_HCB_ONLINE:
+ case RPSM_EVENT_FAB_SCN:
+ case RPSM_EVENT_LOGO_IMP:
case RPSM_EVENT_ADDRESS_CHANGE:
/*
* rport is already going offline.
@@ -907,24 +1148,36 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
*/
case RPSM_EVENT_ADDRESS_CHANGE:
- if (bfa_fcs_lport_is_online(rport->port)) {
- if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
- bfa_sm_set_state(rport,
- bfa_fcs_rport_sm_nsdisc_sending);
- rport->ns_retries = 0;
- bfa_fcs_rport_send_nsdisc(rport, NULL);
- } else {
- bfa_sm_set_state(rport,
- bfa_fcs_rport_sm_plogi_sending);
- rport->plogi_retries = 0;
- bfa_fcs_rport_send_plogi(rport, NULL);
- }
- } else {
+ if (!bfa_fcs_lport_is_online(rport->port)) {
rport->pid = 0;
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;
+ }
+ if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+ bfa_sm_set_state(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;
+ bfa_fcs_rport_send_plogi(rport, NULL);
}
break;
@@ -933,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:
@@ -1001,13 +1256,19 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_DELETE:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
+ if (rport->pid && (rport->prlo == BFA_TRUE))
+ bfa_fcs_rport_send_prlo_acc(rport);
+ if (rport->pid && (rport->prlo == BFA_FALSE))
+ bfa_fcs_rport_send_logo_acc(rport);
break;
case RPSM_EVENT_LOGO_IMP:
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:
/*
@@ -1040,7 +1301,16 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_LOGO_RCVD:
+ bfa_fcs_rport_send_logo_acc(rport);
case RPSM_EVENT_PRLO_RCVD:
+ if (rport->prlo == BFA_TRUE)
+ bfa_fcs_rport_send_prlo_acc(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;
@@ -1067,12 +1337,18 @@ 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;
case RPSM_EVENT_LOGO_RCVD:
+ bfa_fcs_rport_send_logo_acc(rport);
case RPSM_EVENT_PRLO_RCVD:
+ if (rport->prlo == BFA_TRUE)
+ bfa_fcs_rport_send_prlo_acc(rport);
+
bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
bfa_fcs_rport_free(rport);
@@ -1100,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;
@@ -1123,12 +1401,19 @@ 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:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
bfa_timer_stop(&rport->timer);
- bfa_fcs_rport_hal_online(rport);
+ 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:
@@ -1171,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:
@@ -1190,9 +1475,9 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_PLOGI_COMP:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
- bfa_fcs_rport_hal_online(rport);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
default:
@@ -1217,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);
@@ -1254,9 +1539,9 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_PLOGI_COMP:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
bfa_timer_stop(&rport->timer);
- bfa_fcs_rport_hal_online(rport);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
default:
@@ -1296,6 +1581,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_sm_nsdisc_sending);
bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
+ rport->old_pid = rport->pid;
rport->pid = 0;
bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -1329,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
*/
@@ -1343,9 +1629,9 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_PLOGI_COMP:
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
bfa_fcxp_discard(rport->fcxp);
- bfa_fcs_rport_hal_online(rport);
+ bfa_fcs_rport_fcs_online_action(rport);
break;
default:
@@ -1353,7 +1639,63 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
}
}
+/*
+ * Rport needs to be deleted
+ * waiting for ITNIM clean up to finish
+ */
+static void
+bfa_fcs_rport_sm_fc4_off_delete(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_FC4_OFFLINE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
+ bfa_fcs_rport_hal_offline(rport);
+ break;
+ case RPSM_EVENT_DELETE:
+ case RPSM_EVENT_PLOGI_RCVD:
+ /* Ignore these events */
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ break;
+ }
+}
+
+/*
+ * RPort needs to be deleted
+ * waiting for BFA/FW to finish current processing
+ */
+static void
+bfa_fcs_rport_sm_delete_pending(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_HCB_OFFLINE:
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+ bfa_fcs_rport_free(rport);
+ break;
+
+ case RPSM_EVENT_DELETE:
+ case RPSM_EVENT_LOGO_IMP:
+ case RPSM_EVENT_PLOGI_RCVD:
+ /* Ignore these events */
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
/*
* fcs_rport_private FCS RPORT provate functions
@@ -1370,10 +1712,11 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(rport->fcs, rport->pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_plogi, rport);
+ bfa_fcs_rport_send_plogi, rport, BFA_TRUE);
return;
}
rport->fcxp = fcxp;
@@ -1490,10 +1833,11 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->reply_oxid);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_plogiacc, rport);
+ bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);
return;
}
rport->fcxp = fcxp;
@@ -1522,10 +1866,11 @@ bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(rport->fcs, rport->pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_adisc, rport);
+ bfa_fcs_rport_send_adisc, rport, BFA_TRUE);
return;
}
rport->fcxp = fcxp;
@@ -1585,10 +1930,11 @@ bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(rport->fcs, rport->pid);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_nsdisc, rport);
+ bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);
return;
}
rport->fcxp = fcxp;
@@ -1741,10 +2087,11 @@ bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
port = rport->port;
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_logo, rport);
+ bfa_fcs_rport_send_logo, rport, BFA_FALSE);
return;
}
rport->fcxp = fcxp;
@@ -1778,7 +2125,7 @@ bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
port = rport->port;
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -1849,7 +2196,7 @@ bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
bfa_fcs_itnim_is_initiator(rport->itnim);
}
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -1886,7 +2233,7 @@ bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -1920,7 +2267,7 @@ bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
*/
if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -1957,6 +2304,15 @@ bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
bfa_rport_online(rport->bfa_rport, &rport_info);
}
+static void
+bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)
+{
+ if (rport->bfa_rport)
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
+ else
+ bfa_cb_rport_offline(rport);
+}
+
static struct bfa_fcs_rport_s *
bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
{
@@ -1967,6 +2323,11 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
/*
* allocate rport
*/
+ if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {
+ bfa_trc(fcs, rpid);
+ return NULL;
+ }
+
if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
!= BFA_STATUS_OK) {
bfa_trc(fcs, rpid);
@@ -1981,16 +2342,9 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
rport->rp_drv = rport_drv;
rport->pid = rpid;
rport->pwwn = pwwn;
+ rport->old_pid = 0;
- /*
- * allocate BFA rport
- */
- rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
- if (!rport->bfa_rport) {
- bfa_trc(fcs, rpid);
- kfree(rport_drv);
- return NULL;
- }
+ rport->bfa_rport = NULL;
/*
* allocate FC-4s
@@ -2001,14 +2355,13 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
rport->itnim = bfa_fcs_itnim_create(rport);
if (!rport->itnim) {
bfa_trc(fcs, rpid);
- bfa_sm_send_event(rport->bfa_rport,
- BFA_RPORT_SM_DELETE);
kfree(rport_drv);
return NULL;
}
}
bfa_fcs_lport_add_rport(port, rport);
+ fcs->num_rport_logins++;
bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
@@ -2024,20 +2377,28 @@ static void
bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
{
struct bfa_fcs_lport_s *port = rport->port;
+ struct bfa_fcs_s *fcs = port->fcs;
/*
* - delete FC-4s
* - delete BFA rport
* - remove from queue of rports
*/
+ rport->plogi_pending = BFA_FALSE;
+
if (bfa_fcs_lport_is_initiator(port)) {
bfa_fcs_itnim_delete(rport->itnim);
if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
bfa_fcs_rpf_rport_offline(rport);
}
- bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
+ if (rport->bfa_rport) {
+ bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
+ rport->bfa_rport = NULL;
+ }
+
bfa_fcs_lport_del_rport(port, rport);
+ fcs->num_rport_logins--;
kfree(rport->rp_drv);
}
@@ -2071,7 +2432,18 @@ bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
}
static void
-bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
+bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)
+{
+ if ((!rport->pid) || (!rport->pwwn)) {
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_sm_fault(rport->fcs, rport->pid);
+ }
+
+ bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);
+}
+
+static void
+bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)
{
struct bfa_fcs_lport_s *port = rport->port;
struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
@@ -2086,7 +2458,7 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
}
if (bfa_fcs_lport_is_initiator(port)) {
- bfa_fcs_itnim_rport_online(rport->itnim);
+ bfa_fcs_itnim_brp_online(rport->itnim);
if (!BFA_FCS_PID_IS_WKA(rport->pid))
bfa_fcs_rpf_rport_online(rport);
};
@@ -2102,15 +2474,28 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
}
static void
-bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
+bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)
+{
+ if (!BFA_FCS_PID_IS_WKA(rport->pid))
+ bfa_fcs_rpf_rport_offline(rport);
+
+ bfa_fcs_itnim_rport_offline(rport->itnim);
+}
+
+static void
+bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)
{
struct bfa_fcs_lport_s *port = rport->port;
struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
char lpwwn_buf[BFA_STRING_32];
char rpwwn_buf[BFA_STRING_32];
+ if (!rport->bfa_rport) {
+ bfa_fcs_rport_fcs_offline_action(rport);
+ return;
+ }
+
rport->stats.offlines++;
- rport->plogi_pending = BFA_FALSE;
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
wwn2str(rpwwn_buf, rport->pwwn);
@@ -2337,10 +2722,9 @@ 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);
}
-
/*
* brief
* This routine BFA callback for bfa_rport_online() call.
@@ -2413,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
@@ -2508,7 +2934,7 @@ bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
bfa_trc(rport->fcs, rport->pid);
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
if (!fcxp)
return;
len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
@@ -2534,7 +2960,7 @@ bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
bfa_trc(rport->fcs, rx_fchs->s_id);
- fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
+ fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);
if (!fcxp)
return;
@@ -2582,6 +3008,17 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
}
+/*
+ * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation
+ * which limits number of concurrent logins to remote ports
+ */
+void
+bfa_fcs_rport_set_max_logins(u32 max_logins)
+{
+ if (max_logins > 0)
+ bfa_fcs_rport_max_logins = max_logins;
+}
+
void
bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
struct bfa_rport_attr_s *rport_attr)
@@ -2589,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));
@@ -2605,9 +3045,11 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
rport_attr->curr_speed = rport->rpf.rpsc_speed;
rport_attr->assigned_speed = rport->rpf.assigned_speed;
- qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
- qos_attr.qos_flow_id =
- cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
+ if (rport->bfa_rport) {
+ qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
+ qos_attr.qos_flow_id =
+ cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
+ }
rport_attr->qos_attr = qos_attr;
rport_attr->trl_enforced = BFA_FALSE;
@@ -2617,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;
}
}
@@ -2940,10 +3383,11 @@ bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
bfa_trc(rport->fcs, rport->pwwn);
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ fcxp = fcxp_alloced ? fcxp_alloced :
+ bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
if (!fcxp) {
bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
- bfa_fcs_rpf_send_rpsc2, rpf);
+ bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);
return;
}
rpf->fcxp = fcxp;
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 21ad2902e5ce..0116c1032e25 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -92,7 +92,6 @@ static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
enum bfa_ioc_event_e event);
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_debug_save_ftrc(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);
@@ -599,8 +598,9 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
break;
case IOC_E_HWERROR:
+ case IOC_E_HWFAILED:
/*
- * HB failure notification, ignore.
+ * HB failure / HW error notification, ignore.
*/
break;
default:
@@ -632,6 +632,10 @@ bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
break;
+ case IOC_E_HWERROR:
+ /* Ignore - already in hwfail state */
+ break;
+
default:
bfa_sm_fault(ioc, event);
}
@@ -727,8 +731,7 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
/*
* 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.
@@ -1455,7 +1458,7 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
- if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[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]);
@@ -1480,7 +1483,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
- if (fwhdr.signature != drv_fwhdr->signature) {
+ if (fwhdr.signature != cpu_to_le32(drv_fwhdr->signature)) {
bfa_trc(ioc, fwhdr.signature);
bfa_trc(ioc, drv_fwhdr->signature);
return BFA_FALSE;
@@ -1704,7 +1707,7 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
* write smem
*/
bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
- fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
+ cpu_to_le32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]));
loff += sizeof(u32);
@@ -1747,6 +1750,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);
}
@@ -2260,6 +2264,12 @@ bfa_ioc_disable(struct bfa_ioc_s *ioc)
bfa_fsm_send_event(ioc, IOC_E_DISABLE);
}
+void
+bfa_ioc_suspend(struct bfa_ioc_s *ioc)
+{
+ ioc->dbg_fwsave_once = BFA_TRUE;
+ bfa_fsm_send_event(ioc, IOC_E_HWERROR);
+}
/*
* Initialize memory for saving firmware trace. Driver must initialize
@@ -2269,7 +2279,7 @@ void
bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
{
ioc->dbg_fwsave = dbg_fwsave;
- ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+ ioc->dbg_fwsave_len = BFA_DBG_FWTRC_LEN;
}
/*
@@ -2487,6 +2497,9 @@ 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;
}
enum bfa_ioc_type_e
@@ -2856,7 +2869,7 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
/*
* Save firmware trace if configured.
*/
-static void
+void
bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
{
int tlen;
@@ -2913,7 +2926,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;
@@ -3006,7 +3019,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];
@@ -3017,8 +3029,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);
}
}
}
@@ -3160,7 +3174,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;
@@ -3184,7 +3199,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);
@@ -3284,8 +3300,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;
@@ -3307,7 +3323,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;
@@ -4670,22 +4687,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;
}
@@ -4914,6 +4934,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);
@@ -5605,7 +5626,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,
@@ -5645,7 +5666,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);
@@ -5843,7 +5864,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)
@@ -5851,6 +5871,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);
}
@@ -5935,3 +5956,448 @@ 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;
+
+ 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)
+{
+ 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)
+ 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;
+
+ 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)
+ 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)
+ *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);
+ }
+}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 7b916e04ca56..23a90e7b7107 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -702,6 +702,55 @@ 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;
+};
+
+#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);
+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 +765,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 +788,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 +813,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)
@@ -820,6 +873,7 @@ void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);
void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
void bfa_ioc_detach(struct bfa_ioc_s *ioc);
+void bfa_ioc_suspend(struct bfa_ioc_s *ioc);
void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
enum bfi_pcifn_class clscode);
void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa);
@@ -866,6 +920,7 @@ bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event);
bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
+void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
/*
* asic block configuration related APIs
@@ -883,12 +938,12 @@ 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,
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 2eb0c6a2938d..de4e726a1263 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -57,13 +57,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 +108,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 +386,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
@@ -759,25 +744,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 +751,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 +781,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 +810,142 @@ 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);
- WARN_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
+ 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;
+
+ 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);
+
+ }
}
/*
* 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;
}
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index 2d36e4823835..a14c784ff3fc 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 */
};
/*
@@ -121,6 +122,7 @@ struct bfa_s {
bfa_boolean_t fcs; /* FCS is attached to BFA */
struct bfa_msix_s msix;
int bfa_aen_seq;
+ bfa_boolean_t intr_enabled; /* Status of interrupts */
};
extern bfa_boolean_t bfa_auto_recover;
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index 95e4ad8759ac..8ea7697deb9b 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 947f897328d6..2fcab6bc6280 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 2e856e6710f7..299c1c889b33 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -67,6 +67,9 @@ 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 */
};
/*
@@ -197,6 +200,10 @@ 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_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 +233,8 @@ 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_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
};
@@ -440,9 +449,11 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
- INIT_LIST_HEAD(&mod->fcxp_free_q);
+ INIT_LIST_HEAD(&mod->fcxp_req_free_q);
+ INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
INIT_LIST_HEAD(&mod->fcxp_active_q);
- INIT_LIST_HEAD(&mod->fcxp_unused_q);
+ INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
+ INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
mod->fcxp_list = fcxp;
@@ -450,7 +461,14 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
fcxp->fcxp_mod = mod;
fcxp->fcxp_tag = i;
- list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+ if (i < (mod->num_fcxps / 2)) {
+ list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
+ fcxp->req_rsp = BFA_TRUE;
+ } else {
+ list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
+ fcxp->req_rsp = BFA_FALSE;
+ }
+
bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
fcxp->reqq_waiting = BFA_FALSE;
@@ -514,7 +532,8 @@ bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
if (!cfg->drvcfg.min_cfg)
mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
- INIT_LIST_HEAD(&mod->wait_q);
+ INIT_LIST_HEAD(&mod->req_wait_q);
+ INIT_LIST_HEAD(&mod->rsp_wait_q);
claim_fcxps_mem(mod);
}
@@ -542,7 +561,8 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)
struct list_head *qe, *qen;
/* Enqueue unused fcxp resources to free_q */
- list_splice_tail_init(&mod->fcxp_unused_q, &mod->fcxp_free_q);
+ list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
+ list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
fcxp = (struct bfa_fcxp_s *) qe;
@@ -559,11 +579,14 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)
}
static struct bfa_fcxp_s *
-bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
+bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
{
struct bfa_fcxp_s *fcxp;
- bfa_q_deq(&fm->fcxp_free_q, &fcxp);
+ if (req)
+ bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
+ else
+ bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
if (fcxp)
list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
@@ -642,7 +665,11 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
struct bfa_fcxp_wqe_s *wqe;
- bfa_q_deq(&mod->wait_q, &wqe);
+ if (fcxp->req_rsp)
+ bfa_q_deq(&mod->req_wait_q, &wqe);
+ else
+ bfa_q_deq(&mod->rsp_wait_q, &wqe);
+
if (wqe) {
bfa_trc(mod->bfa, fcxp->fcxp_tag);
@@ -657,7 +684,11 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
list_del(&fcxp->qe);
- list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+
+ if (fcxp->req_rsp)
+ list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
+ else
+ list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
}
static void
@@ -900,21 +931,23 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
* Address (given the sge index).
* @param[in] get_rsp_sglen function ptr to be called to get a response SG
* len (given the sge index).
+ * @param[in] req Allocated FCXP is used to send req or rsp?
+ * request - BFA_TRUE, response - BFA_FALSE
*
* @return FCXP instance. NULL on failure.
*/
struct bfa_fcxp_s *
-bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
- int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
- bfa_fcxp_get_sglen_t req_sglen_cbfn,
- bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
- bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
+ int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+ bfa_fcxp_get_sglen_t req_sglen_cbfn,
+ bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+ bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
{
struct bfa_fcxp_s *fcxp = NULL;
WARN_ON(bfa == NULL);
- fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
+ fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
if (fcxp == NULL)
return NULL;
@@ -1071,17 +1104,20 @@ bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
}
void
-bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
void *caller, int nreq_sgles,
int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
bfa_fcxp_get_sglen_t req_sglen_cbfn,
bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
- bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+ bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
{
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
- WARN_ON(!list_empty(&mod->fcxp_free_q));
+ if (req)
+ WARN_ON(!list_empty(&mod->fcxp_req_free_q));
+ else
+ WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
wqe->alloc_cbfn = alloc_cbfn;
wqe->alloc_cbarg = alloc_cbarg;
@@ -1094,7 +1130,10 @@ bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
wqe->rsp_sga_cbfn = rsp_sga_cbfn;
wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
- list_add_tail(&wqe->qe, &mod->wait_q);
+ if (req)
+ list_add_tail(&wqe->qe, &mod->req_wait_q);
+ else
+ list_add_tail(&wqe->qe, &mod->rsp_wait_q);
}
void
@@ -1102,7 +1141,8 @@ bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
{
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
- WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe));
+ WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
+ !bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
list_del(&wqe->qe);
}
@@ -1153,8 +1193,13 @@ bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
int i;
for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
- bfa_q_deq_tail(&mod->fcxp_free_q, &qe);
- list_add_tail(qe, &mod->fcxp_unused_q);
+ if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
+ bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
+ list_add_tail(qe, &mod->fcxp_req_unused_q);
+ } else {
+ bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
+ list_add_tail(qe, &mod->fcxp_rsp_unused_q);
+ }
}
}
@@ -1208,6 +1253,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);
@@ -1225,6 +1276,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
switch (event) {
case BFA_LPS_SM_FWRSP:
+ case BFA_LPS_SM_OFFLINE:
if (lps->status == BFA_STATUS_OK) {
bfa_sm_set_state(lps, bfa_lps_sm_online);
if (lps->fdisc)
@@ -1253,7 +1305,6 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
bfa_lps_login_comp(lps);
break;
- case BFA_LPS_SM_OFFLINE:
case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
break;
@@ -1404,11 +1455,11 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
switch (event) {
case BFA_LPS_SM_FWRSP:
+ case BFA_LPS_SM_OFFLINE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
bfa_lps_logout_comp(lps);
break;
- case BFA_LPS_SM_OFFLINE:
case BFA_LPS_SM_DELETE:
bfa_sm_set_state(lps, bfa_lps_sm_init);
break;
@@ -1786,6 +1837,8 @@ bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
if (lps->fdisc)
bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+ else
+ bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
}
/*
@@ -2131,6 +2184,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);
}
@@ -2187,6 +2246,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);
}
@@ -2212,11 +2277,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");
@@ -2273,6 +2338,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);
}
@@ -2366,6 +2437,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);
}
@@ -2411,6 +2488,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);
}
@@ -2562,6 +2645,10 @@ 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;
+
default:
bfa_sm_fault(fcport->bfa, event);
}
@@ -2642,6 +2729,81 @@ 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_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
*/
@@ -2905,6 +3067,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
@@ -2915,6 +3078,9 @@ 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;
INIT_LIST_HEAD(&fcport->stats_pending_q);
INIT_LIST_HEAD(&fcport->statsclr_pending_q);
@@ -2958,6 +3124,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)
{
@@ -2967,12 +3148,15 @@ 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;
/*
* update trunk state if applicable
@@ -2981,7 +3165,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);
@@ -3415,6 +3600,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 =
@@ -3430,6 +3616,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;
}
@@ -3438,6 +3626,9 @@ 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;
+
bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
}
break;
@@ -3450,8 +3641,17 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
case BFI_FCPORT_I2H_EVENT:
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:
@@ -3571,6 +3771,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;
@@ -3625,7 +3828,26 @@ 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;
+ break;
+
case BFA_PORT_TOPOLOGY_AUTO:
break;
@@ -3648,6 +3870,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)
{
@@ -3723,9 +3956,11 @@ 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
@@ -3812,8 +4047,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;
@@ -3838,6 +4074,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;
@@ -3867,6 +4107,40 @@ 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_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);
@@ -3943,6 +4217,26 @@ bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
return fcport->cfg.trunked;
}
+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);
+}
+
/*
* Rport State machine functions
*/
@@ -4237,6 +4531,10 @@ bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
break;
+ case BFA_RPORT_SM_OFFLINE:
+ bfa_rport_offline_cb(rp);
+ break;
+
default:
bfa_stats(rp, sm_off_unexp);
bfa_sm_fault(rp->bfa, event);
@@ -4353,6 +4651,7 @@ bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
case BFA_RPORT_SM_HWFAIL:
bfa_stats(rp, sm_offp_hwf);
bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ bfa_rport_offline_cb(rp);
break;
default:
@@ -4664,6 +4963,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);
@@ -4731,8 +5045,10 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
WARN_ON(speed == 0);
WARN_ON(speed == BFA_PORT_SPEED_AUTO);
- rport->rport_info.speed = speed;
- bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
+ if (rport) {
+ rport->rport_info.speed = speed;
+ bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
+ }
}
/* Set Rport LUN Mask */
@@ -5303,6 +5619,37 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
}
/*
+ * Dport forward declaration
+ */
+
+/*
+ * 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 */
+};
+
+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_qresume(void *cbarg);
+static void bfa_dport_req_comp(struct bfa_dport_s *dport,
+ bfi_diag_dport_rsp_t *msg);
+
+/*
* BFA fcdiag module
*/
#define BFA_DIAG_QTEST_TOV 1000 /* msec */
@@ -5332,15 +5679,24 @@ 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;
}
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;
@@ -5348,6 +5704,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
@@ -5532,6 +5890,9 @@ 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, (bfi_diag_dport_rsp_t *)msg);
+ break;
default:
bfa_trc(fcdiag, msg->mhdr.msg_id);
WARN_ON(1);
@@ -5601,12 +5962,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 ||
@@ -5719,3 +6086,379 @@ 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
+ */
+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;
+
+ 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:
+ 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_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
+{
+ bfa_trc(dport->bfa, event);
+
+ switch (event) {
+ case BFA_DPORT_SM_ENABLE:
+ /* Already enabled */
+ 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;
+
+ 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;
+
+ 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:
+ 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;
+
+ 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;
+
+ /*
+ * Increment message tag before queue check, so that responses to old
+ * requests are discarded.
+ */
+ dport->msgtag++;
+
+ /*
+ * 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;
+ m->msgtag = dport->msgtag;
+
+ /*
+ * 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, bfi_diag_dport_rsp_t *msg)
+{
+ bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
+ bfa_cb_fcdiag_dport(dport, msg->status);
+}
+
+/*
+ * Dport enable
+ *
+ * @param[in] *bfa - bfa data struct
+ */
+bfa_status_t
+bfa_dport_enable(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;
+
+ /*
+ * 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;
+ }
+
+ /*
+ * 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 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_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)) {
+ 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;
+ }
+
+ 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 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_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))
+ 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;
+}
+
+/*
+ * Get D-port state
+ *
+ * @param[in] *bfa - bfa data struct
+ */
+
+bfa_status_t
+bfa_dport_get_state(struct bfa_s *bfa, enum bfa_dport_state *state)
+{
+ struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+ struct bfa_dport_s *dport = &fcdiag->dport;
+
+ if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled))
+ *state = BFA_DPORT_ST_ENABLED;
+ else if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait))
+ *state = BFA_DPORT_ST_ENABLING;
+ else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled))
+ *state = BFA_DPORT_ST_DISABLED;
+ else if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) ||
+ bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait))
+ *state = BFA_DPORT_ST_DISABLING;
+ else {
+ bfa_trc(dport->bfa, BFA_STATUS_EINVAL);
+ return BFA_STATUS_EINVAL;
+ }
+ return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index f30067564639..8d7fbecfcb22 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -97,10 +97,13 @@ struct bfa_fcxp_mod_s {
struct bfa_s *bfa; /* backpointer to BFA */
struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */
u16 num_fcxps; /* max num FCXP requests */
- struct list_head fcxp_free_q; /* free FCXPs */
- struct list_head fcxp_active_q; /* active FCXPs */
- struct list_head wait_q; /* wait queue for free fcxp */
- struct list_head fcxp_unused_q; /* unused fcxps */
+ struct list_head fcxp_req_free_q; /* free FCXPs used for sending req */
+ struct list_head fcxp_rsp_free_q; /* free FCXPs used for sending req */
+ struct list_head fcxp_active_q; /* active FCXPs */
+ struct list_head req_wait_q; /* wait queue for free req_fcxp */
+ struct list_head rsp_wait_q; /* wait queue for free rsp_fcxp */
+ struct list_head fcxp_req_unused_q; /* unused req_fcxps */
+ struct list_head fcxp_rsp_unused_q; /* unused rsp_fcxps */
u32 req_pld_sz;
u32 rsp_pld_sz;
struct bfa_mem_dma_s dma_seg[BFA_FCXP_DMA_SEGS];
@@ -197,6 +200,7 @@ struct bfa_fcxp_s {
struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
struct bfa_reqq_wait_s reqq_wqe;
bfa_boolean_t reqq_waiting;
+ bfa_boolean_t req_rsp; /* Used to track req/rsp fcxp */
};
struct bfa_fcxp_wqe_s {
@@ -470,8 +474,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,6 +514,7 @@ struct bfa_fcport_s {
struct bfa_fcport_trunk_s trunk;
u16 fcoe_vlan;
struct bfa_mem_dma_s fcport_dma;
+ bfa_boolean_t stats_dma_ready;
};
#define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport)
@@ -530,6 +537,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);
@@ -543,6 +551,9 @@ 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_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);
@@ -556,6 +567,8 @@ 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);
@@ -571,6 +584,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);
@@ -586,20 +602,22 @@ void bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
/*
* bfa fcxp API functions
*/
-struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
+struct bfa_fcxp_s *bfa_fcxp_req_rsp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
int nreq_sgles, int nrsp_sgles,
bfa_fcxp_get_sgaddr_t get_req_sga,
bfa_fcxp_get_sglen_t get_req_sglen,
bfa_fcxp_get_sgaddr_t get_rsp_sga,
- bfa_fcxp_get_sglen_t get_rsp_sglen);
-void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+ bfa_fcxp_get_sglen_t get_rsp_sglen,
+ bfa_boolean_t req);
+void bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
bfa_fcxp_alloc_cbfn_t alloc_cbfn,
void *cbarg, void *bfad_fcxp,
int nreq_sgles, int nrsp_sgles,
bfa_fcxp_get_sgaddr_t get_req_sga,
bfa_fcxp_get_sglen_t get_req_sglen,
bfa_fcxp_get_sgaddr_t get_rsp_sga,
- bfa_fcxp_get_sglen_t get_rsp_sglen);
+ bfa_fcxp_get_sglen_t get_rsp_sglen,
+ bfa_boolean_t req);
void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
struct bfa_fcxp_wqe_s *wqe);
void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
@@ -658,6 +676,7 @@ u8 bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag);
u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);
void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
@@ -690,11 +709,21 @@ 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 */
+ u32 msgtag; /* firmware msg tag for reply */
+ struct bfa_reqq_wait_s reqq_wait;
+ bfa_cb_diag_t cbfn;
+ void *cbarg;
+};
+
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)
@@ -710,5 +739,11 @@ 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, 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_get_state(struct bfa_s *bfa,
+ enum bfa_dport_state *state);
#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 2c8f0c713076..895b0e516e07 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -57,14 +57,15 @@ int pcie_max_read_reqsz;
int bfa_debugfs_enable = 1;
int msix_disable_cb = 0, msix_disable_ct = 0;
int max_xfer_size = BFAD_MAX_SECTORS >> 1;
+int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
/* Firmware releated */
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.1.0.0.bin"
+#define BFAD_FW_FILE_CT "ctfw-3.1.0.0.bin"
+#define BFAD_FW_FILE_CT2 "ct2fw-3.1.0.0.bin"
static u32 *bfad_load_fwimg(struct pci_dev *pdev);
static void bfad_free_fwimg(void);
@@ -148,6 +149,8 @@ MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
module_param(max_xfer_size, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(max_xfer_size, "default=32MB,"
" Range[64k|128k|256k|512k|1024k|2048k]");
+module_param(max_rport_logins, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_rport_logins, "Max number of logins to initiator and target rports on a port (physical/logical), default=1024");
static void
bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
@@ -736,6 +739,9 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
}
}
+ /* Enable PCIE Advanced Error Recovery (AER) if kernel supports */
+ pci_enable_pcie_error_reporting(pdev);
+
bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2));
@@ -806,6 +812,8 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
}
}
+ pci_save_state(pdev);
+
return 0;
out_release_region:
@@ -822,6 +830,8 @@ bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
pci_iounmap(pdev, bfad->pci_bar0_kva);
pci_iounmap(pdev, bfad->pci_bar2_kva);
pci_release_regions(pdev);
+ /* Disable PCIE Advanced Error Recovery (AER) */
+ pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
}
@@ -1258,6 +1268,16 @@ bfad_setup_intr(struct bfad_s *bfad)
error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
if (error) {
+ /* In CT1 & CT2, try to allocate just one vector */
+ if (bfa_asic_id_ctc(pdev->device)) {
+ printk(KERN_WARNING "bfa %s: trying one msix "
+ "vector failed to allocate %d[%d]\n",
+ bfad->pci_name, bfad->nvec, error);
+ bfad->nvec = 1;
+ error = pci_enable_msix(bfad->pcidev,
+ msix_entries, bfad->nvec);
+ }
+
/*
* Only error number of vector is available.
* We don't have a mechanism to map multiple
@@ -1267,12 +1287,13 @@ bfad_setup_intr(struct bfad_s *bfad)
* vectors. Linux doesn't duplicate vectors
* in the MSIX table for this case.
*/
-
- printk(KERN_WARNING "bfad%d: "
- "pci_enable_msix failed (%d),"
- " use line based.\n", bfad->inst_no, error);
-
- goto line_based;
+ if (error) {
+ printk(KERN_WARNING "bfad%d: "
+ "pci_enable_msix failed (%d), "
+ "use line based.\n",
+ bfad->inst_no, error);
+ goto line_based;
+ }
}
/* Disable INTX in MSI-X mode */
@@ -1470,6 +1491,197 @@ bfad_pci_remove(struct pci_dev *pdev)
kfree(bfad);
}
+/*
+ * PCI Error Recovery entry, error detected.
+ */
+static pci_ers_result_t
+bfad_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+ struct bfad_s *bfad = pci_get_drvdata(pdev);
+ unsigned long flags;
+ pci_ers_result_t ret = PCI_ERS_RESULT_NONE;
+
+ dev_printk(KERN_ERR, &pdev->dev,
+ "error detected state: %d - flags: 0x%x\n",
+ state, bfad->bfad_flags);
+
+ switch (state) {
+ case pci_channel_io_normal: /* non-fatal error */
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfad->bfad_flags &= ~BFAD_EEH_BUSY;
+ /* Suspend/fail all bfa operations */
+ bfa_ioc_suspend(&bfad->bfa.ioc);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ del_timer_sync(&bfad->hal_tmo);
+ ret = PCI_ERS_RESULT_CAN_RECOVER;
+ break;
+ case pci_channel_io_frozen: /* fatal error */
+ init_completion(&bfad->comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfad->bfad_flags |= BFAD_EEH_BUSY;
+ /* Suspend/fail all bfa operations */
+ bfa_ioc_suspend(&bfad->bfa.ioc);
+ bfa_fcs_stop(&bfad->bfa_fcs);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ wait_for_completion(&bfad->comp);
+
+ bfad_remove_intr(bfad);
+ del_timer_sync(&bfad->hal_tmo);
+ pci_disable_device(pdev);
+ ret = PCI_ERS_RESULT_NEED_RESET;
+ break;
+ case pci_channel_io_perm_failure: /* PCI Card is DEAD */
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfad->bfad_flags |= BFAD_EEH_BUSY |
+ BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ /* If the error_detected handler is called with the reason
+ * pci_channel_io_perm_failure - it will subsequently call
+ * pci_remove() entry point to remove the pci device from the
+ * system - So defer the cleanup to pci_remove(); cleaning up
+ * here causes inconsistent state during pci_remove().
+ */
+ ret = PCI_ERS_RESULT_DISCONNECT;
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ return ret;
+}
+
+int
+restart_bfa(struct bfad_s *bfad)
+{
+ unsigned long flags;
+ struct pci_dev *pdev = bfad->pcidev;
+
+ bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg,
+ &bfad->meminfo, &bfad->hal_pcidev);
+
+ /* Enable Interrupt and wait bfa_init completion */
+ 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);
+ return -1;
+ }
+
+ init_completion(&bfad->comp);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_iocfc_init(&bfad->bfa);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ /* Set up interrupt handler for each vectors */
+ if ((bfad->bfad_flags & BFAD_MSIX_ON) &&
+ bfad_install_msix_handler(bfad))
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "%s: install_msix failed.\n", bfad->pci_name);
+
+ bfad_init_timer(bfad);
+ wait_for_completion(&bfad->comp);
+ bfad_drv_start(bfad);
+
+ return 0;
+}
+
+/*
+ * PCI Error Recovery entry, re-initialize the chip.
+ */
+static pci_ers_result_t
+bfad_pci_slot_reset(struct pci_dev *pdev)
+{
+ struct bfad_s *bfad = pci_get_drvdata(pdev);
+ u8 byte;
+
+ dev_printk(KERN_ERR, &pdev->dev,
+ "bfad_pci_slot_reset flags: 0x%x\n", bfad->bfad_flags);
+
+ if (pci_enable_device(pdev)) {
+ dev_printk(KERN_ERR, &pdev->dev, "Cannot re-enable "
+ "PCI device after reset.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_restore_state(pdev);
+
+ /*
+ * Read some byte (e.g. DMA max. payload size which can't
+ * be 0xff any time) to make sure - we did not hit another PCI error
+ * in the middle of recovery. If we did, then declare permanent failure.
+ */
+ pci_read_config_byte(pdev, 0x68, &byte);
+ if (byte == 0xff) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "slot_reset failed ... got another PCI error !\n");
+ goto out_disable_device;
+ }
+
+ pci_save_state(pdev);
+ pci_set_master(pdev);
+
+ if (pci_set_dma_mask(bfad->pcidev, DMA_BIT_MASK(64)) != 0)
+ if (pci_set_dma_mask(bfad->pcidev, DMA_BIT_MASK(32)) != 0)
+ goto out_disable_device;
+
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+
+ if (restart_bfa(bfad) == -1)
+ goto out_disable_device;
+
+ pci_enable_pcie_error_reporting(pdev);
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "slot_reset completed flags: 0x%x!\n", bfad->bfad_flags);
+
+ return PCI_ERS_RESULT_RECOVERED;
+
+out_disable_device:
+ pci_disable_device(pdev);
+ return PCI_ERS_RESULT_DISCONNECT;
+}
+
+static pci_ers_result_t
+bfad_pci_mmio_enabled(struct pci_dev *pdev)
+{
+ unsigned long flags;
+ struct bfad_s *bfad = pci_get_drvdata(pdev);
+
+ dev_printk(KERN_INFO, &pdev->dev, "mmio_enabled\n");
+
+ /* Fetch FW diagnostic information */
+ bfa_ioc_debug_save_ftrc(&bfad->bfa.ioc);
+
+ /* Cancel all pending IOs */
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ init_completion(&bfad->comp);
+ bfa_fcs_stop(&bfad->bfa_fcs);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ wait_for_completion(&bfad->comp);
+
+ bfad_remove_intr(bfad);
+ del_timer_sync(&bfad->hal_tmo);
+ pci_disable_device(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static void
+bfad_pci_resume(struct pci_dev *pdev)
+{
+ unsigned long flags;
+ struct bfad_s *bfad = pci_get_drvdata(pdev);
+
+ dev_printk(KERN_WARNING, &pdev->dev, "resume\n");
+
+ /* wait until the link is online */
+ bfad_rport_online_wait(bfad);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfad->bfad_flags &= ~BFAD_EEH_BUSY;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
struct pci_device_id bfad_id_table[] = {
{
.vendor = BFA_PCI_VENDOR_ID_BROCADE,
@@ -1513,11 +1725,22 @@ struct pci_device_id bfad_id_table[] = {
MODULE_DEVICE_TABLE(pci, bfad_id_table);
+/*
+ * PCI error recovery handlers.
+ */
+static struct pci_error_handlers bfad_err_handler = {
+ .error_detected = bfad_pci_error_detected,
+ .slot_reset = bfad_pci_slot_reset,
+ .mmio_enabled = bfad_pci_mmio_enabled,
+ .resume = bfad_pci_resume,
+};
+
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),
+ .err_handler = &bfad_err_handler,
};
/*
@@ -1546,6 +1769,7 @@ bfad_init(void)
bfa_auto_recover = ioc_auto_recover;
bfa_fcs_rport_set_del_timeout(rport_del_timeout);
+ bfa_fcs_rport_set_max_logins(max_rport_logins);
error = pci_register_driver(&bfad_pci_driver);
if (error) {
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index b83927440171..72f5dc32cc12 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -587,6 +587,37 @@ bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable)
return 0;
}
+void
+bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
+{
+ struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data;
+ struct bfad_im_port_s *im_port =
+ (struct bfad_im_port_s *)vport->drv_port.im_port;
+ struct bfad_s *bfad = im_port->bfad;
+ struct Scsi_Host *vshost = vport->drv_port.im_port->shost;
+ char *sym_name = fc_vport->symbolic_name;
+ struct bfa_fcs_vport_s *fcs_vport;
+ wwn_t pwwn;
+ unsigned long flags;
+
+ u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (fcs_vport == NULL)
+ 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);
+ }
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
struct fc_function_template bfad_im_fc_function_template = {
/* Target dynamic attributes */
@@ -640,6 +671,7 @@ struct fc_function_template bfad_im_fc_function_template = {
.vport_create = bfad_im_vport_create,
.vport_delete = bfad_im_vport_delete,
.vport_disable = bfad_im_vport_disable,
+ .set_vport_symbolic_name = bfad_im_vport_set_symbolic_name,
.bsg_request = bfad_im_bsg_request,
.bsg_timeout = bfad_im_bsg_timeout,
};
@@ -792,6 +824,13 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 16Gbps PCIe dual port FC HBA");
+ } else if (!strcmp(model, "Brocade-1867")) {
+ if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 16Gbps PCIe single port FC HBA for IBM");
+ else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 16Gbps PCIe dual port FC HBA for IBM");
} else
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Invalid Model");
@@ -909,15 +948,16 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,
struct bfad_port_s *port = im_port->port;
struct bfad_s *bfad = im_port->bfad;
int nrports = 2048;
- wwn_t *rports = NULL;
+ struct bfa_rport_qualifier_s *rports = NULL;
unsigned long flags;
- rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
+ rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports,
+ GFP_ATOMIC);
if (rports == NULL)
return snprintf(buf, PAGE_SIZE, "Failed\n");
spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports);
+ bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
kfree(rports);
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 9c1495b321d9..555e7db94a1c 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;
@@ -535,7 +542,8 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
if (bfad_chk_iocmd_sz(payload_len,
sizeof(struct bfa_bsg_lport_get_rports_s),
- sizeof(wwn_t) * iocmd->nrports) != BFA_STATUS_OK) {
+ sizeof(struct bfa_rport_qualifier_s) * iocmd->nrports)
+ != BFA_STATUS_OK) {
iocmd->status = BFA_STATUS_VERSION_FAIL;
return 0;
}
@@ -552,8 +560,9 @@ bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
goto out;
}
- bfa_fcs_lport_get_rports(fcs_port, (wwn_t *)iocmd_bufptr,
- &iocmd->nrports);
+ bfa_fcs_lport_get_rport_quals(fcs_port,
+ (struct bfa_rport_qualifier_s *)iocmd_bufptr,
+ &iocmd->nrports);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
iocmd->status = BFA_STATUS_OK;
out:
@@ -578,7 +587,11 @@ bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd)
goto out;
}
- fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
+ if (iocmd->pid)
+ fcs_rport = bfa_fcs_lport_get_rport_by_qualifier(fcs_port,
+ iocmd->rpwwn, iocmd->pid);
+ else
+ fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
if (fcs_rport == NULL) {
bfa_trc(bfad, 0);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -671,9 +684,11 @@ bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd)
memcpy((void *)&iocmd->stats, (void *)&fcs_rport->stats,
sizeof(struct bfa_rport_stats_s));
- memcpy((void *)&iocmd->stats.hal_stats,
- (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats),
- sizeof(struct bfa_rport_hal_stats_s));
+ if (bfa_fcs_rport_get_halrport(fcs_rport)) {
+ memcpy((void *)&iocmd->stats.hal_stats,
+ (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats),
+ sizeof(struct bfa_rport_hal_stats_s));
+ }
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
iocmd->status = BFA_STATUS_OK;
@@ -709,7 +724,8 @@ bfad_iocmd_rport_clr_stats(struct bfad_s *bfad, void *cmd)
memset((char *)&fcs_rport->stats, 0, sizeof(struct bfa_rport_stats_s));
rport = bfa_fcs_rport_get_halrport(fcs_rport);
- memset(&rport->stats, 0, sizeof(rport->stats));
+ if (rport)
+ memset(&rport->stats, 0, sizeof(rport->stats));
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
iocmd->status = BFA_STATUS_OK;
out:
@@ -744,7 +760,8 @@ bfad_iocmd_rport_set_speed(struct bfad_s *bfad, void *cmd)
fcs_rport->rpf.assigned_speed = iocmd->speed;
/* Set this speed in f/w only if the RPSC speed is not available */
if (fcs_rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
- bfa_rport_speed(fcs_rport->bfa_rport, iocmd->speed);
+ if (fcs_rport->bfa_rport)
+ bfa_rport_speed(fcs_rport->bfa_rport, iocmd->speed);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
iocmd->status = BFA_STATUS_OK;
out:
@@ -870,6 +887,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;
@@ -878,16 +908,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;
}
@@ -909,8 +945,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;
@@ -1030,9 +1071,10 @@ bfad_iocmd_itnim_get_iostats(struct bfad_s *bfad, void *cmd)
iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
else {
iocmd->status = BFA_STATUS_OK;
- memcpy((void *)&iocmd->iostats, (void *)
- &(bfa_fcs_itnim_get_halitn(itnim)->stats),
- sizeof(struct bfa_itnim_iostats_s));
+ if (bfa_fcs_itnim_get_halitn(itnim))
+ memcpy((void *)&iocmd->iostats, (void *)
+ &(bfa_fcs_itnim_get_halitn(itnim)->stats),
+ sizeof(struct bfa_itnim_iostats_s));
}
}
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -1156,8 +1198,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;
@@ -1200,8 +1242,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)
@@ -1725,6 +1767,52 @@ bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
}
int
+bfad_iocmd_diag_cfg_dport(struct bfad_s *bfad, unsigned int cmd, 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);
+ if (cmd == IOCMD_DIAG_DPORT_ENABLE)
+ iocmd->status = bfa_dport_enable(&bfad->bfa,
+ bfad_hcb_comp, &fcomp);
+ else if (cmd == IOCMD_DIAG_DPORT_DISABLE)
+ iocmd->status = bfa_dport_disable(&bfad->bfa,
+ bfad_hcb_comp, &fcomp);
+ else {
+ bfa_trc(bfad, 0);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return -EINVAL;
+ }
+ 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_get_state(struct bfad_s *bfad, void *pcmd)
+{
+ struct bfa_bsg_diag_dport_get_state_s *iocmd =
+ (struct bfa_bsg_diag_dport_get_state_s *)pcmd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_dport_get_state(&bfad->bfa, &iocmd->state);
+ 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 =
@@ -2041,7 +2129,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);
@@ -2063,7 +2151,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);
@@ -2150,22 +2238,31 @@ 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))
+ return BFA_STATUS_DPORT_ERR;
+
+ 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);
- 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;
}
@@ -2178,12 +2275,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;
}
@@ -2196,14 +2298,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;
}
@@ -2215,11 +2325,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;
}
@@ -2263,6 +2383,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,
@@ -2270,7 +2391,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);
@@ -2289,6 +2414,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,
@@ -2296,7 +2422,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);
@@ -2424,6 +2554,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);
+ 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)
@@ -2649,6 +2912,13 @@ 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:
+ case IOCMD_DIAG_DPORT_DISABLE:
+ rc = bfad_iocmd_diag_cfg_dport(bfad, cmd, iocmd);
+ break;
+ case IOCMD_DIAG_DPORT_GET_STATE:
+ rc = bfad_iocmd_diag_dport_get_state(bfad, iocmd);
+ break;
case IOCMD_PHY_GET_ATTR:
rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
break;
@@ -2730,6 +3000,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;
@@ -2748,6 +3021,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;
@@ -2949,13 +3245,13 @@ bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
spin_lock_irqsave(&bfad->bfad_lock, flags);
/* Allocate bfa_fcxp structure */
- hal_fcxp = bfa_fcxp_alloc(drv_fcxp, &bfad->bfa,
+ hal_fcxp = bfa_fcxp_req_rsp_alloc(drv_fcxp, &bfad->bfa,
drv_fcxp->num_req_sgles,
drv_fcxp->num_rsp_sgles,
bfad_fcxp_get_req_sgaddr_cb,
bfad_fcxp_get_req_sglen_cb,
bfad_fcxp_get_rsp_sgaddr_cb,
- bfad_fcxp_get_rsp_sglen_cb);
+ bfad_fcxp_get_rsp_sglen_cb, BFA_TRUE);
if (!hal_fcxp) {
bfa_trc(bfad, 0);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index 17ad67283130..15e1fc8e796b 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -141,6 +141,17 @@ enum {
IOCMD_FCPIM_LUNMASK_QUERY,
IOCMD_FCPIM_LUNMASK_ADD,
IOCMD_FCPIM_LUNMASK_DELETE,
+ IOCMD_DIAG_DPORT_ENABLE,
+ IOCMD_DIAG_DPORT_DISABLE,
+ IOCMD_DIAG_DPORT_GET_STATE,
+ 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,
};
struct bfa_bsg_gen_s {
@@ -319,6 +330,8 @@ struct bfa_bsg_rport_attr_s {
u16 vf_id;
wwn_t pwwn;
wwn_t rpwwn;
+ u32 pid;
+ u32 rsvd;
struct bfa_rport_attr_s attr;
};
@@ -461,7 +474,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];
@@ -611,6 +625,13 @@ struct bfa_bsg_diag_lb_stat_s {
u16 rsvd;
};
+struct bfa_bsg_diag_dport_get_state_s {
+ bfa_status_t status;
+ u16 bfad_num;
+ u16 rsvd;
+ enum bfa_dport_state state;
+};
+
struct bfa_bsg_phy_attr_s {
bfa_status_t status;
u16 bfad_num;
@@ -692,6 +713,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;
@@ -720,6 +748,41 @@ 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 rsvd;
+ u32 offset;
+ u32 len;
+ u8 data[BFA_MAX_FRUVPD_TRANSFER_SIZE];
+};
+
+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;
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 7f74f1d19124..0c64a04f01fa 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -37,6 +37,7 @@
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
+#include <linux/aer.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
@@ -56,7 +57,7 @@
#ifdef BFA_DRIVER_VERSION
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
#else
-#define BFAD_DRIVER_VERSION "3.0.23.0"
+#define BFAD_DRIVER_VERSION "3.1.2.1"
#endif
#define BFAD_PROTO_NAME FCPI_NAME
@@ -81,6 +82,8 @@
#define BFAD_FC4_PROBE_DONE 0x00000200
#define BFAD_PORT_DELETE 0x00000001
#define BFAD_INTX_ON 0x00000400
+#define BFAD_EEH_BUSY 0x00000800
+#define BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE 0x00001000
/*
* BFAD related definition
*/
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 2eebf8d4d58b..8f92732655c7 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1216,6 +1216,15 @@ bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd
return 0;
}
+ if (bfad->bfad_flags & BFAD_EEH_BUSY) {
+ if (bfad->bfad_flags & BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE)
+ cmnd->result = DID_NO_CONNECT << 16;
+ else
+ cmnd->result = DID_REQUEUE << 16;
+ done(cmnd);
+ return 0;
+ }
+
sg_cnt = scsi_dma_map(cmnd);
if (sg_cnt < 0)
return SCSI_MLQUEUE_HOST_BUSY;
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index b2ba0b2e91b2..57b146bca18c 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -210,7 +210,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
@@ -288,6 +289,9 @@ 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 */
};
/*
@@ -687,7 +691,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 +962,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 +972,7 @@ 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),
};
#define BFI_DIAG_MAX_SGES 2
@@ -1052,6 +1059,23 @@ 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 */
+};
+
+struct bfi_diag_dport_req_s {
+ struct bfi_mhdr_s mh; /* 4 bytes */
+ u8 req; /* request 1: enable 0: disable */
+ u8 status; /* reply status */
+ u8 rsvd[2];
+ u32 msgtag; /* msgtag for reply */
+};
+#define bfi_diag_dport_rsp_t struct bfi_diag_dport_req_s
+
+/*
* PHY module specific
*/
enum bfi_phy_h2i_msgs_e {
@@ -1147,6 +1171,50 @@ 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[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 d4220e13cafa..5ae2c167b2c8 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -426,6 +426,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 {
@@ -499,6 +500,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 +555,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 +575,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 +841,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 ed5f159e1867..99133bcf53f9 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
*/