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: Oliver Neukum <oneukum@suse.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Oliver Neukum 2016-09-12 15:19:41 +02:00 committed by Greg Kroah-Hartman
parent 6406c3d226
commit 050bc4e846
5 changed files with 24 additions and 1 deletions

View File

@ -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]

View File

@ -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 {
/* /*

View File

@ -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",

View File

@ -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 */
} }
} }

View File

@ -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 };