summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorHyeoncheol Jeong <hyenc.jeong@samsung.com>2026-07-28 18:27:41 +0900
committerMartin K. Petersen (Oracle) <mkp@kernel.org>2026-08-07 11:32:19 -0400
commit8f5bbff8749ab886557cc27dc09729c911c122fa (patch)
tree8221407c45fb80813fb6f1f0df2d810e3692740d /include
parentdca46c4ff2cd5be17039a99613b6b4bb0923fe9a (diff)
downloadlinux-8f5bbff8749ab886557cc27dc09729c911c122fa.tar.gz
linux-8f5bbff8749ab886557cc27dc09729c911c122fa.zip
scsi: ufs: Add support for the aggregated read query opcode
UFS 5.0 / JEDEC 220H introduces the AGGREGATED READ query opcode (0x9), which retrieves an aggregated data packet in a single query request. The packet may bundle multiple Descriptors, Attributes and Flags as group-headed groups, returned in the Data Segment of the QUERY RESPONSE UPIU. Such a packet can be far larger than a single descriptor (up to a few KiB vs the 255-byte descriptor limit), so its response UPIU buffer must be enlarged. Enlarging the shared utp_transfer_cmd_desc would waste that extra space per tag, so add a dedicated utp_devman_cmd_desc with a 4 KiB response area (ALIGNED_DEVMAN_RSP_SIZE), allocated once for the reserved (device management) tag that aggregated read uses. Regular tags keep the 512-byte descriptor in a pool of (nutrs - UFSHCD_NUM_RESERVED) entries, leaving normal I/O unchanged. ufshcd_init_lrb() and ufshcd_host_memory_configure() pick the devman descriptor for the reserved tag and index the pool at (tag - UFSHCD_NUM_RESERVED) otherwise. The pre-4.1 MCQ tag recovery adds one compare against the devman UCD address and returns the reserved tag (UFSHCI 4.1+ carries the tag in the CQE), and the BSG raw-UPIU and device management paths learn the new opcode, sizing descriptors by QUERY_AGGREGATED_MAX_SIZE. Signed-off-by: Hyeoncheol Jeong <hyenc.jeong@samsung.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Link: https://patch.msgid.link/20260728092741epcms2p8c53432ef3c2f0d6a63dd980ad5ef9f00@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 248d0a5bef40..6007c9eeb43f 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -237,11 +237,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;
};
/**
@@ -952,9 +954,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.
@@ -1093,11 +1099,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;
@@ -1356,6 +1364,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
*/