summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorsubhashj@codeaurora.org <subhashj@codeaurora.org>2016-11-23 16:31:41 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2016-11-29 12:06:56 -0500
commitbde44bb665d049468b6a1a2fa7d666434de4f83f (patch)
tree9db028632329b36273e734839fbcdf2bd1a6ed4e /drivers
parent24d6243204633be4b710754f279b3ca57c69ceec (diff)
downloadlinux-bde44bb665d049468b6a1a2fa7d666434de4f83f.tar.bz2
scsi: ufs: fix failure to read the string descriptor
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). Reviewed-by: Venkat Gopalakrishnan <venkatg@codeaurora.org> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ufs/ufshcd.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9abc11e77a55..d6e87dc472c4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2108,16 +2108,38 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba,
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 ,index %d, ret %d",
- __func__, desc_id, param_offset, buff_len,
- desc_index, ret);
- if (!ret)
- ret = -EINVAL;
+ if (ret) {
+ dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d",
+ __func__, desc_id, desc_index, param_offset, ret);
+
+ goto out;
+ }
+
+ /* Sanity check */
+ if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) {
+ dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header",
+ __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]);
+ ret = -EINVAL;
+ 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;
}