FROMLIST: scsi: ufs: clear uac for rpmb lun

This patch clears UA condition for RPMB lun.

Bug: 169682240
Link: https://lore.kernel.org/linux-scsi/20201005223635.2922805-2-jaegeuk@kernel.org/T/#u
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
Change-Id: Ia088deb649a7f9dbabbdc1622041ea30f1e2f375
This commit is contained in:
Jaegeuk Kim 2020-10-05 15:02:31 -07:00
parent a428f6d3cd
commit fedfc101f8
2 changed files with 37 additions and 18 deletions

View File

@ -6861,7 +6861,6 @@ static inline void ufshcd_blk_pm_runtime_init(struct scsi_device *sdev)
static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
{
int ret = 0;
struct scsi_device *sdev_rpmb;
struct scsi_device *sdev_boot;
hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0,
@ -6874,14 +6873,14 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device);
scsi_device_put(hba->sdev_ufs_device);
sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL);
if (IS_ERR(sdev_rpmb)) {
ret = PTR_ERR(sdev_rpmb);
if (IS_ERR(hba->sdev_rpmb)) {
ret = PTR_ERR(hba->sdev_rpmb);
goto remove_sdev_ufs_device;
}
ufshcd_blk_pm_runtime_init(sdev_rpmb);
scsi_device_put(sdev_rpmb);
ufshcd_blk_pm_runtime_init(hba->sdev_rpmb);
scsi_device_put(hba->sdev_rpmb);
sdev_boot = __scsi_add_device(hba->host, 0, 0,
ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL);
@ -7408,14 +7407,20 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
static int
ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp);
static int ufshcd_clear_uac(struct ufs_hba *hba)
static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun)
{
struct scsi_device *sdp;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(hba->host->host_lock, flags);
sdp = hba->sdev_ufs_device;
if (wlun == UFS_UPIU_UFS_DEVICE_WLUN)
sdp = hba->sdev_ufs_device;
else if (wlun == UFS_UPIU_RPMB_WLUN)
sdp = hba->sdev_rpmb;
else
return -EINVAL;
if (sdp) {
ret = scsi_device_get(sdp);
if (!ret && !scsi_device_online(sdp)) {
@ -7429,18 +7434,31 @@ static int ufshcd_clear_uac(struct ufs_hba *hba)
if (ret)
goto out_err;
if (hba->wlun_dev_clr_ua) {
ret = ufshcd_send_request_sense(hba, sdp);
if (ret)
goto out;
/* Unit attention condition is cleared now */
hba->wlun_dev_clr_ua = false;
}
out:
ret = ufshcd_send_request_sense(hba, sdp);
scsi_device_put(sdp);
out_err:
if (ret)
dev_err(hba->dev, "%s: UAC clear ret = %d\n", __func__, ret);
dev_err(hba->dev, "%s: UAC clear LU=%x ret = %d\n",
__func__, wlun, ret);
return ret;
}
static int ufshcd_clear_ua_wluns(struct ufs_hba *hba)
{
int ret = 0;
if (!hba->wlun_dev_clr_ua)
goto out;
ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN);
if (!ret)
ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN);
if (!ret)
hba->wlun_dev_clr_ua = false;
out:
if (ret)
dev_err(hba->dev, "%s: Failed to clear UAC WLUNS ret = %d\n",
__func__, ret);
return ret;
}
@ -7560,7 +7578,7 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
ufshcd_exit_clk_scaling(hba);
ufshcd_hba_exit(hba);
} else {
ufshcd_clear_uac(hba);
ufshcd_clear_ua_wluns(hba);
}
}

View File

@ -693,6 +693,7 @@ struct ufs_hba {
* "UFS device" W-LU.
*/
struct scsi_device *sdev_ufs_device;
struct scsi_device *sdev_rpmb;
enum ufs_dev_pwr_mode curr_dev_pwr_mode;
enum uic_link_state uic_link_state;