patch-1.3.26 linux/drivers/scsi/scsi.c
Next file: linux/drivers/scsi/scsi.h
Previous file: linux/drivers/scsi/hosts.h
Back to the patch index
Back to the overall index
- Lines: 162
- Date:
Mon Sep 11 10:23:41 1995
- Orig file:
v1.3.25/linux/drivers/scsi/scsi.c
- Orig date:
Mon Aug 28 14:52:21 1995
diff -u --recursive --new-file v1.3.25/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -13,7 +13,7 @@
* Tommy Thorn <tthorn>
* Thomas Wuensche <[email protected]>
*
- * Modified by Eric Youngdale [email protected] to
+ * Modified by Eric Youngdale [email protected] to
* add scatter-gather, multiple outstanding request, and other
* enhancements.
*
@@ -430,6 +430,7 @@
* and then fix this field later if it turns out it doesn't
*/
SDpnt->borken = 1;
+ SDpnt->was_reset = 0;
scsi_cmd[0] = TEST_UNIT_READY;
scsi_cmd[1] = lun << 5;
@@ -801,7 +802,7 @@
case IN_ABORT:
printk("SCSI host %d abort() timed out - resetting\n",
SCpnt->host->host_no);
- if (!scsi_reset (SCpnt))
+ if (!scsi_reset (SCpnt, FALSE))
return;
case IN_RESET:
case (IN_ABORT | IN_RESET):
@@ -811,6 +812,7 @@
*/
printk("Unable to reset scsi host %d - ", SCpnt->host->host_no);
printk("probably a SCSI bus hang.\n");
+ scsi_reset (SCpnt, TRUE);
return;
default:
@@ -1319,7 +1321,7 @@
#endif
SCpnt->flags |= (WAS_RESET | IS_RESETTING);
- scsi_reset(SCpnt);
+ scsi_reset(SCpnt, FALSE);
#ifdef DEBUG
printk("performing request sense\n");
@@ -1865,7 +1867,7 @@
}
}
-int scsi_reset (Scsi_Cmnd * SCpnt)
+int scsi_reset (Scsi_Cmnd * SCpnt, int bus_reset_flag)
{
int temp, oldto;
unsigned long flags;
@@ -1876,6 +1878,43 @@
printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",
host->host_no);
#endif
+
+ /*
+ * First of all, we need to make a recommendation to the low-level
+ * driver as to whether a BUS_DEVICE_RESET should be performed,
+ * or whether we should do a full BUS_RESET. There is no simple
+ * algorithm here - we basically use a series of heuristics
+ * to determine what we should do.
+ */
+ SCpnt->host->suggest_bus_reset = FALSE;
+
+ /*
+ * First see if all of the active devices on the bus have
+ * been jammed up so that we are attempting resets. If so,
+ * then suggest a bus reset. Forcing a bus reset could
+ * result in some race conditions, but no more than
+ * you would usually get with timeouts. We will cross
+ * that bridge when we come to it.
+ */
+ SCpnt1 = host->host_queue;
+ while(SCpnt1) {
+ if( SCpnt->request.dev > 0
+ && (SCpnt->flags & WAS_RESET) == 0 )
+ break;
+ SCpnt1 = SCpnt1->next;
+ }
+ if( SCpnt1 == NULL )
+ SCpnt->host->suggest_bus_reset = TRUE;
+
+
+ /*
+ * If the code that called us is suggesting a hard reset, then
+ * definitely request it. This usually occurs because a
+ * BUS_DEVICE_RESET times out.
+ */
+ if( bus_reset_flag )
+ SCpnt->host->suggest_bus_reset = TRUE;
+
while (1) {
save_flags(flags);
cli();
@@ -1923,7 +1962,26 @@
#ifdef DEBUG
printk("scsi reset function returned %d\n", temp);
#endif
- switch(temp) {
+
+ if( temp & SCSI_RESET_BUS_RESET )
+ {
+ /*
+ * The low level driver did a bus reset, so we should
+ * go through and mark all of the devices on that bus
+ * as having been reset.
+ */
+ SCpnt1 = host->host_queue;
+ while(SCpnt1) {
+ SCpnt1->device->was_reset = 1;
+ SCpnt1 = SCpnt1->next;
+ }
+ }
+
+ /*
+ * Now figure out what we need to do, based upon
+ * what the low level driver said that it did.
+ */
+ switch(temp & SCSI_RESET_ACTION) {
case SCSI_RESET_SUCCESS:
save_flags(flags);
cli();
@@ -1934,9 +1992,27 @@
case SCSI_RESET_PENDING:
return 0;
case SCSI_RESET_PUNT:
+ SCpnt->internal_timeout &= ~IN_RESET;
+ scsi_request_sense (SCpnt);
+ return 0;
case SCSI_RESET_WAKEUP:
SCpnt->internal_timeout &= ~IN_RESET;
scsi_request_sense (SCpnt);
+ /*
+ * Since a bus reset was performed, we
+ * need to wake up each and every command
+ * that was active on the bus.
+ */
+ if( temp & SCSI_RESET_BUS_RESET )
+ {
+ SCpnt1 = host->host_queue;
+ while(SCpnt1) {
+ if( SCpnt->request.dev > 0
+ && SCpnt1 != SCpnt)
+ scsi_request_sense (SCpnt);
+ SCpnt1 = SCpnt1->next;
+ }
+ }
return 0;
case SCSI_RESET_SNOOZE:
/* In this case, we set the timeout field to 0
@@ -2856,7 +2932,8 @@
* If any of the devices would match this driver, then perform the
* init function.
*/
- if(tpnt->init && tpnt->dev_noticed) (*tpnt->init)();
+ if(tpnt->init && tpnt->dev_noticed)
+ if ((*tpnt->init)()) return 1;
/*
* Now actually connect the devices to the new driver.
FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen, [email protected]
with Sam's (original) version of this