Loading drivers/scsi/ufs/ufs-debugfs.c +2 −2 Original line number Diff line number Diff line Loading @@ -850,8 +850,8 @@ static const struct file_operations ufsdbg_host_regs_fops = { static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data) { int err = 0; int buff_len = QUERY_DESC_DEVICE_MAX_SIZE; u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE]; int buff_len = QUERY_DESC_DEVICE_DEF_SIZE; u8 desc_buf[QUERY_DESC_DEVICE_DEF_SIZE]; struct ufs_hba *hba = (struct ufs_hba *)file->private; struct desc_field_offset device_desc_field_name[] = { Loading drivers/scsi/ufs/ufs.h +8 −13 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID) #define UFS_UPIU_WLUN_ID (1 << 7) #define UFS_UPIU_MAX_GENERAL_LUN 8 #define QUERY_DESC_IDN_CONFIGURATION QUERY_DESC_IDN_CONFIGURAION /* Well known logical unit id in LUN field of UPIU */ enum { Loading Loading @@ -144,19 +145,13 @@ enum desc_header_offset { QUERY_DESC_DESC_TYPE_OFFSET = 0x01, }; enum ufs_desc_max_size { QUERY_DESC_DEVICE_MAX_SIZE = 0x40, QUERY_DESC_CONFIGURAION_MAX_SIZE = 0x90, QUERY_DESC_UNIT_MAX_SIZE = 0x23, QUERY_DESC_INTERCONNECT_MAX_SIZE = 0x06, /* * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes * of descriptor header. */ QUERY_DESC_STRING_MAX_SIZE = 0xFE, QUERY_DESC_GEOMETRY_MAZ_SIZE = 0x44, QUERY_DESC_POWER_MAX_SIZE = 0x62, QUERY_DESC_RFU_MAX_SIZE = 0x00, enum ufs_desc_def_size { QUERY_DESC_DEVICE_DEF_SIZE = 0x40, QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, QUERY_DESC_UNIT_DEF_SIZE = 0x23, QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44, QUERY_DESC_POWER_DEF_SIZE = 0x62, }; /* Unit descriptor parameters offsets in bytes*/ Loading drivers/scsi/ufs/ufs_quirks.c +4 −4 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ static struct ufs_card_fix ufs_fixups[] = { void ufs_advertise_fixup_device(struct ufs_hba *hba) { int err; u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1]; u8 str_desc_buf[QUERY_DESC_MAX_SIZE + 1]; char *model; struct ufs_card_fix *f; Loading @@ -59,13 +59,13 @@ void ufs_advertise_fixup_device(struct ufs_hba *hba) if (!model) goto out; memset(str_desc_buf, 0, QUERY_DESC_STRING_MAX_SIZE); memset(str_desc_buf, 0, QUERY_DESC_MAX_SIZE); err = ufshcd_read_string_desc(hba, hba->dev_info.i_product_name, str_desc_buf, QUERY_DESC_STRING_MAX_SIZE, ASCII_STD); str_desc_buf, QUERY_DESC_MAX_SIZE, ASCII_STD); if (err) goto out; str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0'; str_desc_buf[QUERY_DESC_MAX_SIZE] = '\0'; strlcpy(model, (str_desc_buf + QUERY_DESC_HDR_SIZE), min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET], MAX_MODEL_LEN)); Loading drivers/scsi/ufs/ufs_test.c +2 −2 Original line number Diff line number Diff line Loading @@ -603,8 +603,8 @@ static void ufs_test_random_async_query(void *data, async_cookie_t cookie) struct ufs_test_data *utd = test_iosched->blk_dev_test_data; struct scsi_device *sdev; struct ufs_hba *hba; int buff_len = QUERY_DESC_UNIT_MAX_SIZE; u8 desc_buf[QUERY_DESC_UNIT_MAX_SIZE]; int buff_len = QUERY_DESC_UNIT_DEF_SIZE; u8 desc_buf[QUERY_DESC_UNIT_DEF_SIZE]; bool flag; u32 att; int ret = 0; Loading drivers/scsi/ufs/ufshcd.c +186 −53 Original line number Diff line number Diff line Loading @@ -251,19 +251,6 @@ static void ufshcd_hex_dump(struct ufs_hba *hba, const char * const str, 16, 4, buf, len, false); } static u32 ufs_query_desc_max_size[] = { QUERY_DESC_DEVICE_MAX_SIZE, QUERY_DESC_CONFIGURAION_MAX_SIZE, QUERY_DESC_UNIT_MAX_SIZE, QUERY_DESC_RFU_MAX_SIZE, QUERY_DESC_INTERCONNECT_MAX_SIZE, QUERY_DESC_STRING_MAX_SIZE, QUERY_DESC_RFU_MAX_SIZE, QUERY_DESC_GEOMETRY_MAZ_SIZE, QUERY_DESC_POWER_MAX_SIZE, QUERY_DESC_RFU_MAX_SIZE, }; enum { UFSHCD_MAX_CHANNEL = 0, UFSHCD_MAX_ID = 1, Loading Loading @@ -3628,7 +3615,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, goto out; } if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { if (*buf_len < QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", __func__, *buf_len); err = -EINVAL; Loading Loading @@ -3707,6 +3694,92 @@ int ufshcd_query_descriptor(struct ufs_hba *hba, } EXPORT_SYMBOL(ufshcd_query_descriptor); /** * ufshcd_read_desc_length - read the specified descriptor length from header * @hba: Pointer to adapter instance * @desc_id: descriptor idn value * @desc_index: descriptor index * @desc_length: pointer to variable to read the length of descriptor * * Return 0 in case of success, non-zero otherwise */ static int ufshcd_read_desc_length(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, int *desc_length) { int ret; u8 header[QUERY_DESC_HDR_SIZE]; int header_len = QUERY_DESC_HDR_SIZE; if (desc_id >= QUERY_DESC_IDN_MAX) return -EINVAL; ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, desc_id, desc_index, 0, header, &header_len); if (ret) { dev_err(hba->dev, "%s: Failed to get descriptor header id %d", __func__, desc_id); return ret; } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) { dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch", __func__, header[QUERY_DESC_DESC_TYPE_OFFSET], desc_id); ret = -EINVAL; } *desc_length = header[QUERY_DESC_LENGTH_OFFSET]; return ret; } /** * 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) * * Return 0 in case of success, non-zero otherwise */ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, int *desc_len) { switch (desc_id) { case QUERY_DESC_IDN_DEVICE: *desc_len = hba->desc_size.dev_desc; break; case QUERY_DESC_IDN_POWER: *desc_len = hba->desc_size.pwr_desc; break; case QUERY_DESC_IDN_GEOMETRY: *desc_len = hba->desc_size.geom_desc; break; case QUERY_DESC_IDN_CONFIGURATION: *desc_len = hba->desc_size.conf_desc; break; case QUERY_DESC_IDN_UNIT: *desc_len = hba->desc_size.unit_desc; break; case QUERY_DESC_IDN_INTERCONNECT: *desc_len = hba->desc_size.interc_desc; break; case QUERY_DESC_IDN_STRING: *desc_len = QUERY_DESC_MAX_SIZE; break; case QUERY_DESC_IDN_RFU_0: case QUERY_DESC_IDN_RFU_1: *desc_len = 0; break; default: *desc_len = 0; return -EINVAL; } return 0; } EXPORT_SYMBOL(ufshcd_map_desc_id_to_length); /** * ufshcd_read_desc_param - read the specified descriptor parameter * @hba: Pointer to adapter instance Loading @@ -3721,37 +3794,45 @@ EXPORT_SYMBOL(ufshcd_query_descriptor); static int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, u32 param_offset, u8 param_offset, u8 *param_read_buf, u32 param_size) u8 param_size) { int ret; u8 *desc_buf; u32 buff_len; int buff_len; bool is_kmalloc = true; /* safety checks */ if (desc_id >= QUERY_DESC_IDN_MAX) /* Safety check */ if (desc_id >= QUERY_DESC_IDN_MAX || !param_size) return -EINVAL; buff_len = ufs_query_desc_max_size[desc_id]; if ((param_offset + param_size) > buff_len) return -EINVAL; /* Get the max length of descriptor from structure filled up at probe * time. */ ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); if (!param_offset && (param_size == buff_len)) { /* memory space already available to hold full descriptor */ desc_buf = param_read_buf; is_kmalloc = false; } else { /* allocate memory to hold full descriptor */ /* Sanity checks */ if (ret || !buff_len) { dev_err(hba->dev, "%s: Failed to get full descriptor length", __func__); return ret; } /* Check whether we need temp memory */ if (param_offset != 0 || param_size < buff_len) { desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) return -ENOMEM; } else { desc_buf = param_read_buf; is_kmalloc = false; } /* Request for full descriptor */ ret = ufshcd_query_descriptor(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", Loading @@ -3768,25 +3849,9 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba, goto out; } /* * While reading variable size descriptors (like string descriptor), * some UFS devices may report the "LENGTH" (field in "Transaction * Specific fields" of Query Response UPIU) same as what was requested * in Query Request UPIU instead of reporting the actual size of the * variable size descriptor. * Although it's safe to ignore the "LENGTH" field for variable size * descriptors as we can always derive the length of the descriptor from * the descriptor header fields. Hence this change impose the length * match check only for fixed size descriptors (for which we always * request the correct size as part of Query Request UPIU). */ if ((desc_id != QUERY_DESC_IDN_STRING) && (buff_len != desc_buf[QUERY_DESC_LENGTH_OFFSET])) { dev_err(hba->dev, "%s: desc_buf length mismatch: buff_len %d, buff_len(desc_header) %d", __func__, buff_len, desc_buf[QUERY_DESC_LENGTH_OFFSET]); ret = -EINVAL; goto out; } /* Check wherher we will not copy more data, than available */ if (is_kmalloc && param_size > buff_len) param_size = buff_len; if (is_kmalloc) memcpy(param_read_buf, &desc_buf[param_offset], param_size); Loading Loading @@ -7170,10 +7235,19 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba, static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba) { int ret; int buff_len = QUERY_DESC_POWER_MAX_SIZE; u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE]; int buff_len = hba->desc_size.pwr_desc; u8 *desc_buf = NULL; u32 icc_level; if (buff_len) { desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) { dev_err(hba->dev, "%s: Failed to allocate desc_buf\n", __func__); return; } } ret = ufshcd_read_power_desc(hba, desc_buf, buff_len); if (ret) { dev_err(hba->dev, Loading Loading @@ -7554,9 +7628,18 @@ static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba) static int ufs_read_device_desc_data(struct ufs_hba *hba) { int err; u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE]; u8 *desc_buf = NULL; err = ufshcd_read_device_desc(hba, desc_buf, sizeof(desc_buf)); if (hba->desc_size.dev_desc) { desc_buf = kmalloc(hba->desc_size.dev_desc, GFP_KERNEL); if (!desc_buf) { err = -ENOMEM; dev_err(hba->dev, "%s: Failed to allocate desc_buf\n", __func__); return err; } } err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc); if (err) return err; Loading @@ -7574,6 +7657,51 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba) return 0; } static void ufshcd_init_desc_sizes(struct ufs_hba *hba) { int err; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_DEVICE, 0, &hba->desc_size.dev_desc); if (err) hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_POWER, 0, &hba->desc_size.pwr_desc); if (err) hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_INTERCONNECT, 0, &hba->desc_size.interc_desc); if (err) hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_CONFIGURATION, 0, &hba->desc_size.conf_desc); if (err) hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_UNIT, 0, &hba->desc_size.unit_desc); if (err) hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_GEOMETRY, 0, &hba->desc_size.geom_desc); if (err) hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; } static void ufshcd_def_desc_sizes(struct ufs_hba *hba) { hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; } /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance Loading Loading @@ -7614,6 +7742,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) if (ret) goto out; /* Init check for device descriptor sizes */ ufshcd_init_desc_sizes(hba); ufs_advertise_fixup_device(hba); ufshcd_tune_unipro_params(hba); Loading Loading @@ -10075,6 +10205,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ufshcd_init_lanes_per_dir(hba); /* Set descriptor lengths to specification defaults */ ufshcd_def_desc_sizes(hba); err = ufshcd_hba_init(hba); if (err) goto out_error; Loading Loading
drivers/scsi/ufs/ufs-debugfs.c +2 −2 Original line number Diff line number Diff line Loading @@ -850,8 +850,8 @@ static const struct file_operations ufsdbg_host_regs_fops = { static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data) { int err = 0; int buff_len = QUERY_DESC_DEVICE_MAX_SIZE; u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE]; int buff_len = QUERY_DESC_DEVICE_DEF_SIZE; u8 desc_buf[QUERY_DESC_DEVICE_DEF_SIZE]; struct ufs_hba *hba = (struct ufs_hba *)file->private; struct desc_field_offset device_desc_field_name[] = { Loading
drivers/scsi/ufs/ufs.h +8 −13 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID) #define UFS_UPIU_WLUN_ID (1 << 7) #define UFS_UPIU_MAX_GENERAL_LUN 8 #define QUERY_DESC_IDN_CONFIGURATION QUERY_DESC_IDN_CONFIGURAION /* Well known logical unit id in LUN field of UPIU */ enum { Loading Loading @@ -144,19 +145,13 @@ enum desc_header_offset { QUERY_DESC_DESC_TYPE_OFFSET = 0x01, }; enum ufs_desc_max_size { QUERY_DESC_DEVICE_MAX_SIZE = 0x40, QUERY_DESC_CONFIGURAION_MAX_SIZE = 0x90, QUERY_DESC_UNIT_MAX_SIZE = 0x23, QUERY_DESC_INTERCONNECT_MAX_SIZE = 0x06, /* * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes * of descriptor header. */ QUERY_DESC_STRING_MAX_SIZE = 0xFE, QUERY_DESC_GEOMETRY_MAZ_SIZE = 0x44, QUERY_DESC_POWER_MAX_SIZE = 0x62, QUERY_DESC_RFU_MAX_SIZE = 0x00, enum ufs_desc_def_size { QUERY_DESC_DEVICE_DEF_SIZE = 0x40, QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, QUERY_DESC_UNIT_DEF_SIZE = 0x23, QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44, QUERY_DESC_POWER_DEF_SIZE = 0x62, }; /* Unit descriptor parameters offsets in bytes*/ Loading
drivers/scsi/ufs/ufs_quirks.c +4 −4 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ static struct ufs_card_fix ufs_fixups[] = { void ufs_advertise_fixup_device(struct ufs_hba *hba) { int err; u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1]; u8 str_desc_buf[QUERY_DESC_MAX_SIZE + 1]; char *model; struct ufs_card_fix *f; Loading @@ -59,13 +59,13 @@ void ufs_advertise_fixup_device(struct ufs_hba *hba) if (!model) goto out; memset(str_desc_buf, 0, QUERY_DESC_STRING_MAX_SIZE); memset(str_desc_buf, 0, QUERY_DESC_MAX_SIZE); err = ufshcd_read_string_desc(hba, hba->dev_info.i_product_name, str_desc_buf, QUERY_DESC_STRING_MAX_SIZE, ASCII_STD); str_desc_buf, QUERY_DESC_MAX_SIZE, ASCII_STD); if (err) goto out; str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0'; str_desc_buf[QUERY_DESC_MAX_SIZE] = '\0'; strlcpy(model, (str_desc_buf + QUERY_DESC_HDR_SIZE), min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET], MAX_MODEL_LEN)); Loading
drivers/scsi/ufs/ufs_test.c +2 −2 Original line number Diff line number Diff line Loading @@ -603,8 +603,8 @@ static void ufs_test_random_async_query(void *data, async_cookie_t cookie) struct ufs_test_data *utd = test_iosched->blk_dev_test_data; struct scsi_device *sdev; struct ufs_hba *hba; int buff_len = QUERY_DESC_UNIT_MAX_SIZE; u8 desc_buf[QUERY_DESC_UNIT_MAX_SIZE]; int buff_len = QUERY_DESC_UNIT_DEF_SIZE; u8 desc_buf[QUERY_DESC_UNIT_DEF_SIZE]; bool flag; u32 att; int ret = 0; Loading
drivers/scsi/ufs/ufshcd.c +186 −53 Original line number Diff line number Diff line Loading @@ -251,19 +251,6 @@ static void ufshcd_hex_dump(struct ufs_hba *hba, const char * const str, 16, 4, buf, len, false); } static u32 ufs_query_desc_max_size[] = { QUERY_DESC_DEVICE_MAX_SIZE, QUERY_DESC_CONFIGURAION_MAX_SIZE, QUERY_DESC_UNIT_MAX_SIZE, QUERY_DESC_RFU_MAX_SIZE, QUERY_DESC_INTERCONNECT_MAX_SIZE, QUERY_DESC_STRING_MAX_SIZE, QUERY_DESC_RFU_MAX_SIZE, QUERY_DESC_GEOMETRY_MAZ_SIZE, QUERY_DESC_POWER_MAX_SIZE, QUERY_DESC_RFU_MAX_SIZE, }; enum { UFSHCD_MAX_CHANNEL = 0, UFSHCD_MAX_ID = 1, Loading Loading @@ -3628,7 +3615,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, goto out; } if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { if (*buf_len < QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", __func__, *buf_len); err = -EINVAL; Loading Loading @@ -3707,6 +3694,92 @@ int ufshcd_query_descriptor(struct ufs_hba *hba, } EXPORT_SYMBOL(ufshcd_query_descriptor); /** * ufshcd_read_desc_length - read the specified descriptor length from header * @hba: Pointer to adapter instance * @desc_id: descriptor idn value * @desc_index: descriptor index * @desc_length: pointer to variable to read the length of descriptor * * Return 0 in case of success, non-zero otherwise */ static int ufshcd_read_desc_length(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, int *desc_length) { int ret; u8 header[QUERY_DESC_HDR_SIZE]; int header_len = QUERY_DESC_HDR_SIZE; if (desc_id >= QUERY_DESC_IDN_MAX) return -EINVAL; ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, desc_id, desc_index, 0, header, &header_len); if (ret) { dev_err(hba->dev, "%s: Failed to get descriptor header id %d", __func__, desc_id); return ret; } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) { dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch", __func__, header[QUERY_DESC_DESC_TYPE_OFFSET], desc_id); ret = -EINVAL; } *desc_length = header[QUERY_DESC_LENGTH_OFFSET]; return ret; } /** * 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) * * Return 0 in case of success, non-zero otherwise */ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, int *desc_len) { switch (desc_id) { case QUERY_DESC_IDN_DEVICE: *desc_len = hba->desc_size.dev_desc; break; case QUERY_DESC_IDN_POWER: *desc_len = hba->desc_size.pwr_desc; break; case QUERY_DESC_IDN_GEOMETRY: *desc_len = hba->desc_size.geom_desc; break; case QUERY_DESC_IDN_CONFIGURATION: *desc_len = hba->desc_size.conf_desc; break; case QUERY_DESC_IDN_UNIT: *desc_len = hba->desc_size.unit_desc; break; case QUERY_DESC_IDN_INTERCONNECT: *desc_len = hba->desc_size.interc_desc; break; case QUERY_DESC_IDN_STRING: *desc_len = QUERY_DESC_MAX_SIZE; break; case QUERY_DESC_IDN_RFU_0: case QUERY_DESC_IDN_RFU_1: *desc_len = 0; break; default: *desc_len = 0; return -EINVAL; } return 0; } EXPORT_SYMBOL(ufshcd_map_desc_id_to_length); /** * ufshcd_read_desc_param - read the specified descriptor parameter * @hba: Pointer to adapter instance Loading @@ -3721,37 +3794,45 @@ EXPORT_SYMBOL(ufshcd_query_descriptor); static int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, u32 param_offset, u8 param_offset, u8 *param_read_buf, u32 param_size) u8 param_size) { int ret; u8 *desc_buf; u32 buff_len; int buff_len; bool is_kmalloc = true; /* safety checks */ if (desc_id >= QUERY_DESC_IDN_MAX) /* Safety check */ if (desc_id >= QUERY_DESC_IDN_MAX || !param_size) return -EINVAL; buff_len = ufs_query_desc_max_size[desc_id]; if ((param_offset + param_size) > buff_len) return -EINVAL; /* Get the max length of descriptor from structure filled up at probe * time. */ ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); if (!param_offset && (param_size == buff_len)) { /* memory space already available to hold full descriptor */ desc_buf = param_read_buf; is_kmalloc = false; } else { /* allocate memory to hold full descriptor */ /* Sanity checks */ if (ret || !buff_len) { dev_err(hba->dev, "%s: Failed to get full descriptor length", __func__); return ret; } /* Check whether we need temp memory */ if (param_offset != 0 || param_size < buff_len) { desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) return -ENOMEM; } else { desc_buf = param_read_buf; is_kmalloc = false; } /* Request for full descriptor */ ret = ufshcd_query_descriptor(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", Loading @@ -3768,25 +3849,9 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba, goto out; } /* * While reading variable size descriptors (like string descriptor), * some UFS devices may report the "LENGTH" (field in "Transaction * Specific fields" of Query Response UPIU) same as what was requested * in Query Request UPIU instead of reporting the actual size of the * variable size descriptor. * Although it's safe to ignore the "LENGTH" field for variable size * descriptors as we can always derive the length of the descriptor from * the descriptor header fields. Hence this change impose the length * match check only for fixed size descriptors (for which we always * request the correct size as part of Query Request UPIU). */ if ((desc_id != QUERY_DESC_IDN_STRING) && (buff_len != desc_buf[QUERY_DESC_LENGTH_OFFSET])) { dev_err(hba->dev, "%s: desc_buf length mismatch: buff_len %d, buff_len(desc_header) %d", __func__, buff_len, desc_buf[QUERY_DESC_LENGTH_OFFSET]); ret = -EINVAL; goto out; } /* Check wherher we will not copy more data, than available */ if (is_kmalloc && param_size > buff_len) param_size = buff_len; if (is_kmalloc) memcpy(param_read_buf, &desc_buf[param_offset], param_size); Loading Loading @@ -7170,10 +7235,19 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba, static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba) { int ret; int buff_len = QUERY_DESC_POWER_MAX_SIZE; u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE]; int buff_len = hba->desc_size.pwr_desc; u8 *desc_buf = NULL; u32 icc_level; if (buff_len) { desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) { dev_err(hba->dev, "%s: Failed to allocate desc_buf\n", __func__); return; } } ret = ufshcd_read_power_desc(hba, desc_buf, buff_len); if (ret) { dev_err(hba->dev, Loading Loading @@ -7554,9 +7628,18 @@ static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba) static int ufs_read_device_desc_data(struct ufs_hba *hba) { int err; u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE]; u8 *desc_buf = NULL; err = ufshcd_read_device_desc(hba, desc_buf, sizeof(desc_buf)); if (hba->desc_size.dev_desc) { desc_buf = kmalloc(hba->desc_size.dev_desc, GFP_KERNEL); if (!desc_buf) { err = -ENOMEM; dev_err(hba->dev, "%s: Failed to allocate desc_buf\n", __func__); return err; } } err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc); if (err) return err; Loading @@ -7574,6 +7657,51 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba) return 0; } static void ufshcd_init_desc_sizes(struct ufs_hba *hba) { int err; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_DEVICE, 0, &hba->desc_size.dev_desc); if (err) hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_POWER, 0, &hba->desc_size.pwr_desc); if (err) hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_INTERCONNECT, 0, &hba->desc_size.interc_desc); if (err) hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_CONFIGURATION, 0, &hba->desc_size.conf_desc); if (err) hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_UNIT, 0, &hba->desc_size.unit_desc); if (err) hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_GEOMETRY, 0, &hba->desc_size.geom_desc); if (err) hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; } static void ufshcd_def_desc_sizes(struct ufs_hba *hba) { hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; } /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance Loading Loading @@ -7614,6 +7742,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) if (ret) goto out; /* Init check for device descriptor sizes */ ufshcd_init_desc_sizes(hba); ufs_advertise_fixup_device(hba); ufshcd_tune_unipro_params(hba); Loading Loading @@ -10075,6 +10205,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ufshcd_init_lanes_per_dir(hba); /* Set descriptor lengths to specification defaults */ ufshcd_def_desc_sizes(hba); err = ufshcd_hba_init(hba); if (err) goto out_error; Loading