diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2011-06-24 23:24:52 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-06-29 18:12:11 -0400 |
commit | d7be54cc5c5f6f9cb9ac67462aadda57813698b8 (patch) | |
tree | 2f77812fe06a7ed59172a51f11166aadd6a262d8 /drivers/scsi/bfa/bfa_fcs_lport.c | |
parent | 4507025d01149aea8705e43508d0ef11e7010cfd (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.c | 170 |
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 | */ | ||
333 | static void | ||
334 | bfa_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 | */ |
333 | static void | 367 | static 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); |
1138 | static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, | 1182 | static 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); |
1184 | u32 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 | */ | ||
2325 | u32 | ||
2326 | bfa_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 | ||
2253 | void | 2358 | void |
2254 | bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms) | 2359 | bfa_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); |
4997 | static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, | 5100 | static 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); |
5102 | static void bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, | ||
5103 | enum bfa_fcs_vport_event event); | ||
4999 | static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, | 5104 | static 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); |
5001 | static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, | 5106 | static 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 | */ | ||
5326 | static void | ||
5327 | bfa_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 | */ |
5220 | static void | 5359 | static void |
@@ -5529,7 +5668,10 @@ void | |||
5529 | bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport) | 5668 | bfa_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 | /* |