Skip to content

Commit

Permalink
scsi: ufs: Introduce UFSHCD_QUIRK_PRDT_BYTE_GRAN quirk
Browse files Browse the repository at this point in the history
Some UFS host controllers like Exynos uses granularities of PRDT length and
offset as bytes, whereas others use actual segment count.

Link: https://lore.kernel.org/r/20200528011658.71590-5-alim.akhtar@samsung.com
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Alim Akhtar authored and Martin K. Petersen committed Jun 15, 2020
1 parent 39bf2d8 commit 26f968d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
30 changes: 23 additions & 7 deletions drivers/scsi/ufs/ufshcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2168,8 +2168,14 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
return sg_segments;

if (sg_segments) {
lrbp->utr_descriptor_ptr->prd_table_length =
cpu_to_le16((u16)sg_segments);

if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
lrbp->utr_descriptor_ptr->prd_table_length =
cpu_to_le16((sg_segments *
sizeof(struct ufshcd_sg_entry)));
else
lrbp->utr_descriptor_ptr->prd_table_length =
cpu_to_le16((u16) (sg_segments));

prd_table = (struct ufshcd_sg_entry *)lrbp->ucd_prdt_ptr;

Expand Down Expand Up @@ -3518,11 +3524,21 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
cpu_to_le32(upper_32_bits(cmd_desc_element_addr));

/* Response upiu and prdt offset should be in double words */
utrdlp[i].response_upiu_offset =
cpu_to_le16(response_offset >> 2);
utrdlp[i].prd_table_offset = cpu_to_le16(prdt_offset >> 2);
utrdlp[i].response_upiu_length =
cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) {
utrdlp[i].response_upiu_offset =
cpu_to_le16(response_offset);
utrdlp[i].prd_table_offset =
cpu_to_le16(prdt_offset);
utrdlp[i].response_upiu_length =
cpu_to_le16(ALIGNED_UPIU_SIZE);
} else {
utrdlp[i].response_upiu_offset =
cpu_to_le16(response_offset >> 2);
utrdlp[i].prd_table_offset =
cpu_to_le16(prdt_offset >> 2);
utrdlp[i].response_upiu_length =
cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
}

ufshcd_init_lrb(hba, &hba->lrb[i], i);
}
Expand Down
6 changes: 6 additions & 0 deletions drivers/scsi/ufs/ufshcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,12 @@ enum ufshcd_quirks {
* enabled via HCE register.
*/
UFSHCI_QUIRK_BROKEN_HCE = 1 << 8,

/*
* This quirk needs to be enabled if the host controller regards
* resolution of the values of PRDTO and PRDTL in UTRD as byte.
*/
UFSHCD_QUIRK_PRDT_BYTE_GRAN = 1 << 9,
};

enum ufshcd_caps {
Expand Down

0 comments on commit 26f968d

Please sign in to comment.