Commit e89860f1 authored by Can Guo's avatar Can Guo Committed by Martin K. Petersen

scsi: ufs: Do not rely on prefetched data

We were setting bActiveICCLevel attribute for UFS device only once but the
type of this attribute has changed from persistent to volatile since UFS
device specification v2.1. This attribute is set to the default value after
power cycle or hardware reset event. It isn't safe to rely on prefetched
data (only used for bActiveICCLevel attribute now). Hence this change
removes the code related to data prefetching and set this parameter on
every attempt to probe the UFS device.
Tested-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Reviewed-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Reviewed-by: default avatarAvri Altman <avri.altman@wdc.com>
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent ccfa00a8
...@@ -6475,11 +6475,12 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba, ...@@ -6475,11 +6475,12 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba,
return icc_level; return icc_level;
} }
static void ufshcd_init_icc_levels(struct ufs_hba *hba) static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba)
{ {
int ret; int ret;
int buff_len = hba->desc_size.pwr_desc; int buff_len = hba->desc_size.pwr_desc;
u8 *desc_buf; u8 *desc_buf;
u32 icc_level;
desc_buf = kmalloc(buff_len, GFP_KERNEL); desc_buf = kmalloc(buff_len, GFP_KERNEL);
if (!desc_buf) if (!desc_buf)
...@@ -6494,20 +6495,17 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) ...@@ -6494,20 +6495,17 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
goto out; goto out;
} }
hba->init_prefetch_data.icc_level = icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf,
ufshcd_find_max_sup_active_icc_level(hba, buff_len);
desc_buf, buff_len); dev_dbg(hba->dev, "%s: setting icc_level 0x%x", __func__, icc_level);
dev_dbg(hba->dev, "%s: setting icc_level 0x%x",
__func__, hba->init_prefetch_data.icc_level);
ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, &icc_level);
&hba->init_prefetch_data.icc_level);
if (ret) if (ret)
dev_err(hba->dev, dev_err(hba->dev,
"%s: Failed configuring bActiveICCLevel = %d ret = %d", "%s: Failed configuring bActiveICCLevel = %d ret = %d",
__func__, hba->init_prefetch_data.icc_level , ret); __func__, icc_level, ret);
out: out:
kfree(desc_buf); kfree(desc_buf);
...@@ -7027,8 +7025,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) ...@@ -7027,8 +7025,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
{ {
int ret; int ret;
ufshcd_init_icc_levels(hba);
/* Add required well known logical units to scsi mid layer */ /* Add required well known logical units to scsi mid layer */
ret = ufshcd_scsi_add_wlus(hba); ret = ufshcd_scsi_add_wlus(hba);
if (ret) if (ret)
...@@ -7126,6 +7122,14 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async) ...@@ -7126,6 +7122,14 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
} }
} }
/*
* bActiveICCLevel is volatile for UFS device (as per latest v2.1 spec)
* and for removable UFS card as well, hence always set the parameter.
* Note: Error handler may issue the device reset hence resetting
* bActiveICCLevel as well so it is always safe to set this here.
*/
ufshcd_set_active_icc_lvl(hba);
/* set the state as operational after switching to desired gear */ /* set the state as operational after switching to desired gear */
hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
......
...@@ -408,15 +408,6 @@ struct ufs_clk_scaling { ...@@ -408,15 +408,6 @@ struct ufs_clk_scaling {
bool is_suspended; bool is_suspended;
}; };
/**
* struct ufs_init_prefetch - contains data that is pre-fetched once during
* initialization
* @icc_level: icc level which was read during initialization
*/
struct ufs_init_prefetch {
u32 icc_level;
};
#define UFS_ERR_REG_HIST_LENGTH 8 #define UFS_ERR_REG_HIST_LENGTH 8
/** /**
* struct ufs_err_reg_hist - keeps history of errors * struct ufs_err_reg_hist - keeps history of errors
...@@ -585,7 +576,6 @@ enum ufshcd_caps { ...@@ -585,7 +576,6 @@ enum ufshcd_caps {
* @intr_mask: Interrupt Mask Bits * @intr_mask: Interrupt Mask Bits
* @ee_ctrl_mask: Exception event control mask * @ee_ctrl_mask: Exception event control mask
* @is_powered: flag to check if HBA is powered * @is_powered: flag to check if HBA is powered
* @init_prefetch_data: data pre-fetched during initialization
* @eh_work: Worker to handle UFS errors that require s/w attention * @eh_work: Worker to handle UFS errors that require s/w attention
* @eeh_work: Worker to handle exception events * @eeh_work: Worker to handle exception events
* @errors: HBA errors * @errors: HBA errors
...@@ -674,7 +664,6 @@ struct ufs_hba { ...@@ -674,7 +664,6 @@ struct ufs_hba {
u16 ee_ctrl_mask; u16 ee_ctrl_mask;
u16 hba_enable_delay_us; u16 hba_enable_delay_us;
bool is_powered; bool is_powered;
struct ufs_init_prefetch init_prefetch_data;
/* Work Queues */ /* Work Queues */
struct work_struct eh_work; struct work_struct eh_work;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment