Skip to content

Commit

Permalink
scsi: introduce a quirk for false cache reporting
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Oliver Neukum authored and Greg Kroah-Hartman committed Sep 13, 2016
1 parent 6406c3d commit 050bc4e
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4238,6 +4238,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
u = IGNORE_UAS (don't bind to the uas driver);
w = NO_WP_DETECT (don't test whether the
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

user_debug= [KNL,ARM]
Expand Down
8 changes: 8 additions & 0 deletions drivers/usb/storage/scsiglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,14 @@ static int slave_configure(struct scsi_device *sdev)
if (us->fflags & US_FL_BROKEN_FUA)
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 {

/*
Expand Down
7 changes: 7 additions & 0 deletions drivers/usb/storage/unusual_devs.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,13 @@ UNUSUAL_DEV( 0x046b, 0xff40, 0x0100, 0x0100,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
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> */
UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
"Kyocera",
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/storage/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_INITIAL_READ10 | US_FL_WRITE_CACHE |
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;
while (*p) {
Expand Down Expand Up @@ -581,6 +582,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
case 'w':
f |= US_FL_NO_WP_DETECT;
break;
case 'y':
f |= US_FL_ALWAYS_SYNC;
break;
/* Ignore unrecognized flag characters */
}
}
Expand Down
2 changes: 2 additions & 0 deletions include/linux/usb_usual.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
/* Sets max_sectors to 240 */ \
US_FLAG(NO_REPORT_LUNS, 0x10000000) \
/* Cannot handle REPORT_LUNS */ \
US_FLAG(ALWAYS_SYNC, 0x20000000) \
/* lies about caching, so always sync */ \

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

0 comments on commit 050bc4e

Please sign in to comment.