Signed-off-by: Robert Love <[EMAIL PROTECTED]>
---
drivers/scsi/libfc/fc_lport.c | 155 ++++++++++++++++++-----------------------
1 files changed, 67 insertions(+), 88 deletions(-)
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index c15e37c..4856f5b 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -36,6 +36,8 @@
static int fc_lport_debug;
+static void fc_lport_error(struct fc_lport *, struct fc_frame *);
+
static void fc_lport_enter_flogi(struct fc_lport *);
static void fc_lport_enter_dns(struct fc_lport *);
static void fc_lport_enter_reg_pn(struct fc_lport *);
@@ -466,42 +468,10 @@ static void fc_lport_enter_ready(struct fc_lport *lport)
}
/*
- * re-enter state for retrying a request after a timeout or alloc failure.
- */
-static void fc_lport_enter_retry(struct fc_lport *lport)
-{
- switch (lport->state) {
- case LPORT_ST_NONE:
- case LPORT_ST_READY:
- case LPORT_ST_RESET:
- WARN_ON(1);
- break;
- case LPORT_ST_FLOGI:
- fc_lport_enter_flogi(lport);
- break;
- case LPORT_ST_DNS:
- fc_lport_enter_dns(lport);
- break;
- case LPORT_ST_REG_PN:
- fc_lport_enter_reg_pn(lport);
- break;
- case LPORT_ST_REG_FT:
- fc_lport_enter_reg_ft(lport);
- break;
- case LPORT_ST_SCR:
- fc_lport_enter_scr(lport);
- break;
- case LPORT_ST_LOGO:
- fc_lport_enter_logo(lport);
- break;
- }
-}
-
-/*
* enter next state for handling an exchange reject or retry exhaustion
* in the current state.
*/
-static void fc_lport_enter_reject(struct fc_lport *lport)
+static void fc_lport_reject(struct fc_lport *lport)
{
switch (lport->state) {
case LPORT_ST_NONE:
@@ -519,28 +489,6 @@ static void fc_lport_enter_reject(struct fc_lport *lport)
}
/*
- * Handle resource allocation problem by retrying in a bit.
- */
-static void fc_lport_retry(struct fc_lport *lport)
-{
- if (lport->retry_count == 0)
- FC_DBG("local port %6x alloc failure in state %s "
- "- will retry\n", lport->fid, fc_lport_state(lport));
-
- if (lport->retry_count < lport->max_retry_count) {
- lport->retry_count++;
- schedule_delayed_work(&lport->retry_work,
- jiffies +
- msecs_to_jiffies(lport->e_d_tov));
- } else {
- FC_DBG("local port %6x alloc failure in state %s "
- "- retries exhausted\n", lport->fid,
- fc_lport_state(lport));
- fc_lport_enter_reject(lport);
- }
-}
-
-/*
* A received FLOGI request indicates a point-to-point connection.
* Accept it with the common service parameters indicating our N port.
* Set up to do a PLOGI if we have the higher-number WWPN.
@@ -604,7 +552,7 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
lport->tt.seq_send(lport, sp, fp, f_ctl);
} else {
- fc_lport_retry(lport);
+ fc_lport_error(lport, fp);
}
fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,
get_unaligned_be64(&flp->fl_wwnn));
@@ -725,30 +673,34 @@ int fc_lport_enter_reset(struct fc_lport *lport)
}
EXPORT_SYMBOL(fc_lport_enter_reset);
-/*
- * Handle errors on local port requests.
- * Don't get locks if in RESET state.
- * The only possible errors so far are exchange TIMEOUT and CLOSED (reset).
+/**
+ * fc_lport_error - Handler for any errors
+ * @lport: The fc_lport object
+ * @fp: The frame pointer
+ *
+ * If the error was caused by a resource allocation failure
+ * then wait for half a second and retry, otherwise retry
+ * after the e_d_tov time.
*/
static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
{
- if (lport->state == LPORT_ST_RESET)
- return;
-
- fc_lport_lock(lport);
- if (PTR_ERR(fp) == -FC_EX_TIMEOUT) {
- if (lport->retry_count < lport->max_retry_count) {
- lport->retry_count++;
- fc_lport_enter_retry(lport);
- } else {
- fc_lport_enter_reject(lport);
-
- }
- }
+ unsigned long delay = 0;
if (fc_lport_debug)
- FC_DBG("error %ld retries %d limit %d\n",
- PTR_ERR(fp), lport->retry_count, lport->max_retry_count);
- fc_lport_unlock(lport);
+ FC_DBG("Error %ld in state %s, retries %d\n",
+ PTR_ERR(fp), fc_lport_state(lport),
+ lport->retry_count);
+
+ if (lport->retry_count < lport->max_retry_count) {
+ lport->retry_count++;
+ if (!fp)
+ delay = msecs_to_jiffies(500);
+ else
+ delay = jiffies +
+ msecs_to_jiffies(lport->e_d_tov);
+
+ schedule_delayed_work(&lport->retry_work, delay);
+ } else
+ fc_lport_reject(lport);
}
/*
@@ -769,7 +721,7 @@ static void fc_lport_ns_resp(struct fc_seq *sp, struct
fc_frame *fp,
fc_lport_enter_scr(lport);
} else {
- fc_lport_retry(lport);
+ fc_lport_error(lport, fp);
}
fc_lport_unlock(lport);
fc_frame_free(fp);
@@ -877,9 +829,9 @@ static void fc_lport_enter_reg_ft(struct fc_lport *lport)
FC_FID_DIR_SERV,
FC_FC_SEQ_INIT |
FC_FC_END_SEQ))
- fc_lport_retry(lport);
+ fc_lport_error(lport, fp);
} else {
- fc_lport_retry(lport);
+ fc_lport_error(lport, fp);
}
} else {
fc_lport_enter_scr(lport);
@@ -903,7 +855,7 @@ static void fc_lport_enter_reg_pn(struct fc_lport *lport)
fc_lport_state_enter(lport, LPORT_ST_REG_PN);
fp = fc_frame_alloc(lport, sizeof(*req));
if (!fp) {
- fc_lport_retry(lport);
+ fc_lport_error(lport, fp);
return;
}
req = fc_frame_payload_get(fp, sizeof(*req));
@@ -918,7 +870,7 @@ static void fc_lport_enter_reg_pn(struct fc_lport *lport)
lport->fid,
FC_FID_DIR_SERV,
FC_FC_SEQ_INIT | FC_FC_END_SEQ))
- fc_lport_retry(lport);
+ fc_lport_error(lport, fp);
}
/*
@@ -966,13 +918,14 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
}
return;
- /*
- * Resource allocation problem (malloc). Try again in 500 mS.
- */
err:
- fc_lport_retry(lport);
+ fc_lport_error(lport, NULL);
}
+/**
+ * fc_lport_timeout - Handler for the retry_work timer.
+ * @work: The work struct of the fc_lport
+ */
static void fc_lport_timeout(struct work_struct *work)
{
struct fc_lport *lport =
@@ -980,7 +933,33 @@ static void fc_lport_timeout(struct work_struct *work)
retry_work.work);
fc_lport_lock(lport);
- fc_lport_enter_retry(lport);
+
+ switch (lport->state) {
+ case LPORT_ST_NONE:
+ case LPORT_ST_READY:
+ case LPORT_ST_RESET:
+ WARN_ON(1);
+ break;
+ case LPORT_ST_FLOGI:
+ fc_lport_enter_flogi(lport);
+ break;
+ case LPORT_ST_DNS:
+ fc_lport_enter_dns(lport);
+ break;
+ case LPORT_ST_REG_PN:
+ fc_lport_enter_reg_pn(lport);
+ break;
+ case LPORT_ST_REG_FT:
+ fc_lport_enter_reg_ft(lport);
+ break;
+ case LPORT_ST_SCR:
+ fc_lport_enter_scr(lport);
+ break;
+ case LPORT_ST_LOGO:
+ fc_lport_enter_logo(lport);
+ break;
+ }
+
fc_lport_unlock(lport);
}
@@ -1117,7 +1096,7 @@ static void fc_lport_flogi_send(struct fc_lport *lport)
fp = fc_frame_alloc(lport, sizeof(*flp));
if (!fp)
- return fc_lport_retry(lport);
+ return fc_lport_error(lport, fp);
flp = fc_frame_payload_get(fp, sizeof(*flp));
fc_lport_flogi_fill(lport, flp, ELS_FLOGI);
@@ -1130,7 +1109,7 @@ static void fc_lport_flogi_send(struct fc_lport *lport)
lport, lport->e_d_tov,
0, FC_FID_FLOGI,
FC_FC_SEQ_INIT | FC_FC_END_SEQ))
- fc_lport_retry(lport);
+ fc_lport_error(lport, fp);
}
void fc_lport_enter_flogi(struct fc_lport *lport)
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel