Retirement of CAM_QUIRK_NOSERIAL

From: Scott Long <scottl_at_samsco.org>
Date: Mon, 10 Sep 2007 22:12:52 -0600
All,

The attached patch should make CAM behave properly with regard to
probing device serial numbers only when the device advertises that
it supports it.  It will hopefully eliminate the need for the 
CAM_QUIRK_NOSERIAL quirk (one instance is left because of an unrelated 
legacy problem that may or may not be possible to fix).  This should
especially benefit USB-UMASS devices, where the console output should
be less noisy.  It might even make more devices work out-of-the-box.
So please focus testing on USB, but I'd also ask that people test
the following devices as well as any firewire devices:

  * Western Digital My Book 250GB (USB)
  * Maxtor Personal Storage 3000XT (Firewire)

Thanks,

Scott

Index: cam_xpt.c
===================================================================
RCS file: /usr/ncvs/src/sys/cam/cam_xpt.c,v
retrieving revision 1.190
diff -u -r1.190 cam_xpt.c
--- cam_xpt.c	30 Jun 2007 14:58:56 -0000	1.190
+++ cam_xpt.c	11 Sep 2007 04:00:19 -0000
_at__at_ -464,7 +464,7 _at__at_
 	{
 		/* I can't believe we need a quirk for DPT volumes. */
 		{ T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" },
-		CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS,
+		CAM_QUIRK_NOLUNS,
 		/*mintags*/0, /*maxtags*/255
 	},
 	{
_at__at_ -495,7 +495,7 _at__at_
 			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
 			"EXB-8200*", "*"
 		},
-		CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
 	},
 	{
 		/*
_at__at_ -506,7 +506,7 _at__at_
 			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
 			"IPL-6860*", "*"
 		},
-		CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
 	},
 	{
 		/*
_at__at_ -551,17 +551,6 _at__at_
 	},
 	{
 		/*
-		 * Maxtor Personal Storage 3000XT (Firewire)
-		 * hangs upon serial number probing.
-		 */
-		{
-			T_DIRECT, SIP_MEDIA_FIXED, "Maxtor",
-			"1394 storage", "*"
-		},
-		CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
-	},
-	{
-		/*
 		 * Would repond to all LUNs if asked for.
 		 */
 		{
_at__at_ -620,18 +609,6 _at__at_
 		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
 	},
 	{
-		/*
-		 * Western Digital My Book 250GB (USB)
-		 * hangs upon serial number probing.
-		 * PR: 107495
-		 */
-		{
-			T_DIRECT, SIP_MEDIA_FIXED, "WD",
-			"2500JB External", "*"
-		},
-		CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
-	},
-	{
 		/* Default tagged queuing parameters for all devices */
 		{
 		  T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
_at__at_ -5472,7 +5449,8 _at__at_
 	PROBE_INQUIRY,	/* this counts as DV0 for Basic Domain Validation */
 	PROBE_FULL_INQUIRY,
 	PROBE_MODE_SENSE,
-	PROBE_SERIAL_NUM,
+	PROBE_SERIAL_NUM_0,
+	PROBE_SERIAL_NUM_1,
 	PROBE_TUR_FOR_NEGOTIATION,
 	PROBE_INQUIRY_BASIC_DV1,
 	PROBE_INQUIRY_BASIC_DV2,
_at__at_ -5815,10 +5793,42 _at__at_
 		}
 		xpt_print(periph->path, "Unable to mode sense control page - "
 		    "malloc failure\n");
-		softc->action = PROBE_SERIAL_NUM;
+		softc->action = PROBE_SERIAL_NUM_0;
 	}
 	/* FALLTHROUGH */
-	case PROBE_SERIAL_NUM:
+	case PROBE_SERIAL_NUM_0:
+	{
+		struct scsi_vpd_supported_page_list *vpd_list = NULL;
+		struct cam_ed *device;
+
+		device = periph->path->device;
+		if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0) {
+			vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT,
+			    M_NOWAIT | M_ZERO);
+		}
+
+		if (vpd_list != NULL) {
+			scsi_inquiry(csio,
+				     /*retries*/4,
+				     probedone,
+				     MSG_SIMPLE_Q_TAG,
+				     (u_int8_t *)vpd_list,
+				     sizeof(*vpd_list) + 28,
+				     /*evpd*/TRUE,
+				     SVPD_SUPPORTED_PAGE_LIST,
+				     SSD_MIN_SIZE,
+				     /*timeout*/60 * 1000);
+			break;
+		}
+		/*
+		 * We'll have to do without, let our probedone
+		 * routine finish up for us.
+		 */
+		start_ccb->csio.data_ptr = NULL;
+		probedone(periph, start_ccb);
+		return;
+	}
+	case PROBE_SERIAL_NUM_1:
 	{
 		struct scsi_vpd_unit_serial_number *serial_buf;
 		struct cam_ed* device;
_at__at_ -5828,10 +5838,8 _at__at_
 		device->serial_num = NULL;
 		device->serial_num_len = 0;
 
-		if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0)
-			serial_buf = (struct scsi_vpd_unit_serial_number *)
-				malloc(sizeof(*serial_buf), M_CAMXPT,
-					M_NOWAIT | M_ZERO);
+		serial_buf = (struct scsi_vpd_unit_serial_number *)
+			malloc(sizeof(*serial_buf), M_CAMXPT, M_NOWAIT|M_ZERO);
 
 		if (serial_buf != NULL) {
 			scsi_inquiry(csio,
_at__at_ -6056,7 +6064,7 _at__at_
 				if (INQ_DATA_TQ_ENABLED(inq_buf))
 					softc->action = PROBE_MODE_SENSE;
 				else
-					softc->action = PROBE_SERIAL_NUM;
+					softc->action = PROBE_SERIAL_NUM_0;
 
 				path->device->flags &= ~CAM_DEV_UNCONFIGURED;
 
_at__at_ -6121,11 +6129,61 _at__at_
 		}
 		xpt_release_ccb(done_ccb);
 		free(mode_hdr, M_CAMXPT);
-		softc->action = PROBE_SERIAL_NUM;
+		softc->action = PROBE_SERIAL_NUM_0;
 		xpt_schedule(periph, priority);
 		return;
 	}
-	case PROBE_SERIAL_NUM:
+	case PROBE_SERIAL_NUM_0:
+	{
+		struct ccb_scsiio *csio;
+		struct scsi_vpd_supported_page_list *page_list;
+		int length, serialnum_supported, i;
+
+		serialnum_supported = 0;
+		csio = &done_ccb->csio;
+		page_list =
+		    (struct scsi_vpd_supported_page_list *)csio->data_ptr;
+
+		if (page_list == NULL) {
+			/*
+			 * Don't process the command as it was never sent
+			 */
+		} else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP
+		    && (page_list->length > 0)) {
+			length = min(page_list->length, csio->dxfer_len - 4);
+			for (i = 0; i < length; i++) {
+				if (page_list->list[i] ==
+				    SVPD_UNIT_SERIAL_NUMBER) {
+					serialnum_supported = 1;
+					break;
+				}
+			}
+		} else if (cam_periph_error(done_ccb, 0,
+					    SF_RETRY_UA|SF_NO_PRINT,
+					    &softc->saved_ccb) == ERESTART) {
+			return;
+		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+			/* Don't wedge the queue */
+			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+					 /*run_queue*/TRUE);
+		}
+
+		if (page_list != NULL)
+			free(page_list, M_DEVBUF);
+
+		if (serialnum_supported) {
+			xpt_release_ccb(done_ccb);
+			softc->action = PROBE_SERIAL_NUM_1;
+			xpt_schedule(periph, priority);
+			return;
+		}
+		xpt_release_ccb(done_ccb);
+		softc->action = PROBE_TUR_FOR_NEGOTIATION;
+		xpt_schedule(periph, done_ccb->ccb_h.pinfo.priority);
+		return;
+	}
+			
+	case PROBE_SERIAL_NUM_1:
 	{
 		struct ccb_scsiio *csio;
 		struct scsi_vpd_unit_serial_number *serial_buf;
Index: scsi/scsi_all.h
===================================================================
RCS file: /usr/ncvs/src/sys/cam/scsi/scsi_all.h,v
retrieving revision 1.28
diff -u -r1.28 scsi_all.h
--- scsi/scsi_all.h	4 Dec 2006 23:04:13 -0000	1.28
+++ scsi/scsi_all.h	11 Sep 2007 03:10:52 -0000
_at__at_ -663,6 +663,17 _at__at_
 	u_int8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE];
 };
 
+struct scsi_vpd_supported_page_list
+{
+	u_int8_t device;
+	u_int8_t page_code;
+#define SVPD_SUPPORTED_PAGE_LIST 0x00
+	u_int8_t reserved;
+	u_int8_t length;	/* number of VPD entries */
+#define SVPD_SUPPORTED_PAGES_SIZE	251
+	u_int8_t list[SVPD_SUPPORTED_PAGES_SIZE];
+};
+
 struct scsi_vpd_unit_serial_number
 {
 	u_int8_t device;
Received on Tue Sep 11 2007 - 02:13:17 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:17 UTC