summaryrefslogtreecommitdiff
path: root/drivers/scsi/ufs
diff options
context:
space:
mode:
authorKiwoong Kim <kwmad.kim@samsung.com>2021-01-19 06:33:41 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2021-01-21 05:53:44 +0300
commit2b2bfc8aa519f696087475ed8e8c61850c673272 (patch)
treed74967d2dc89cda465b0c416c02d0abccf0bd78b /drivers/scsi/ufs
parent60ec37555d05b023721a08005f5dbf716ab5394f (diff)
downloadlinux-2b2bfc8aa519f696087475ed8e8c61850c673272.tar.xz
scsi: ufs: Introduce a quirk to allow only page-aligned sg entries
Some SoCs require a single scatterlist entry for smaller than page size, i.e. 4KB. When dispatching commands with more than one scatterlist entry under 4KB in size the following behavior is observed: A command to read a block range is dispatched with two scatterlist entries that are named AAA and BBB. After dispatching, the host builds two PRDT entries and during transmission, device sends just one DATA IN because device doesn't care about host DMA. The host then transfers the combined amount of data from start address of the area named AAA. As a consequence, the area that follows AAA in memory would be corrupted. |<------------->| +-------+------------ +-------+ + AAA + (corrupted) ... + BBB + +-------+------------ +-------+ To avoid this we need to enforce page size alignment for sg entries. Link: https://lore.kernel.org/r/56dddef94f60bd9466fd77e69f64bbbd657ed2a1.1611026909.git.kwmad.kim@samsung.com Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r--drivers/scsi/ufs/ufshcd.c2
-rw-r--r--drivers/scsi/ufs/ufshcd.h4
2 files changed, 6 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c22e751bb030..a4631caabf30 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4852,6 +4852,8 @@ static int ufshcd_slave_configure(struct scsi_device *sdev)
struct request_queue *q = sdev->request_queue;
blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1);
+ if (hba->quirks & UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE)
+ blk_queue_update_dma_alignment(q, PAGE_SIZE - 1);
if (ufshcd_is_rpm_autosuspend_allowed(hba))
sdev->rpm_autosuspend = 1;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 5bbe4715d4e9..a5c6084c8615 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -559,6 +559,10 @@ enum ufshcd_quirks {
*/
UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13,
+ /*
+ * This quirk allows only sg entries aligned with page size.
+ */
+ UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE = 1 << 13,
};
enum ufshcd_caps {