Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Jan 2015 07:16:22 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r277367 - in stable/8/sys/dev/usb: . quirk storage
Message-ID:  <201501190716.t0J7GML8045334@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Mon Jan 19 07:16:22 2015
New Revision: 277367
URL: https://svnweb.freebsd.org/changeset/base/277367

Log:
  MFC r239237, r242628 and r277044:
  - Add the UQ_MSC_NO_PREVENT_ALLOW quirk to handle devices that do not support
    the 'PREVENT/ALLOW MEDIUM REMOVAL' SCSI command.
  - Improve auto-quirks detection for certain Kingston memory sticks.
  - Increase the maximum number of dynamic USB quirks. USB memory stick
    devices which don't support the synchronize cache SCSI command are
    likely to also not support the prevent-allow medium removal SCSI
    command.

Modified:
  stable/8/sys/dev/usb/quirk/usb_quirk.c
  stable/8/sys/dev/usb/quirk/usb_quirk.h
  stable/8/sys/dev/usb/storage/umass.c
  stable/8/sys/dev/usb/usb_freebsd.h
  stable/8/sys/dev/usb/usb_msctest.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/dev/   (props changed)
  stable/8/sys/dev/usb/   (props changed)

Modified: stable/8/sys/dev/usb/quirk/usb_quirk.c
==============================================================================
--- stable/8/sys/dev/usb/quirk/usb_quirk.c	Mon Jan 19 07:14:36 2015	(r277366)
+++ stable/8/sys/dev/usb/quirk/usb_quirk.c	Mon Jan 19 07:16:22 2015	(r277367)
@@ -397,6 +397,7 @@ static struct usb_quirk_entry usb_quirks
 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
 	USB_QUIRK(SONY, PORTABLE_HDD_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
 	    UQ_MSC_FORCE_PROTO_SCSI),
+	USB_QUIRK(STMICRO, ST72682, 0x0000, 0xffff, UQ_MSC_NO_PREVENT_ALLOW),
 	USB_QUIRK(SUPERTOP, IDE, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
 	    UQ_MSC_NO_SYNC_CACHE),
 	USB_QUIRK(SUPERTOP, FLASHDRIVE, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
@@ -523,6 +524,7 @@ static const char *usb_quirk_str[USB_QUI
 	[UQ_MSC_NO_GETMAXLUN]		= "UQ_MSC_NO_GETMAXLUN",
 	[UQ_MSC_NO_INQUIRY]		= "UQ_MSC_NO_INQUIRY",
 	[UQ_MSC_NO_INQUIRY_EVPD]	= "UQ_MSC_NO_INQUIRY_EVPD",
+	[UQ_MSC_NO_PREVENT_ALLOW]	= "UQ_MSC_NO_PREVENT_ALLOW",
 	[UQ_MSC_NO_SYNC_CACHE]		= "UQ_MSC_NO_SYNC_CACHE",
 	[UQ_MSC_SHUTTLE_INIT]		= "UQ_MSC_SHUTTLE_INIT",
 	[UQ_MSC_ALT_IFACE_1]		= "UQ_MSC_ALT_IFACE_1",

Modified: stable/8/sys/dev/usb/quirk/usb_quirk.h
==============================================================================
--- stable/8/sys/dev/usb/quirk/usb_quirk.h	Mon Jan 19 07:14:36 2015	(r277366)
+++ stable/8/sys/dev/usb/quirk/usb_quirk.h	Mon Jan 19 07:16:22 2015	(r277367)
@@ -75,6 +75,7 @@ enum {
 	UQ_MSC_NO_GETMAXLUN,		/* does not support get max LUN */
 	UQ_MSC_NO_INQUIRY,		/* fake generic inq response */
 	UQ_MSC_NO_INQUIRY_EVPD,		/* does not support inq EVPD */
+	UQ_MSC_NO_PREVENT_ALLOW,	/* does not support medium removal */ 
 	UQ_MSC_NO_SYNC_CACHE,		/* does not support sync cache */ 
 	UQ_MSC_SHUTTLE_INIT,		/* requires Shuttle init sequence */
 	UQ_MSC_ALT_IFACE_1,		/* switch to alternate interface 1 */

Modified: stable/8/sys/dev/usb/storage/umass.c
==============================================================================
--- stable/8/sys/dev/usb/storage/umass.c	Mon Jan 19 07:14:36 2015	(r277366)
+++ stable/8/sys/dev/usb/storage/umass.c	Mon Jan 19 07:16:22 2015	(r277367)
@@ -371,6 +371,8 @@ typedef uint8_t (umass_transform_t)(stru
 	 * result.
 	 */
 #define	NO_SYNCHRONIZE_CACHE	0x4000
+	/* Device does not support 'PREVENT/ALLOW MEDIUM REMOVAL'. */
+#define	NO_PREVENT_ALLOW	0x8000
 
 struct umass_softc {
 
@@ -841,6 +843,8 @@ umass_probe_proto(device_t dev, struct u
 		quirks |= NO_INQUIRY;
 	if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY_EVPD))
 		quirks |= NO_INQUIRY_EVPD;
+	if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW))
+		quirks |= NO_PREVENT_ALLOW;
 	if (usb_test_quirk(uaa, UQ_MSC_NO_SYNC_CACHE))
 		quirks |= NO_SYNCHRONIZE_CACHE;
 	if (usb_test_quirk(uaa, UQ_MSC_SHUTTLE_INIT))
@@ -2376,6 +2380,13 @@ umass_cam_action(struct cam_sim *sim, un
 					if (sc->sc_quirks & FORCE_SHORT_INQUIRY) {
 						ccb->csio.dxfer_len = SHORT_INQUIRY_LENGTH;
 					}
+				} else if (sc->sc_transfer.cmd_data[0] == PREVENT_ALLOW) {
+					if (sc->sc_quirks & NO_PREVENT_ALLOW) {
+						ccb->csio.scsi_status = SCSI_STATUS_OK;
+						ccb->ccb_h.status = CAM_REQ_CMP;
+						xpt_done(ccb);
+						goto done;
+					}
 				} else if (sc->sc_transfer.cmd_data[0] == SYNCHRONIZE_CACHE) {
 					if (sc->sc_quirks & NO_SYNCHRONIZE_CACHE) {
 						ccb->csio.scsi_status = SCSI_STATUS_OK;

Modified: stable/8/sys/dev/usb/usb_freebsd.h
==============================================================================
--- stable/8/sys/dev/usb/usb_freebsd.h	Mon Jan 19 07:14:36 2015	(r277366)
+++ stable/8/sys/dev/usb/usb_freebsd.h	Mon Jan 19 07:16:22 2015	(r277367)
@@ -63,7 +63,7 @@
 #define	USB_EP0_BUFSIZE		1024	/* bytes */
 #define	USB_CS_RESET_LIMIT	20	/* failures = 20 * 50 ms = 1sec */
 
-#define	USB_MAX_AUTO_QUIRK	4	/* maximum number of dynamic quirks */
+#define	USB_MAX_AUTO_QUIRK	8	/* maximum number of dynamic quirks */
 
 typedef uint32_t usb_timeout_t;		/* milliseconds */
 typedef uint32_t usb_frlength_t;	/* bytes */

Modified: stable/8/sys/dev/usb/usb_msctest.c
==============================================================================
--- stable/8/sys/dev/usb/usb_msctest.c	Mon Jan 19 07:14:36 2015	(r277366)
+++ stable/8/sys/dev/usb/usb_msctest.c	Mon Jan 19 07:16:22 2015	(r277367)
@@ -104,6 +104,8 @@ static uint8_t scsi_sync_cache[] =	{ 0x3
 					  0x00, 0x00, 0x00, 0x00 };
 static uint8_t scsi_request_sense[] =	{ 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
 					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_read_capacity[] =	{ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
+					  0x00, 0x00, 0x00, 0x00 };
 
 #define	BULK_SIZE		64	/* dummy */
 #define	ERR_CSW_FAILED		-1
@@ -648,7 +650,7 @@ usb_msc_auto_quirk(struct usb_device *ud
 	}
 
 	is_no_direct = 1;
-	for (timeout = 4; timeout; timeout--) {
+	for (timeout = 4; timeout != 0; timeout--) {
 		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
 		    SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
 		    USB_MS_HZ);
@@ -677,7 +679,9 @@ usb_msc_auto_quirk(struct usb_device *ud
 		if (err != ERR_CSW_FAILED)
 			goto error;
 	}
+	timeout = 1;
 
+retry_sync_cache:
 	err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
 	    &scsi_sync_cache, sizeof(scsi_sync_cache),
 	    USB_MS_HZ);
@@ -687,9 +691,49 @@ usb_msc_auto_quirk(struct usb_device *ud
 		if (err != ERR_CSW_FAILED)
 			goto error;
 
-		DPRINTF("Device doesn't handle synchronize cache\n");
+		DPRINTF("Device doesn't handle synchronize cache "
+		    "and prevent allow medium removal\n");
 
 		usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+		usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
+	} else {
+
+		/*
+		 * Certain Kingston memory sticks fail the first
+		 * read capacity after a synchronize cache command
+		 * has been issued. Disable the synchronize cache
+		 * command for such devices.
+		 */
+
+		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+		    &scsi_read_capacity, sizeof(scsi_read_capacity),
+		    USB_MS_HZ);
+
+		if (err != 0) {
+			if (err != ERR_CSW_FAILED)
+				goto error;
+
+			err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+			    &scsi_read_capacity, sizeof(scsi_read_capacity),
+			    USB_MS_HZ);
+
+			if (err == 0) {
+				if (timeout--)
+					goto retry_sync_cache;
+
+				DPRINTF("Device most likely doesn't "
+				    "handle synchronize cache nor"
+				    "prevent allow medium removal\n");
+
+				usbd_add_dynamic_quirk(udev,
+				    UQ_MSC_NO_SYNC_CACHE);
+				usbd_add_dynamic_quirk(udev,
+				    UQ_MSC_NO_PREVENT_ALLOW);
+			} else {
+				if (err != ERR_CSW_FAILED)
+					goto error;
+			}
+		}
 	}
 
 	/* clear sense status of any failed commands on the device */
@@ -728,6 +772,7 @@ error:
 	DPRINTF("Device did not respond, enabling all quirks\n");
 
 	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
 	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY);
 
 	/* Need to re-enumerate the device */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501190716.t0J7GML8045334>