summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>2010-07-20 15:21:27 -0700
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 09:06:04 -0500
commit7f985231d274ef3e6e4d56a2939a534906299021 (patch)
treeeddb8ddca9d31d9111b2895cd768171b08b1f619 /drivers
parentcf4aebcafb44a8810af10006dd4a5fcfb07bb810 (diff)
downloadlinux-7f985231d274ef3e6e4d56a2939a534906299021.tar.gz
linux-7f985231d274ef3e6e4d56a2939a534906299021.tar.bz2
linux-7f985231d274ef3e6e4d56a2939a534906299021.zip
[SCSI] libfc: Add retry logic to lport state machine when receiving LS_RJT
Call fc_lport_error to retry upto max retry count when FLOGI/SCR/NS gets rejected. Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libfc/fc_lport.c63
1 files changed, 27 insertions, 36 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 1998c03634da..6eb334a8a7fa 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1012,38 +1012,24 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
PTR_ERR(fp), fc_lport_state(lport),
lport->retry_count);
- if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
- /*
- * Memory allocation failure, or the exchange timed out.
- * Retry after delay
- */
- if (lport->retry_count < lport->max_retry_count) {
- lport->retry_count++;
- if (!fp)
- delay = msecs_to_jiffies(500);
- else
- delay = msecs_to_jiffies(lport->e_d_tov);
-
- schedule_delayed_work(&lport->retry_work, delay);
- } else {
- switch (lport->state) {
- case LPORT_ST_DISABLED:
- case LPORT_ST_READY:
- case LPORT_ST_RESET:
- case LPORT_ST_RNN_ID:
- case LPORT_ST_RSNN_NN:
- case LPORT_ST_RSPN_ID:
- case LPORT_ST_RFT_ID:
- case LPORT_ST_RFF_ID:
- case LPORT_ST_SCR:
- case LPORT_ST_DNS:
- case LPORT_ST_FLOGI:
- case LPORT_ST_LOGO:
- fc_lport_enter_reset(lport);
- break;
- }
- }
- }
+ if (PTR_ERR(fp) == -FC_EX_CLOSED)
+ return;
+
+ /*
+ * Memory allocation failure, or the exchange timed out
+ * or we received LS_RJT.
+ * Retry after delay
+ */
+ if (lport->retry_count < lport->max_retry_count) {
+ lport->retry_count++;
+ if (!fp)
+ delay = msecs_to_jiffies(500);
+ else
+ delay = msecs_to_jiffies(lport->e_d_tov);
+
+ schedule_delayed_work(&lport->retry_work, delay);
+ } else
+ fc_lport_enter_reset(lport);
}
/**
@@ -1461,7 +1447,13 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
}
did = fc_frame_did(fp);
- if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
+
+ if (!did) {
+ FC_LPORT_DBG(lport, "Bad FLOGI response\n");
+ goto out;
+ }
+
+ if (fc_frame_payload_op(fp) == ELS_LS_ACC) {
flp = fc_frame_payload_get(fp, sizeof(*flp));
if (flp) {
mfs = ntohs(flp->fl_csp.sp_bb_data) &
@@ -1500,9 +1492,8 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
fc_lport_enter_dns(lport);
}
}
- } else {
- FC_LPORT_DBG(lport, "Bad FLOGI response\n");
- }
+ } else
+ fc_lport_error(lport, fp);
out:
fc_frame_free(fp);