Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Oliver Neukum and committed by
Greg Kroah-Hartman
050bc4e8 6406c3d2

+24 -1
+2
Documentation/kernel-parameters.txt
··· 4238 4238 u = IGNORE_UAS (don't bind to the uas driver); 4239 4239 w = NO_WP_DETECT (don't test whether the 4240 4240 medium is write-protected). 4241 + y = ALWAYS_SYNC (issue a SYNCHRONIZE_CACHE 4242 + even if the device claims no cache) 4241 4243 Example: quirks=0419:aaf5:rl,0421:0433:rc 4242 4244 4243 4245 user_debug= [KNL,ARM]
+8
drivers/usb/storage/scsiglue.c
··· 296 296 if (us->fflags & US_FL_BROKEN_FUA) 297 297 sdev->broken_fua = 1; 298 298 299 + /* Some even totally fail to indicate a cache */ 300 + if (us->fflags & US_FL_ALWAYS_SYNC) { 301 + /* don't read caching information */ 302 + sdev->skip_ms_page_8 = 1; 303 + sdev->skip_ms_page_3f = 1; 304 + /* assume sync is needed */ 305 + sdev->wce_default_on = 1; 306 + } 299 307 } else { 300 308 301 309 /*
+7
drivers/usb/storage/unusual_devs.h
··· 338 338 USB_SC_DEVICE, USB_PR_DEVICE, NULL, 339 339 US_FL_NO_WP_DETECT), 340 340 341 + /* Reported by Egbert Eich <eich@suse.com> */ 342 + UNUSUAL_DEV( 0x0480, 0xd010, 0x0100, 0x9999, 343 + "Toshiba", 344 + "External USB 3.0", 345 + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 346 + US_FL_ALWAYS_SYNC), 347 + 341 348 /* Patch submitted by Philipp Friedrich <philipp@void.at> */ 342 349 UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, 343 350 "Kyocera",
+5 -1
drivers/usb/storage/usb.c
··· 498 498 US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 | 499 499 US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE | 500 500 US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES | 501 - US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS); 501 + US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS | 502 + US_FL_ALWAYS_SYNC); 502 503 503 504 p = quirks; 504 505 while (*p) { ··· 581 580 break; 582 581 case 'w': 583 582 f |= US_FL_NO_WP_DETECT; 583 + break; 584 + case 'y': 585 + f |= US_FL_ALWAYS_SYNC; 584 586 break; 585 587 /* Ignore unrecognized flag characters */ 586 588 }
+2
include/linux/usb_usual.h
··· 81 81 /* Sets max_sectors to 240 */ \ 82 82 US_FLAG(NO_REPORT_LUNS, 0x10000000) \ 83 83 /* Cannot handle REPORT_LUNS */ \ 84 + US_FLAG(ALWAYS_SYNC, 0x20000000) \ 85 + /* lies about caching, so always sync */ \ 84 86 85 87 #define US_FLAG(name, value) US_FL_##name = value , 86 88 enum { US_DO_ALL_FLAGS };