aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Reed <mdr@sgi.com>2010-02-10 15:32:00 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-02-17 14:38:22 -0500
commit03cb3829e0e5650518ce37e2b4420a35e034dc9e (patch)
tree17ae96241e0eb7e62460150c83a1c374c9e79293
parent4b5aa7cff0e2bd1a9c81b59553ba8ecfa3aa7e1b (diff)
[SCSI] fusion: hold off error recovery while alternate ioc is initializing
After discussing this patch with LSI, I resubmitting with a recommended 40 second wait for the alternate ioc's initialization to complete. -- Fusion FC chips are two function with some shared resources. During initialization of one function its driver inhibits the ability of the other function's driver to allocate message frames by clearing its "active" flag. Should mid-layer error recovery be initiated for a scsi command during this initialization (which can take up to 40 seconds) error recovery will escalate to the level of host reset. This host reset might fail (as the other function is resetting) resulting in all connected targets being taken offline. This patch holds off mid-layer error recovery for up to 40 seconds to permit initialization of the other function to complete. Signed-off-by: Michael Reed <mdr@sgi.com> Acked-by: "Desai, Kashyap" <Kashyap.Desai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/message/fusion/mptfc.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ebf6ae024da4..612ab3c51a6b 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -195,29 +195,34 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
195 unsigned long flags; 195 unsigned long flags;
196 int ready; 196 int ready;
197 MPT_ADAPTER *ioc; 197 MPT_ADAPTER *ioc;
198 int loops = 40; /* seconds */
198 199
199 hd = shost_priv(SCpnt->device->host); 200 hd = shost_priv(SCpnt->device->host);
200 ioc = hd->ioc; 201 ioc = hd->ioc;
201 spin_lock_irqsave(shost->host_lock, flags); 202 spin_lock_irqsave(shost->host_lock, flags);
202 while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) { 203 while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
204 || (loops > 0 && ioc->active == 0)) {
203 spin_unlock_irqrestore(shost->host_lock, flags); 205 spin_unlock_irqrestore(shost->host_lock, flags);
204 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT 206 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
205 "mptfc_block_error_handler.%d: %d:%d, port status is " 207 "mptfc_block_error_handler.%d: %d:%d, port status is "
206 "DID_IMM_RETRY, deferring %s recovery.\n", 208 "%x, active flag %d, deferring %s recovery.\n",
207 ioc->name, ioc->sh->host_no, 209 ioc->name, ioc->sh->host_no,
208 SCpnt->device->id, SCpnt->device->lun, caller)); 210 SCpnt->device->id, SCpnt->device->lun,
211 ready, ioc->active, caller));
209 msleep(1000); 212 msleep(1000);
210 spin_lock_irqsave(shost->host_lock, flags); 213 spin_lock_irqsave(shost->host_lock, flags);
214 loops --;
211 } 215 }
212 spin_unlock_irqrestore(shost->host_lock, flags); 216 spin_unlock_irqrestore(shost->host_lock, flags);
213 217
214 if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) { 218 if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
219 || ioc->active == 0) {
215 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT 220 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
216 "%s.%d: %d:%d, failing recovery, " 221 "%s.%d: %d:%d, failing recovery, "
217 "port state %d, vdevice %p.\n", caller, 222 "port state %x, active %d, vdevice %p.\n", caller,
218 ioc->name, ioc->sh->host_no, 223 ioc->name, ioc->sh->host_no,
219 SCpnt->device->id, SCpnt->device->lun, ready, 224 SCpnt->device->id, SCpnt->device->lun, ready,
220 SCpnt->device->hostdata)); 225 ioc->active, SCpnt->device->hostdata));
221 return FAILED; 226 return FAILED;
222 } 227 }
223 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT 228 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT