In preparation to hold ufshcd_down_write() lock for the entire error handler duration. Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> --- drivers/scsi/ufs/ufshcd.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 495e1c0afae3..74891947bb34 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -898,6 +898,7 @@ struct ufs_hba { bool is_urgent_bkops_lvl_checked; struct rw_semaphore host_rw_sem; + struct task_struct *excl_task; unsigned char desc_size[QUERY_DESC_IDN_MAX]; atomic_t scsi_block_reqs_cnt; @@ -1420,31 +1421,45 @@ static inline int ufshcd_rpmb_rpm_put(struct ufs_hba *hba) static inline void ufshcd_down_read(struct ufs_hba *hba) { - down_read(&hba->host_rw_sem); + if (hba->excl_task != current) + down_read(&hba->host_rw_sem); } static inline void ufshcd_up_read(struct ufs_hba *hba) { - up_read(&hba->host_rw_sem); + if (hba->excl_task != current) + up_read(&hba->host_rw_sem); } static inline int ufshcd_down_read_trylock(struct ufs_hba *hba) { + if (hba->excl_task == current) + return 1; + return down_read_trylock(&hba->host_rw_sem); } static inline void ufshcd_down_write(struct ufs_hba *hba) { down_write(&hba->host_rw_sem); + /* + * Assign exclusive access to this task, which enables bypassing + * down_read/up_read, refer ufshcd_down_read() and ufshcd_up_read(). + * Note, if the same task will not be doing up_write(), it must set + * hba->excl_task to NULL itself. + */ + hba->excl_task = current; } static inline void ufshcd_up_write(struct ufs_hba *hba) { + hba->excl_task = NULL; up_write(&hba->host_rw_sem); } static inline void ufshcd_downgrade_write(struct ufs_hba *hba) { + hba->excl_task = NULL; downgrade_write(&hba->host_rw_sem); } -- 2.25.1