|
|
|
@ -3399,37 +3399,6 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ufshcd_map_desc_id_to_length - map descriptor IDN to its length
|
|
|
|
|
* @hba: Pointer to adapter instance
|
|
|
|
|
* @desc_id: descriptor idn value
|
|
|
|
|
* @desc_len: mapped desc length (out)
|
|
|
|
|
*/
|
|
|
|
|
void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
|
|
|
|
|
int *desc_len)
|
|
|
|
|
{
|
|
|
|
|
if (desc_id >= QUERY_DESC_IDN_MAX || desc_id == QUERY_DESC_IDN_RFU_0 ||
|
|
|
|
|
desc_id == QUERY_DESC_IDN_RFU_1)
|
|
|
|
|
*desc_len = 0;
|
|
|
|
|
else
|
|
|
|
|
*desc_len = hba->desc_size[desc_id];
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL(ufshcd_map_desc_id_to_length);
|
|
|
|
|
|
|
|
|
|
static void ufshcd_update_desc_length(struct ufs_hba *hba,
|
|
|
|
|
enum desc_idn desc_id, int desc_index,
|
|
|
|
|
unsigned char desc_len)
|
|
|
|
|
{
|
|
|
|
|
if (hba->desc_size[desc_id] == QUERY_DESC_MAX_SIZE &&
|
|
|
|
|
desc_id != QUERY_DESC_IDN_STRING && desc_index != UFS_RPMB_UNIT)
|
|
|
|
|
/* For UFS 3.1, the normal unit descriptor is 10 bytes larger
|
|
|
|
|
* than the RPMB unit, however, both descriptors share the same
|
|
|
|
|
* desc_idn, to cover both unit descriptors with one length, we
|
|
|
|
|
* choose the normal unit descriptor length by desc_index.
|
|
|
|
|
*/
|
|
|
|
|
hba->desc_size[desc_id] = desc_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ufshcd_read_desc_param - read the specified descriptor parameter
|
|
|
|
|
* @hba: Pointer to adapter instance
|
|
|
|
@ -3450,26 +3419,13 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
u8 *desc_buf;
|
|
|
|
|
int buff_len;
|
|
|
|
|
int buff_len = QUERY_DESC_MAX_SIZE;
|
|
|
|
|
bool is_kmalloc = true;
|
|
|
|
|
|
|
|
|
|
/* Safety check */
|
|
|
|
|
if (desc_id >= QUERY_DESC_IDN_MAX || !param_size)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
/* Get the length of descriptor */
|
|
|
|
|
ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
|
|
|
|
|
if (!buff_len) {
|
|
|
|
|
dev_err(hba->dev, "%s: Failed to get desc length\n", __func__);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (param_offset >= buff_len) {
|
|
|
|
|
dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n",
|
|
|
|
|
__func__, param_offset, desc_id, buff_len);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check whether we need temp memory */
|
|
|
|
|
if (param_offset != 0 || param_size < buff_len) {
|
|
|
|
|
desc_buf = kzalloc(buff_len, GFP_KERNEL);
|
|
|
|
@ -3482,15 +3438,23 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
|
|
|
|
|
|
|
|
|
|
/* Request for full descriptor */
|
|
|
|
|
ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
|
|
|
|
|
desc_id, desc_index, 0,
|
|
|
|
|
desc_buf, &buff_len);
|
|
|
|
|
|
|
|
|
|
desc_id, desc_index, 0,
|
|
|
|
|
desc_buf, &buff_len);
|
|
|
|
|
if (ret) {
|
|
|
|
|
dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
|
|
|
|
|
__func__, desc_id, desc_index, param_offset, ret);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Update descriptor length */
|
|
|
|
|
buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET];
|
|
|
|
|
|
|
|
|
|
if (param_offset >= buff_len) {
|
|
|
|
|
dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n",
|
|
|
|
|
__func__, param_offset, desc_id, buff_len);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
|
if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) {
|
|
|
|
|
dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n",
|
|
|
|
@ -3499,10 +3463,6 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Update descriptor length */
|
|
|
|
|
buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET];
|
|
|
|
|
ufshcd_update_desc_length(hba, desc_id, desc_index, buff_len);
|
|
|
|
|
|
|
|
|
|
if (is_kmalloc) {
|
|
|
|
|
/* Make sure we don't copy more data than available */
|
|
|
|
|
if (param_offset >= buff_len)
|
|
|
|
@ -4940,7 +4900,7 @@ static void ufshcd_setup_links(struct ufs_hba *hba, struct scsi_device *sdev)
|
|
|
|
|
*/
|
|
|
|
|
static void ufshcd_lu_init(struct ufs_hba *hba, struct scsi_device *sdev)
|
|
|
|
|
{
|
|
|
|
|
int len = hba->desc_size[QUERY_DESC_IDN_UNIT];
|
|
|
|
|
int len = QUERY_DESC_MAX_SIZE;
|
|
|
|
|
u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);
|
|
|
|
|
u8 lun_qdepth = hba->nutrs;
|
|
|
|
|
u8 *desc_buf;
|
|
|
|
@ -7564,12 +7524,11 @@ static u32 ufshcd_get_max_icc_level(int sup_curr_uA, u32 start_scan,
|
|
|
|
|
* In case regulators are not initialized we'll return 0
|
|
|
|
|
* @hba: per-adapter instance
|
|
|
|
|
* @desc_buf: power descriptor buffer to extract ICC levels from.
|
|
|
|
|
* @len: length of desc_buff
|
|
|
|
|
*
|
|
|
|
|
* Returns calculated ICC level
|
|
|
|
|
*/
|
|
|
|
|
static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba,
|
|
|
|
|
const u8 *desc_buf, int len)
|
|
|
|
|
const u8 *desc_buf)
|
|
|
|
|
{
|
|
|
|
|
u32 icc_level = 0;
|
|
|
|
|
|
|
|
|
@ -7611,25 +7570,23 @@ out:
|
|
|
|
|
static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
int buff_len = hba->desc_size[QUERY_DESC_IDN_POWER];
|
|
|
|
|
u8 *desc_buf;
|
|
|
|
|
u32 icc_level;
|
|
|
|
|
|
|
|
|
|
desc_buf = kmalloc(buff_len, GFP_KERNEL);
|
|
|
|
|
desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
|
|
|
|
|
if (!desc_buf)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0, 0,
|
|
|
|
|
desc_buf, buff_len);
|
|
|
|
|
desc_buf, QUERY_DESC_MAX_SIZE);
|
|
|
|
|
if (ret) {
|
|
|
|
|
dev_err(hba->dev,
|
|
|
|
|
"%s: Failed reading power descriptor.len = %d ret = %d",
|
|
|
|
|
__func__, buff_len, ret);
|
|
|
|
|
"%s: Failed reading power descriptor ret = %d",
|
|
|
|
|
__func__, ret);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf,
|
|
|
|
|
buff_len);
|
|
|
|
|
icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf);
|
|
|
|
|
dev_dbg(hba->dev, "%s: setting icc_level 0x%x", __func__, icc_level);
|
|
|
|
|
|
|
|
|
|
ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
|
|
|
|
@ -7739,10 +7696,6 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, const u8 *desc_buf)
|
|
|
|
|
(hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES)))
|
|
|
|
|
goto wb_disabled;
|
|
|
|
|
|
|
|
|
|
if (hba->desc_size[QUERY_DESC_IDN_DEVICE] <
|
|
|
|
|
DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP + 4)
|
|
|
|
|
goto wb_disabled;
|
|
|
|
|
|
|
|
|
|
ext_ufs_feature = get_unaligned_be32(desc_buf +
|
|
|
|
|
DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
|
|
|
|
|
|
|
|
|
@ -7850,14 +7803,14 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
|
|
|
|
|
u8 *desc_buf;
|
|
|
|
|
struct ufs_dev_info *dev_info = &hba->dev_info;
|
|
|
|
|
|
|
|
|
|
desc_buf = kmalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
|
|
|
|
|
desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
|
|
|
|
|
if (!desc_buf) {
|
|
|
|
|
err = -ENOMEM;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_DEVICE, 0, 0, desc_buf,
|
|
|
|
|
hba->desc_size[QUERY_DESC_IDN_DEVICE]);
|
|
|
|
|
QUERY_DESC_MAX_SIZE);
|
|
|
|
|
if (err) {
|
|
|
|
|
dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n",
|
|
|
|
|
__func__, err);
|
|
|
|
@ -8104,18 +8057,16 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba)
|
|
|
|
|
static int ufshcd_device_geo_params_init(struct ufs_hba *hba)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
size_t buff_len;
|
|
|
|
|
u8 *desc_buf;
|
|
|
|
|
|
|
|
|
|
buff_len = hba->desc_size[QUERY_DESC_IDN_GEOMETRY];
|
|
|
|
|
desc_buf = kmalloc(buff_len, GFP_KERNEL);
|
|
|
|
|
desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
|
|
|
|
|
if (!desc_buf) {
|
|
|
|
|
err = -ENOMEM;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0,
|
|
|
|
|
desc_buf, buff_len);
|
|
|
|
|
desc_buf, QUERY_DESC_MAX_SIZE);
|
|
|
|
|
if (err) {
|
|
|
|
|
dev_err(hba->dev, "%s: Failed reading Geometry Desc. err = %d\n",
|
|
|
|
|
__func__, err);
|
|
|
|
@ -8127,7 +8078,7 @@ static int ufshcd_device_geo_params_init(struct ufs_hba *hba)
|
|
|
|
|
else if (desc_buf[GEOMETRY_DESC_PARAM_MAX_NUM_LUN] == 0)
|
|
|
|
|
hba->dev_info.max_lu_supported = 8;
|
|
|
|
|
|
|
|
|
|
if (hba->desc_size[QUERY_DESC_IDN_GEOMETRY] >=
|
|
|
|
|
if (desc_buf[QUERY_DESC_LENGTH_OFFSET] >=
|
|
|
|
|
GEOMETRY_DESC_PARAM_HPB_MAX_ACTIVE_REGS)
|
|
|
|
|
ufshpb_get_geo_info(hba, desc_buf);
|
|
|
|
|
|
|
|
|
@ -8212,11 +8163,7 @@ out:
|
|
|
|
|
static int ufshcd_device_params_init(struct ufs_hba *hba)
|
|
|
|
|
{
|
|
|
|
|
bool flag;
|
|
|
|
|
int ret, i;
|
|
|
|
|
|
|
|
|
|
/* Init device descriptor sizes */
|
|
|
|
|
for (i = 0; i < QUERY_DESC_IDN_MAX; i++)
|
|
|
|
|
hba->desc_size[i] = QUERY_DESC_MAX_SIZE;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
/* Init UFS geometry descriptor related parameters */
|
|
|
|
|
ret = ufshcd_device_geo_params_init(hba);
|
|
|
|
|