Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: ufs: Factor out ufshcd_read_desc_param

Since in UFS 2.1 specification some of the descriptor lengths differs
from 2.0 specification and some devices, which are reporting spec
version 2.0 have different descriptor lengths we can not rely on
hardcoded values taken from 2.0 specification. This patch introduces
reading these lengths per each device from descriptor headers at probe
time to ensure their correctness.

Signed-off-by: Michal' Potomski <michalx.potomski@intel.com>
Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Potomski, MichalX and committed by
Martin K. Petersen
a4b0e8a4 6f8830f5

+196 -72
+8 -14
drivers/scsi/ufs/ufs.h
··· 146 146 /* Descriptor idn for Query requests */ 147 147 enum desc_idn { 148 148 QUERY_DESC_IDN_DEVICE = 0x0, 149 - QUERY_DESC_IDN_CONFIGURAION = 0x1, 149 + QUERY_DESC_IDN_CONFIGURATION = 0x1, 150 150 QUERY_DESC_IDN_UNIT = 0x2, 151 151 QUERY_DESC_IDN_RFU_0 = 0x3, 152 152 QUERY_DESC_IDN_INTERCONNECT = 0x4, ··· 162 162 QUERY_DESC_DESC_TYPE_OFFSET = 0x01, 163 163 }; 164 164 165 - enum ufs_desc_max_size { 166 - QUERY_DESC_DEVICE_MAX_SIZE = 0x40, 167 - QUERY_DESC_CONFIGURAION_MAX_SIZE = 0x90, 168 - QUERY_DESC_UNIT_MAX_SIZE = 0x23, 169 - QUERY_DESC_INTERCONNECT_MAX_SIZE = 0x06, 170 - /* 171 - * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes 172 - * of descriptor header. 173 - */ 174 - QUERY_DESC_STRING_MAX_SIZE = 0xFE, 175 - QUERY_DESC_GEOMETRY_MAX_SIZE = 0x44, 176 - QUERY_DESC_POWER_MAX_SIZE = 0x62, 177 - QUERY_DESC_RFU_MAX_SIZE = 0x00, 165 + enum ufs_desc_def_size { 166 + QUERY_DESC_DEVICE_DEF_SIZE = 0x40, 167 + QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, 168 + QUERY_DESC_UNIT_DEF_SIZE = 0x23, 169 + QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, 170 + QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44, 171 + QUERY_DESC_POWER_DEF_SIZE = 0x62, 178 172 }; 179 173 180 174 /* Unit descriptor parameters offsets in bytes*/
+173 -58
drivers/scsi/ufs/ufshcd.c
··· 100 100 #define ufshcd_hex_dump(prefix_str, buf, len) \ 101 101 print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false) 102 102 103 - static u32 ufs_query_desc_max_size[] = { 104 - QUERY_DESC_DEVICE_MAX_SIZE, 105 - QUERY_DESC_CONFIGURAION_MAX_SIZE, 106 - QUERY_DESC_UNIT_MAX_SIZE, 107 - QUERY_DESC_RFU_MAX_SIZE, 108 - QUERY_DESC_INTERCONNECT_MAX_SIZE, 109 - QUERY_DESC_STRING_MAX_SIZE, 110 - QUERY_DESC_RFU_MAX_SIZE, 111 - QUERY_DESC_GEOMETRY_MAX_SIZE, 112 - QUERY_DESC_POWER_MAX_SIZE, 113 - QUERY_DESC_RFU_MAX_SIZE, 114 - }; 115 - 116 103 enum { 117 104 UFSHCD_MAX_CHANNEL = 0, 118 105 UFSHCD_MAX_ID = 1, ··· 2844 2857 goto out; 2845 2858 } 2846 2859 2847 - if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { 2860 + if (*buf_len < QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { 2848 2861 dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", 2849 2862 __func__, *buf_len); 2850 2863 err = -EINVAL; ··· 2925 2938 } 2926 2939 2927 2940 /** 2941 + * ufshcd_read_desc_length - read the specified descriptor length from header 2942 + * @hba: Pointer to adapter instance 2943 + * @desc_id: descriptor idn value 2944 + * @desc_index: descriptor index 2945 + * @desc_length: pointer to variable to read the length of descriptor 2946 + * 2947 + * Return 0 in case of success, non-zero otherwise 2948 + */ 2949 + static int ufshcd_read_desc_length(struct ufs_hba *hba, 2950 + enum desc_idn desc_id, 2951 + int desc_index, 2952 + int *desc_length) 2953 + { 2954 + int ret; 2955 + u8 header[QUERY_DESC_HDR_SIZE]; 2956 + int header_len = QUERY_DESC_HDR_SIZE; 2957 + 2958 + if (desc_id >= QUERY_DESC_IDN_MAX) 2959 + return -EINVAL; 2960 + 2961 + ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, 2962 + desc_id, desc_index, 0, header, 2963 + &header_len); 2964 + 2965 + if (ret) { 2966 + dev_err(hba->dev, "%s: Failed to get descriptor header id %d", 2967 + __func__, desc_id); 2968 + return ret; 2969 + } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) { 2970 + dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch", 2971 + __func__, header[QUERY_DESC_DESC_TYPE_OFFSET], 2972 + desc_id); 2973 + ret = -EINVAL; 2974 + } 2975 + 2976 + *desc_length = header[QUERY_DESC_LENGTH_OFFSET]; 2977 + return ret; 2978 + 2979 + } 2980 + 2981 + /** 2982 + * ufshcd_map_desc_id_to_length - map descriptor IDN to its length 2983 + * @hba: Pointer to adapter instance 2984 + * @desc_id: descriptor idn value 2985 + * @desc_len: mapped desc length (out) 2986 + * 2987 + * Return 0 in case of success, non-zero otherwise 2988 + */ 2989 + int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, 2990 + enum desc_idn desc_id, int *desc_len) 2991 + { 2992 + switch (desc_id) { 2993 + case QUERY_DESC_IDN_DEVICE: 2994 + *desc_len = hba->desc_size.dev_desc; 2995 + break; 2996 + case QUERY_DESC_IDN_POWER: 2997 + *desc_len = hba->desc_size.pwr_desc; 2998 + break; 2999 + case QUERY_DESC_IDN_GEOMETRY: 3000 + *desc_len = hba->desc_size.geom_desc; 3001 + break; 3002 + case QUERY_DESC_IDN_CONFIGURATION: 3003 + *desc_len = hba->desc_size.conf_desc; 3004 + break; 3005 + case QUERY_DESC_IDN_UNIT: 3006 + *desc_len = hba->desc_size.unit_desc; 3007 + break; 3008 + case QUERY_DESC_IDN_INTERCONNECT: 3009 + *desc_len = hba->desc_size.interc_desc; 3010 + break; 3011 + case QUERY_DESC_IDN_STRING: 3012 + *desc_len = QUERY_DESC_MAX_SIZE; 3013 + break; 3014 + case QUERY_DESC_IDN_RFU_0: 3015 + case QUERY_DESC_IDN_RFU_1: 3016 + *desc_len = 0; 3017 + break; 3018 + default: 3019 + *desc_len = 0; 3020 + return -EINVAL; 3021 + } 3022 + return 0; 3023 + } 3024 + EXPORT_SYMBOL(ufshcd_map_desc_id_to_length); 3025 + 3026 + /** 2928 3027 * ufshcd_read_desc_param - read the specified descriptor parameter 2929 3028 * @hba: Pointer to adapter instance 2930 3029 * @desc_id: descriptor idn value ··· 3024 2951 static int ufshcd_read_desc_param(struct ufs_hba *hba, 3025 2952 enum desc_idn desc_id, 3026 2953 int desc_index, 3027 - u32 param_offset, 2954 + u8 param_offset, 3028 2955 u8 *param_read_buf, 3029 - u32 param_size) 2956 + u8 param_size) 3030 2957 { 3031 2958 int ret; 3032 2959 u8 *desc_buf; 3033 - u32 buff_len; 2960 + int buff_len; 3034 2961 bool is_kmalloc = true; 3035 2962 3036 - /* safety checks */ 3037 - if (desc_id >= QUERY_DESC_IDN_MAX) 2963 + /* Safety check */ 2964 + if (desc_id >= QUERY_DESC_IDN_MAX || !param_size) 3038 2965 return -EINVAL; 3039 2966 3040 - buff_len = ufs_query_desc_max_size[desc_id]; 3041 - if ((param_offset + param_size) > buff_len) 3042 - return -EINVAL; 2967 + /* Get the max length of descriptor from structure filled up at probe 2968 + * time. 2969 + */ 2970 + ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); 3043 2971 3044 - if (!param_offset && (param_size == buff_len)) { 3045 - /* memory space already available to hold full descriptor */ 3046 - desc_buf = param_read_buf; 3047 - is_kmalloc = false; 3048 - } else { 3049 - /* allocate memory to hold full descriptor */ 2972 + /* Sanity checks */ 2973 + if (ret || !buff_len) { 2974 + dev_err(hba->dev, "%s: Failed to get full descriptor length", 2975 + __func__); 2976 + return ret; 2977 + } 2978 + 2979 + /* Check whether we need temp memory */ 2980 + if (param_offset != 0 || param_size < buff_len) { 3050 2981 desc_buf = kmalloc(buff_len, GFP_KERNEL); 3051 2982 if (!desc_buf) 3052 2983 return -ENOMEM; 2984 + } else { 2985 + desc_buf = param_read_buf; 2986 + is_kmalloc = false; 3053 2987 } 3054 2988 2989 + /* Request for full descriptor */ 3055 2990 ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, 3056 - desc_id, desc_index, 0, desc_buf, 3057 - &buff_len); 2991 + desc_id, desc_index, 0, 2992 + desc_buf, &buff_len); 3058 2993 3059 2994 if (ret) { 3060 2995 dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d", 3061 2996 __func__, desc_id, desc_index, param_offset, ret); 3062 - 3063 2997 goto out; 3064 2998 } 3065 2999 ··· 3078 2998 goto out; 3079 2999 } 3080 3000 3081 - /* 3082 - * While reading variable size descriptors (like string descriptor), 3083 - * some UFS devices may report the "LENGTH" (field in "Transaction 3084 - * Specific fields" of Query Response UPIU) same as what was requested 3085 - * in Query Request UPIU instead of reporting the actual size of the 3086 - * variable size descriptor. 3087 - * Although it's safe to ignore the "LENGTH" field for variable size 3088 - * descriptors as we can always derive the length of the descriptor from 3089 - * the descriptor header fields. Hence this change impose the length 3090 - * match check only for fixed size descriptors (for which we always 3091 - * request the correct size as part of Query Request UPIU). 3092 - */ 3093 - if ((desc_id != QUERY_DESC_IDN_STRING) && 3094 - (buff_len != desc_buf[QUERY_DESC_LENGTH_OFFSET])) { 3095 - dev_err(hba->dev, "%s: desc_buf length mismatch: buff_len %d, buff_len(desc_header) %d", 3096 - __func__, buff_len, desc_buf[QUERY_DESC_LENGTH_OFFSET]); 3097 - ret = -EINVAL; 3098 - goto out; 3099 - } 3001 + /* Check wherher we will not copy more data, than available */ 3002 + if (is_kmalloc && param_size > buff_len) 3003 + param_size = buff_len; 3100 3004 3101 3005 if (is_kmalloc) 3102 3006 memcpy(param_read_buf, &desc_buf[param_offset], param_size); ··· 5983 5919 static void ufshcd_init_icc_levels(struct ufs_hba *hba) 5984 5920 { 5985 5921 int ret; 5986 - int buff_len = QUERY_DESC_POWER_MAX_SIZE; 5987 - u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE]; 5922 + int buff_len = hba->desc_size.pwr_desc; 5923 + u8 desc_buf[hba->desc_size.pwr_desc]; 5988 5924 5989 5925 ret = ufshcd_read_power_desc(hba, desc_buf, buff_len); 5990 5926 if (ret) { ··· 6081 6017 { 6082 6018 int err; 6083 6019 u8 model_index; 6084 - u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1] = {0}; 6085 - u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE]; 6020 + u8 str_desc_buf[QUERY_DESC_MAX_SIZE + 1] = {0}; 6021 + u8 desc_buf[hba->desc_size.dev_desc]; 6086 6022 6087 - err = ufshcd_read_device_desc(hba, desc_buf, 6088 - QUERY_DESC_DEVICE_MAX_SIZE); 6023 + err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc); 6089 6024 if (err) { 6090 6025 dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n", 6091 6026 __func__, err); ··· 6101 6038 model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; 6102 6039 6103 6040 err = ufshcd_read_string_desc(hba, model_index, str_desc_buf, 6104 - QUERY_DESC_STRING_MAX_SIZE, ASCII_STD); 6041 + QUERY_DESC_MAX_SIZE, ASCII_STD); 6105 6042 if (err) { 6106 6043 dev_err(hba->dev, "%s: Failed reading Product Name. err = %d\n", 6107 6044 __func__, err); 6108 6045 goto out; 6109 6046 } 6110 6047 6111 - str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0'; 6048 + str_desc_buf[QUERY_DESC_MAX_SIZE] = '\0'; 6112 6049 strlcpy(dev_desc->model, (str_desc_buf + QUERY_DESC_HDR_SIZE), 6113 6050 min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET], 6114 6051 MAX_MODEL_LEN)); ··· 6314 6251 hba->req_abort_count = 0; 6315 6252 } 6316 6253 6254 + static void ufshcd_init_desc_sizes(struct ufs_hba *hba) 6255 + { 6256 + int err; 6257 + 6258 + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_DEVICE, 0, 6259 + &hba->desc_size.dev_desc); 6260 + if (err) 6261 + hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; 6262 + 6263 + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_POWER, 0, 6264 + &hba->desc_size.pwr_desc); 6265 + if (err) 6266 + hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; 6267 + 6268 + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_INTERCONNECT, 0, 6269 + &hba->desc_size.interc_desc); 6270 + if (err) 6271 + hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; 6272 + 6273 + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_CONFIGURATION, 0, 6274 + &hba->desc_size.conf_desc); 6275 + if (err) 6276 + hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; 6277 + 6278 + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_UNIT, 0, 6279 + &hba->desc_size.unit_desc); 6280 + if (err) 6281 + hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; 6282 + 6283 + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_GEOMETRY, 0, 6284 + &hba->desc_size.geom_desc); 6285 + if (err) 6286 + hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; 6287 + } 6288 + 6289 + static void ufshcd_def_desc_sizes(struct ufs_hba *hba) 6290 + { 6291 + hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; 6292 + hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; 6293 + hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; 6294 + hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; 6295 + hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; 6296 + hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; 6297 + } 6298 + 6317 6299 /** 6318 6300 * ufshcd_probe_hba - probe hba to detect device and initialize 6319 6301 * @hba: per-adapter instance ··· 6392 6284 ret = ufshcd_complete_dev_init(hba); 6393 6285 if (ret) 6394 6286 goto out; 6287 + 6288 + /* Init check for device descriptor sizes */ 6289 + ufshcd_init_desc_sizes(hba); 6395 6290 6396 6291 ret = ufs_get_device_desc(hba, &card); 6397 6292 if (ret) { ··· 6431 6320 6432 6321 /* set the state as operational after switching to desired gear */ 6433 6322 hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; 6323 + 6434 6324 /* 6435 6325 * If we are in error handling context or in power management callbacks 6436 6326 * context, no need to scan the host ··· 7885 7773 7886 7774 hba->mmio_base = mmio_base; 7887 7775 hba->irq = irq; 7776 + 7777 + /* Set descriptor lengths to specification defaults */ 7778 + ufshcd_def_desc_sizes(hba); 7888 7779 7889 7780 err = ufshcd_hba_init(hba); 7890 7781 if (err)
+15
drivers/scsi/ufs/ufshcd.h
··· 220 220 struct ufs_query query; 221 221 }; 222 222 223 + struct ufs_desc_size { 224 + int dev_desc; 225 + int pwr_desc; 226 + int geom_desc; 227 + int interc_desc; 228 + int unit_desc; 229 + int conf_desc; 230 + }; 231 + 223 232 /** 224 233 * struct ufs_clk_info - UFS clock related info 225 234 * @list: list headed by hba->clk_list_head ··· 492 483 * @clk_list_head: UFS host controller clocks list node head 493 484 * @pwr_info: holds current power mode 494 485 * @max_pwr_info: keeps the device max valid pwm 486 + * @desc_size: descriptor sizes reported by device 495 487 * @urgent_bkops_lvl: keeps track of urgent bkops level for device 496 488 * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for 497 489 * device is known or not. ··· 676 666 bool is_urgent_bkops_lvl_checked; 677 667 678 668 struct rw_semaphore clk_scaling_lock; 669 + struct ufs_desc_size desc_size; 679 670 }; 680 671 681 672 /* Returns true if clocks can be gated. Otherwise false */ ··· 843 832 enum flag_idn idn, bool *flag_res); 844 833 int ufshcd_hold(struct ufs_hba *hba, bool async); 845 834 void ufshcd_release(struct ufs_hba *hba); 835 + 836 + int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, 837 + int *desc_length); 838 + 846 839 u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba); 847 840 848 841 /* Wrapper functions for safely calling variant operations */