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:
Родитель
6406c3d226
Коммит
050bc4e846
|
@ -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]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
Загрузка…
Ссылка в новой задаче