From 5100a4a672c3db5bd28a5ea533c180193eddccbd Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sat, 16 Aug 2008 14:51:25 -0500 Subject: [PATCH 17/23] libfc: fix fc_eh_host_reset When fc_eh_host_reset returns success, scsi-ml will send a TUR to check us so we must be ready to go. This has us wait for some timeout while we try to relogin. In the future I would like to remove the poll for the state, and instead have the lport code notify us but for now this is good enough. Signed-off-by: Mike Christie --- drivers/scsi/libfc/fc_fcp.c | 33 ++++++++++++++++++++++++--------- 1 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 1feac6d..e61dae7 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -175,6 +175,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); #define FC_SCSI_ER_TIMEOUT (10 * HZ) #define FC_SCSI_TM_TOV (10 * HZ) #define FC_SCSI_REC_TOV (2 * HZ) +#define FC_HOST_RESET_TIMEOUT (30 * HZ) #define FC_MAX_ERROR_CNT 5 #define FC_MAX_RECOV_RETRY 3 @@ -1646,6 +1647,12 @@ out: fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ } +static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp) +{ + /* lock ? */ + return (lp->state == LPORT_ST_READY) && (lp->link_status & FC_LINK_UP); +} + /** * fc_queuecommand - The queuecommand function of the scsi template * @cmd: struct scsi_cmnd to be executed @@ -1685,14 +1692,9 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) rp = rport->dd_data; - if (lp->state != LPORT_ST_READY) { + if (!fc_fcp_lport_queue_ready(lp)) { rc = SCSI_MLQUEUE_HOST_BUSY; goto out; - } else { - if (!(lp->link_status & FC_LINK_UP)) { - rc = SCSI_MLQUEUE_HOST_BUSY; - goto out; - } } sp = fc_fcp_pkt_alloc(lp); @@ -1980,10 +1982,23 @@ EXPORT_SYMBOL(fc_eh_device_reset); */ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) { - struct fc_lport *lp; + struct Scsi_Host *shost = sc_cmd->device->host; + struct fc_lport *lp = shost_priv(shost); + unsigned long wait_tmo; - lp = shost_priv(sc_cmd->device->host); - return lp->tt.lport_reset(lp) ? FAILED : SUCCESS; + lp->tt.lport_reset(lp); + wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT; + while (!fc_fcp_lport_queue_ready(lp) && time_before(jiffies, wait_tmo)) + msleep(1000); + + if (fc_fcp_lport_queue_ready(lp)) { + shost_printk(KERN_INFO, shost, "Host reset succeeded.\n"); + return SUCCESS; + } else { + shost_printk(KERN_INFO, shost, "Host reset succeeded failed." + "lport not ready.\n"); + return FAILED; + } } EXPORT_SYMBOL(fc_eh_host_reset); -- 1.5.5.1