summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMartin K. Petersen (Oracle) <mkp@kernel.org>2026-08-07 11:34:35 -0400
committerMartin K. Petersen (Oracle) <mkp@kernel.org>2026-08-07 11:34:35 -0400
commitf574a022ee5d1f23e9dd6f6a4e4c8a8af7bbb477 (patch)
tree9b93a3d4188bb943015860336a7c5d03c57d40a6 /include
parent654fdae895253ef4ce5bf0cfa261d0e1547347c2 (diff)
parent8f5bbff8749ab886557cc27dc09729c911c122fa (diff)
downloadlinux-stable-f574a022ee5d1f23e9dd6f6a4e4c8a8af7bbb477.tar.gz
linux-stable-f574a022ee5d1f23e9dd6f6a4e4c8a8af7bbb477.zip
Merge patch series "scsi: ufs: Add support for the aggregated read query opcode"
Hyeoncheol Jeong <hyenc.jeong@samsung.com> says: UFS 5.0 / JEDEC 220H introduces the AGGREGATED READ query opcode (0x9), which retrieves an aggregated data packet bundling multiple Descriptors, Attributes and Flags in a single QUERY RESPONSE UPIU. Such a packet can be far larger than a single descriptor, so the reserved (device management) tag gets a dedicated UCD with an enlarged response area. Patch 1 is a preparatory cleanup that switches the BSG query descriptor length to unsigned types. Patch 2 adds the aggregated read support. v3: https://lore.kernel.org/linux-scsi/20260724030812epcms2p4eb2c77cb4dcd5fd51ca9c3eaa5ea4bfa@epcms2p4/ v2: https://lore.kernel.org/linux-scsi/20260722084819epcms2p49c27fce999e821385f7b5d7ea5a02868@epcms2p4/ Link: https://patch.msgid.link/20260728092208epcms2p881b17276fb41c006a4229c1d073b4ad0@epcms2p8 Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/ufs/ufs.h6
-rw-r--r--include/ufs/ufshcd.h20
-rw-r--r--include/ufs/ufshci.h12
3 files changed, 38 insertions, 0 deletions
diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h
index 0d48e137d66d..afbb32654fab 100644
--- a/include/ufs/ufs.h
+++ b/include/ufs/ufs.h
@@ -25,6 +25,11 @@ static_assert(sizeof(struct utp_upiu_query) == 20);
#define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req))
#define QUERY_DESC_MAX_SIZE 255
+/*
+ * Max aggregated read data segment: the devman response area
+ * (ALIGNED_DEVMAN_RSP_SIZE) minus the fixed UPIU header it follows.
+ */
+#define QUERY_AGGREGATED_MAX_SIZE (4096 - GENERAL_UPIU_REQUEST_SIZE)
#define QUERY_DESC_MIN_SIZE 2
#define QUERY_DESC_HDR_SIZE 2
#define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \
@@ -464,6 +469,7 @@ enum query_opcode {
UPIU_QUERY_OPCODE_SET_FLAG = 0x6,
UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7,
UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8,
+ UPIU_QUERY_OPCODE_AGGREGATED_READ = 0x9,
};
/* bRefClkFreq attribute values */
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 26118b28b2dc..dfd302f2dc7c 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -235,11 +235,13 @@ struct ufs_query {
* @type: device management command type - Query, NOP OUT
* @lock: lock to allow one command at a time
* @query: Device management query information
+ * @tag: tag of the reserved request in use
*/
struct ufs_dev_cmd {
enum dev_cmd_type type;
struct mutex lock;
struct ufs_query query;
+ u8 tag;
};
/**
@@ -954,9 +956,13 @@ enum ufshcd_mcq_opr {
* @ucdl_base_addr: UFS Command Descriptor base address
* @utrdl_base_addr: UTP Transfer Request Descriptor base address
* @utmrdl_base_addr: UTP Task Management Descriptor base address
+ * @devman_ucd_base_addr: UFS Command Descriptor base address for the reserved
+ * device management tag (has a larger response area)
* @ucdl_dma_addr: UFS Command Descriptor DMA address
* @utrdl_dma_addr: UTRDL DMA address
* @utmrdl_dma_addr: UTMRDL DMA address
+ * @devman_ucd_dma_addr: UFS Command Descriptor DMA address for the reserved
+ * device management tag
* @host: Scsi_Host instance of the driver
* @dev: device handle
* @ufs_device_wlun: WLUN that controls the entire UFS device.
@@ -1098,11 +1104,13 @@ struct ufs_hba {
struct utp_transfer_cmd_desc *ucdl_base_addr;
struct utp_transfer_req_desc *utrdl_base_addr;
struct utp_task_req_desc *utmrdl_base_addr;
+ struct utp_devman_cmd_desc *devman_ucd_base_addr;
/* DMA memory reference */
dma_addr_t ucdl_dma_addr;
dma_addr_t utrdl_dma_addr;
dma_addr_t utmrdl_dma_addr;
+ dma_addr_t devman_ucd_dma_addr;
struct Scsi_Host *host;
struct device *dev;
@@ -1361,6 +1369,18 @@ static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba)
return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba);
}
+/*
+ * Two entries should be enough for the largest devman PRDT transfer (4 KiB),
+ * like advanced RPMB.
+ */
+#define UFSHCD_DEVMAN_SG_ENTRIES 2
+
+static inline size_t ufshcd_get_devman_ucd_size(const struct ufs_hba *hba)
+{
+ return sizeof(struct utp_devman_cmd_desc) +
+ UFSHCD_DEVMAN_SG_ENTRIES * ufshcd_sg_entry_size(hba);
+}
+
/* Returns true if clocks can be gated. Otherwise false */
static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba)
{
diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h
index 9f0fdd850e54..c3537bb544ae 100644
--- a/include/ufs/ufshci.h
+++ b/include/ufs/ufshci.h
@@ -18,6 +18,8 @@ enum {
TASK_REQ_UPIU_SIZE_DWORDS = 8,
TASK_RSP_UPIU_SIZE_DWORDS = 8,
ALIGNED_UPIU_SIZE = 512,
+ /* Larger response area, only for the devman UCD */
+ ALIGNED_DEVMAN_RSP_SIZE = 4096,
};
/* UFSHCI Registers */
@@ -501,6 +503,16 @@ struct utp_transfer_cmd_desc {
u8 prd_table[];
};
+/* Dedicated UCD for the devman/reserved slot */
+struct utp_devman_cmd_desc {
+ u8 command_upiu[ALIGNED_UPIU_SIZE];
+ u8 response_upiu[ALIGNED_DEVMAN_RSP_SIZE];
+ u8 prd_table[];
+};
+
+static_assert(sizeof(struct utp_upiu_req) + QUERY_AGGREGATED_MAX_SIZE <=
+ ALIGNED_DEVMAN_RSP_SIZE);
+
/**
* struct request_desc_header - Descriptor Header common to both UTRD and UTMRD
*/