Index: linux/drivers/scsi/scsi.c
diff -u linux/drivers/scsi/scsi.c:1.1.1.7 linux/drivers/scsi/scsi.c:1.1.1.7.2.1
--- linux/drivers/scsi/scsi.c:1.1.1.7	Tue Jun 13 17:24:04 2000
+++ linux/drivers/scsi/scsi.c	Tue Jun 13 18:01:08 2000
@@ -716,7 +716,7 @@
   SCSI_LOG_SCAN_BUS(3,print_hostbyte(SCpnt->result));
   SCSI_LOG_SCAN_BUS(3,printk("\n"));
 
-  if (SCpnt->result) {
+  if (SCpnt->result && status_byte(SCpnt->result) != RESERVATION_CONFLICT) {
     if (((driver_byte (SCpnt->result) & DRIVER_SENSE) ||
          (status_byte (SCpnt->result) & CHECK_CONDITION)) &&
         ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
Index: linux/drivers/scsi/scsi.h
diff -u linux/drivers/scsi/scsi.h:1.1.1.4 linux/drivers/scsi/scsi.h:1.1.1.4.6.1
--- linux/drivers/scsi/scsi.h:1.1.1.4	Wed Jan  5 12:24:50 2000
+++ linux/drivers/scsi/scsi.h	Tue Jun 13 17:59:02 2000
@@ -732,6 +732,14 @@
 	remove_wait_queue(QUEUE, &wait);\
 	current->state = TASK_RUNNING;	\
     }; }
+/* old style reset request from external source (private to sg.c and
+ * scsi_error.c, supplied by scsi_obsolete.c)
+ * */
+#define SCSI_TRY_RESET_DEVICE	1
+#define SCSI_TRY_RESET_BUS	2
+#define SCSI_TRY_RESET_HOST	3
+extern int scsi_old_reset(Scsi_Cmnd *, unsigned int);
+extern int scsi_reset_provider(Scsi_Device *, int);
 
 #endif
 
Index: linux/drivers/scsi/scsi_error.c
diff -u linux/drivers/scsi/scsi_error.c:1.1.1.3 linux/drivers/scsi/scsi_error.c:1.1.1.3.12.2
--- linux/drivers/scsi/scsi_error.c:1.1.1.3	Thu Aug 26 08:18:40 1999
+++ linux/drivers/scsi/scsi_error.c	Tue Jun 13 18:01:08 2000
@@ -34,6 +34,7 @@
 #include "scsi.h"
 #include "hosts.h"
 #include "constants.h"
+#include <scsi/sg.h>
 
 #define SHUTDOWN_SIGS	(sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
 
@@ -981,9 +982,14 @@
     case DID_SOFT_ERROR:
       return NEEDS_RETRY;
 
+    case DID_ERROR:
+      if(msg_byte(SCpnt->result) == COMMAND_COMPLETE 
+         && status_byte(SCpnt->result) == RESERVATION_CONFLICT)
+        /* execute reservation conflict processing code lower down */
+        break;
+      /* fall through */
     case DID_BUS_BUSY:
     case DID_PARITY:
-    case DID_ERROR:
       goto maybe_retry;
     case DID_TIME_OUT:
       /*
@@ -1059,8 +1065,12 @@
        */
       return SUCCESS;
     case BUSY:
-    case RESERVATION_CONFLICT:
       goto maybe_retry;
+    case RESERVATION_CONFLICT:
+      printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", 
+             SCpnt->host->host_no, SCpnt->channel,
+             SCpnt->device->id, SCpnt->device->lun);
+       return SUCCESS;          /* causes immediate I/O error */
     default:
       return FAILED;
     }
@@ -2041,6 +2051,62 @@
 	 */
 	if( host->eh_notify != NULL )
 	  up(host->eh_notify);
+}
+
+/*
+ * Function:	scsi_reset_provider
+ *
+ * Purpose:	Send requested reset to a bus or device at any phase.
+ *
+ * Arguments:	device	- device to send reset to
+ *		flag - reset type (see scsi.h)
+ *
+ * Returns:	SUCCESS/FAILURE.
+ *
+ * Notes:	This is used by the SCSI Generic driver to provide
+ *		Bus/Device reset capability.
+ */
+int
+scsi_reset_provider(Scsi_Device *dev, int flag)
+{
+    int rtn;
+    /* get a dummy command to issue the reset to */
+    Scsi_Cmnd *SCpnt = scsi_allocate_device(NULL, dev, 1);
+    switch(flag) {
+    case SCSI_TRY_RESET_DEVICE:
+        rtn = scsi_try_bus_device_reset(SCpnt, 0);
+        if(rtn == SUCCESS)
+            break;
+        /* fall through */
+    case SCSI_TRY_RESET_BUS:
+        rtn = scsi_try_bus_reset(SCpnt);
+        if(rtn == SUCCESS)
+            break;
+        /* fall through */
+    case SCSI_TRY_RESET_HOST:
+        rtn = scsi_try_host_reset(SCpnt);
+        break;
+    default:
+        rtn = FAILED;
+        goto error_out;
+    }
+    if(rtn == FAILED) {
+        /* if we get here, the new code all failed, so try the old
+         * reset code */
+        unsigned int old_flags = SCSI_RESET_SYNCHRONOUS;
+        switch(flag) {
+        case SCSI_TRY_RESET_BUS:
+            old_flags |= SCSI_RESET_SUGGEST_BUS_RESET;
+            break;
+        case SCSI_TRY_RESET_HOST:
+            old_flags |= SCSI_RESET_SUGGEST_HOST_RESET;
+            break;
+        }
+        rtn = (scsi_old_reset(SCpnt, old_flags) == 0) ? SUCCESS : FAILED;
+    }
+ error_out:
+    scsi_release_command(SCpnt);
+    return rtn;
 }
 
 /*
Index: linux/drivers/scsi/scsi_obsolete.c
diff -u linux/drivers/scsi/scsi_obsolete.c:1.1.1.1 linux/drivers/scsi/scsi_obsolete.c:1.1.1.1.48.2
--- linux/drivers/scsi/scsi_obsolete.c:1.1.1.1	Thu Mar 18 10:33:14 1999
+++ linux/drivers/scsi/scsi_obsolete.c	Tue Jun 13 18:01:09 2000
@@ -507,11 +507,14 @@
 		break;
 
 	    case RESERVATION_CONFLICT:
-		printk("scsi%d, channel %d : RESERVATION CONFLICT performing"
-		       " reset.\n", SCpnt->host->host_no, SCpnt->channel);
-                scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
-		status = REDO;
-		break;
+                /* Most HAs will return an error for this, so usually
+                 * reservation conflicts will be processed under DID_ERROR
+                 * code */
+                printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", 
+                       SCpnt->host->host_no, SCpnt->channel,
+                       SCpnt->device->id, SCpnt->device->lun);
+                status = CMD_FINISHED; /* returns I/O error */
+                break;
 	    default:
 		printk ("Internal error %s %d \n"
 			"status byte = %d \n", __FILE__,
@@ -564,6 +567,14 @@
 	exit  = (DRIVER_HARD | SUGGEST_ABORT);
 	break;
     case DID_ERROR:
+        if(msg_byte(result) == COMMAND_COMPLETE
+           && status_byte(result) == RESERVATION_CONFLICT) {
+            printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", 
+                   SCpnt->host->host_no, SCpnt->channel,
+                   SCpnt->device->id, SCpnt->device->lun);
+            status = CMD_FINISHED; /* returns I/O error */
+            break;
+        }
 	status = MAYREDO;
 	exit = (DRIVER_HARD | SUGGEST_ABORT);
 	break;
@@ -1119,6 +1130,16 @@
 
   return rtn;
 }
+
+/* This function exports SCSI Bus, Device or Host reset capability
+ * and is for use with the SCSI generic driver.
+ */
+int scsi_old_reset(Scsi_Cmnd *SCpnt, unsigned int flag)
+{
+    int retval = scsi_reset(SCpnt, flag);
+    return retval;
+}
+
 
 
 /*
Index: linux/drivers/scsi/scsi_syms.c
diff -u linux/drivers/scsi/scsi_syms.c:1.1.1.2 linux/drivers/scsi/scsi_syms.c:1.1.1.2.12.1
--- linux/drivers/scsi/scsi_syms.c:1.1.1.2	Thu Aug 26 08:18:33 1999
+++ linux/drivers/scsi/scsi_syms.c	Tue Jun 13 17:59:02 2000
@@ -80,5 +80,10 @@
 EXPORT_SYMBOL(scsi_devicelist);
 EXPORT_SYMBOL(scsi_device_types);
 
+/*
+ * This symbol is for the sg device only
+ */
+EXPORT_SYMBOL(scsi_reset_provider);
+
 
 #endif /* CONFIG_MODULES */

