scsi: ufs: clear and apply dev_quirks on every device probe
We should clear the dev_quirks on every device probe to make sure
that we apply the quirks for newly detected UFS device. This is
particularly important with removable UFS devices.
Change-Id: I4632741c3a3b281c4c5a6c4a1887bad8fa18676b
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 7e9f67b..bea0183 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1271,7 +1271,7 @@ static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba)
{
int err = 0;
- if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME)
+ if (hba->dev_info.quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME)
err = ufs_qcom_quirk_host_pa_saveconfigtime(hba);
return err;
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 144a65f..3245fe1 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -515,6 +515,9 @@ struct ufs_dev_info {
bool is_lu_power_on_wp;
/* is Unit Attention Condition cleared on UFS Device LUN? */
unsigned is_ufs_dev_wlun_ua_cleared:1;
+
+ /* Device deviations from standard UFS device spec. */
+ unsigned int quirks;
};
#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c
index b818028..b22a4c4 100644
--- a/drivers/scsi/ufs/ufs_quirks.c
+++ b/drivers/scsi/ufs/ufs_quirks.c
@@ -67,7 +67,7 @@ void ufs_advertise_fixup_device(struct ufs_hba *hba)
(STR_PRFX_EQUAL(f->model, model) ||
!strcmp(f->model, UFS_ANY_MODEL)))
/* update quirks */
- hba->dev_quirks |= f->quirk;
+ hba->dev_info.quirks |= f->quirk;
}
out:
kfree(model);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 69275c6..7ffa3a7 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -638,7 +638,7 @@ static void ufshcd_print_host_state(struct ufs_hba *hba)
dev_err(hba->dev, "Host capabilities=0x%x, caps=0x%x\n",
hba->capabilities, hba->caps);
dev_err(hba->dev, "quirks=0x%x, dev. quirks=0x%x\n", hba->quirks,
- hba->dev_quirks);
+ hba->dev_info.quirks);
}
/**
@@ -4611,7 +4611,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
goto out;
}
- if (hba->dev_quirks & UFS_DEVICE_QUIRK_BROKEN_LCC) {
+ if (hba->dev_info.quirks & UFS_DEVICE_QUIRK_BROKEN_LCC) {
ret = ufshcd_disable_host_tx_lcc(hba);
if (ret)
goto out;
@@ -5638,7 +5638,8 @@ static void ufshcd_err_handler(struct work_struct *work)
/* Complete requests that have door-bell cleared by h/w */
ufshcd_complete_requests(hba);
- if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
+ if (hba->dev_info.quirks &
+ UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
bool ret;
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -5808,7 +5809,7 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT) {
hba->uic_error |= UFSHCD_UIC_DL_PA_INIT_ERROR;
- } else if (hba->dev_quirks &
+ } else if (hba->dev_info.quirks &
UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) {
if (reg & UIC_DATA_LINK_LAYER_ERROR_NAC_RECEIVED)
hba->uic_error |=
@@ -6818,11 +6819,11 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
ufshcd_tune_pa_hibern8time(hba);
}
- if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE)
+ if (hba->dev_info.quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE)
/* set 1ms timeout for PA_TACTIVATE */
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10);
- if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
+ if (hba->dev_info.quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
ufshcd_quirk_tune_host_pa_tactivate(hba);
ufshcd_vops_apply_dev_quirks(hba);
@@ -6846,7 +6847,7 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba)
static void ufshcd_apply_pm_quirks(struct ufs_hba *hba)
{
- if (hba->dev_quirks & UFS_DEVICE_QUIRK_NO_LINK_OFF) {
+ if (hba->dev_info.quirks & UFS_DEVICE_QUIRK_NO_LINK_OFF) {
if (ufs_get_pm_lvl_to_link_pwr_state(hba->rpm_lvl) ==
UIC_LINK_OFF_STATE) {
hba->rpm_lvl =
@@ -6996,7 +6997,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
ufshcd_apply_pm_quirks(hba);
ret = ufshcd_set_vccq_rail_unused(hba,
- (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false);
+ (hba->dev_info.quirks & UFS_DEVICE_NO_VCCQ) ? true : false);
if (ret)
goto out;
@@ -8880,7 +8881,7 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up)
/* scale down gear */
new_pwr_info.gear_tx = scale_down_gear;
new_pwr_info.gear_rx = scale_down_gear;
- if (!(hba->dev_quirks & UFS_DEVICE_NO_FASTAUTO)) {
+ if (!(hba->dev_info.quirks & UFS_DEVICE_NO_FASTAUTO)) {
new_pwr_info.pwr_tx = FASTAUTO_MODE;
new_pwr_info.pwr_rx = FASTAUTO_MODE;
}
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 0740072..d17dd49 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -774,9 +774,6 @@ struct ufs_hba {
unsigned int quirks; /* Deviations from standard UFSHCI spec. */
- /* Device deviations from standard UFS device spec. */
- unsigned int dev_quirks;
-
wait_queue_head_t tm_wq;
wait_queue_head_t tm_tag_wq;
unsigned long tm_condition;