Loading drivers/scsi/ufs/ufs.h +22 −3 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ #define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F #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 /* Well known logical unit id in LUN field of UPIU */ enum { Loading Loading @@ -150,10 +151,29 @@ enum desc_idn { QUERY_DESC_IDN_RFU_1 = 0x6, QUERY_DESC_IDN_GEOMETRY = 0x7, QUERY_DESC_IDN_POWER = 0x8, QUERY_DESC_IDN_RFU_2 = 0x9, QUERY_DESC_IDN_MAX, }; enum desc_header_offset { QUERY_DESC_LENGTH_OFFSET = 0x00, QUERY_DESC_DESC_TYPE_OFFSET = 0x01, }; enum ufs_desc_max_size { QUERY_DESC_DEVICE_MAX_SIZE = 0x1F, 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, }; #define UNIT_DESC_MAX_SIZE 0x22 /* Unit descriptor parameters offsets in bytes*/ enum unit_desc_param { UNIT_DESC_PARAM_LEN = 0x0, Loading Loading @@ -182,7 +202,6 @@ enum { UFSHCD_AMP = 3, }; #define POWER_DESC_MAX_SIZE 0x62 #define POWER_DESC_MAX_ACTV_ICC_LVLS 16 /* Attribute bActiveICCLevel parameter bit masks definitions */ Loading drivers/scsi/ufs/ufshcd.c +141 −42 Original line number Diff line number Diff line Loading @@ -100,6 +100,19 @@ print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false) /* Interrupt aggregation default timeout, unit: 40us */ #define INT_AGGR_DEF_TO 0x02 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 @@ -178,10 +191,14 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, struct scsi_device *sdev); static void ufshcd_hba_exit(struct ufs_hba *hba); static int ufshcd_probe_hba(struct ufs_hba *hba); static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, int lun, enum unit_desc_param param_offset, u8 *param_read_buf, u32 param_size); static inline void ufshcd_enable_irq(struct ufs_hba *hba) { if (!hba->is_irq_enabled) { Loading Loading @@ -1571,6 +1588,116 @@ out: return err; } /** * ufshcd_read_desc_param - read the specified descriptor parameter * @hba: Pointer to adapter instance * @desc_id: descriptor idn value * @desc_index: descriptor index * @param_offset: offset of the parameter to read * @param_read_buf: pointer to buffer where parameter would be read * @param_size: sizeof(param_read_buf) * * Return 0 in case of success, non-zero otherwise */ static int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, u32 param_offset, u8 *param_read_buf, u32 param_size) { int ret; u8 *desc_buf; u32 buff_len; bool is_kmalloc = true; /* safety checks */ if (desc_id >= QUERY_DESC_IDN_MAX) return -EINVAL; buff_len = ufs_query_desc_max_size[desc_id]; if ((param_offset + param_size) > buff_len) return -EINVAL; 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 */ desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) return -ENOMEM; } ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, desc_id, desc_index, 0, desc_buf, &buff_len); if (ret || (buff_len < ufs_query_desc_max_size[desc_id]) || (desc_buf[QUERY_DESC_LENGTH_OFFSET] != ufs_query_desc_max_size[desc_id]) || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) { dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d param_offset %d buff_len %d ret %d", __func__, desc_id, param_offset, buff_len, ret); if (!ret) ret = -EINVAL; goto out; } if (is_kmalloc) memcpy(param_read_buf, &desc_buf[param_offset], param_size); out: if (is_kmalloc) kfree(desc_buf); return ret; } static inline int ufshcd_read_desc(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, u8 *buf, u32 size) { return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size); } static inline int ufshcd_read_power_desc(struct ufs_hba *hba, u8 *buf, u32 size) { return ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf, size); } /** * ufshcd_read_unit_desc_param - read the specified unit descriptor parameter * @hba: Pointer to adapter instance * @lun: lun id * @param_offset: offset of the parameter to read * @param_read_buf: pointer to buffer where parameter would be read * @param_size: sizeof(param_read_buf) * * Return 0 in case of success, non-zero otherwise */ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, int lun, enum unit_desc_param param_offset, u8 *param_read_buf, u32 param_size) { /* * Unit descriptors are only available for general purpose LUs (LUN id * from 0 to 7) and RPMB Well known LU. */ if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN)) return -EOPNOTSUPP; return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun, param_offset, param_read_buf, param_size); } /** * ufshcd_memory_alloc - allocate memory for host memory space data structures * @hba: per adapter instance Loading Loading @@ -2295,7 +2422,8 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba) static int ufshcd_slave_alloc(struct scsi_device *sdev) { struct ufs_hba *hba; int lun_qdepth; u8 lun_qdepth; int ret; hba = shost_priv(sdev->host); sdev->tagged_supported = 1; Loading @@ -2313,8 +2441,12 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev) /* try read capactiy (10) first as rc_16 is optional in UFS spec. */ sdev->try_rc_10_first = 1; lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev); if (lun_qdepth <= 0) ret = ufshcd_read_unit_desc_param(hba, ufshcd_scsi_to_upiu_lun(sdev->lun), UNIT_DESC_PARAM_LU_Q_DEPTH, &lun_qdepth, sizeof(lun_qdepth)); if (!ret || !lun_qdepth) /* eventually, we can figure out the real queue depth */ lun_qdepth = hba->nutrs; else Loading Loading @@ -3470,38 +3602,6 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) return err; } /** * ufshcd_read_sdev_qdepth - read the lun command queue depth * @hba: Pointer to adapter instance * @sdev: pointer to SCSI device * * Return in case of success the lun's queue depth else error. */ static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, struct scsi_device *sdev) { int ret; int buff_len = UNIT_DESC_MAX_SIZE; u8 desc_buf[UNIT_DESC_MAX_SIZE]; ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len); if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) { dev_err(hba->dev, "%s:Failed reading unit descriptor. len = %d ret = %d" , __func__, buff_len, ret); if (!ret) ret = -EINVAL; goto out; } ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF; out: return ret; } /** * ufshcd_get_max_icc_level - calculate the ICC level * @sup_curr_uA: max. current supported by the regulator Loading Loading @@ -3589,13 +3689,12 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) { u32 icc_level; int ret; int buff_len = POWER_DESC_MAX_SIZE; u8 desc_buf[POWER_DESC_MAX_SIZE]; int buff_len = QUERY_DESC_POWER_MAX_SIZE; u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE]; ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_POWER, 0, 0, desc_buf, &buff_len); ret = ufshcd_read_power_desc(hba, desc_buf, buff_len); if (ret || (buff_len < POWER_DESC_MAX_SIZE)) { if (ret) { dev_err(hba->dev, "%s: Failed reading power descriptor.len = %d ret = %d", __func__, buff_len, ret); Loading Loading
drivers/scsi/ufs/ufs.h +22 −3 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ #define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F #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 /* Well known logical unit id in LUN field of UPIU */ enum { Loading Loading @@ -150,10 +151,29 @@ enum desc_idn { QUERY_DESC_IDN_RFU_1 = 0x6, QUERY_DESC_IDN_GEOMETRY = 0x7, QUERY_DESC_IDN_POWER = 0x8, QUERY_DESC_IDN_RFU_2 = 0x9, QUERY_DESC_IDN_MAX, }; enum desc_header_offset { QUERY_DESC_LENGTH_OFFSET = 0x00, QUERY_DESC_DESC_TYPE_OFFSET = 0x01, }; enum ufs_desc_max_size { QUERY_DESC_DEVICE_MAX_SIZE = 0x1F, 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, }; #define UNIT_DESC_MAX_SIZE 0x22 /* Unit descriptor parameters offsets in bytes*/ enum unit_desc_param { UNIT_DESC_PARAM_LEN = 0x0, Loading Loading @@ -182,7 +202,6 @@ enum { UFSHCD_AMP = 3, }; #define POWER_DESC_MAX_SIZE 0x62 #define POWER_DESC_MAX_ACTV_ICC_LVLS 16 /* Attribute bActiveICCLevel parameter bit masks definitions */ Loading
drivers/scsi/ufs/ufshcd.c +141 −42 Original line number Diff line number Diff line Loading @@ -100,6 +100,19 @@ print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false) /* Interrupt aggregation default timeout, unit: 40us */ #define INT_AGGR_DEF_TO 0x02 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 @@ -178,10 +191,14 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, struct scsi_device *sdev); static void ufshcd_hba_exit(struct ufs_hba *hba); static int ufshcd_probe_hba(struct ufs_hba *hba); static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, int lun, enum unit_desc_param param_offset, u8 *param_read_buf, u32 param_size); static inline void ufshcd_enable_irq(struct ufs_hba *hba) { if (!hba->is_irq_enabled) { Loading Loading @@ -1571,6 +1588,116 @@ out: return err; } /** * ufshcd_read_desc_param - read the specified descriptor parameter * @hba: Pointer to adapter instance * @desc_id: descriptor idn value * @desc_index: descriptor index * @param_offset: offset of the parameter to read * @param_read_buf: pointer to buffer where parameter would be read * @param_size: sizeof(param_read_buf) * * Return 0 in case of success, non-zero otherwise */ static int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, u32 param_offset, u8 *param_read_buf, u32 param_size) { int ret; u8 *desc_buf; u32 buff_len; bool is_kmalloc = true; /* safety checks */ if (desc_id >= QUERY_DESC_IDN_MAX) return -EINVAL; buff_len = ufs_query_desc_max_size[desc_id]; if ((param_offset + param_size) > buff_len) return -EINVAL; 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 */ desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) return -ENOMEM; } ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, desc_id, desc_index, 0, desc_buf, &buff_len); if (ret || (buff_len < ufs_query_desc_max_size[desc_id]) || (desc_buf[QUERY_DESC_LENGTH_OFFSET] != ufs_query_desc_max_size[desc_id]) || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) { dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d param_offset %d buff_len %d ret %d", __func__, desc_id, param_offset, buff_len, ret); if (!ret) ret = -EINVAL; goto out; } if (is_kmalloc) memcpy(param_read_buf, &desc_buf[param_offset], param_size); out: if (is_kmalloc) kfree(desc_buf); return ret; } static inline int ufshcd_read_desc(struct ufs_hba *hba, enum desc_idn desc_id, int desc_index, u8 *buf, u32 size) { return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size); } static inline int ufshcd_read_power_desc(struct ufs_hba *hba, u8 *buf, u32 size) { return ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf, size); } /** * ufshcd_read_unit_desc_param - read the specified unit descriptor parameter * @hba: Pointer to adapter instance * @lun: lun id * @param_offset: offset of the parameter to read * @param_read_buf: pointer to buffer where parameter would be read * @param_size: sizeof(param_read_buf) * * Return 0 in case of success, non-zero otherwise */ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, int lun, enum unit_desc_param param_offset, u8 *param_read_buf, u32 param_size) { /* * Unit descriptors are only available for general purpose LUs (LUN id * from 0 to 7) and RPMB Well known LU. */ if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN)) return -EOPNOTSUPP; return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun, param_offset, param_read_buf, param_size); } /** * ufshcd_memory_alloc - allocate memory for host memory space data structures * @hba: per adapter instance Loading Loading @@ -2295,7 +2422,8 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba) static int ufshcd_slave_alloc(struct scsi_device *sdev) { struct ufs_hba *hba; int lun_qdepth; u8 lun_qdepth; int ret; hba = shost_priv(sdev->host); sdev->tagged_supported = 1; Loading @@ -2313,8 +2441,12 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev) /* try read capactiy (10) first as rc_16 is optional in UFS spec. */ sdev->try_rc_10_first = 1; lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev); if (lun_qdepth <= 0) ret = ufshcd_read_unit_desc_param(hba, ufshcd_scsi_to_upiu_lun(sdev->lun), UNIT_DESC_PARAM_LU_Q_DEPTH, &lun_qdepth, sizeof(lun_qdepth)); if (!ret || !lun_qdepth) /* eventually, we can figure out the real queue depth */ lun_qdepth = hba->nutrs; else Loading Loading @@ -3470,38 +3602,6 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) return err; } /** * ufshcd_read_sdev_qdepth - read the lun command queue depth * @hba: Pointer to adapter instance * @sdev: pointer to SCSI device * * Return in case of success the lun's queue depth else error. */ static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, struct scsi_device *sdev) { int ret; int buff_len = UNIT_DESC_MAX_SIZE; u8 desc_buf[UNIT_DESC_MAX_SIZE]; ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len); if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) { dev_err(hba->dev, "%s:Failed reading unit descriptor. len = %d ret = %d" , __func__, buff_len, ret); if (!ret) ret = -EINVAL; goto out; } ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF; out: return ret; } /** * ufshcd_get_max_icc_level - calculate the ICC level * @sup_curr_uA: max. current supported by the regulator Loading Loading @@ -3589,13 +3689,12 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) { u32 icc_level; int ret; int buff_len = POWER_DESC_MAX_SIZE; u8 desc_buf[POWER_DESC_MAX_SIZE]; int buff_len = QUERY_DESC_POWER_MAX_SIZE; u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE]; ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_POWER, 0, 0, desc_buf, &buff_len); ret = ufshcd_read_power_desc(hba, desc_buf, buff_len); if (ret || (buff_len < POWER_DESC_MAX_SIZE)) { if (ret) { dev_err(hba->dev, "%s: Failed reading power descriptor.len = %d ret = %d", __func__, buff_len, ret); Loading