Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 953f1de8 authored by Pavankumar Kondeti's avatar Pavankumar Kondeti
Browse files

USB: storage: Allow UICC cards to perform house keeping operations



Some UICC cards needs to perform the flash related operations during idle
time. The idle time is detected by the card by counting the consecutive
TEST_UNIT_READY commands. If the card does not find idle time, it perform
them while processing a WRITE(10) command. If the card is kept busy which
happens during continuous mass storage interfaces, it takes lot of time to
respond to the commands on the CCID interface.

Introduce a quirk called US_FL_TUR_AFTER_WRITE for sending 5 consecutive
TEST_UNIT_READY commands for every 8 WRITE(10) commands. This approach
forces the card to perform house keeping operations during continuous
mass storage transfers. The test result indicate no degradation in
the performance.

CRs-Fixed: 639155
Change-Id: Icff9ac232973d2adceb7d968dca5a2c987031384
Signed-off-by: default avatarPavankumar Kondeti <pkondeti@codeaurora.org>
parent acf473c0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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
+36 −0
Original line number Diff line number Diff line
@@ -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
+6 −0
Original line number Diff line number Diff line
@@ -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),
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+4 −2
Original line number Diff line number Diff line
@@ -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 };