Loading drivers/usb/storage/scsiglue.c +8 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,14 @@ static int slave_configure(struct scsi_device *sdev) sdev->autosuspend_delay = us->sdev_autosuspend_delay; } /* * This quirk enables sending consecutive TEST_UNIT_READY * commands in WRITE(10) command processing context. Increase * the timeout to 60 seconds. */ if (us->fflags & US_FL_TUR_AFTER_WRITE) blk_queue_rq_timeout(sdev->request_queue, (60 * HZ)); } else { /* Non-disk-type devices don't need to blacklist any pages Loading drivers/usb/storage/transport.c +36 −0 Original line number Diff line number Diff line Loading @@ -858,6 +858,42 @@ Retry_Sense: srb->result = DID_ERROR << 16; last_sector_hacks(us, srb); /* * TMC UICC cards expect 5 TEST_UNIT_READY commands after * writing some data. The card performs the flash related * house keeping operations after receiving these commands. * Send 5 TEST_UNIT_READY commands for every 8 WRITE_10 * commands. */ if (unlikely((us->fflags & US_FL_TUR_AFTER_WRITE) && srb->cmnd[0] == WRITE_10)) { int i; int temp_result; struct scsi_eh_save ses; unsigned char cmd[] = { TEST_UNIT_READY, 0, 0, 0, 0, 0, }; us->tur_count[srb->device->lun]++; if (++us->tur_count[srb->device->lun] == 8) { us->tur_count[srb->device->lun] = 0; scsi_eh_prep_cmnd(srb, &ses, cmd, 6, 0); for (i = 0; i < 5; i++) { temp_result = us->transport(us->srb, us); if (temp_result != USB_STOR_TRANSPORT_GOOD) { usb_stor_dbg(us, "TUR failed %d %d\n", i, temp_result); break; } } scsi_eh_restore_cmnd(srb, &ses); } } return; /* Error and abort processing: try to resynchronize with the device Loading drivers/usb/storage/unusual_devs.h +6 −0 Original line number Diff line number Diff line Loading @@ -2072,6 +2072,12 @@ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001, "Digital MP3 Audio Player", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Reported by Pavankumar Kondeti <pkondeti@codeaurora.org> */ UNUSUAL_DEV(0x0925, 0x9011, 0x0100, 0x0100, "TMC", "USB DISK", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_TUR_AFTER_WRITE), /* Control/Bulk transport for all SubClass values */ USUAL_DEV(USB_SC_RBC, USB_PR_CB), USUAL_DEV(USB_SC_8020, USB_PR_CB), Loading drivers/usb/storage/usb.h +2 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,8 @@ struct us_data { int use_last_sector_hacks; int last_sector_retries; int sdev_autosuspend_delay; /* consecutive TEST_UNIT_READY commands during write */ int tur_count[16]; }; /* Convert between us_data and the corresponding Scsi_Host */ Loading include/linux/usb_usual.h +4 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,10 @@ /* Initial READ(10) (and others) must be retried */ \ US_FLAG(WRITE_CACHE, 0x00200000) \ /* Write Cache status is not available */ \ US_FLAG(NEEDS_CAP16, 0x00400000) /* cannot handle READ_CAPACITY_10 */ US_FLAG(NEEDS_CAP16, 0x00400000) \ /* cannot handle READ_CAPACITY_10 */ \ US_FLAG(TUR_AFTER_WRITE, 0x00800000) \ /* 5 TEST_UNIT_READY after 8 WRITE(10) */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; Loading Loading
drivers/usb/storage/scsiglue.c +8 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,14 @@ static int slave_configure(struct scsi_device *sdev) sdev->autosuspend_delay = us->sdev_autosuspend_delay; } /* * This quirk enables sending consecutive TEST_UNIT_READY * commands in WRITE(10) command processing context. Increase * the timeout to 60 seconds. */ if (us->fflags & US_FL_TUR_AFTER_WRITE) blk_queue_rq_timeout(sdev->request_queue, (60 * HZ)); } else { /* Non-disk-type devices don't need to blacklist any pages Loading
drivers/usb/storage/transport.c +36 −0 Original line number Diff line number Diff line Loading @@ -858,6 +858,42 @@ Retry_Sense: srb->result = DID_ERROR << 16; last_sector_hacks(us, srb); /* * TMC UICC cards expect 5 TEST_UNIT_READY commands after * writing some data. The card performs the flash related * house keeping operations after receiving these commands. * Send 5 TEST_UNIT_READY commands for every 8 WRITE_10 * commands. */ if (unlikely((us->fflags & US_FL_TUR_AFTER_WRITE) && srb->cmnd[0] == WRITE_10)) { int i; int temp_result; struct scsi_eh_save ses; unsigned char cmd[] = { TEST_UNIT_READY, 0, 0, 0, 0, 0, }; us->tur_count[srb->device->lun]++; if (++us->tur_count[srb->device->lun] == 8) { us->tur_count[srb->device->lun] = 0; scsi_eh_prep_cmnd(srb, &ses, cmd, 6, 0); for (i = 0; i < 5; i++) { temp_result = us->transport(us->srb, us); if (temp_result != USB_STOR_TRANSPORT_GOOD) { usb_stor_dbg(us, "TUR failed %d %d\n", i, temp_result); break; } } scsi_eh_restore_cmnd(srb, &ses); } } return; /* Error and abort processing: try to resynchronize with the device Loading
drivers/usb/storage/unusual_devs.h +6 −0 Original line number Diff line number Diff line Loading @@ -2072,6 +2072,12 @@ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001, "Digital MP3 Audio Player", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Reported by Pavankumar Kondeti <pkondeti@codeaurora.org> */ UNUSUAL_DEV(0x0925, 0x9011, 0x0100, 0x0100, "TMC", "USB DISK", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_TUR_AFTER_WRITE), /* Control/Bulk transport for all SubClass values */ USUAL_DEV(USB_SC_RBC, USB_PR_CB), USUAL_DEV(USB_SC_8020, USB_PR_CB), Loading
drivers/usb/storage/usb.h +2 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,8 @@ struct us_data { int use_last_sector_hacks; int last_sector_retries; int sdev_autosuspend_delay; /* consecutive TEST_UNIT_READY commands during write */ int tur_count[16]; }; /* Convert between us_data and the corresponding Scsi_Host */ Loading
include/linux/usb_usual.h +4 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,10 @@ /* Initial READ(10) (and others) must be retried */ \ US_FLAG(WRITE_CACHE, 0x00200000) \ /* Write Cache status is not available */ \ US_FLAG(NEEDS_CAP16, 0x00400000) /* cannot handle READ_CAPACITY_10 */ US_FLAG(NEEDS_CAP16, 0x00400000) \ /* cannot handle READ_CAPACITY_10 */ \ US_FLAG(TUR_AFTER_WRITE, 0x00800000) \ /* 5 TEST_UNIT_READY after 8 WRITE(10) */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; Loading