From 111ecbe426241bdc89c33e9acd08eb15744ce031 Mon Sep 17 00:00:00 2001 From: Vijay Mohan Guvva Date: Mon, 13 May 2013 03:49:44 -0600 Subject: [SCSI] bfa: fix faulty handling of events in lps sm When a switch disable/enable or a reboot is done, the HBA port gets an offline and a subsequent online notification. When the port comes up a link up notification is sent to bfa from the firmware. The bfa then send an FLOGI to the firmware which is sent out on the wire. The switch port meanwhile goes offline (presumably for diagnostics) which causes the switch not to respond to the FLOGI. The link down notification is sent to the HBA driver. However owing to a bug in the lps state machine handling the lps state machine does not move to sm_init state (it remains in sm_login state and send a login complete message to fcs). This results in a zero PID assignment as the login is not really complete. This fix is to correctly handle the events in lps state machine. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_svc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 299c1c889b3..7ed2c57d873 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -1276,7 +1276,6 @@ 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) @@ -1305,6 +1304,7 @@ 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; -- cgit v1.2.3-70-g09d2 From 07cdc0464fb9438fd205069dc09d47b8783ad271 Mon Sep 17 00:00:00 2001 From: Vijay Mohan Guvva Date: Mon, 13 May 2013 03:56:48 -0600 Subject: [SCSI] bfa: fix for FC Direct Attach LUN discovery failure Resending the patch as it didn't make the linux-scsi list. This patch fixes fcs rport state machine to address ocassional Brocade FC Direct Attach LUN discovery failure due to not sending PLOGI accept to the target. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcs_rport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 58ac643ba9f..610ca9500aa 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -189,8 +189,8 @@ bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event) break; case RPSM_EVENT_PLOGI_RCVD: - bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online); - bfa_fcs_rport_fcs_online_action(rport); + bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); + bfa_fcs_rport_send_plogiacc(rport, NULL); break; case RPSM_EVENT_PLOGI_COMP: -- cgit v1.2.3-70-g09d2 From c6e23d83c35380909edf2eb364943719bc10e9be Mon Sep 17 00:00:00 2001 From: Jakob Normark Date: Wed, 15 May 2013 21:41:51 +0200 Subject: [SCSI] bfa: Fixes for 0-terminated strncpy and possible null pointer dereference This patch fixes two cppcheck errors in drivers/scsi/bfa/bfad_im.c [jejb: correct strlcpy fix] Signed-off-by: Jakob Normark Acked-by: Vijay Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad_im.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 5864f987f20..9796284512a 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -944,13 +944,15 @@ static int bfad_im_slave_alloc(struct scsi_device *sdev) { struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); - struct bfad_itnim_data_s *itnim_data = - (struct bfad_itnim_data_s *) rport->dd_data; - struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa; + struct bfad_itnim_data_s *itnim_data; + struct bfa_s *bfa; if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; + itnim_data = (struct bfad_itnim_data_s *) rport->dd_data; + bfa = itnim_data->itnim->bfa_itnim->bfa; + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) { /* * We should not mask LUN 0 - since this will translate @@ -1035,7 +1037,7 @@ bfad_fc_host_init(struct bfad_im_port_s *im_port) /* For fibre channel services type 0x20 */ fc_host_supported_fc4s(host)[7] = 1; - strncpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname, + strlcpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname, BFA_SYMNAME_MAXLEN); sprintf(fc_host_symbolic_name(host), "%s", symname); -- cgit v1.2.3-70-g09d2 From bbe37a67d9da18e40dfd9232586612424b1466f7 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:19 -0700 Subject: [SCSI] bfa: Support for FC BB credit recovery This patch includes changes to 1) Enable/disable fc credit recovery on Brocade FC adapter port operating at max supported speed. 2) Get credit recovery status and stats related to credit loss and recovered credits Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs.h | 10 +++++ drivers/scsi/bfa/bfa_defs_svc.h | 49 +++++++++++++++++---- drivers/scsi/bfa/bfa_fcs.c | 62 +++----------------------- drivers/scsi/bfa/bfa_fcs.h | 5 --- drivers/scsi/bfa/bfa_fcs_rport.c | 2 +- drivers/scsi/bfa/bfa_svc.c | 95 +++++++++++++++++++++++++++++++++++----- drivers/scsi/bfa/bfa_svc.h | 12 ++--- drivers/scsi/bfa/bfad_bsg.c | 47 ++++++++++++++------ drivers/scsi/bfa/bfad_bsg.h | 19 +++++++- drivers/scsi/bfa/bfi_ms.h | 5 +-- 10 files changed, 202 insertions(+), 104 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index 0efdf312b42..bdd1bae971e 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -185,6 +185,8 @@ enum bfa_status { BFA_STATUS_FAA_DISABLED = 198, /* FAA is already disabled */ BFA_STATUS_FAA_ACQUIRED = 199, /* FAA is already acquired */ BFA_STATUS_FAA_ACQ_ADDR = 200, /* Acquiring addr */ + BFA_STATUS_BBCR_FC_ONLY = 201, /*!< BBCredit Recovery is supported for * + * FC mode only */ BFA_STATUS_ERROR_TRUNK_ENABLED = 203, /* Trunk enabled on adapter */ BFA_STATUS_MAX_ENTRY_REACHED = 212, /* MAX entry reached */ BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */ @@ -198,6 +200,14 @@ enum bfa_status { 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_ERR_BBCR_SPEED_UNSUPPORT = 258, /*!< BB credit recovery is + * supported at max port speed alone */ + BFA_STATUS_ERROR_BBCR_ENABLED = 259, /*!< BB credit recovery + * is enabled */ + BFA_STATUS_INVALID_BBSCN = 260, /*!< Invalid BBSCN value. + * Valid range is [1-15] */ + BFA_STATUS_BBCR_CFG_NO_CHANGE = 265, /*!< BBCR is operational. + * Disable BBCR and try this operation again. */ BFA_STATUS_MAX_VAL /* Unknown error code */ }; #define bfa_status_t enum bfa_status diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index ec03c8cd8da..c06359b76c4 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -257,8 +257,6 @@ struct bfa_fw_port_lksm_stats_s { u32 nos_tx; /* No. of times NOS tx started */ u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */ u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */ - u32 bbsc_lr; /* LKSM LR tx for credit recovery */ - u32 rsvd; }; struct bfa_fw_port_snsm_stats_s { @@ -409,7 +407,7 @@ struct bfa_fw_trunk_stats_s { u32 rsvd; /* padding for 64 bit alignment */ }; -struct bfa_fw_advsm_stats_s { +struct bfa_fw_aport_stats_s { u32 flogi_sent; /* Flogi sent */ u32 flogi_acc_recvd; /* Flogi Acc received */ u32 flogi_rjt_recvd; /* Flogi rejects received */ @@ -419,6 +417,12 @@ struct bfa_fw_advsm_stats_s { u32 elp_accepted; /* ELP Accepted */ u32 elp_rejected; /* ELP rejected */ u32 elp_dropped; /* ELP dropped */ + + u32 bbcr_lr_count; /*!< BBCR Link Resets */ + u32 frame_lost_intrs; /*!< BBCR Frame loss intrs */ + u32 rrdy_lost_intrs; /*!< BBCR Rrdy loss intrs */ + + u32 rsvd; }; /* @@ -489,7 +493,7 @@ struct bfa_fw_stats_s { struct bfa_fw_fcxchg_stats_s fcxchg_stats; struct bfa_fw_lps_stats_s lps_stats; struct bfa_fw_trunk_stats_s trunk_stats; - struct bfa_fw_advsm_stats_s advsm_stats; + struct bfa_fw_aport_stats_s aport_stats; struct bfa_fw_mac_mod_stats_s macmod_stats; struct bfa_fw_ct_mod_stats_s ctmod_stats; struct bfa_fw_eth_sndrcv_stats_s ethsndrcv_stats; @@ -545,6 +549,27 @@ struct bfa_qos_attr_s { struct bfa_qos_bw_s qos_bw_op; /* QOS bw operational */ }; +enum bfa_bbcr_state { + BFA_BBCR_DISABLED, /*!< BBCR is disable */ + BFA_BBCR_ONLINE, /*!< BBCR is online */ + BFA_BBCR_OFFLINE, /*!< BBCR is offline */ +}; + +enum bfa_bbcr_err_reason { + BFA_BBCR_ERR_REASON_NONE, /*!< Unknown */ + BFA_BBCR_ERR_REASON_SPEED_UNSUP, /*!< Port speed < max sup_speed */ + BFA_BBCR_ERR_REASON_PEER_UNSUP, /*!< BBCR is disable on peer port */ + BFA_BBCR_ERR_REASON_NON_BRCD_SW, /*!< Connected to non BRCD switch */ + BFA_BBCR_ERR_REASON_FLOGI_RJT, /*!< Login rejected by the switch */ +}; + +struct bfa_bbcr_attr_s { + u8 state; + u8 peer_bb_scn; + u8 reason; + u8 rsvd; +}; + /* * These fields should be displayed only from the CLI. * There will be a separate BFAL API (get_qos_vc_attr ?) @@ -892,6 +917,9 @@ struct bfa_defs_fcpim_throttle_s { u16 rsvd; }; +#define BFA_BB_SCN_DEF 3 +#define BFA_BB_SCN_MAX 0x0F + /* * Physical port configuration */ @@ -907,8 +935,8 @@ struct bfa_port_cfg_s { u8 tx_bbcredit; /* transmit buffer credits */ u8 ratelimit; /* ratelimit enabled or not */ u8 trl_def_speed; /* ratelimit default speed */ - u8 bb_scn; /* BB_SCN value from FLOGI Exchg */ - u8 bb_scn_state; /* Config state of BB_SCN */ + u8 bb_cr_enabled; /*!< Config state of BB_SCN */ + u8 bb_scn; /*!< BB_SCN value for FLOGI Exchg */ u8 faa_state; /* FAA enabled/disabled */ u8 rsvd1; u16 path_tov; /* device path timeout */ @@ -1052,6 +1080,7 @@ struct bfa_port_link_s { struct bfa_qos_attr_s qos_attr; /* QoS Attributes */ union { struct bfa_fcport_loop_info_s loop_info; + struct bfa_bbcr_attr_s bbcr_attr; union { struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */ @@ -1215,9 +1244,11 @@ struct bfa_port_fc_stats_s { u64 bad_os_count; /* Invalid ordered sets */ u64 err_enc_out; /* Encoding err nonframe_8b10b */ u64 err_enc; /* Encoding err frame_8b10b */ - u64 bbsc_frames_lost; /* Credit Recovery-Frames Lost */ - u64 bbsc_credits_lost; /* Credit Recovery-Credits Lost */ - u64 bbsc_link_resets; /* Credit Recovery-Link Resets */ + u64 bbcr_frames_lost; /*!< BBCR Frames Lost */ + u64 bbcr_rrdys_lost; /*!< BBCR RRDYs Lost */ + u64 bbcr_link_resets; /*!< BBCR Link Resets */ + u64 bbcr_frame_lost_intrs; /*!< BBCR Frame loss intrs */ + u64 bbcr_rrdy_lost_intrs; /*!< BBCR Rrdy loss intrs */ u64 loop_timeouts; /* Loop timeouts */ }; diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index d428808fb37..a3ab5cce420 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -240,9 +240,6 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg, u32 rsp_len, u32 resid_len, struct fchs_s *rspfchs); -static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric); -static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled( - struct bfa_fcs_fabric_s *fabric); static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event); @@ -404,8 +401,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_CONT_OP: bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, - fabric->bb_credit, - bfa_fcs_fabric_oper_bbscn(fabric)); + fabric->bb_credit); fabric->fab_type = BFA_FCS_FABRIC_SWITCHED; if (fabric->auth_reqd && fabric->is_auth) { @@ -433,8 +429,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_NO_FABRIC: fabric->fab_type = BFA_FCS_FABRIC_N2N; bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, - fabric->bb_credit, - bfa_fcs_fabric_oper_bbscn(fabric)); + fabric->bb_credit); bfa_fcs_fabric_notify_online(fabric); bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric); break; @@ -602,8 +597,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_NO_FABRIC: bfa_trc(fabric->fcs, fabric->bb_credit); bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, - fabric->bb_credit, - bfa_fcs_fabric_oper_bbscn(fabric)); + fabric->bb_credit); break; case BFA_FCS_FABRIC_SM_RETRY_OP: @@ -965,10 +959,6 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status) case BFA_STATUS_FABRIC_RJT: fabric->stats.flogi_rejects++; - if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR && - fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO) - fabric->fcs->bbscn_flogi_rjt = BFA_TRUE; - bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); return; @@ -1014,14 +1004,11 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric) { struct bfa_s *bfa = fabric->fcs->bfa; struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg; - u8 alpa = 0, bb_scn = 0; + u8 alpa = 0; - if (bfa_fcs_fabric_is_bbscn_enabled(fabric) && - (!fabric->fcs->bbscn_flogi_rjt)) - bb_scn = BFA_FCS_PORT_DEF_BB_SCN; bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa), - pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn); + pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd); fabric->stats.flogi_sent++; } @@ -1101,40 +1088,6 @@ bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric) bfa_wc_wait(&fabric->stop_wc); } -/* - * Computes operating BB_SCN value - */ -static u8 -bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric) -{ - u8 pr_bbscn = fabric->lps->pr_bbscn; - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa); - - if (!(fcport->cfg.bb_scn_state && pr_bbscn)) - return 0; - - /* return max of local/remote bb_scn values */ - return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ? - pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN); -} - -/* - * Check if BB_SCN can be enabled. - */ -static bfa_boolean_t -bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa); - - if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) && - fcport->cfg.bb_scn_state && - !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) && - !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa)) - return BFA_TRUE; - else - return BFA_FALSE; -} - /* * Delete all vports and wait for vport delete completions. */ @@ -1273,7 +1226,6 @@ void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric) { bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); - fabric->fcs->bbscn_flogi_rjt = BFA_FALSE; bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN); } @@ -1480,7 +1432,6 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, } fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred); - fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12); bport->port_topo.pn2n.rem_port_wwn = flogi->port_name; bport->port_topo.pn2n.reply_oxid = fchs->ox_id; @@ -1513,8 +1464,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric) n2n_port->reply_oxid, pcfg->pwwn, pcfg->nwwn, bfa_fcport_get_maxfrsize(bfa), - bfa_fcport_get_rx_bbcredit(bfa), - bfa_fcs_fabric_oper_bbscn(fabric)); + bfa_fcport_get_rx_bbcredit(bfa), 0); bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag, BFA_FALSE, FC_CLASS_3, diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index a449706c6bc..1369682f63d 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -258,9 +258,6 @@ struct bfa_fcs_fabric_s; #define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48 #define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16 -/* bb_scn value in 2^bb_scn */ -#define BFA_FCS_PORT_DEF_BB_SCN 3 - /* * Get FC port ID for a logical port. */ @@ -683,8 +680,6 @@ struct bfa_fcs_s { struct bfa_trc_mod_s *trcmod; /* tracing module */ bfa_boolean_t vf_enabled; /* VF mode is enabled */ bfa_boolean_t fdmi_enabled; /* FDMI is enabled */ - bfa_boolean_t bbscn_enabled; /* Driver Config Parameter */ - bfa_boolean_t bbscn_flogi_rjt;/* FLOGI reject due to BB_SCN */ bfa_boolean_t min_cfg; /* min cfg enabled/disabled */ u16 port_vfid; /* port default VF ID */ struct bfa_fcs_driver_info_s driver_info; diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 610ca9500aa..62713a7c2da 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -2577,7 +2577,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi) port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred); bfa_fcport_set_tx_bbcredit(port->fcs->bfa, - port->fabric->bb_credit, 0); + port->fabric->bb_credit); } } diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 7ed2c57d873..6ed60425dd3 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -1614,7 +1614,6 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp) lps->lp_mac = rsp->lp_mac; lps->brcd_switch = rsp->brcd_switch; lps->fcf_mac = rsp->fcf_mac; - lps->pr_bbscn = rsp->bb_scn; break; @@ -1744,7 +1743,6 @@ bfa_lps_send_login(struct bfa_lps_s *lps) m->nwwn = lps->nwwn; m->fdisc = lps->fdisc; m->auth_en = lps->auth_en; - m->bb_scn = lps->bb_scn; bfa_reqq_produce(lps->bfa, lps->reqq, m->mh); list_del(&lps->qe); @@ -1940,7 +1938,7 @@ bfa_lps_delete(struct bfa_lps_s *lps) */ void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, - wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en, uint8_t bb_scn) + wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en) { lps->uarg = uarg; lps->alpa = alpa; @@ -1949,7 +1947,6 @@ bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, lps->nwwn = nwwn; lps->fdisc = BFA_FALSE; lps->auth_en = auth_en; - lps->bb_scn = bb_scn; bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN); } @@ -3158,6 +3155,8 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport) fcport->qos_attr = pevent->link_state.qos_attr; fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr; + if (fcport->cfg.bb_cr_enabled) + fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr; /* * update trunk state if applicable */ @@ -3177,7 +3176,6 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport) { fcport->speed = BFA_PORT_SPEED_UNKNOWN; fcport->topology = BFA_PORT_TOPOLOGY_NONE; - fcport->bbsc_op_state = BFA_FALSE; } /* @@ -3629,6 +3627,11 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) fcport->qos_attr.qos_bw_op = i2hmsg.penable_rsp->port_cfg.qos_bw; + if (fcport->cfg.bb_cr_enabled) + fcport->bbcr_attr.state = BFA_BBCR_OFFLINE; + else + fcport->bbcr_attr.state = BFA_BBCR_DISABLED; + bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP); } break; @@ -3639,6 +3642,11 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) break; case BFI_FCPORT_I2H_EVENT: + if (fcport->cfg.bb_cr_enabled) + fcport->bbcr_attr.state = BFA_BBCR_OFFLINE; + else + fcport->bbcr_attr.state = BFA_BBCR_DISABLED; + if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP) bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP); else { @@ -3964,14 +3972,11 @@ bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa) } void -bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn) +bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit) { struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); fcport->cfg.tx_bbcredit = (u8)tx_bbcredit; - fcport->cfg.bb_scn = bb_scn; - if (bb_scn) - fcport->bbsc_op_state = BFA_TRUE; } /* @@ -4021,7 +4026,6 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr) attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa); attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa); attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm); - attr->bbsc_op_status = fcport->bbsc_op_state; /* PBC Disabled State */ if (bfa_fcport_is_pbcdisabled(bfa)) @@ -4217,6 +4221,77 @@ bfa_fcport_is_trunk_enabled(struct bfa_s *bfa) return fcport->cfg.trunked; } +bfa_status_t +bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn) +{ + struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + + bfa_trc(bfa, on_off); + + if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC) + return BFA_STATUS_BBCR_FC_ONLY; + + if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) && + (bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK)) + return BFA_STATUS_CMD_NOTSUPP_MEZZ; + + if (on_off) { + if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) + return BFA_STATUS_TOPOLOGY_LOOP; + + if (fcport->cfg.qos_enabled) + return BFA_STATUS_ERROR_QOS_ENABLED; + + if (fcport->cfg.trunked) + return BFA_STATUS_TRUNK_ENABLED; + + if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) && + (fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc))) + return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT; + + if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS) + return BFA_STATUS_FEATURE_NOT_SUPPORTED; + + if (fcport->cfg.bb_cr_enabled) { + if (bb_scn != fcport->cfg.bb_scn) + return BFA_STATUS_BBCR_CFG_NO_CHANGE; + else + return BFA_STATUS_NO_CHANGE; + } + + if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX)) + bb_scn = BFA_BB_SCN_DEF; + + fcport->cfg.bb_cr_enabled = on_off; + fcport->cfg.bb_scn = bb_scn; + } else { + if (!fcport->cfg.bb_cr_enabled) + return BFA_STATUS_NO_CHANGE; + + fcport->cfg.bb_cr_enabled = on_off; + fcport->cfg.bb_scn = 0; + } + + return BFA_STATUS_OK; +} + +bfa_status_t +bfa_fcport_get_bbcr_attr(struct bfa_s *bfa, + struct bfa_bbcr_attr_s *bbcr_attr) +{ + struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + + if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC) + return BFA_STATUS_BBCR_FC_ONLY; + + if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) + return BFA_STATUS_TOPOLOGY_LOOP; + + *bbcr_attr = fcport->bbcr_attr; + + return BFA_STATUS_OK; +} + void bfa_fcport_dportenable(struct bfa_s *bfa) { diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 8d7fbecfcb2..768ed6ac18f 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -405,8 +405,6 @@ struct bfa_lps_s { bfa_status_t status; /* login status */ u16 pdusz; /* max receive PDU size */ u16 pr_bbcred; /* BB_CREDIT from peer */ - u8 pr_bbscn; /* BB_SCN from peer */ - u8 bb_scn; /* local BB_SCN */ u8 lsrjt_rsn; /* LSRJT reason */ u8 lsrjt_expl; /* LSRJT explanation */ u8 lun_mask; /* LUN mask flag */ @@ -510,11 +508,11 @@ struct bfa_fcport_s { bfa_boolean_t diag_busy; /* diag busy status */ bfa_boolean_t beacon; /* port beacon status */ bfa_boolean_t link_e2e_beacon; /* link beacon status */ - bfa_boolean_t bbsc_op_state; /* Cred recov Oper State */ struct bfa_fcport_trunk_s trunk; u16 fcoe_vlan; struct bfa_mem_dma_s fcport_dma; bfa_boolean_t stats_dma_ready; + struct bfa_bbcr_attr_s bbcr_attr; }; #define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport) @@ -556,7 +554,7 @@ bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw); enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa); -void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn); +void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit); bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa); void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon, bfa_boolean_t link_e2e_beacon); @@ -571,6 +569,10 @@ void bfa_fcport_dportenable(struct bfa_s *bfa); void bfa_fcport_dportdisable(struct bfa_s *bfa); bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa); void bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state); +bfa_status_t bfa_fcport_cfg_bbcr(struct bfa_s *bfa, + bfa_boolean_t on_off, u8 bb_scn); +bfa_status_t bfa_fcport_get_bbcr_attr(struct bfa_s *bfa, + struct bfa_bbcr_attr_s *bbcr_attr); /* * bfa rport API functions @@ -667,7 +669,7 @@ struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa); void bfa_lps_delete(struct bfa_lps_s *lps); void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, wwn_t pwwn, wwn_t nwwn, - bfa_boolean_t auth_en, u8 bb_scn); + bfa_boolean_t auth_en); void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, wwn_t nwwn); void bfa_lps_fdisclogo(struct bfa_lps_s *lps); diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 555e7db94a1..bda1500e1a2 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -402,25 +402,43 @@ bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd) } int -bfad_iocmd_port_cfg_bbsc(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +bfad_iocmd_port_cfg_bbcr(struct bfad_s *bfad, unsigned int cmd, void *pcmd) { - struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); - unsigned long flags; + struct bfa_bsg_bbcr_enable_s *iocmd = + (struct bfa_bsg_bbcr_enable_s *)pcmd; + unsigned long flags; + int rc; spin_lock_irqsave(&bfad->bfad_lock, flags); - if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) { - if (v_cmd == IOCMD_PORT_BBSC_ENABLE) - fcport->cfg.bb_scn_state = BFA_TRUE; - else if (v_cmd == IOCMD_PORT_BBSC_DISABLE) - fcport->cfg.bb_scn_state = BFA_FALSE; + if (cmd == IOCMD_PORT_BBCR_ENABLE) + rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_TRUE, iocmd->bb_scn); + else if (cmd == IOCMD_PORT_BBCR_DISABLE) + rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_FALSE, 0); + else { + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + return -EINVAL; } spin_unlock_irqrestore(&bfad->bfad_lock, flags); - iocmd->status = BFA_STATUS_OK; + iocmd->status = rc; return 0; } +int +bfad_iocmd_port_get_bbcr_attr(struct bfad_s *bfad, void *pcmd) +{ + struct bfa_bsg_bbcr_attr_s *iocmd = (struct bfa_bsg_bbcr_attr_s *) pcmd; + unsigned long flags; + + spin_lock_irqsave(&bfad->bfad_lock, flags); + iocmd->status = + bfa_fcport_get_bbcr_attr(&bfad->bfa, &iocmd->attr); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + + return 0; +} + + static int bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd) { @@ -2750,9 +2768,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, case IOCMD_PORT_CFG_MAXFRSZ: rc = bfad_iocmd_port_cfg_maxfrsize(bfad, iocmd); break; - case IOCMD_PORT_BBSC_ENABLE: - case IOCMD_PORT_BBSC_DISABLE: - rc = bfad_iocmd_port_cfg_bbsc(bfad, iocmd, cmd); + case IOCMD_PORT_BBCR_ENABLE: + case IOCMD_PORT_BBCR_DISABLE: + rc = bfad_iocmd_port_cfg_bbcr(bfad, cmd, iocmd); + break; + case IOCMD_PORT_BBCR_GET_ATTR: + rc = bfad_iocmd_port_get_bbcr_attr(bfad, iocmd); break; case IOCMD_LPORT_GET_ATTR: rc = bfad_iocmd_lport_get_attr(bfad, iocmd); diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index 15e1fc8e796..612463b6006 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -46,8 +46,9 @@ enum { IOCMD_PORT_CFG_ALPA, IOCMD_PORT_CFG_MAXFRSZ, IOCMD_PORT_CLR_ALPA, - IOCMD_PORT_BBSC_ENABLE, - IOCMD_PORT_BBSC_DISABLE, + IOCMD_PORT_BBCR_ENABLE, + IOCMD_PORT_BBCR_DISABLE, + IOCMD_PORT_BBCR_GET_ATTR, IOCMD_LPORT_GET_ATTR, IOCMD_LPORT_GET_RPORTS, IOCMD_LPORT_GET_STATS, @@ -495,6 +496,20 @@ struct bfa_bsg_port_cfg_mode_s { struct bfa_port_cfg_mode_s cfg; }; +struct bfa_bsg_bbcr_enable_s { + bfa_status_t status; + u16 bfad_num; + u8 bb_scn; + u8 rsvd; +}; + +struct bfa_bsg_bbcr_attr_s { + bfa_status_t status; + u16 bfad_num; + u16 rsvd; + struct bfa_bbcr_attr_s attr; +}; + struct bfa_bsg_faa_attr_s { bfa_status_t status; u16 bfad_num; diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h index 5ae2c167b2c..1a3fe5ad58f 100644 --- a/drivers/scsi/bfa/bfi_ms.h +++ b/drivers/scsi/bfa/bfi_ms.h @@ -276,8 +276,7 @@ struct bfi_fcport_enable_req_s { struct bfi_fcport_set_svc_params_req_s { struct bfi_mhdr_s mh; /* msg header */ __be16 tx_bbcredit; /* Tx credits */ - u8 bb_scn; /* BB_SC FC credit recovery */ - u8 rsvd; + u8 rsvd[2]; }; /* @@ -446,8 +445,8 @@ struct bfi_lps_login_rsp_s { mac_t fcf_mac; u8 ext_status; u8 brcd_switch; /* attached peer is brcd switch */ - u8 bb_scn; /* atatched port's bb_scn */ u8 bfa_tag; + u8 rsvd; }; struct bfi_lps_logout_req_s { -- cgit v1.2.3-70-g09d2 From 4e1e0d8d71810fb5e4c294299ab35c30a746353d Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:20 -0700 Subject: [SCSI] bfa: Forward Error Correction status query This patch includes changes to get FC HBA feature Forward Error Correction (FEC) (enabled at 16Gig speed) status from firmware and to return to brocade HBA management utility. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs_svc.h | 15 +++++++++++++-- drivers/scsi/bfa/bfa_svc.c | 8 ++++++++ drivers/scsi/bfa/bfa_svc.h | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index c06359b76c4..0880d86c354 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -882,6 +882,15 @@ enum bfa_lunmask_state_s { BFA_LUNMASK_UNINITIALIZED = 0xff, }; +/** + * FEC states + */ +enum bfa_fec_state_s { + BFA_FEC_ONLINE = 1, /*!< FEC is online */ + BFA_FEC_OFFLINE = 2, /*!< FEC is offline */ + BFA_FEC_OFFLINE_NOT_16G = 3, /*!< FEC is offline (speed not 16Gig) */ +}; + #pragma pack(1) /* * LUN mask configuration @@ -978,6 +987,7 @@ struct bfa_port_attr_s { bfa_boolean_t link_e2e_beacon; /* link beacon is on */ bfa_boolean_t bbsc_op_status; /* fc credit recovery oper * state */ + enum bfa_fec_state_s fec_state; /*!< current FEC state */ /* * Dynamic field - info from FCS @@ -989,7 +999,7 @@ struct bfa_port_attr_s { /* FCoE specific */ u16 fcoe_vlan; - u8 rsvd1[6]; + u8 rsvd1[2]; }; /* @@ -1076,7 +1086,8 @@ 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[7]; + u8 fec_state; /*!< State of FEC */ + u8 resvd[6]; struct bfa_qos_attr_s qos_attr; /* QoS Attributes */ union { struct bfa_fcport_loop_info_s loop_info; diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 6ed60425dd3..1baa9b348c5 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -3079,6 +3079,8 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, port_cfg->qos_bw.med = BFA_QOS_BW_MED; port_cfg->qos_bw.low = BFA_QOS_BW_LOW; + fcport->fec_state = BFA_FEC_OFFLINE; + INIT_LIST_HEAD(&fcport->stats_pending_q); INIT_LIST_HEAD(&fcport->statsclr_pending_q); @@ -3157,6 +3159,9 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport) if (fcport->cfg.bb_cr_enabled) fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr; + + fcport->fec_state = pevent->link_state.fec_state; + /* * update trunk state if applicable */ @@ -3176,6 +3181,7 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport) { fcport->speed = BFA_PORT_SPEED_UNKNOWN; fcport->topology = BFA_PORT_TOPOLOGY_NONE; + fcport->fec_state = BFA_FEC_OFFLINE; } /* @@ -4027,6 +4033,8 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr) attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa); attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm); + attr->fec_state = fcport->fec_state; + /* PBC Disabled State */ if (bfa_fcport_is_pbcdisabled(bfa)) attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED; diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 768ed6ac18f..5af64de152b 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -513,6 +513,7 @@ struct bfa_fcport_s { struct bfa_mem_dma_s fcport_dma; bfa_boolean_t stats_dma_ready; struct bfa_bbcr_attr_s bbcr_attr; + enum bfa_fec_state_s fec_state; }; #define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport) -- cgit v1.2.3-70-g09d2 From 1a898a794d5913c899a329c5dec39d28e6065672 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:21 -0700 Subject: [SCSI] bfa: Add dynamic diagnostic port support D-Port is a new port type created with the intention of running link level diagnostic tests like loopback, traffic test. In static D-port mode, user configures the port to D-port mode and starts the test, but in dynamic D-port, once the Brocade switch port is configured to D-port, it will reject the regular FLOGI from HBA with reason that it is in D-port mode. So based on the reason code HBA port will turn itself into D-port and start diagnostic test. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs.h | 79 +++++- drivers/scsi/bfa/bfa_defs_svc.h | 1 + drivers/scsi/bfa/bfa_svc.c | 595 +++++++++++++++++++++++++++++++++++++--- drivers/scsi/bfa/bfa_svc.h | 21 +- drivers/scsi/bfa/bfad_bsg.c | 81 ++++-- drivers/scsi/bfa/bfad_bsg.h | 25 +- drivers/scsi/bfa/bfi.h | 68 ++++- 7 files changed, 781 insertions(+), 89 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index bdd1bae971e..d65a9b4a6f6 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -199,15 +199,34 @@ enum bfa_status { BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */ BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */ BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */ + BFA_STATUS_DPORT_NO_SFP = 243, /* SFP is not present.\n D-port will be + * enabled but it will be operational + * only after inserting a valid SFP. */ BFA_STATUS_DPORT_ERR = 245, /* D-port mode is enabled */ + BFA_STATUS_DPORT_ENOSYS = 254, /* Switch has no D_Port functionality */ + BFA_STATUS_DPORT_CANT_PERF = 255, /* Switch port is not D_Port capable + * or D_Port is disabled */ + BFA_STATUS_DPORT_LOGICALERR = 256, /* Switch D_Port fail */ + BFA_STATUS_DPORT_SWBUSY = 257, /* Switch port busy */ BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT = 258, /*!< BB credit recovery is * supported at max port speed alone */ BFA_STATUS_ERROR_BBCR_ENABLED = 259, /*!< BB credit recovery * is enabled */ BFA_STATUS_INVALID_BBSCN = 260, /*!< Invalid BBSCN value. * Valid range is [1-15] */ + BFA_STATUS_DDPORT_ERR = 261, /* Dynamic D_Port mode is active.\n To + * exit dynamic mode, disable D_Port on + * the remote port */ + BFA_STATUS_DPORT_SFPWRAP_ERR = 262, /* Clear e/o_wrap fail, check or + * replace SFP */ BFA_STATUS_BBCR_CFG_NO_CHANGE = 265, /*!< BBCR is operational. * Disable BBCR and try this operation again. */ + BFA_STATUS_DPORT_SW_NOTREADY = 268, /* Remote port is not ready to + * start dport test. Check remote + * port status. */ + BFA_STATUS_DPORT_INV_SFP = 271, /* Invalid SFP for D-PORT mode. */ + BFA_STATUS_DPORT_CMD_NOTSUPP = 273, /* Dport is not supported by + * remote port */ BFA_STATUS_MAX_VAL /* Unknown error code */ }; #define bfa_status_t enum bfa_status @@ -526,17 +545,6 @@ struct bfa_ioc_aen_data_s { mac_t mac; }; -/* - * 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 ------------ */ @@ -1136,6 +1144,7 @@ struct bfa_flash_attr_s { #define LB_PATTERN_DEFAULT 0xB5B5B5B5 #define QTEST_CNT_DEFAULT 10 #define QTEST_PAT_DEFAULT LB_PATTERN_DEFAULT +#define DPORT_ENABLE_LOOPCNT_DEFAULT (1024 * 1024) struct bfa_diag_memtest_s { u8 algo; @@ -1164,6 +1173,54 @@ struct bfa_diag_loopback_result_s { u8 rsvd[3]; }; +enum bfa_diag_dport_test_status { + DPORT_TEST_ST_IDLE = 0, /* the test has not started yet. */ + DPORT_TEST_ST_FINAL = 1, /* the test done successfully */ + DPORT_TEST_ST_SKIP = 2, /* the test skipped */ + DPORT_TEST_ST_FAIL = 3, /* the test failed */ + DPORT_TEST_ST_INPRG = 4, /* the testing is in progress */ + DPORT_TEST_ST_RESPONDER = 5, /* test triggered from remote port */ + DPORT_TEST_ST_STOPPED = 6, /* the test stopped by user. */ + DPORT_TEST_ST_MAX +}; + +enum bfa_diag_dport_test_type { + DPORT_TEST_ELOOP = 0, + DPORT_TEST_OLOOP = 1, + DPORT_TEST_ROLOOP = 2, + DPORT_TEST_LINK = 3, + DPORT_TEST_MAX +}; + +enum bfa_diag_dport_test_opmode { + BFA_DPORT_OPMODE_AUTO = 0, + BFA_DPORT_OPMODE_MANU = 1, +}; + +struct bfa_diag_dport_subtest_result_s { + u8 status; /* bfa_diag_dport_test_status */ + u8 rsvd[7]; /* 64bit align */ + u64 start_time; /* timestamp */ +}; + +struct bfa_diag_dport_result_s { + wwn_t rp_pwwn; /* switch port wwn */ + wwn_t rp_nwwn; /* switch node wwn */ + u64 start_time; /* user/sw start time */ + u64 end_time; /* timestamp */ + u8 status; /* bfa_diag_dport_test_status */ + u8 mode; /* bfa_diag_dport_test_opmode */ + u8 rsvd; /* 64bit align */ + u8 speed; /* link speed for buf_reqd */ + u16 buffer_required; + u16 frmsz; /* frame size for buf_reqd */ + u32 lpcnt; /* Frame count */ + u32 pat; /* Pattern */ + u32 roundtrip_latency; /* in nano sec */ + u32 est_cable_distance; /* in meter */ + struct bfa_diag_dport_subtest_result_s subtest[DPORT_TEST_MAX]; +}; + struct bfa_diag_ledtest_s { u32 cmd; /* bfa_led_op_t */ u32 color; /* bfa_led_color_t */ diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index 0880d86c354..2f20ba5f57b 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -761,6 +761,7 @@ enum bfa_port_states { BFA_PORT_ST_TOGGLING_QWAIT = 14, BFA_PORT_ST_FAA_MISCONFIG = 15, BFA_PORT_ST_DPORT = 16, + BFA_PORT_ST_DDPORT = 17, BFA_PORT_ST_MAX_STATE, }; diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 1baa9b348c5..6c41e57fd75 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -70,6 +70,8 @@ enum bfa_fcport_sm_event { BFA_FCPORT_SM_DPORTENABLE = 10, /* enable dport */ BFA_FCPORT_SM_DPORTDISABLE = 11,/* disable dport */ BFA_FCPORT_SM_FAA_MISCONFIG = 12, /* FAA misconfiguratin */ + BFA_FCPORT_SM_DDPORTENABLE = 13, /* enable ddport */ + BFA_FCPORT_SM_DDPORTDISABLE = 14, /* disable ddport */ }; /* @@ -202,6 +204,8 @@ static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event); static void bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event); +static void bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport, + enum bfa_fcport_sm_event event); static void bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event); @@ -234,6 +238,7 @@ static struct bfa_sm_table_s hal_port_sm_table[] = { {BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN}, {BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN}, {BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT}, + {BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT}, {BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG}, }; @@ -2646,6 +2651,10 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport, bfa_sm_set_state(fcport, bfa_fcport_sm_dport); break; + case BFA_FCPORT_SM_DDPORTENABLE: + bfa_sm_set_state(fcport, bfa_fcport_sm_ddport); + break; + default: bfa_sm_fault(fcport->bfa, event); } @@ -2758,6 +2767,40 @@ bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event) } } +static void +bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport, + enum bfa_fcport_sm_event event) +{ + bfa_trc(fcport->bfa, event); + + switch (event) { + case BFA_FCPORT_SM_DISABLE: + case BFA_FCPORT_SM_DDPORTDISABLE: + bfa_sm_set_state(fcport, bfa_fcport_sm_disabled); + break; + + case BFA_FCPORT_SM_DPORTENABLE: + case BFA_FCPORT_SM_DPORTDISABLE: + case BFA_FCPORT_SM_ENABLE: + case BFA_FCPORT_SM_START: + /** + * Ignore event for a port that is ddport + */ + break; + + case BFA_FCPORT_SM_STOP: + bfa_sm_set_state(fcport, bfa_fcport_sm_stopped); + break; + + case BFA_FCPORT_SM_HWFAIL: + bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail); + break; + + default: + bfa_sm_fault(fcport->bfa, event); + } +} + static void bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event) @@ -3860,6 +3903,8 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology) return BFA_STATUS_LOOP_UNSUPP_MEZZ; if (bfa_fcport_is_dport(bfa) != BFA_FALSE) return BFA_STATUS_DPORT_ERR; + if (bfa_fcport_is_ddport(bfa) != BFA_FALSE) + return BFA_STATUS_DPORT_ERR; break; case BFA_PORT_TOPOLOGY_AUTO: @@ -4127,6 +4172,15 @@ bfa_fcport_is_dport(struct bfa_s *bfa) BFA_PORT_ST_DPORT); } +bfa_boolean_t +bfa_fcport_is_ddport(struct bfa_s *bfa) +{ + struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + + return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) == + BFA_PORT_ST_DDPORT); +} + bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw) { @@ -4320,6 +4374,24 @@ bfa_fcport_dportdisable(struct bfa_s *bfa) bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE); } +void +bfa_fcport_ddportenable(struct bfa_s *bfa) +{ + /* + * Assume caller check for port is in disable state + */ + bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE); +} + +void +bfa_fcport_ddportdisable(struct bfa_s *bfa) +{ + /* + * Assume caller check for port is in disable state + */ + bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE); +} + /* * Rport State machine functions */ @@ -5705,6 +5777,14 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw) * Dport forward declaration */ +enum bfa_dport_test_state_e { + BFA_DPORT_ST_DISABLED = 0, /*!< dport is disabled */ + BFA_DPORT_ST_INP = 1, /*!< test in progress */ + BFA_DPORT_ST_COMP = 2, /*!< test complete successfully */ + BFA_DPORT_ST_NO_SFP = 3, /*!< sfp is not present */ + BFA_DPORT_ST_NOTSTART = 4, /*!< test not start dport is enabled */ +}; + /* * BFA DPORT state machine events */ @@ -5714,6 +5794,9 @@ enum bfa_dport_sm_event { BFA_DPORT_SM_FWRSP = 3, /* fw enable/disable rsp */ BFA_DPORT_SM_QRESUME = 4, /* CQ space available */ BFA_DPORT_SM_HWFAIL = 5, /* IOC h/w failure */ + BFA_DPORT_SM_START = 6, /* re-start dport test */ + BFA_DPORT_SM_REQFAIL = 7, /* request failure */ + BFA_DPORT_SM_SCN = 8, /* state change notify frm fw */ }; static void bfa_dport_sm_disabled(struct bfa_dport_s *dport, @@ -5728,9 +5811,19 @@ static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport, enum bfa_dport_sm_event event); static void bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event); +static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport, + enum bfa_dport_sm_event event); +static void bfa_dport_sm_starting(struct bfa_dport_s *dport, + enum bfa_dport_sm_event event); +static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport, + enum bfa_dport_sm_event event); +static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport, + enum bfa_dport_sm_event event); static void bfa_dport_qresume(void *cbarg); static void bfa_dport_req_comp(struct bfa_dport_s *dport, - bfi_diag_dport_rsp_t *msg); + struct bfi_diag_dport_rsp_s *msg); +static void bfa_dport_scn(struct bfa_dport_s *dport, + struct bfi_diag_dport_scn_s *msg); /* * BFA fcdiag module @@ -5772,6 +5865,8 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport); dport->cbfn = NULL; dport->cbarg = NULL; + dport->test_state = BFA_DPORT_ST_DISABLED; + memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s)); } static void @@ -5974,7 +6069,12 @@ bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg) 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); + bfa_dport_req_comp(&fcdiag->dport, + (struct bfi_diag_dport_rsp_s *)msg); + break; + case BFI_DIAG_I2H_DPORT_SCN: + bfa_dport_scn(&fcdiag->dport, + (struct bfi_diag_dport_scn_s *)msg); break; default: bfa_trc(fcdiag, msg->mhdr.msg_id); @@ -6069,7 +6169,11 @@ bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode, return BFA_STATUS_UNSUPP_SPEED; } } - + /* check to see if fcport is dport */ + if (bfa_fcport_is_dport(bfa)) { + bfa_trc(fcdiag, fcdiag->lb.lock); + return BFA_STATUS_DPORT_ENABLED; + } /* check to see if there is another destructive diag cmd running */ if (fcdiag->lb.lock) { bfa_trc(fcdiag, fcdiag->lb.lock); @@ -6173,6 +6277,15 @@ bfa_fcdiag_lb_is_running(struct bfa_s *bfa) /* * D-port */ +#define bfa_dport_result_start(__dport, __mode) do { \ + (__dport)->result.start_time = bfa_get_log_time(); \ + (__dport)->result.status = DPORT_TEST_ST_INPRG; \ + (__dport)->result.mode = (__mode); \ + (__dport)->result.rp_pwwn = (__dport)->rp_pwwn; \ + (__dport)->result.rp_nwwn = (__dport)->rp_nwwn; \ + (__dport)->result.lpcnt = (__dport)->lpcnt; \ +} while (0) + static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req); static void @@ -6207,6 +6320,18 @@ bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) /* ignore */ break; + case BFA_DPORT_SM_SCN: + if (dport->i2hmsg.scn.state == BFI_DPORT_SCN_DDPORT_ENABLE) { + bfa_fcport_ddportenable(dport->bfa); + dport->dynamic = BFA_TRUE; + dport->test_state = BFA_DPORT_ST_NOTSTART; + bfa_sm_set_state(dport, bfa_dport_sm_enabled); + } else { + bfa_trc(dport->bfa, dport->i2hmsg.scn.state); + WARN_ON(1); + } + break; + default: bfa_sm_fault(dport->bfa, event); } @@ -6242,9 +6367,23 @@ bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) switch (event) { case BFA_DPORT_SM_FWRSP: + memset(&dport->result, 0, + sizeof(struct bfa_diag_dport_result_s)); + if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) { + dport->test_state = BFA_DPORT_ST_NO_SFP; + } else { + dport->test_state = BFA_DPORT_ST_INP; + bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO); + } bfa_sm_set_state(dport, bfa_dport_sm_enabled); break; + case BFA_DPORT_SM_REQFAIL: + dport->test_state = BFA_DPORT_ST_DISABLED; + bfa_fcport_dportdisable(dport->bfa); + bfa_sm_set_state(dport, bfa_dport_sm_disabled); + break; + case BFA_DPORT_SM_HWFAIL: bfa_sm_set_state(dport, bfa_dport_sm_disabled); bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); @@ -6261,8 +6400,11 @@ 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 */ + case BFA_DPORT_SM_START: + if (bfa_dport_send_req(dport, BFI_DPORT_START)) + bfa_sm_set_state(dport, bfa_dport_sm_starting); + else + bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait); break; case BFA_DPORT_SM_DISABLE: @@ -6277,6 +6419,48 @@ bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) bfa_sm_set_state(dport, bfa_dport_sm_disabled); break; + case BFA_DPORT_SM_SCN: + switch (dport->i2hmsg.scn.state) { + case BFI_DPORT_SCN_TESTCOMP: + dport->test_state = BFA_DPORT_ST_COMP; + break; + + case BFI_DPORT_SCN_TESTSTART: + dport->test_state = BFA_DPORT_ST_INP; + break; + + case BFI_DPORT_SCN_TESTSKIP: + case BFI_DPORT_SCN_SUBTESTSTART: + /* no state change */ + break; + + case BFI_DPORT_SCN_SFP_REMOVED: + dport->test_state = BFA_DPORT_ST_NO_SFP; + break; + + case BFI_DPORT_SCN_DDPORT_DISABLE: + bfa_fcport_ddportdisable(dport->bfa); + + if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE)) + bfa_sm_set_state(dport, + bfa_dport_sm_dynamic_disabling); + else + bfa_sm_set_state(dport, + bfa_dport_sm_dynamic_disabling_qwait); + break; + + case BFI_DPORT_SCN_FCPORT_DISABLE: + bfa_fcport_ddportdisable(dport->bfa); + + bfa_sm_set_state(dport, bfa_dport_sm_disabled); + dport->dynamic = BFA_FALSE; + break; + + default: + bfa_trc(dport->bfa, dport->i2hmsg.scn.state); + bfa_sm_fault(dport->bfa, event); + } + break; default: bfa_sm_fault(dport->bfa, event); } @@ -6300,6 +6484,10 @@ bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport, bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); break; + case BFA_DPORT_SM_SCN: + /* ignore */ + break; + default: bfa_sm_fault(dport->bfa, event); } @@ -6312,7 +6500,98 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) switch (event) { case BFA_DPORT_SM_FWRSP: + dport->test_state = BFA_DPORT_ST_DISABLED; + bfa_sm_set_state(dport, bfa_dport_sm_disabled); + break; + + case BFA_DPORT_SM_HWFAIL: bfa_sm_set_state(dport, bfa_dport_sm_disabled); + bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); + break; + + case BFA_DPORT_SM_SCN: + /* no state change */ + break; + + default: + bfa_sm_fault(dport->bfa, event); + } +} + +static void +bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport, + enum bfa_dport_sm_event event) +{ + bfa_trc(dport->bfa, event); + + switch (event) { + case BFA_DPORT_SM_QRESUME: + bfa_sm_set_state(dport, bfa_dport_sm_starting); + bfa_dport_send_req(dport, BFI_DPORT_START); + break; + + case BFA_DPORT_SM_HWFAIL: + bfa_reqq_wcancel(&dport->reqq_wait); + bfa_sm_set_state(dport, bfa_dport_sm_disabled); + bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); + break; + + default: + bfa_sm_fault(dport->bfa, event); + } +} + +static void +bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) +{ + bfa_trc(dport->bfa, event); + + switch (event) { + case BFA_DPORT_SM_FWRSP: + memset(&dport->result, 0, + sizeof(struct bfa_diag_dport_result_s)); + if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) { + dport->test_state = BFA_DPORT_ST_NO_SFP; + } else { + dport->test_state = BFA_DPORT_ST_INP; + bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU); + } + /* fall thru */ + + case BFA_DPORT_SM_REQFAIL: + bfa_sm_set_state(dport, bfa_dport_sm_enabled); + break; + + case BFA_DPORT_SM_HWFAIL: + bfa_sm_set_state(dport, bfa_dport_sm_disabled); + bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); + break; + + default: + bfa_sm_fault(dport->bfa, event); + } +} + +static void +bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport, + enum bfa_dport_sm_event event) +{ + bfa_trc(dport->bfa, event); + + switch (event) { + case BFA_DPORT_SM_SCN: + switch (dport->i2hmsg.scn.state) { + case BFI_DPORT_SCN_DDPORT_DISABLED: + bfa_sm_set_state(dport, bfa_dport_sm_disabled); + dport->dynamic = BFA_FALSE; + bfa_fcport_enable(dport->bfa); + break; + + default: + bfa_trc(dport->bfa, dport->i2hmsg.scn.state); + bfa_sm_fault(dport->bfa, event); + + } break; case BFA_DPORT_SM_HWFAIL: @@ -6325,18 +6604,38 @@ bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) } } +static void +bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport, + enum bfa_dport_sm_event event) +{ + bfa_trc(dport->bfa, event); + + switch (event) { + case BFA_DPORT_SM_QRESUME: + bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling); + bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE); + break; + + case BFA_DPORT_SM_HWFAIL: + bfa_sm_set_state(dport, bfa_dport_sm_disabled); + bfa_reqq_wcancel(&dport->reqq_wait); + bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); + break; + + case BFA_DPORT_SM_SCN: + /* ignore */ + break; + + default: + bfa_sm_fault(dport->bfa, event); + } +} static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req) { struct bfi_diag_dport_req_s *m; - /* - * 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 */ @@ -6349,7 +6648,10 @@ bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req) bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT, bfa_fn_lpu(dport->bfa)); m->req = req; - m->msgtag = dport->msgtag; + if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) { + m->lpcnt = cpu_to_be32(dport->lpcnt); + m->payload = cpu_to_be32(dport->payload); + } /* * queue I/O message to firmware @@ -6368,19 +6670,131 @@ bfa_dport_qresume(void *cbarg) } static void -bfa_dport_req_comp(struct bfa_dport_s *dport, bfi_diag_dport_rsp_t *msg) +bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg) { - bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP); + msg->status = cpu_to_be32(msg->status); + dport->i2hmsg.rsp.status = msg->status; + dport->rp_pwwn = msg->pwwn; + dport->rp_nwwn = msg->nwwn; + + if ((msg->status == BFA_STATUS_OK) || + (msg->status == BFA_STATUS_DPORT_NO_SFP)) { + bfa_trc(dport->bfa, msg->status); + bfa_trc(dport->bfa, dport->rp_pwwn); + bfa_trc(dport->bfa, dport->rp_nwwn); + bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP); + + } else { + bfa_trc(dport->bfa, msg->status); + bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL); + } bfa_cb_fcdiag_dport(dport, msg->status); } +static bfa_boolean_t +bfa_dport_is_sending_req(struct bfa_dport_s *dport) +{ + if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling) || + bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) || + bfa_sm_cmp_state(dport, bfa_dport_sm_disabling) || + bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) || + bfa_sm_cmp_state(dport, bfa_dport_sm_starting) || + bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) { + return BFA_TRUE; + } else { + return BFA_FALSE; + } +} + +static void +bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg) +{ + int i; + uint8_t subtesttype; + + bfa_trc(dport->bfa, msg->state); + dport->i2hmsg.scn.state = msg->state; + + switch (dport->i2hmsg.scn.state) { + case BFI_DPORT_SCN_TESTCOMP: + dport->result.end_time = bfa_get_log_time(); + bfa_trc(dport->bfa, dport->result.end_time); + + dport->result.status = msg->info.testcomp.status; + bfa_trc(dport->bfa, dport->result.status); + + dport->result.roundtrip_latency = + cpu_to_be32(msg->info.testcomp.latency); + dport->result.est_cable_distance = + cpu_to_be32(msg->info.testcomp.distance); + dport->result.buffer_required = + be16_to_cpu(msg->info.testcomp.numbuffer); + + dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz); + dport->result.speed = msg->info.testcomp.speed; + + bfa_trc(dport->bfa, dport->result.roundtrip_latency); + bfa_trc(dport->bfa, dport->result.est_cable_distance); + bfa_trc(dport->bfa, dport->result.buffer_required); + bfa_trc(dport->bfa, dport->result.frmsz); + bfa_trc(dport->bfa, dport->result.speed); + + for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) { + dport->result.subtest[i].status = + msg->info.testcomp.subtest_status[i]; + bfa_trc(dport->bfa, dport->result.subtest[i].status); + } + break; + + case BFI_DPORT_SCN_TESTSKIP: + case BFI_DPORT_SCN_DDPORT_ENABLE: + memset(&dport->result, 0, + sizeof(struct bfa_diag_dport_result_s)); + break; + + case BFI_DPORT_SCN_TESTSTART: + memset(&dport->result, 0, + sizeof(struct bfa_diag_dport_result_s)); + dport->rp_pwwn = msg->info.teststart.pwwn; + dport->rp_nwwn = msg->info.teststart.nwwn; + dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm); + bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO); + break; + + case BFI_DPORT_SCN_SUBTESTSTART: + subtesttype = msg->info.teststart.type; + dport->result.subtest[subtesttype].start_time = + bfa_get_log_time(); + dport->result.subtest[subtesttype].status = + DPORT_TEST_ST_INPRG; + + bfa_trc(dport->bfa, subtesttype); + bfa_trc(dport->bfa, + dport->result.subtest[subtesttype].start_time); + break; + + case BFI_DPORT_SCN_SFP_REMOVED: + case BFI_DPORT_SCN_DDPORT_DISABLED: + case BFI_DPORT_SCN_DDPORT_DISABLE: + case BFI_DPORT_SCN_FCPORT_DISABLE: + dport->result.status = DPORT_TEST_ST_IDLE; + break; + + default: + bfa_sm_fault(dport->bfa, msg->state); + } + + bfa_sm_send_event(dport, BFA_DPORT_SM_SCN); +} + /* * Dport enable * * @param[in] *bfa - bfa data struct */ bfa_status_t -bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) +bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat, + bfa_cb_diag_t cbfn, void *cbarg) { struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); struct bfa_dport_s *dport = &fcdiag->dport; @@ -6393,6 +6807,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) return BFA_STATUS_CMD_NOTSUPP_MEZZ; } + /* + * Dport is supported in CT2 or above + */ + if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) { + bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id); + return BFA_STATUS_FEATURE_NOT_SUPPORTED; + } + /* * Check to see if IOC is down */ @@ -6430,6 +6852,14 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) return BFA_STATUS_ERROR_TRUNK_ENABLED; } + /* + * Check if diag loopback is running + */ + if (bfa_fcdiag_lb_is_running(bfa)) { + bfa_trc(dport->bfa, 0); + return BFA_STATUS_DIAG_BUSY; + } + /* * Check to see if port is disable or in dport state */ @@ -6439,15 +6869,17 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) return BFA_STATUS_PORT_NOT_DISABLED; } + /* + * Check if dport is in dynamic mode + */ + if (dport->dynamic) + return BFA_STATUS_DDPORT_ERR; + /* * Check if dport is busy */ - if (bfa_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)) { + if (bfa_dport_is_sending_req(dport)) return BFA_STATUS_DEVBUSY; - } /* * Check if dport is already enabled @@ -6457,6 +6889,10 @@ bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) return BFA_STATUS_DPORT_ENABLED; } + bfa_trc(dport->bfa, lpcnt); + bfa_trc(dport->bfa, pat); + dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT; + dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT; dport->cbfn = cbfn; dport->cbarg = cbarg; @@ -6484,6 +6920,13 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) return BFA_STATUS_PBC; } + /* + * Check if dport is in dynamic mode + */ + if (dport->dynamic) { + return BFA_STATUS_DDPORT_ERR; + } + /* * Check to see if port is disable or in dport state */ @@ -6496,10 +6939,7 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) /* * 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)) + if (bfa_dport_is_sending_req(dport)) return BFA_STATUS_DEVBUSY; /* @@ -6518,30 +6958,105 @@ bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) } /* - * Get D-port state + * Dport start -- restart dport test * - * @param[in] *bfa - bfa data struct + * @param[in] *bfa - bfa data struct */ +bfa_status_t +bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat, + bfa_cb_diag_t cbfn, void *cbarg) +{ + struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); + struct bfa_dport_s *dport = &fcdiag->dport; + /* + * Check to see if IOC is down + */ + if (!bfa_iocfc_is_operational(bfa)) + return BFA_STATUS_IOC_NON_OP; + + /* + * Check if dport is in dynamic mode + */ + if (dport->dynamic) + return BFA_STATUS_DDPORT_ERR; + + /* + * Check if dport is busy + */ + if (bfa_dport_is_sending_req(dport)) + return BFA_STATUS_DEVBUSY; + + /* + * Check if dport is in enabled state. + * Test can only be restart when previous test has completed + */ + if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) { + bfa_trc(dport->bfa, 0); + return BFA_STATUS_DPORT_DISABLED; + + } else { + if (dport->test_state == BFA_DPORT_ST_NO_SFP) + return BFA_STATUS_DPORT_INV_SFP; + + if (dport->test_state == BFA_DPORT_ST_INP) + return BFA_STATUS_DEVBUSY; + + WARN_ON(dport->test_state != BFA_DPORT_ST_COMP); + } + + bfa_trc(dport->bfa, lpcnt); + bfa_trc(dport->bfa, pat); + + dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT; + dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT; + + dport->cbfn = cbfn; + dport->cbarg = cbarg; + + bfa_sm_send_event(dport, BFA_DPORT_SM_START); + return BFA_STATUS_OK; +} + +/* + * Dport show -- return dport test result + * + * @param[in] *bfa - bfa data struct + */ bfa_status_t -bfa_dport_get_state(struct bfa_s *bfa, enum bfa_dport_state *state) +bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result) { struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); struct bfa_dport_s *dport = &fcdiag->dport; - 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; + /* + * Check to see if IOC is down + */ + if (!bfa_iocfc_is_operational(bfa)) + return BFA_STATUS_IOC_NON_OP; + + /* + * Check if dport is busy + */ + if (bfa_dport_is_sending_req(dport)) + return BFA_STATUS_DEVBUSY; + + /* + * Check if dport is in enabled state. + */ + if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) { + bfa_trc(dport->bfa, 0); + return BFA_STATUS_DPORT_DISABLED; + } + + /* + * Check if there is SFP + */ + if (dport->test_state == BFA_DPORT_ST_NO_SFP) + return BFA_STATUS_DPORT_INV_SFP; + + memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s)); + return BFA_STATUS_OK; } diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 5af64de152b..ef07365991e 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -551,6 +551,7 @@ void bfa_fcport_event_register(struct bfa_s *bfa, enum bfa_port_linkstate event), void *event_cbarg); bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa); bfa_boolean_t bfa_fcport_is_dport(struct bfa_s *bfa); +bfa_boolean_t bfa_fcport_is_ddport(struct bfa_s *bfa); bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw); enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa); @@ -715,10 +716,18 @@ struct bfa_fcdiag_lb_s { 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; + union bfi_diag_dport_msg_u i2hmsg; + u8 test_state; /* enum dport_test_state */ + u8 dynamic; /* boolean_t */ + u8 rsvd[2]; + u32 lpcnt; + u32 payload; /* user defined payload pattern */ + wwn_t rp_pwwn; + wwn_t rp_nwwn; + struct bfa_diag_dport_result_s result; }; struct bfa_fcdiag_s { @@ -742,11 +751,13 @@ bfa_status_t bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore, u32 queue, struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn, void *cbarg); bfa_status_t bfa_fcdiag_lb_is_running(struct bfa_s *bfa); -bfa_status_t bfa_dport_enable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, - void *cbarg); +bfa_status_t bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat, + bfa_cb_diag_t cbfn, void *cbarg); bfa_status_t bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg); -bfa_status_t bfa_dport_get_state(struct bfa_s *bfa, - enum bfa_dport_state *state); +bfa_status_t bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat, + bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t bfa_dport_show(struct bfa_s *bfa, + struct bfa_diag_dport_result_s *result); #endif /* __BFA_SVC_H__ */ diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index bda1500e1a2..f31acfa3f11 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -1785,51 +1785,87 @@ 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) +bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd) { - struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; + struct bfa_bsg_dport_enable_s *iocmd = + (struct bfa_bsg_dport_enable_s *)pcmd; unsigned long flags; struct bfad_hal_comp fcomp; init_completion(&fcomp.comp); spin_lock_irqsave(&bfad->bfad_lock, flags); - 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); + iocmd->status = bfa_dport_enable(&bfad->bfa, iocmd->lpcnt, + iocmd->pat, bfad_hcb_comp, &fcomp); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + if (iocmd->status != BFA_STATUS_OK) + bfa_trc(bfad, iocmd->status); else { - bfa_trc(bfad, 0); - spin_unlock_irqrestore(&bfad->bfad_lock, flags); - return -EINVAL; + wait_for_completion(&fcomp.comp); + iocmd->status = fcomp.status; } - spin_unlock_irqrestore(&bfad->bfad_lock, flags); + return 0; +} +int +bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd) +{ + struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; + unsigned long flags; + struct bfad_hal_comp fcomp; + + init_completion(&fcomp.comp); + spin_lock_irqsave(&bfad->bfad_lock, flags); + iocmd->status = bfa_dport_disable(&bfad->bfa, bfad_hcb_comp, &fcomp); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); if (iocmd->status != BFA_STATUS_OK) bfa_trc(bfad, iocmd->status); else { wait_for_completion(&fcomp.comp); iocmd->status = fcomp.status; } + return 0; +} + +int +bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd) +{ + struct bfa_bsg_dport_enable_s *iocmd = + (struct bfa_bsg_dport_enable_s *)pcmd; + unsigned long flags; + struct bfad_hal_comp fcomp; + + init_completion(&fcomp.comp); + spin_lock_irqsave(&bfad->bfad_lock, flags); + iocmd->status = bfa_dport_start(&bfad->bfa, iocmd->lpcnt, + iocmd->pat, bfad_hcb_comp, + &fcomp); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); + + if (iocmd->status != BFA_STATUS_OK) { + bfa_trc(bfad, iocmd->status); + } else { + wait_for_completion(&fcomp.comp); + iocmd->status = fcomp.status; + } return 0; } int -bfad_iocmd_diag_dport_get_state(struct bfad_s *bfad, void *pcmd) +bfad_iocmd_diag_dport_show(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; + struct bfa_bsg_diag_dport_show_s *iocmd = + (struct bfa_bsg_diag_dport_show_s *)pcmd; + unsigned long flags; spin_lock_irqsave(&bfad->bfad_lock, flags); - iocmd->status = bfa_dport_get_state(&bfad->bfa, &iocmd->state); + iocmd->status = bfa_dport_show(&bfad->bfa, &iocmd->result); spin_unlock_irqrestore(&bfad->bfad_lock, flags); return 0; } + int bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd) { @@ -2934,11 +2970,16 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, rc = bfad_iocmd_diag_lb_stat(bfad, iocmd); break; case IOCMD_DIAG_DPORT_ENABLE: + rc = bfad_iocmd_diag_dport_enable(bfad, iocmd); + break; case IOCMD_DIAG_DPORT_DISABLE: - rc = bfad_iocmd_diag_cfg_dport(bfad, cmd, iocmd); + rc = bfad_iocmd_diag_dport_disable(bfad, iocmd); + break; + case IOCMD_DIAG_DPORT_SHOW: + rc = bfad_iocmd_diag_dport_show(bfad, iocmd); break; - case IOCMD_DIAG_DPORT_GET_STATE: - rc = bfad_iocmd_diag_dport_get_state(bfad, iocmd); + case IOCMD_DIAG_DPORT_START: + rc = bfad_iocmd_diag_dport_start(bfad, iocmd); break; case IOCMD_PHY_GET_ATTR: rc = bfad_iocmd_phy_get_attr(bfad, iocmd); diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index 612463b6006..3ef321cd7e2 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -144,7 +144,6 @@ enum { 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, @@ -153,6 +152,8 @@ enum { IOCMD_FRUVPD_READ, IOCMD_FRUVPD_UPDATE, IOCMD_FRUVPD_GET_MAX_SIZE, + IOCMD_DIAG_DPORT_SHOW, + IOCMD_DIAG_DPORT_START, }; struct bfa_bsg_gen_s { @@ -593,6 +594,21 @@ struct bfa_bsg_diag_loopback_s { struct bfa_diag_loopback_result_s result; }; +struct bfa_bsg_diag_dport_show_s { + bfa_status_t status; + u16 bfad_num; + u16 rsvd; + struct bfa_diag_dport_result_s result; +}; + +struct bfa_bsg_dport_enable_s { + bfa_status_t status; + u16 bfad_num; + u16 rsvd; + u16 lpcnt; + u16 pat; +}; + struct bfa_bsg_diag_fwping_s { bfa_status_t status; u16 bfad_num; @@ -640,13 +656,6 @@ 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; diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index 57b146bca18..e70e0832eaf 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -973,6 +973,7 @@ enum bfi_diag_i2h { BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST), BFI_DIAG_I2H_QTEST = BFA_I2HM(BFI_DIAG_H2I_QTEST), BFI_DIAG_I2H_DPORT = BFA_I2HM(BFI_DIAG_H2I_DPORT), + BFI_DIAG_I2H_DPORT_SCN = BFA_I2HM(8), }; #define BFI_DIAG_MAX_SGES 2 @@ -1064,16 +1065,73 @@ struct bfi_diag_qtest_req_s { enum bfi_dport_req { BFI_DPORT_DISABLE = 0, /* disable dport request */ BFI_DPORT_ENABLE = 1, /* enable dport request */ + BFI_DPORT_START = 2, /* start dport request */ + BFI_DPORT_SHOW = 3, /* show dport request */ + BFI_DPORT_DYN_DISABLE = 4, /* disable dynamic dport request */ +}; + +enum bfi_dport_scn { + BFI_DPORT_SCN_TESTSTART = 1, + BFI_DPORT_SCN_TESTCOMP = 2, + BFI_DPORT_SCN_SFP_REMOVED = 3, + BFI_DPORT_SCN_DDPORT_ENABLE = 4, + BFI_DPORT_SCN_DDPORT_DISABLE = 5, + BFI_DPORT_SCN_FCPORT_DISABLE = 6, + BFI_DPORT_SCN_SUBTESTSTART = 7, + BFI_DPORT_SCN_TESTSKIP = 8, + BFI_DPORT_SCN_DDPORT_DISABLED = 9, }; struct bfi_diag_dport_req_s { struct bfi_mhdr_s mh; /* 4 bytes */ - u8 req; /* request 1: enable 0: disable */ - u8 status; /* reply status */ - u8 rsvd[2]; - u32 msgtag; /* msgtag for reply */ + u8 req; /* request 1: enable 0: disable */ + u8 rsvd[3]; + u32 lpcnt; + u32 payload; +}; + +struct bfi_diag_dport_rsp_s { + struct bfi_mhdr_s mh; /* header 4 bytes */ + bfa_status_t status; /* reply status */ + wwn_t pwwn; /* switch port wwn. 8 bytes */ + wwn_t nwwn; /* switch node wwn. 8 bytes */ +}; + +struct bfi_diag_dport_scn_teststart_s { + wwn_t pwwn; /* switch port wwn. 8 bytes */ + wwn_t nwwn; /* switch node wwn. 8 bytes */ + u8 type; /* bfa_diag_dport_test_type_e */ + u8 rsvd[3]; + u32 numfrm; /* from switch uint in 1M */ +}; + +struct bfi_diag_dport_scn_testcomp_s { + u8 status; /* bfa_diag_dport_test_status_e */ + u8 speed; /* bfa_port_speed_t */ + u16 numbuffer; /* from switch */ + u8 subtest_status[DPORT_TEST_MAX]; /* 4 bytes */ + u32 latency; /* from switch */ + u32 distance; /* from swtich unit in meters */ + /* Buffers required to saturate the link */ + u16 frm_sz; /* from switch for buf_reqd */ + u8 rsvd[2]; +}; + +struct bfi_diag_dport_scn_s { /* max size == RDS_RMESZ */ + struct bfi_mhdr_s mh; /* header 4 bytes */ + u8 state; /* new state */ + u8 rsvd[3]; + union { + struct bfi_diag_dport_scn_teststart_s teststart; + struct bfi_diag_dport_scn_testcomp_s testcomp; + } info; +}; + +union bfi_diag_dport_msg_u { + struct bfi_diag_dport_req_s req; + struct bfi_diag_dport_rsp_s rsp; + struct bfi_diag_dport_scn_s scn; }; -#define bfi_diag_dport_rsp_t struct bfi_diag_dport_req_s /* * PHY module specific -- cgit v1.2.3-70-g09d2 From 1287641e945de1bf533178c2e0e31eed287b4a60 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:22 -0700 Subject: [SCSI] bfa: Fix WARN_ON condition check The WARN_ON condition check in IO completion path is wrong. IOtags returned by the firmware is compared with driver/bfa iotag after masking the retry count bits. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcpim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 27b56096235..d7385d1d9c5 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -2882,7 +2882,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) iotag = be16_to_cpu(rsp->io_tag); ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); - WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag); + WARN_ON(ioim->iotag != iotag); bfa_ioim_cb_profile_comp(fcpim, ioim); -- cgit v1.2.3-70-g09d2 From d7cbc3044f2b28837dd4a46824274294f8fa9d60 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:23 -0700 Subject: [SCSI] bfa: FDMI enhancements Update addl. fields in FDMI to confirm to FC-GS6 standard for RPA and RHBA commands. Signed-off-by: Anil Gurumurthy Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fc.h | 15 ++++ drivers/scsi/bfa/bfa_fcs.h | 21 ++++- drivers/scsi/bfa/bfa_fcs_lport.c | 190 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index bea821b9803..562ef739b0b 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -1531,6 +1531,12 @@ enum fdmi_hba_attribute_type { FDMI_HBA_ATTRIB_FW_VERSION, /* 0x0009 */ FDMI_HBA_ATTRIB_OS_NAME, /* 0x000A */ FDMI_HBA_ATTRIB_MAX_CT, /* 0x000B */ + FDMI_HBA_ATTRIB_NODE_SYM_NAME, /* 0x000C */ + FDMI_HBA_ATTRIB_VENDOR_INFO, /* 0x000D */ + FDMI_HBA_ATTRIB_NUM_PORTS, /* 0x000E */ + FDMI_HBA_ATTRIB_FABRIC_NAME, /* 0x000F */ + FDMI_HBA_ATTRIB_BIOS_VER, /* 0x0010 */ + FDMI_HBA_ATTRIB_VENDOR_ID = 0x00E0, FDMI_HBA_ATTRIB_MAX_TYPE }; @@ -1545,6 +1551,15 @@ enum fdmi_port_attribute_type { FDMI_PORT_ATTRIB_FRAME_SIZE, /* 0x0004 */ FDMI_PORT_ATTRIB_DEV_NAME, /* 0x0005 */ FDMI_PORT_ATTRIB_HOST_NAME, /* 0x0006 */ + FDMI_PORT_ATTRIB_NODE_NAME, /* 0x0007 */ + FDMI_PORT_ATTRIB_PORT_NAME, /* 0x0008 */ + FDMI_PORT_ATTRIB_PORT_SYM_NAME, /* 0x0009 */ + FDMI_PORT_ATTRIB_PORT_TYPE, /* 0x000A */ + FDMI_PORT_ATTRIB_SUPP_COS, /* 0x000B */ + FDMI_PORT_ATTRIB_PORT_FAB_NAME, /* 0x000C */ + FDMI_PORT_ATTRIB_PORT_FC4_TYPE, /* 0x000D */ + FDMI_PORT_ATTRIB_PORT_STATE = 0x101, /* 0x0101 */ + FDMI_PORT_ATTRIB_PORT_NUM_RPRT = 0x102, /* 0x0102 */ FDMI_PORT_ATTR_MAX_TYPE }; diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 1369682f63d..4f1e650f332 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -627,6 +627,9 @@ void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, #define BFA_FCS_FDMI_SUPP_SPEEDS_10G FDMI_TRANS_SPEED_10G +#define BFA_FCS_FDMI_VENDOR_INFO_LEN 8 +#define BFA_FCS_FDMI_FC4_TYPE_LEN 32 + /* * HBA Attribute Block : BFA internal representation. Note : Some variable * sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based @@ -637,25 +640,39 @@ struct bfa_fcs_fdmi_hba_attr_s { u8 manufacturer[64]; u8 serial_num[64]; u8 model[16]; - u8 model_desc[256]; + u8 model_desc[128]; u8 hw_version[8]; u8 driver_version[BFA_VERSION_LEN]; u8 option_rom_ver[BFA_VERSION_LEN]; u8 fw_version[BFA_VERSION_LEN]; u8 os_name[256]; __be32 max_ct_pyld; + struct bfa_lport_symname_s node_sym_name; + u8 vendor_info[BFA_FCS_FDMI_VENDOR_INFO_LEN]; + __be32 num_ports; + wwn_t fabric_name; + u8 bios_ver[BFA_VERSION_LEN]; }; /* * Port Attribute Block */ struct bfa_fcs_fdmi_port_attr_s { - u8 supp_fc4_types[32]; /* supported FC4 types */ + u8 supp_fc4_types[BFA_FCS_FDMI_FC4_TYPE_LEN]; __be32 supp_speed; /* supported speed */ __be32 curr_speed; /* current Speed */ __be32 max_frm_size; /* max frame size */ u8 os_device_name[256]; /* OS device Name */ u8 host_name[256]; /* host name */ + wwn_t port_name; + wwn_t node_name; + struct bfa_lport_symname_s port_sym_name; + __be32 port_type; + enum fc_cos scos; + wwn_t port_fabric_name; + u8 port_act_fc4_type[BFA_FCS_FDMI_FC4_TYPE_LEN]; + __be32 port_state; + __be32 num_ports; }; struct bfa_fcs_stats_s { diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 1224d0462a4..8773d5e10d3 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -2048,10 +2048,71 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT); templen = sizeof(fcs_hba_attr->max_ct_pyld); memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; len += templen; count++; attr->len = cpu_to_be16(templen + sizeof(attr->type) + sizeof(templen)); + /* + * Send extended attributes ( FOS 7.1 support ) + */ + if (fdmi->retry_cnt == 0) { + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME); + templen = sizeof(fcs_hba_attr->node_sym_name); + memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + count++; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID); + templen = sizeof(fcs_hba_attr->vendor_info); + memcpy(attr->value, &fcs_hba_attr->vendor_info, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + count++; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS); + templen = sizeof(fcs_hba_attr->num_ports); + memcpy(attr->value, &fcs_hba_attr->num_ports, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + count++; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME); + templen = sizeof(fcs_hba_attr->fabric_name); + memcpy(attr->value, &fcs_hba_attr->fabric_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + count++; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER); + templen = sizeof(fcs_hba_attr->bios_ver); + memcpy(attr->value, &fcs_hba_attr->bios_ver, templen); + templen = fc_roundup(attr->len, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + count++; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + } /* * Update size of payload @@ -2252,6 +2313,113 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi, sizeof(templen)); } + if (fdmi->retry_cnt == 0) { + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME); + templen = sizeof(fcs_port_attr.node_name); + memcpy(attr->value, &fcs_port_attr.node_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME); + templen = sizeof(fcs_port_attr.port_name); + memcpy(attr->value, &fcs_port_attr.port_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + if (fcs_port_attr.port_sym_name.symname[0] != '\0') { + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = + cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME); + templen = sizeof(fcs_port_attr.port_sym_name); + memcpy(attr->value, + &fcs_port_attr.port_sym_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + + sizeof(attr->type) + sizeof(templen)); + } + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE); + templen = sizeof(fcs_port_attr.port_type); + memcpy(attr->value, &fcs_port_attr.port_type, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS); + templen = sizeof(fcs_port_attr.scos); + memcpy(attr->value, &fcs_port_attr.scos, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME); + templen = sizeof(fcs_port_attr.port_fabric_name); + memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE); + templen = sizeof(fcs_port_attr.port_act_fc4_type); + memcpy(attr->value, fcs_port_attr.port_act_fc4_type, + templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE); + templen = sizeof(fcs_port_attr.port_state); + memcpy(attr->value, &fcs_port_attr.port_state, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + + attr = (struct fdmi_attr_s *) curr_ptr; + attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT); + templen = sizeof(fcs_port_attr.num_ports); + memcpy(attr->value, &fcs_port_attr.num_ports, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; + ++count; + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); + } + /* * Update size of payload */ @@ -2458,6 +2626,15 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, /* Retrieve the max frame size from the port attr */ bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size; + + strncpy(hba_attr->node_sym_name.symname, + port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN); + strcpy(hba_attr->vendor_info, "BROCADE"); + hba_attr->num_ports = + cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc)); + hba_attr->fabric_name = port->fabric->lps->pr_nwwn; + strncpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); + } static void @@ -2467,6 +2644,7 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, struct bfa_fcs_lport_s *port = fdmi->ms->port; struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; struct bfa_port_attr_s pport_attr; + struct bfa_lport_attr_s lport_attr; memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s)); @@ -2531,6 +2709,18 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, strncpy(port_attr->host_name, (char *)driver_info->host_machine_name, sizeof(port_attr->host_name)); + port_attr->node_name = bfa_fcs_lport_get_nwwn(port); + port_attr->port_name = bfa_fcs_lport_get_pwwn(port); + + strncpy(port_attr->port_sym_name.symname, + (char *)&bfa_fcs_lport_get_psym_name(port), BFA_SYMNAME_MAXLEN); + bfa_fcs_lport_get_attr(port, &lport_attr); + port_attr->port_type = cpu_to_be32(lport_attr.port_type); + port_attr->scos = pport_attr.cos_supported; + port_attr->port_fabric_name = port->fabric->lps->pr_nwwn; + fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type); + port_attr->port_state = cpu_to_be32(pport_attr.port_state); + port_attr->num_ports = cpu_to_be32(port->num_rports); } /* -- cgit v1.2.3-70-g09d2 From e1aaab89dee184646f7001850e1fe6d55090a728 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:24 -0700 Subject: [SCSI] bfa: Fix 1860 port initialize when ATC is enabled On Xen kernels, if ATC (address translation cache) is enabled, the first PCIe DMA read from the adapter fails with an error. This is due to a bug ASIC, which leads to a failure of 1860 ports to be initialised. This patch includes the fix to disable Invalidated Tag Match Enable capability by setting the bit 26 of CHIP_MISC_PRG to 0, by default it is set to 1. Signed-off-by: Anil Gurumurthy Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc_ct.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index de4e726a126..a8e52a10871 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -918,6 +918,16 @@ bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode) } } + /* + * The very first PCIe DMA Read done by LPU fails with a fatal error, + * when Address Translation Cache (ATC) has been enabled by system BIOS. + * + * Workaround: + * Disable Invalidated Tag Match Enable capability by setting the bit 26 + * of CHIP_MISC_PRG to 0, by default it is set to 1. + */ + r32 = readl(rb + CT2_CHIP_MISC_PRG); + writel((r32 & 0xfbffffff), (rb + CT2_CHIP_MISC_PRG)); /* * Mask the interrupts and clear any -- cgit v1.2.3-70-g09d2 From f2a0cc3ffd5ee123086b8e76522a85a937d89878 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:25 -0700 Subject: [SCSI] bfa: Fix FDISC timeout handling Retry FDISC a max of 6 times. Introduce new events to handle vport login fails due to max logins to fabric/switch. Signed-off-by: Anil Gurumurthy Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcs_lport.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 8773d5e10d3..2f61a5af365 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -5988,6 +5988,7 @@ enum bfa_fcs_vport_event { BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/ BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */ BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */ + BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */ }; static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, @@ -6173,6 +6174,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, break; case BFA_FCS_VPORT_SM_RSP_FAILED: + case BFA_FCS_VPORT_SM_FABRIC_MAX: bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); break; @@ -6243,6 +6245,7 @@ bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, case BFA_FCS_VPORT_SM_OFFLINE: case BFA_FCS_VPORT_SM_RSP_ERROR: case BFA_FCS_VPORT_SM_RSP_FAILED: + case BFA_FCS_VPORT_SM_FABRIC_MAX: case BFA_FCS_VPORT_SM_RSP_DUP_WWN: bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); @@ -6528,7 +6531,7 @@ bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) else { bfa_fcs_vport_aen_post(&vport->lport, BFA_LPORT_AEN_NPIV_FABRIC_MAX); - bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); + bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX); } break; @@ -6914,7 +6917,19 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) break; } - bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); + if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) + bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); + else + bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); + + break; + + case BFA_STATUS_ETIMER: + vport->vport_stats.fdisc_timeouts++; + if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) + bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); + else + bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); break; case BFA_STATUS_FABRIC_RJT: -- cgit v1.2.3-70-g09d2 From c679b599afa5dd38d20e058aa68bc94c1c1416a1 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:26 -0700 Subject: [SCSI] bfa: kdump fix on 815 and 825 adapters Root cause: When kernel crashes, On brocade 815/825 adapters, bfa IOC state machine and FW doesn't get a notification and hence are not cleanly shutdown. So registers holding driver/IOC state information are not reset back to valid disabled/parking values. This causes subsequent driver initialization to fail during kdump kernel boot. Fix description: during the initialization of first PCI function, reset corresponding register when unclean shutown is detect by reading chip registers. This will make sure that ioc/fw gets clean re-initialization. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc.c | 42 ++++++++++++--------- drivers/scsi/bfa/bfa_ioc.h | 6 +++ drivers/scsi/bfa/bfa_ioc_cb.c | 86 +++++++++++++++++++++++++++++++++++++++---- drivers/scsi/bfa/bfa_ioc_ct.c | 36 ++++++++++++++++++ drivers/scsi/bfa/bfi.h | 4 ++ 5 files changed, 150 insertions(+), 24 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 0116c1032e2..8928b68551c 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -67,6 +67,14 @@ BFA_TRC_FILE(CNA, IOC); ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc)) #define bfa_ioc_sync_complete(__ioc) \ ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc)) +#define bfa_ioc_set_cur_ioc_fwstate(__ioc, __fwstate) \ + ((__ioc)->ioc_hwif->ioc_set_fwstate(__ioc, __fwstate)) +#define bfa_ioc_get_cur_ioc_fwstate(__ioc) \ + ((__ioc)->ioc_hwif->ioc_get_fwstate(__ioc)) +#define bfa_ioc_set_alt_ioc_fwstate(__ioc, __fwstate) \ + ((__ioc)->ioc_hwif->ioc_set_alt_fwstate(__ioc, __fwstate)) +#define bfa_ioc_get_alt_ioc_fwstate(__ioc) \ + ((__ioc)->ioc_hwif->ioc_get_alt_fwstate(__ioc)) #define bfa_ioc_mbox_cmd_pending(__ioc) \ (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ @@ -698,7 +706,7 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf) } /* h/w sem init */ - fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate); + fwstate = bfa_ioc_get_cur_ioc_fwstate(iocpf->ioc); if (fwstate == BFI_IOC_UNINIT) { writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg); goto sem_get; @@ -725,8 +733,8 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf) bfa_trc(iocpf->ioc, fwstate); bfa_trc(iocpf->ioc, swab32(fwhdr.exec)); - writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate); - writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.alt_ioc_fwstate); + bfa_ioc_set_cur_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT); + bfa_ioc_set_alt_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT); /* * Unlock the hw semaphore. Should be here only once per boot. @@ -1037,7 +1045,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) */ case IOCPF_E_TIMEOUT: - writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); break; @@ -1138,7 +1146,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) case IOCPF_E_SEMLOCKED: bfa_ioc_notify_fail(ioc); bfa_ioc_sync_leave(ioc); - writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); break; @@ -1227,7 +1235,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) bfa_ioc_notify_fail(ioc); if (!iocpf->auto_recover) { bfa_ioc_sync_leave(ioc); - writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); } else { @@ -1519,7 +1527,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force) u32 boot_type; u32 boot_env; - ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); + ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc); if (force) ioc_fwstate = BFI_IOC_UNINIT; @@ -2006,11 +2014,11 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env) * Initialize IOC state of all functions on a chip reset. */ if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) { - writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate); - writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate); + bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_MEMTEST); + bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_MEMTEST); } else { - writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate); - writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate); + bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_INITING); + bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_INITING); } bfa_ioc_msgflush(ioc); @@ -2038,7 +2046,7 @@ bfa_ioc_is_operational(struct bfa_ioc_s *ioc) bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc) { - u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); + u32 r32 = bfa_ioc_get_cur_ioc_fwstate(ioc); return ((r32 != BFI_IOC_UNINIT) && (r32 != BFI_IOC_INITING) && @@ -2430,12 +2438,12 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled)) return BFA_FALSE; - ioc_state = readl(ioc->ioc_regs.ioc_fwstate); + ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc); if (!bfa_ioc_state_disabled(ioc_state)) return BFA_FALSE; if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) { - ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate); + ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc); if (!bfa_ioc_state_disabled(ioc_state)) return BFA_FALSE; } @@ -2449,8 +2457,8 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) void bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc) { - writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); - writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); + bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_UNINIT); + bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_UNINIT); } #define BFA_MFG_NAME "Brocade" @@ -2917,7 +2925,7 @@ bfa_iocpf_sem_timeout(void *ioc_arg) static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc) { - u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate); + u32 fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc); bfa_trc(ioc, fwstate); diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 23a90e7b710..de62b68beb6 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -346,6 +346,12 @@ struct bfa_ioc_hwif_s { void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); bfa_boolean_t (*ioc_sync_complete) (struct bfa_ioc_s *ioc); bfa_boolean_t (*ioc_lpu_read_stat) (struct bfa_ioc_s *ioc); + void (*ioc_set_fwstate) (struct bfa_ioc_s *ioc, + enum bfi_ioc_state fwstate); + enum bfi_ioc_state (*ioc_get_fwstate) (struct bfa_ioc_s *ioc); + void (*ioc_set_alt_fwstate) (struct bfa_ioc_s *ioc, + enum bfi_ioc_state fwstate); + enum bfi_ioc_state (*ioc_get_alt_fwstate) (struct bfa_ioc_s *ioc); }; /* diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index 30df8a28471..e3b92874667 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -22,6 +22,8 @@ BFA_TRC_FILE(CNA, IOC_CB); +#define bfa_ioc_cb_join_pos(__ioc) ((u32) (1 << BFA_IOC_CB_JOIN_SH)) + /* * forward declarations */ @@ -37,6 +39,12 @@ static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_set_cur_ioc_fwstate( + struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_set_alt_ioc_fwstate( + struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc); static struct bfa_ioc_hwif_s hwif_cb; @@ -59,6 +67,10 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete; + hwif_cb.ioc_set_fwstate = bfa_ioc_cb_set_cur_ioc_fwstate; + hwif_cb.ioc_get_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate; + hwif_cb.ioc_set_alt_fwstate = bfa_ioc_cb_set_alt_ioc_fwstate; + hwif_cb.ioc_get_alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate; ioc->ioc_hwif = &hwif_cb; } @@ -187,6 +199,20 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc) { + u32 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); + + /** + * Driver load time. If the join bit is set, + * it is due to an unclean exit by the driver for this + * PCI fn in the previous incarnation. Whoever comes here first + * should clean it up, no matter which PCI fn. + */ + if (ioc_fwstate & BFA_IOC_CB_JOIN_MASK) { + writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); + writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); + return BFA_TRUE; + } + return bfa_ioc_cb_sync_complete(ioc); } @@ -212,24 +238,66 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc) static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc) { + u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); + u32 join_pos = bfa_ioc_cb_join_pos(ioc); + + writel((r32 | join_pos), ioc->ioc_regs.ioc_fwstate); } static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc) { + u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); + u32 join_pos = bfa_ioc_cb_join_pos(ioc); + + writel((r32 & ~join_pos), ioc->ioc_regs.ioc_fwstate); +} + +static void +bfa_ioc_cb_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc, + enum bfi_ioc_state fwstate) +{ + u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); + + writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)), + ioc->ioc_regs.ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc) +{ + return (enum bfi_ioc_state)(readl(ioc->ioc_regs.ioc_fwstate) & + BFA_IOC_CB_FWSTATE_MASK); +} + +static void +bfa_ioc_cb_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc, + enum bfi_ioc_state fwstate) +{ + u32 r32 = readl(ioc->ioc_regs.alt_ioc_fwstate); + + writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)), + ioc->ioc_regs.alt_ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc) +{ + return (enum bfi_ioc_state)(readl(ioc->ioc_regs.alt_ioc_fwstate) & + BFA_IOC_CB_FWSTATE_MASK); } static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc) { - writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + bfa_ioc_cb_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); } static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc) { - uint32_t fwstate, alt_fwstate; - fwstate = readl(ioc->ioc_regs.ioc_fwstate); + u32 fwstate, alt_fwstate; + fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc); /* * At this point, this IOC is hoding the hw sem in the @@ -257,7 +325,7 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc) fwstate == BFI_IOC_OP) return BFA_TRUE; else { - alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate); + alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc); if (alt_fwstate == BFI_IOC_FAIL || alt_fwstate == BFI_IOC_DISABLED || alt_fwstate == BFI_IOC_UNINIT || @@ -272,7 +340,7 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc) bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode) { - u32 pll_sclk, pll_fclk; + u32 pll_sclk, pll_fclk, join_bits; pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_P0_1(3U) | @@ -282,8 +350,12 @@ bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode) __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) | __APP_PLL_LCLK_JITLMT0_1(3U) | __APP_PLL_LCLK_CNTLMT0_1(3U); - writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG)); - writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG)); + join_bits = readl(rb + BFA_IOC0_STATE_REG) & + BFA_IOC_CB_JOIN_MASK; + writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC0_STATE_REG)); + join_bits = readl(rb + BFA_IOC1_STATE_REG) & + BFA_IOC_CB_JOIN_MASK; + writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC1_STATE_REG)); writel(0xffffffffU, (rb + HOSTFN0_INT_MSK)); writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS)); diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index a8e52a10871..bd53150e4ee 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -43,6 +43,12 @@ static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_set_cur_ioc_fwstate( + struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_set_alt_ioc_fwstate( + struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc); static struct bfa_ioc_hwif_s hwif_ct; static struct bfa_ioc_hwif_s hwif_ct2; @@ -512,6 +518,10 @@ bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif) hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave; hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack; hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete; + hwif->ioc_set_fwstate = bfa_ioc_ct_set_cur_ioc_fwstate; + hwif->ioc_get_fwstate = bfa_ioc_ct_get_cur_ioc_fwstate; + hwif->ioc_set_alt_fwstate = bfa_ioc_ct_set_alt_ioc_fwstate; + hwif->ioc_get_alt_fwstate = bfa_ioc_ct_get_alt_ioc_fwstate; } /** @@ -959,3 +969,29 @@ bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode) return BFA_STATUS_OK; } + +static void +bfa_ioc_ct_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc, + enum bfi_ioc_state fwstate) +{ + writel(fwstate, ioc->ioc_regs.ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc) +{ + return (enum bfi_ioc_state)readl(ioc->ioc_regs.ioc_fwstate); +} + +static void +bfa_ioc_ct_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc, + enum bfi_ioc_state fwstate) +{ + writel(fwstate, ioc->ioc_regs.alt_ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc) +{ + return (enum bfi_ioc_state) readl(ioc->ioc_regs.alt_ioc_fwstate); +} diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index e70e0832eaf..bf0a58d03be 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -374,6 +374,10 @@ enum bfi_ioc_state { BFI_IOC_MEMTEST = 9, /* IOC is doing memtest */ }; +#define BFA_IOC_CB_JOIN_SH 16 +#define BFA_IOC_CB_FWSTATE_MASK 0x0000ffff +#define BFA_IOC_CB_JOIN_MASK 0xffff0000 + #define BFI_IOC_ENDIAN_SIG 0x12345678 enum { -- cgit v1.2.3-70-g09d2 From bccd2683df56ddce98964f93f6984df743004240 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:27 -0700 Subject: [SCSI] bfa: driver compatibility with 32bit libs Replaced usage of void * with u64 in data structure shared between brocade user space libraries and the bfa driver to address pointer size changes across 32-bit vs 64-bit to have the compatibility between 32bit library and 64bit driver and vice versa. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad_bsg.c | 7 ++++--- drivers/scsi/bfa/bfad_bsg.h | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index f31acfa3f11..9863b1c2e56 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -3371,7 +3371,8 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job) goto out; } - if (copy_from_user((uint8_t *)bsg_fcpt, bsg_data->payload, + if (copy_from_user((uint8_t *)bsg_fcpt, + (void *)(unsigned long)bsg_data->payload, bsg_data->payload_len)) { kfree(bsg_fcpt); rc = -EIO; @@ -3525,8 +3526,8 @@ out_free_mem: kfree(rsp_kbuf); /* Need a copy to user op */ - if (copy_to_user(bsg_data->payload, (void *) bsg_fcpt, - bsg_data->payload_len)) + if (copy_to_user((void *)(unsigned long)bsg_data->payload, + (void *)bsg_fcpt, bsg_data->payload_len)) rc = -EIO; kfree(bsg_fcpt); diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index 3ef321cd7e2..b0b5ac7a75f 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -819,10 +819,12 @@ struct bfa_bsg_fcpt_s { }; #define bfa_bsg_fcpt_t struct bfa_bsg_fcpt_s +#pragma pack(1) struct bfa_bsg_data { int payload_len; - void *payload; + u64 payload; }; +#pragma pack() #define bfad_chk_iocmd_sz(__payload_len, __hdrsz, __bufsz) \ (((__payload_len) != ((__hdrsz) + (__bufsz))) ? \ -- cgit v1.2.3-70-g09d2 From 079bcbc35ca9241abf212a795a000b2d6c2038cd Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:28 -0700 Subject: [SCSI] bfa: fru vpd date update changes 1. While FRU VPD data update, inform firmware to send a completion event on I2C bus. Without this change, firmware used to send completion message on I2C bus for every chunk of FRU VPD update. 2. Support for FRU VPN update on CHINOOK2 cards. 3. Append port count to the model name to differentiate between single port and dual port model of 1860. 4. Update the size of the model name to 16bytes Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs.h | 9 +++++++-- drivers/scsi/bfa/bfa_fcs.h | 8 ++++---- drivers/scsi/bfa/bfa_ioc.c | 29 +++++++++++++++++++++-------- drivers/scsi/bfa/bfa_ioc.h | 3 ++- drivers/scsi/bfa/bfad_bsg.c | 2 +- drivers/scsi/bfa/bfad_bsg.h | 4 +++- drivers/scsi/bfa/bfi.h | 6 +++++- 7 files changed, 43 insertions(+), 18 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index d65a9b4a6f6..bef16d27666 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -45,6 +45,7 @@ enum { BFA_MFG_TYPE_PROWLER_C = 1710, /* Prowler CNA only cards */ BFA_MFG_TYPE_PROWLER_D = 1860, /* Prowler Dual cards */ BFA_MFG_TYPE_CHINOOK = 1867, /* Chinook cards */ + BFA_MFG_TYPE_CHINOOK2 = 1869, /*!< Chinook2 cards */ BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */ }; @@ -59,7 +60,8 @@ enum { (type) == BFA_MFG_TYPE_ASTRA || \ (type) == BFA_MFG_TYPE_LIGHTNING_P0 || \ (type) == BFA_MFG_TYPE_LIGHTNING || \ - (type) == BFA_MFG_TYPE_CHINOOK)) + (type) == BFA_MFG_TYPE_CHINOOK || \ + (type) == BFA_MFG_TYPE_CHINOOK2)) /* * Check if the card having old wwn/mac handling @@ -263,6 +265,7 @@ enum { BFA_ADAPTER_MFG_NAME_LEN = 8, /* manufacturer name length */ BFA_ADAPTER_SYM_NAME_LEN = 64, /* adapter symbolic name length */ BFA_ADAPTER_OS_TYPE_LEN = 64, /* adapter os type length */ + BFA_ADAPTER_UUID_LEN = 16, /* adapter uuid length */ }; struct bfa_adapter_attr_s { @@ -296,6 +299,7 @@ struct bfa_adapter_attr_s { u8 mfg_month; /* manufacturing month */ u16 mfg_year; /* manufacturing year */ u16 rsvd; + u8 uuid[BFA_ADAPTER_UUID_LEN]; }; /* @@ -409,7 +413,8 @@ struct bfa_ioc_attr_s { u8 port_mode; /* bfa_mode_s */ u8 cap_bm; /* capability */ u8 port_mode_cfg; /* bfa_mode_s */ - u8 rsvd[4]; /* 64bit align */ + u8 def_fn; /* 1 if default fn */ + u8 rsvd[3]; /* 64bit align */ }; /* diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 4f1e650f332..94d5d0102f7 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -243,19 +243,19 @@ struct bfa_fcs_fabric_s; * Symbolic Name. * * Physical Port's symbolic name Format : (Total 128 bytes) - * Adapter Model number/name : 12 bytes + * Adapter Model number/name : 16 bytes * Driver Version : 10 bytes * Host Machine Name : 30 bytes - * Host OS Info : 48 bytes + * Host OS Info : 44 bytes * Host OS PATCH Info : 16 bytes * ( remaining 12 bytes reserved to be used for separator) */ #define BFA_FCS_PORT_SYMBNAME_SEPARATOR " | " -#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 12 +#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 16 #define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 10 #define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 30 -#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48 +#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 44 #define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16 /* diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 8928b68551c..c31cb3ca07e 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -2508,6 +2508,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, ad_attr->mfg_day = ioc_attr->mfg_day; ad_attr->mfg_month = ioc_attr->mfg_month; ad_attr->mfg_year = ioc_attr->mfg_year; + memcpy(ad_attr->uuid, ioc_attr->uuid, BFA_ADAPTER_UUID_LEN); } enum bfa_ioc_type_e @@ -2572,13 +2573,19 @@ void bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model) { struct bfi_ioc_attr_s *ioc_attr; + u8 nports = bfa_ioc_get_nports(ioc); WARN_ON(!model); memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN); ioc_attr = ioc->attr; - snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u", + if (bfa_asic_id_ct2(ioc->pcidev.device_id) && + (!bfa_mfg_is_mezz(ioc_attr->card_type))) + snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u-%u%s", + BFA_MFG_NAME, ioc_attr->card_type, nports, "p"); + else + snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u", BFA_MFG_NAME, ioc_attr->card_type); } @@ -2628,7 +2635,7 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr) memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s)); ioc_attr->state = bfa_ioc_get_state(ioc); - ioc_attr->port_id = ioc->port_id; + ioc_attr->port_id = bfa_ioc_portid(ioc); ioc_attr->port_mode = ioc->port_mode; ioc_attr->port_mode_cfg = ioc->port_mode_cfg; ioc_attr->cap_bm = ioc->ad_cap_bm; @@ -2637,8 +2644,9 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr) bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr); - ioc_attr->pci_attr.device_id = ioc->pcidev.device_id; - ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func; + ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc); + ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc); + ioc_attr->def_fn = (bfa_ioc_pcifn(ioc) == bfa_ioc_portid(ioc)); bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev); } @@ -6018,6 +6026,7 @@ bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type) */ msg->last = (len == fru->residue) ? 1 : 0; + msg->trfr_cmpl = (len == fru->residue) ? fru->trfr_cmpl : 0; bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc)); bfa_alen_set(&msg->alen, len, fru->dbuf_pa); @@ -6132,13 +6141,14 @@ bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa, */ 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_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl) { bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ); bfa_trc(fru, len); bfa_trc(fru, offset); - if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2) + if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2 && + fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2) return BFA_STATUS_FRU_NOT_PRESENT; if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK) @@ -6160,6 +6170,7 @@ bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset, fru->offset = 0; fru->addr_off = offset; fru->ubuf = buf; + fru->trfr_cmpl = trfr_cmpl; bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ); @@ -6189,7 +6200,8 @@ bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 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) + if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK && + fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2) return BFA_STATUS_CMD_NOTSUPP; if (!bfa_ioc_is_operational(fru->ioc)) @@ -6230,7 +6242,8 @@ bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size) if (!bfa_ioc_is_operational(fru->ioc)) return BFA_STATUS_IOC_NON_OP; - if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK) + if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK || + fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK2) *max_size = BFA_FRU_CHINOOK_MAX_SIZE; else return BFA_STATUS_CMD_NOTSUPP; diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index de62b68beb6..90814fe85ac 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -731,6 +731,7 @@ struct bfa_fru_s { struct bfa_mbox_cmd_s mb; /* mailbox */ struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */ struct bfa_mem_dma_s fru_dma; + u8 trfr_cmpl; }; #define BFA_FRU(__bfa) (&(__bfa)->modules.fru) @@ -738,7 +739,7 @@ struct bfa_fru_s { 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_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl); bfa_status_t bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset, bfa_cb_fru_t cbfn, void *cbarg); diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 9863b1c2e56..0467c349251 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -2716,7 +2716,7 @@ bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd) 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); + bfad_hcb_comp, &fcomp, iocmd->trfr_cmpl); spin_unlock_irqrestore(&bfad->bfad_lock, flags); if (iocmd->status == BFA_STATUS_OK) { wait_for_completion(&fcomp.comp); diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index b0b5ac7a75f..05f0fc9cf06 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -794,10 +794,12 @@ struct bfa_bsg_tfru_s { struct bfa_bsg_fruvpd_s { bfa_status_t status; u16 bfad_num; - u16 rsvd; + u16 rsvd1; u32 offset; u32 len; u8 data[BFA_MAX_FRUVPD_TRANSFER_SIZE]; + u8 trfr_cmpl; + u8 rsvd2[3]; }; struct bfa_bsg_fruvpd_max_size_s { diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index bf0a58d03be..37bd2564e83 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -264,6 +264,7 @@ struct bfi_ioc_getattr_req_s { union bfi_addr_u attr_addr; }; +#define BFI_IOC_ATTR_UUID_SZ 16 struct bfi_ioc_attr_s { wwn_t mfg_pwwn; /* Mfg port wwn */ wwn_t mfg_nwwn; /* Mfg node wwn */ @@ -292,6 +293,7 @@ struct bfi_ioc_attr_s { u8 mfg_day; /* manufacturing day */ u8 mfg_month; /* manufacturing month */ u16 mfg_year; /* manufacturing year */ + u8 uuid[BFI_IOC_ATTR_UUID_SZ]; /*!< chinook uuid */ }; /* @@ -1253,7 +1255,9 @@ enum bfi_fru_i2h_msgs { struct bfi_fru_write_req_s { struct bfi_mhdr_s mh; /* Common msg header */ u8 last; - u8 rsv[3]; + u8 rsv_1[3]; + u8 trfr_cmpl; + u8 rsv_2[3]; u32 offset; u32 length; struct bfi_alen_s alen; -- cgit v1.2.3-70-g09d2 From f52c98d4079df695ece1b2cd82fb5dc9372badf6 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:29 -0700 Subject: [SCSI] bfa: firmware statistics update Get RDS drop interrupts and REC (Read Exchange Concise) related stats from firmware. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs_svc.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index 2f20ba5f57b..638f441ffc3 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -105,6 +105,9 @@ struct bfa_fw_ioim_stats_s { * an error condition*/ u32 wait_for_si; /* FW wait for SI */ u32 rec_rsp_inval; /* REC rsp invalid */ + u32 rec_rsp_xchg_comp; /* REC rsp xchg complete */ + u32 rec_rsp_rd_si_ownd; /* REC rsp read si owned */ + u32 seqr_io_abort; /* target does not know cmd so abort */ u32 seqr_io_retry; /* SEQR failed so retry IO */ @@ -482,6 +485,14 @@ struct bfa_fw_ct_mod_stats_s { u32 rsvd; /* 64bit align */ }; +/* + * RDS mod stats + */ +struct bfa_fw_rds_stats_s { + u32 no_fid_drop_err; /* RDS no fid drop error */ + u32 rsvd; /* 64bit align */ +}; + /* * IOC firmware stats */ @@ -497,6 +508,7 @@ struct bfa_fw_stats_s { struct bfa_fw_mac_mod_stats_s macmod_stats; struct bfa_fw_ct_mod_stats_s ctmod_stats; struct bfa_fw_eth_sndrcv_stats_s ethsndrcv_stats; + struct bfa_fw_rds_stats_s rds_stats; }; #define BFA_IOCFC_PATHTOV_MAX 60 -- cgit v1.2.3-70-g09d2 From ea3837a7121a18f5a4f3be2b8c66ab78d8263988 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:30 -0700 Subject: [SCSI] bfa: Allow rsp queue process during ioc disable Allow processing completions from firmware during IOC_DISABLE request is being processed by the firmware, by setting the queue_process flag appropriately. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 342d7d9c099..520540a5fef 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -1432,6 +1432,7 @@ bfa_iocfc_disable_cbfn(void *bfa_arg) { struct bfa_s *bfa = bfa_arg; + bfa->queue_process = BFA_FALSE; bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_IOC_DISABLED); } @@ -1567,7 +1568,6 @@ bfa_iocfc_start(struct bfa_s *bfa) void bfa_iocfc_stop(struct bfa_s *bfa) { - bfa->queue_process = BFA_FALSE; bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_STOP); } @@ -1674,7 +1674,6 @@ bfa_iocfc_disable(struct bfa_s *bfa) bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0, "IOC Disable"); - bfa->queue_process = BFA_FALSE; bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DISABLE); } -- cgit v1.2.3-70-g09d2 From 36ec9712d5c353636f3be959c153f9b2199854de Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:31 -0700 Subject: [SCSI] bfa: Fix bug_on condition in RPSC rsp handling Fix bug_on condition check in RPSC (Report Port Speed Capabilities) response processing. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcs_rport.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 62713a7c2da..2035b0d6435 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -3430,9 +3430,10 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, num_ents = be16_to_cpu(rpsc2_acc->num_pids); bfa_trc(rport->fcs, num_ents); if (num_ents > 0) { - WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid); + WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) != + bfa_ntoh3b(rport->pid)); bfa_trc(rport->fcs, - be16_to_cpu(rpsc2_acc->port_info[0].pid)); + be32_to_cpu(rpsc2_acc->port_info[0].pid)); bfa_trc(rport->fcs, be16_to_cpu(rpsc2_acc->port_info[0].speed)); bfa_trc(rport->fcs, -- cgit v1.2.3-70-g09d2 From ba1340788ff3023b1b083db96d82f546b8401ffd Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:32 -0700 Subject: [SCSI] bfa: fix endianess issue for firmware stats Fix endianess issue on Big-endian architecture for firmware statistics Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index c31cb3ca07e..a4f37414774 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -1858,7 +1858,7 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz) bfa_trc(ioc, len); for (i = 0; i < len; i++) { r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff); - buf[i] = be32_to_cpu(r32); + buf[i] = swab32(r32); loff += sizeof(u32); /* -- cgit v1.2.3-70-g09d2 From f9c867b45c7c1be4c4920471250a52a053c7a8c2 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:33 -0700 Subject: [SCSI] bfa: Support for chinook-quad port card This patch enables support for chinook quad port 16G FC card (falcon) Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs.h | 5 ++++- drivers/scsi/bfa/bfa_ioc.c | 1 + drivers/scsi/bfa/bfad.c | 8 ++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index bef16d27666..d40a79f5265 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -637,6 +637,7 @@ enum { BFA_PCI_DEVICE_ID_CT = 0x14, BFA_PCI_DEVICE_ID_CT_FC = 0x21, BFA_PCI_DEVICE_ID_CT2 = 0x22, + BFA_PCI_DEVICE_ID_CT2_QUAD = 0x23, }; #define bfa_asic_id_cb(__d) \ @@ -645,7 +646,9 @@ enum { #define bfa_asic_id_ct(__d) \ ((__d) == BFA_PCI_DEVICE_ID_CT || \ (__d) == BFA_PCI_DEVICE_ID_CT_FC) -#define bfa_asic_id_ct2(__d) ((__d) == BFA_PCI_DEVICE_ID_CT2) +#define bfa_asic_id_ct2(__d) \ + ((__d) == BFA_PCI_DEVICE_ID_CT2 || \ + (__d) == BFA_PCI_DEVICE_ID_CT2_QUAD) #define bfa_asic_id_ctc(__d) \ (bfa_asic_id_ct(__d) || bfa_asic_id_ct2(__d)) diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index a4f37414774..f78bcb6696b 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -2196,6 +2196,7 @@ bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, break; case BFA_PCI_DEVICE_ID_CT2: + case BFA_PCI_DEVICE_ID_CT2_QUAD: ioc->asic_gen = BFI_ASIC_GEN_CT2; if (clscode == BFI_PCIFN_CLASS_FC && pcidev->ssid == BFA_PCI_CT2_SSID_FC) { diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index a5f7690e819..bf5c5d33c90 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1720,6 +1720,14 @@ struct pci_device_id bfad_id_table[] = { .class_mask = ~0, }, + { + .vendor = BFA_PCI_VENDOR_ID_BROCADE, + .device = BFA_PCI_DEVICE_ID_CT2_QUAD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class = (PCI_CLASS_SERIAL_FIBER << 8), + .class_mask = ~0, + }, {0, 0}, }; -- cgit v1.2.3-70-g09d2 From 4dde506944f8ea3431bf4a250c13621c8f3939bb Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:34 -0700 Subject: [SCSI] bfa: dis-associate bfa path_tov with dev_loss_tmo Disassoicate path_tov in the driver with the dev_loss_tmo set by the application. Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad_attr.c | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 72f5dc32cc1..e9a681d3122 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -334,24 +334,11 @@ bfad_im_reset_stats(struct Scsi_Host *shost) return; } -/* - * FC transport template entry, get rport loss timeout. - */ -static void -bfad_im_get_rport_loss_tmo(struct fc_rport *rport) -{ - struct bfad_itnim_data_s *itnim_data = rport->dd_data; - struct bfad_itnim_s *itnim = itnim_data->itnim; - struct bfad_s *bfad = itnim->im->bfad; - unsigned long flags; - - spin_lock_irqsave(&bfad->bfad_lock, flags); - rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); - spin_unlock_irqrestore(&bfad->bfad_lock, flags); -} - /* * FC transport template entry, set rport loss timeout. + * Update dev_loss_tmo based on the value pushed down by the stack + * In case it is lesser than path_tov of driver, set it to path_tov + 1 + * to ensure that the driver times out before the application */ static void bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) @@ -359,15 +346,11 @@ bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) struct bfad_itnim_data_s *itnim_data = rport->dd_data; struct bfad_itnim_s *itnim = itnim_data->itnim; struct bfad_s *bfad = itnim->im->bfad; - unsigned long flags; - - if (timeout > 0) { - spin_lock_irqsave(&bfad->bfad_lock, flags); - bfa_fcpim_path_tov_set(&bfad->bfa, timeout); - rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); - spin_unlock_irqrestore(&bfad->bfad_lock, flags); - } + uint16_t path_tov = bfa_fcpim_path_tov_get(&bfad->bfa); + rport->dev_loss_tmo = timeout; + if (timeout < path_tov) + rport->dev_loss_tmo = path_tov + 1; } static int @@ -665,7 +648,6 @@ struct fc_function_template bfad_im_fc_function_template = { .show_rport_maxframe_size = 1, .show_rport_supported_classes = 1, .show_rport_dev_loss_tmo = 1, - .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, .issue_fc_host_lip = bfad_im_issue_fc_host_lip, .vport_create = bfad_im_vport_create, @@ -723,7 +705,6 @@ struct fc_function_template bfad_im_vport_fc_function_template = { .show_rport_maxframe_size = 1, .show_rport_supported_classes = 1, .show_rport_dev_loss_tmo = 1, - .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, }; -- cgit v1.2.3-70-g09d2 From 607be2cff4f4899f47ef906eba5b147abc3c5da4 Mon Sep 17 00:00:00 2001 From: Vijaya Mohan Guvva Date: Mon, 13 May 2013 02:33:35 -0700 Subject: [SCSI] bfa: Update the driver version to 3.2.21.1 Update bfa driver version to 3.2.21.1 Update bfa to use firmware image versions 3.2.1.0 Signed-off-by: Vijaya Mohan Guvva Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad.c | 6 +++--- drivers/scsi/bfa/bfad_drv.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/bfa') diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index bf5c5d33c90..9611195d670 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -63,9 +63,9 @@ int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS; u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size; u32 *bfi_image_cb, *bfi_image_ct, *bfi_image_ct2; -#define BFAD_FW_FILE_CB "cbfw-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" +#define BFAD_FW_FILE_CB "cbfw-3.2.1.0.bin" +#define BFAD_FW_FILE_CT "ctfw-3.2.1.0.bin" +#define BFAD_FW_FILE_CT2 "ct2fw-3.2.1.0.bin" static u32 *bfad_load_fwimg(struct pci_dev *pdev); static void bfad_free_fwimg(void); diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 0c64a04f01f..78d3401bc16 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -57,7 +57,7 @@ #ifdef BFA_DRIVER_VERSION #define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION #else -#define BFAD_DRIVER_VERSION "3.1.2.1" +#define BFAD_DRIVER_VERSION "3.2.21.1" #endif #define BFAD_PROTO_NAME FCPI_NAME -- cgit v1.2.3-70-g09d2