aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa/bfa_fcs_lport.c
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2011-06-24 23:24:52 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-06-29 18:12:11 -0400
commitd7be54cc5c5f6f9cb9ac67462aadda57813698b8 (patch)
tree2f77812fe06a7ed59172a51f11166aadd6a262d8 /drivers/scsi/bfa/bfa_fcs_lport.c
parent4507025d01149aea8705e43508d0ef11e7010cfd (diff)
[SCSI] bfa: FCS bug fixes.
- Added logic to initiate a PLOGI to the target, while processing a LOGO from the same target in Direct attach mode. - Added logic to generate a FCCT Reject indicating unsupported command, upon receiving FCCT/FCGS requests. - Added logic to set the fcpim in offline state and avoid any PRLI retries if a PRLI response is a reject with a reason Command Not Supported. - Updated the FDMI Supported/Current speeds. - Added logic to wait for the response from the firmware before sending ACC to PLOGI and transitioning to subsequent states - while processing an Incoming PLOGI in online state. - Added a wait state in the fcs_vport state machine - For case where FDISC is in progress and we get a vport delete request we wait for fdisc response and will transition to the appropriate state based on rsp status, else its causing both driver/fw resources to be not freed. - Remove the fc_credit_recovery module param. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa/bfa_fcs_lport.c')
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c170
1 files changed, 156 insertions, 14 deletions
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 942443e711e..f8251a91ba9 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -328,6 +328,40 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
328} 328}
329 329
330/* 330/*
331 * Send a FCCT Reject
332 */
333static void
334bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
335 struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl)
336{
337 struct fchs_s fchs;
338 struct bfa_fcxp_s *fcxp;
339 struct bfa_rport_s *bfa_rport = NULL;
340 int len;
341 struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1);
342 struct ct_hdr_s *ct_hdr;
343
344 bfa_trc(port->fcs, rx_fchs->d_id);
345 bfa_trc(port->fcs, rx_fchs->s_id);
346
347 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
348 if (!fcxp)
349 return;
350
351 ct_hdr = bfa_fcxp_get_reqbuf(fcxp);
352 ct_hdr->gs_type = rx_cthdr->gs_type;
353 ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type;
354
355 len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id,
356 bfa_fcs_lport_get_fcid(port),
357 rx_fchs->ox_id, reason_code, reason_code_expl);
358
359 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
360 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
361 FC_MAX_PDUSZ, 0);
362}
363
364/*
331 * Process incoming plogi from a remote port. 365 * Process incoming plogi from a remote port.
332 */ 366 */
333static void 367static void
@@ -710,6 +744,16 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
710 bfa_fcs_lport_abts_acc(lport, fchs); 744 bfa_fcs_lport_abts_acc(lport, fchs);
711 return; 745 return;
712 } 746 }
747
748 if (fchs->type == FC_TYPE_SERVICES) {
749 /*
750 * Unhandled FC-GS frames. Send a FC-CT Reject
751 */
752 bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP,
753 CT_NS_EXP_NOADDITIONAL);
754 return;
755 }
756
713 /* 757 /*
714 * look for a matching remote port ID 758 * look for a matching remote port ID
715 */ 759 */
@@ -1137,6 +1181,8 @@ static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1137 struct bfa_fcs_fdmi_hba_attr_s *hba_attr); 1181 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1138static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, 1182static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1139 struct bfa_fcs_fdmi_port_attr_s *port_attr); 1183 struct bfa_fcs_fdmi_port_attr_s *port_attr);
1184u32 bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed);
1185
1140/* 1186/*
1141 * fcs_fdmi_sm FCS FDMI state machine 1187 * fcs_fdmi_sm FCS FDMI state machine
1142 */ 1188 */
@@ -2223,12 +2269,36 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2223 /* 2269 /*
2224 * Supported Speeds 2270 * Supported Speeds
2225 */ 2271 */
2226 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS); 2272 switch (pport_attr.speed_supported) {
2273 case BFA_PORT_SPEED_16GBPS:
2274 port_attr->supp_speed =
2275 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
2276 break;
2277
2278 case BFA_PORT_SPEED_10GBPS:
2279 port_attr->supp_speed =
2280 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
2281 break;
2282
2283 case BFA_PORT_SPEED_8GBPS:
2284 port_attr->supp_speed =
2285 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
2286 break;
2287
2288 case BFA_PORT_SPEED_4GBPS:
2289 port_attr->supp_speed =
2290 cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
2291 break;
2292
2293 default:
2294 bfa_sm_fault(port->fcs, pport_attr.speed_supported);
2295 }
2227 2296
2228 /* 2297 /*
2229 * Current Speed 2298 * Current Speed
2230 */ 2299 */
2231 port_attr->curr_speed = cpu_to_be32(pport_attr.speed); 2300 port_attr->curr_speed = cpu_to_be32(
2301 bfa_fcs_fdmi_convert_speed(pport_attr.speed));
2232 2302
2233 /* 2303 /*
2234 * Max PDU Size. 2304 * Max PDU Size.
@@ -2249,6 +2319,41 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2249 2319
2250} 2320}
2251 2321
2322/*
2323 * Convert BFA speed to FDMI format.
2324 */
2325u32
2326bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
2327{
2328 u32 ret;
2329
2330 switch (pport_speed) {
2331 case BFA_PORT_SPEED_1GBPS:
2332 case BFA_PORT_SPEED_2GBPS:
2333 ret = pport_speed;
2334 break;
2335
2336 case BFA_PORT_SPEED_4GBPS:
2337 ret = FDMI_TRANS_SPEED_4G;
2338 break;
2339
2340 case BFA_PORT_SPEED_8GBPS:
2341 ret = FDMI_TRANS_SPEED_8G;
2342 break;
2343
2344 case BFA_PORT_SPEED_10GBPS:
2345 ret = FDMI_TRANS_SPEED_10G;
2346 break;
2347
2348 case BFA_PORT_SPEED_16GBPS:
2349 ret = FDMI_TRANS_SPEED_16G;
2350 break;
2351
2352 default:
2353 ret = FDMI_TRANS_SPEED_UNKNOWN;
2354 }
2355 return ret;
2356}
2252 2357
2253void 2358void
2254bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms) 2359bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
@@ -4827,8 +4932,8 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4827 while (qe != qh) { 4932 while (qe != qh) {
4828 rport = (struct bfa_fcs_rport_s *) qe; 4933 rport = (struct bfa_fcs_rport_s *) qe;
4829 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) || 4934 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
4830 (bfa_fcs_rport_get_state(rport) == 4935 (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
4831 BFA_RPORT_OFFLINE)) { 4936 (rport->scsi_function != BFA_RPORT_TARGET)) {
4832 qe = bfa_q_next(qe); 4937 qe = bfa_q_next(qe);
4833 continue; 4938 continue;
4834 } 4939 }
@@ -4841,17 +4946,15 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4841 bfa_fcport_get_ratelim_speed(port->fcs->bfa); 4946 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4842 } 4947 }
4843 4948
4844 if ((rport_speed == BFA_PORT_SPEED_8GBPS) || 4949 if (rport_speed > max_speed)
4845 (rport_speed > port_speed)) {
4846 max_speed = rport_speed;
4847 break;
4848 } else if (rport_speed > max_speed) {
4849 max_speed = rport_speed; 4950 max_speed = rport_speed;
4850 }
4851 4951
4852 qe = bfa_q_next(qe); 4952 qe = bfa_q_next(qe);
4853 } 4953 }
4854 4954
4955 if (max_speed > port_speed)
4956 max_speed = port_speed;
4957
4855 bfa_trc(fcs, max_speed); 4958 bfa_trc(fcs, max_speed);
4856 return max_speed; 4959 return max_speed;
4857} 4960}
@@ -4996,6 +5099,8 @@ static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4996 enum bfa_fcs_vport_event event); 5099 enum bfa_fcs_vport_event event);
4997static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, 5100static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4998 enum bfa_fcs_vport_event event); 5101 enum bfa_fcs_vport_event event);
5102static void bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
5103 enum bfa_fcs_vport_event event);
4999static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, 5104static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5000 enum bfa_fcs_vport_event event); 5105 enum bfa_fcs_vport_event event);
5001static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, 5106static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
@@ -5017,6 +5122,7 @@ static struct bfa_sm_table_s vport_sm_table[] = {
5017 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE}, 5122 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
5018 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC}, 5123 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
5019 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY}, 5124 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
5125 {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
5020 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE}, 5126 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
5021 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING}, 5127 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
5022 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP}, 5128 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
@@ -5145,9 +5251,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5145 5251
5146 switch (event) { 5252 switch (event) {
5147 case BFA_FCS_VPORT_SM_DELETE: 5253 case BFA_FCS_VPORT_SM_DELETE:
5148 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); 5254 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
5149 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5150 bfa_fcs_lport_delete(&vport->lport);
5151 break; 5255 break;
5152 5256
5153 case BFA_FCS_VPORT_SM_OFFLINE: 5257 case BFA_FCS_VPORT_SM_OFFLINE:
@@ -5215,6 +5319,41 @@ bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5215} 5319}
5216 5320
5217/* 5321/*
5322 * FDISC is in progress and we got a vport delete request -
5323 * this is a wait state while we wait for fdisc response and
5324 * we will transition to the appropriate state - on rsp status.
5325 */
5326static void
5327bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
5328 enum bfa_fcs_vport_event event)
5329{
5330 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5331 bfa_trc(__vport_fcs(vport), event);
5332
5333 switch (event) {
5334 case BFA_FCS_VPORT_SM_RSP_OK:
5335 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5336 bfa_fcs_lport_delete(&vport->lport);
5337 break;
5338
5339 case BFA_FCS_VPORT_SM_DELETE:
5340 break;
5341
5342 case BFA_FCS_VPORT_SM_OFFLINE:
5343 case BFA_FCS_VPORT_SM_RSP_ERROR:
5344 case BFA_FCS_VPORT_SM_RSP_FAILED:
5345 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5346 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5347 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5348 bfa_fcs_lport_delete(&vport->lport);
5349 break;
5350
5351 default:
5352 bfa_sm_fault(__vport_fcs(vport), event);
5353 }
5354}
5355
5356/*
5218 * Vport is online (FDISC is complete). 5357 * Vport is online (FDISC is complete).
5219 */ 5358 */
5220static void 5359static void
@@ -5529,7 +5668,10 @@ void
5529bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport) 5668bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5530{ 5669{
5531 vport->vport_stats.fab_online++; 5670 vport->vport_stats.fab_online++;
5532 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); 5671 if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
5672 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5673 else
5674 vport->vport_stats.fab_no_npiv++;
5533} 5675}
5534 5676
5535/* 5677/*