From b480a32e69b7b3c88c8459c229146f1d47763a02 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Fri, 21 Sep 2012 17:25:20 -0700 Subject: [SCSI] bfa: Fix few attributes in the RHBA CT passthru command - Made changes to set the RHBA command max payload based on the port configured frame size. - Made changes to fix the driver/fw version size in FMDI structure. - Fix to pass the fw version for FDMI attribute type FDMI_HBA_ATTRIB_FW_VERSION rather than driver version. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/bfa/bfa_ioc.h') diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index b2856f96567c..f16ebc92d1ef 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -761,7 +761,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) -- cgit v1.2.3 From 7ace27ae28a5fa67fa3d25f31d1111991c81e015 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Fri, 21 Sep 2012 17:26:41 -0700 Subject: [SCSI] bfa: Add support for IO throttling at port level Add capability to limit the number of exchanges on a port to avoid queue-full conditions from the target side. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_core.c | 9 +++- drivers/scsi/bfa/bfa_defs_svc.h | 13 +++++ drivers/scsi/bfa/bfa_fcpim.c | 105 +++++++++++++++++++++++++++++++++++++-- drivers/scsi/bfa/bfa_fcpim.h | 9 +++- drivers/scsi/bfa/bfa_fcs_rport.c | 6 ++- drivers/scsi/bfa/bfa_ioc.h | 3 ++ drivers/scsi/bfa/bfad_bsg.c | 36 ++++++++++++++ drivers/scsi/bfa/bfad_bsg.h | 9 ++++ 8 files changed, 182 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/bfa/bfa_ioc.h') diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 837879de72c3..eb296286c37e 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -983,7 +983,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); @@ -1245,10 +1246,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); } diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index 18e4f6ba70d2..0e37e233ebc5 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -875,6 +875,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 */ diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 4118d84be6eb..27b560962357 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -3703,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; @@ -3725,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); @@ -3763,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 @@ -3837,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 b81d51cfe2bb..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)) @@ -150,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; @@ -157,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; }; /* @@ -418,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_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index e90800d0557a..58ac643ba9f3 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -3026,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)); @@ -3056,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; } } diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index f16ebc92d1ef..8e267246c1a5 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -716,6 +716,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 +739,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); diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 90c40e4e2d4b..6e1478ae6251 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -2547,6 +2547,36 @@ 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; +} + static int bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, unsigned int payload_len) @@ -2881,6 +2911,12 @@ 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; default: rc = -EINVAL; break; diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index b67a2292cff3..37922b96079b 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -145,6 +145,8 @@ enum { IOCMD_DIAG_DPORT_DISABLE, IOCMD_DIAG_DPORT_GET_STATE, IOCMD_QOS_SET_BW, + IOCMD_FCPIM_THROTTLE_QUERY, + IOCMD_FCPIM_THROTTLE_SET }; struct bfa_bsg_gen_s { @@ -740,6 +742,13 @@ 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; +}; + struct bfa_bsg_fcpt_s { bfa_status_t status; u16 vf_id; -- cgit v1.2.3 From 1a1297c644b38d2edfef3004bcc6f9c0084b43a9 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Fri, 21 Sep 2012 17:26:50 -0700 Subject: [SCSI] bfa: Add support to configure min/max bandwidth for a pcifn - Added support to configure minimum bandwidth for a pcifn. - Minimum bandwith is guaranteed at per queue level. - Added support to update pcifn bandwidth dynamically without a server reboot. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_core.c | 9 +++++---- drivers/scsi/bfa/bfa_defs.h | 4 +++- drivers/scsi/bfa/bfa_ioc.c | 20 ++++++++++++-------- drivers/scsi/bfa/bfa_ioc.h | 8 ++++---- drivers/scsi/bfa/bfad_bsg.c | 20 +++++++++++++------- drivers/scsi/bfa/bfad_bsg.h | 3 ++- drivers/scsi/bfa/bfi.h | 3 ++- 7 files changed, 41 insertions(+), 26 deletions(-) (limited to 'drivers/scsi/bfa/bfa_ioc.h') diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index eb296286c37e..89ebd4459bfc 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -838,19 +838,20 @@ void bfa_isr_enable(struct bfa_s *bfa) { u32 umsk; - int pci_func = bfa_ioc_pcifn(&bfa->ioc); + int port_id = bfa_ioc_portid(&bfa->ioc); - bfa_trc(bfa, pci_func); + bfa_trc(bfa, bfa_ioc_pcifn(&bfa->ioc)); + bfa_trc(bfa, port_id); bfa_msix_ctrl_install(bfa); if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) { umsk = __HFN_INT_ERR_MASK_CT2; - umsk |= pci_func == 0 ? + umsk |= port_id == 0 ? __HFN_INT_FN0_MASK_CT2 : __HFN_INT_FN1_MASK_CT2; } else { umsk = __HFN_INT_ERR_MASK; - umsk |= pci_func == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK; + umsk |= port_id == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK; } writel(umsk, bfa->iocfc.bfa_regs.intr_status); diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index f8df2c949786..f0b251e928bf 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -190,6 +190,7 @@ enum bfa_status { 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 */ @@ -749,7 +750,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 { diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 4fbff0394985..c697890eeca8 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -3019,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]; @@ -3030,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); } } } @@ -3173,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; @@ -3197,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); @@ -3297,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; @@ -3320,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; diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 8e267246c1a5..0ad221abfc8f 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -889,12 +889,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/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 6e1478ae6251..0ab1d400ac33 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; @@ -1191,8 +1197,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; @@ -1235,8 +1241,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) @@ -2122,7 +2128,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); @@ -2144,7 +2150,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); diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index 37922b96079b..e48dcca0d7fa 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -469,7 +469,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]; diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index 6f1dd9eac1d1..9c9861f8e6ce 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -690,7 +690,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 */ -- cgit v1.2.3 From e6826c96ced7ea8161b2bae52686c99f6fbf8643 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Fri, 21 Sep 2012 17:27:14 -0700 Subject: [SCSI] bfa: Add support to read/update the FRU data. - Add FRU sub-module to support FRU read/write/update. - Add support to read/write from the temp FRU module. [jejb: fix checkpatch issues] Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_core.c | 14 ++ drivers/scsi/bfa/bfa_defs.h | 1 + drivers/scsi/bfa/bfa_ioc.c | 445 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/bfa/bfa_ioc.h | 49 +++++ drivers/scsi/bfa/bfa_modules.h | 1 + drivers/scsi/bfa/bfad_bsg.c | 127 +++++++++++- drivers/scsi/bfa/bfad_bsg.h | 35 +++- drivers/scsi/bfa/bfi.h | 47 ++++- drivers/scsi/bfa/bfi_ms.h | 1 + 9 files changed, 715 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/bfa/bfa_ioc.h') diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 89ebd4459bfc..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 */ @@ -1752,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)); @@ -1776,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)); } /* @@ -1848,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_defs.h b/drivers/scsi/bfa/bfa_defs.h index daf7314d2eea..0efdf312b42c 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -196,6 +196,7 @@ enum bfa_status { 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 */ }; diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index dea6a5e86776..0116c1032e25 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -5956,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 0ad221abfc8f..23a90e7b7107 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -701,6 +701,55 @@ void bfa_phy_memclaim(struct bfa_phy_s *phy, u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg); 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 */ diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h index 189fff71e3c2..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 */ }; /* diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 0ab1d400ac33..555e7db94a1c 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -107,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; @@ -2583,6 +2584,109 @@ bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd) 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) @@ -2923,6 +3027,23 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, 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; diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index e48dcca0d7fa..15e1fc8e796b 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -146,7 +146,12 @@ enum { IOCMD_DIAG_DPORT_GET_STATE, IOCMD_QOS_SET_BW, IOCMD_FCPIM_THROTTLE_QUERY, - IOCMD_FCPIM_THROTTLE_SET + 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 { @@ -750,6 +755,34 @@ struct bfa_bsg_fcpim_throttle_s { 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/bfi.h b/drivers/scsi/bfa/bfi.h index 9c9861f8e6ce..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 @@ -1170,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 c89defc9bb92..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 { -- cgit v1.2.3