|
@@ -4568,6 +4568,41 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
|
|
|
ufshcd_probe_hba(hba);
|
|
|
}
|
|
|
|
|
|
+static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ struct Scsi_Host *host;
|
|
|
+ struct ufs_hba *hba;
|
|
|
+ int index;
|
|
|
+ bool found = false;
|
|
|
+
|
|
|
+ if (!scmd || !scmd->device || !scmd->device->host)
|
|
|
+ return BLK_EH_NOT_HANDLED;
|
|
|
+
|
|
|
+ host = scmd->device->host;
|
|
|
+ hba = shost_priv(host);
|
|
|
+ if (!hba)
|
|
|
+ return BLK_EH_NOT_HANDLED;
|
|
|
+
|
|
|
+ spin_lock_irqsave(host->host_lock, flags);
|
|
|
+
|
|
|
+ for_each_set_bit(index, &hba->outstanding_reqs, hba->nutrs) {
|
|
|
+ if (hba->lrb[index].cmd == scmd) {
|
|
|
+ found = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(host->host_lock, flags);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Bypass SCSI error handling and reset the block layer timer if this
|
|
|
+ * SCSI command was not actually dispatched to UFS driver, otherwise
|
|
|
+ * let SCSI layer handle the error as usual.
|
|
|
+ */
|
|
|
+ return found ? BLK_EH_NOT_HANDLED : BLK_EH_RESET_TIMER;
|
|
|
+}
|
|
|
+
|
|
|
static struct scsi_host_template ufshcd_driver_template = {
|
|
|
.module = THIS_MODULE,
|
|
|
.name = UFSHCD,
|
|
@@ -4580,6 +4615,7 @@ static struct scsi_host_template ufshcd_driver_template = {
|
|
|
.eh_abort_handler = ufshcd_abort,
|
|
|
.eh_device_reset_handler = ufshcd_eh_device_reset_handler,
|
|
|
.eh_host_reset_handler = ufshcd_eh_host_reset_handler,
|
|
|
+ .eh_timed_out = ufshcd_eh_timed_out,
|
|
|
.this_id = -1,
|
|
|
.sg_tablesize = SG_ALL,
|
|
|
.cmd_per_lun = UFSHCD_CMD_PER_LUN,
|