Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
  [SCSI] scsi_transport_spi: fix domain validation failure from incorrect width setting
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 6f56f87..4df21c9 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -787,10 +787,12 @@
 	struct scsi_target *starget = sdev->sdev_target;
 	struct Scsi_Host *shost = sdev->host;
 	int len = sdev->inquiry_len;
+	int min_period = spi_min_period(starget);
+	int max_width = spi_max_width(starget);
 	/* first set us up for narrow async */
 	DV_SET(offset, 0);
 	DV_SET(width, 0);
-	
+
 	if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS)
 	    != SPI_COMPARE_SUCCESS) {
 		starget_printk(KERN_ERR, starget, "Domain Validation Initial Inquiry Failed\n");
@@ -798,9 +800,13 @@
 		return;
 	}
 
+	if (!scsi_device_wide(sdev)) {
+		spi_max_width(starget) = 0;
+		max_width = 0;
+	}
+
 	/* test width */
-	if (i->f->set_width && spi_max_width(starget) &&
-	    scsi_device_wide(sdev)) {
+	if (i->f->set_width && max_width) {
 		i->f->set_width(starget, 1);
 
 		if (spi_dv_device_compare_inquiry(sdev, buffer,
@@ -809,6 +815,11 @@
 		    != SPI_COMPARE_SUCCESS) {
 			starget_printk(KERN_ERR, starget, "Wide Transfers Fail\n");
 			i->f->set_width(starget, 0);
+			/* Make sure we don't force wide back on by asking
+			 * for a transfer period that requires it */
+			max_width = 0;
+			if (min_period < 10)
+				min_period = 10;
 		}
 	}
 
@@ -828,7 +839,8 @@
 
 	/* now set up to the maximum */
 	DV_SET(offset, spi_max_offset(starget));
-	DV_SET(period, spi_min_period(starget));
+	DV_SET(period, min_period);
+
 	/* try QAS requests; this should be harmless to set if the
 	 * target supports it */
 	if (scsi_device_qas(sdev)) {
@@ -837,14 +849,14 @@
 		DV_SET(qas, 0);
 	}
 
-	if (scsi_device_ius(sdev) && spi_min_period(starget) < 9) {
+	if (scsi_device_ius(sdev) && min_period < 9) {
 		/* This u320 (or u640). Set IU transfers */
 		DV_SET(iu, 1);
 		/* Then set the optional parameters */
 		DV_SET(rd_strm, 1);
 		DV_SET(wr_flow, 1);
 		DV_SET(rti, 1);
-		if (spi_min_period(starget) == 8)
+		if (min_period == 8)
 			DV_SET(pcomp_en, 1);
 	} else {
 		DV_SET(iu, 0);
@@ -862,6 +874,10 @@
 	} else {
 		DV_SET(dt, 1);
 	}
+	/* set width last because it will pull all the other
+	 * parameters down to required values */
+	DV_SET(width, max_width);
+
 	/* Do the read only INQUIRY tests */
 	spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len,
 		       spi_dv_device_compare_inquiry);