mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-04 18:19:28 +09:00
scsi: ufs: Clear UAC for FFU and RPMB LUNs
[ Upstream commit 4f3e900b62 ]
In order to conduct FFU or RPMB operations, UFS needs to clear UNIT
ATTENTION condition. Clear it explicitly so that we get no failures during
initialization.
Link: https://lore.kernel.org/r/20201117165839.1643377-4-jaegeuk@kernel.org
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
43dee885be
commit
e5383432d9
@@ -7093,7 +7093,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,
|
||||
@@ -7106,14 +7105,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);
|
||||
@@ -7637,6 +7636,63 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp);
|
||||
|
||||
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);
|
||||
if (wlun == UFS_UPIU_UFS_DEVICE_WLUN)
|
||||
sdp = hba->sdev_ufs_device;
|
||||
else if (wlun == UFS_UPIU_RPMB_WLUN)
|
||||
sdp = hba->sdev_rpmb;
|
||||
else
|
||||
BUG_ON(1);
|
||||
if (sdp) {
|
||||
ret = scsi_device_get(sdp);
|
||||
if (!ret && !scsi_device_online(sdp)) {
|
||||
ret = -ENODEV;
|
||||
scsi_device_put(sdp);
|
||||
}
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
}
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
ret = ufshcd_send_request_sense(hba, sdp);
|
||||
scsi_device_put(sdp);
|
||||
out_err:
|
||||
if (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;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_probe_hba - probe hba to detect device and initialize
|
||||
* @hba: per-adapter instance
|
||||
@@ -7756,6 +7812,8 @@ out:
|
||||
pm_runtime_put_sync(hba->dev);
|
||||
ufshcd_exit_clk_scaling(hba);
|
||||
ufshcd_hba_exit(hba);
|
||||
} else {
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -683,6 +683,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;
|
||||
|
||||
Reference in New Issue
Block a user