Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 050bc4e8 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman
Browse files

scsi: introduce a quirk for false cache reporting



Some SATA to USB bridges fail to cooperate with some
drives resulting in no cache being present being reported
to the host. That causes the host to skip sending
a command to synchronize caches. That causes data loss
when the drive is powered down.

Signed-off-by: default avatarOliver Neukum <oneukum@suse.com>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6406c3d2
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -4238,6 +4238,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
				u = IGNORE_UAS (don't bind to the uas driver);
				u = IGNORE_UAS (don't bind to the uas driver);
				w = NO_WP_DETECT (don't test whether the
				w = NO_WP_DETECT (don't test whether the
					medium is write-protected).
					medium is write-protected).
				y = ALWAYS_SYNC (issue a SYNCHRONIZE_CACHE
					even if the device claims no cache)
			Example: quirks=0419:aaf5:rl,0421:0433:rc
			Example: quirks=0419:aaf5:rl,0421:0433:rc


	user_debug=	[KNL,ARM]
	user_debug=	[KNL,ARM]
+8 −0
Original line number Original line Diff line number Diff line
@@ -296,6 +296,14 @@ static int slave_configure(struct scsi_device *sdev)
		if (us->fflags & US_FL_BROKEN_FUA)
		if (us->fflags & US_FL_BROKEN_FUA)
			sdev->broken_fua = 1;
			sdev->broken_fua = 1;


		/* Some even totally fail to indicate a cache */
		if (us->fflags & US_FL_ALWAYS_SYNC) {
			/* don't read caching information */
			sdev->skip_ms_page_8 = 1;
			sdev->skip_ms_page_3f = 1;
			/* assume sync is needed */
			sdev->wce_default_on = 1;
		}
	} else {
	} else {


		/*
		/*
+7 −0
Original line number Original line Diff line number Diff line
@@ -338,6 +338,13 @@ UNUSUAL_DEV( 0x046b, 0xff40, 0x0100, 0x0100,
		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
		US_FL_NO_WP_DETECT),
		US_FL_NO_WP_DETECT),


/* Reported by Egbert Eich <eich@suse.com> */
UNUSUAL_DEV(  0x0480, 0xd010, 0x0100, 0x9999,
		"Toshiba",
		"External USB 3.0",
		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
		US_FL_ALWAYS_SYNC),

/* Patch submitted by Philipp Friedrich <philipp@void.at> */
/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
		"Kyocera",
		"Kyocera",
+5 −1
Original line number Original line Diff line number Diff line
@@ -498,7 +498,8 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
			US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
			US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
			US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE |
			US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE |
			US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES |
			US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES |
			US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS);
			US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS |
			US_FL_ALWAYS_SYNC);


	p = quirks;
	p = quirks;
	while (*p) {
	while (*p) {
@@ -581,6 +582,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
		case 'w':
		case 'w':
			f |= US_FL_NO_WP_DETECT;
			f |= US_FL_NO_WP_DETECT;
			break;
			break;
		case 'y':
			f |= US_FL_ALWAYS_SYNC;
			break;
		/* Ignore unrecognized flag characters */
		/* Ignore unrecognized flag characters */
		}
		}
	}
	}
+2 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,8 @@
		/* Sets max_sectors to 240 */			\
		/* Sets max_sectors to 240 */			\
	US_FLAG(NO_REPORT_LUNS,	0x10000000)			\
	US_FLAG(NO_REPORT_LUNS,	0x10000000)			\
		/* Cannot handle REPORT_LUNS */			\
		/* Cannot handle REPORT_LUNS */			\
	US_FLAG(ALWAYS_SYNC, 0x20000000)			\
		/* lies about caching, so always sync */	\


#define US_FLAG(name, value)	US_FL_##name = value ,
#define US_FLAG(name, value)	US_FL_##name = value ,
enum { US_DO_ALL_FLAGS };
enum { US_DO_ALL_FLAGS };