summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/ufs/ufshcd.c32
-rw-r--r--drivers/scsi/ufs/ufshcd.h1
2 files changed, 16 insertions, 17 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 06defae6d5ba..2c86606ecd2e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2697,10 +2697,9 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 upiu_wlun_id)
* Lock is predominantly held by shutdown context thus, ensuring
* that no requests from any other context may sneak through.
*/
-static void ufshcd_get_write_lock(struct ufs_hba *hba)
+static inline void ufshcd_get_write_lock(struct ufs_hba *hba)
{
down_write(&hba->lock);
- hba->issuing_task = current;
}
/**
@@ -2710,18 +2709,19 @@ static void ufshcd_get_write_lock(struct ufs_hba *hba)
*
* Returns 1 if acquired, < 0 on contention
*
- * After shutdown's initiated, allow requests only from shutdown
- * context. The sync between scaling & issue is maintained
+ * After shutdown's initiated, allow requests only directed to the
+ * well known device lun. The sync between scaling & issue is maintained
* as is and this restructuring syncs shutdown with these too.
*/
-static int ufshcd_get_read_lock(struct ufs_hba *hba)
+static int ufshcd_get_read_lock(struct ufs_hba *hba, u64 lun)
{
int err = 0;
err = down_read_trylock(&hba->lock);
if (err > 0)
goto out;
- if (hba->issuing_task == current)
+ /* let requests for well known device lun to go through */
+ if (ufshcd_scsi_to_upiu_lun(lun) == UFS_UPIU_UFS_DEVICE_WLUN)
return 0;
else if (!ufshcd_is_shutdown_ongoing(hba))
return -EAGAIN;
@@ -2729,7 +2729,6 @@ static int ufshcd_get_read_lock(struct ufs_hba *hba)
return -EPERM;
out:
- hba->issuing_task = current;
return err;
}
@@ -2742,10 +2741,7 @@ out:
*/
static inline void ufshcd_put_read_lock(struct ufs_hba *hba)
{
- if (!ufshcd_is_shutdown_ongoing(hba)) {
- hba->issuing_task = NULL;
- up_read(&hba->lock);
- }
+ up_read(&hba->lock);
}
/**
@@ -2762,6 +2758,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
unsigned long flags;
int tag;
int err = 0;
+ bool has_read_lock = false;
hba = shost_priv(host);
@@ -2773,7 +2770,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
BUG();
}
- err = ufshcd_get_read_lock(hba);
+ err = ufshcd_get_read_lock(hba, cmd->device->lun);
if (unlikely(err < 0)) {
if (err == -EPERM) {
set_host_byte(cmd, DID_ERROR);
@@ -2782,6 +2779,8 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
}
if (err == -EAGAIN)
return SCSI_MLQUEUE_HOST_BUSY;
+ } else if (err == 1) {
+ has_read_lock = true;
}
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -2922,7 +2921,8 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
out:
- ufshcd_put_read_lock(hba);
+ if (has_read_lock)
+ ufshcd_put_read_lock(hba);
return err;
}
@@ -8808,13 +8808,13 @@ int ufshcd_shutdown(struct ufs_hba *hba)
pm_runtime_get_sync(hba->dev);
ufshcd_hold_all(hba);
/**
- * (1) Acquire the lock to stop any more requests
- * (2) Set state to shutting down
+ * (1) Set state to shutting down
+ * (2) Acquire the lock to stop any more requests
* (3) Suspend clock scaling
* (4) Wait for all issued requests to complete
*/
- ufshcd_get_write_lock(hba);
ufshcd_mark_shutdown_ongoing(hba);
+ ufshcd_get_write_lock(hba);
ufshcd_scsi_block_requests(hba);
ufshcd_suspend_clkscaling(hba);
ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index c5eb21d8a0fe..81eab2cbb6cb 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -897,7 +897,6 @@ struct ufs_hba {
/* sync b/w diff contexts */
struct rw_semaphore lock;
- struct task_struct *issuing_task;
unsigned long shutdown_in_prog;
struct reset_control *core_reset;