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/
Showing the changes to include (3 of 6 files). Show all
Unified · Split
| @@ -25,6 +25,11 @@ static_assert(sizeof(struct utp_upiu_query) == 20); · 24 unmodified lines | |||
| 25 | 25 | ||
| 26 | #define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req)) | 26 | #define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req)) |
| 27 | #define QUERY_DESC_MAX_SIZE 255 | 27 | #define QUERY_DESC_MAX_SIZE 255 |
| 28 | /* | ||
| 29 | * Max aggregated read data segment: the devman response area | ||
| 30 | * (ALIGNED_DEVMAN_RSP_SIZE) minus the fixed UPIU header it follows. | ||
| 31 | */ | ||
| 32 | #define QUERY_AGGREGATED_MAX_SIZE (4096 - GENERAL_UPIU_REQUEST_SIZE) | ||
| 28 | #define QUERY_DESC_MIN_SIZE 2 | 33 | #define QUERY_DESC_MIN_SIZE 2 |
| 29 | #define QUERY_DESC_HDR_SIZE 2 | 34 | #define QUERY_DESC_HDR_SIZE 2 |
| 30 | #define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ | 35 | #define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ |
| @@ -464,6 +469,7 @@ enum query_opcode { · 433 unmodified lines | |||
| 464 | UPIU_QUERY_OPCODE_SET_FLAG = 0x6, | 469 | UPIU_QUERY_OPCODE_SET_FLAG = 0x6, |
| 465 | UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7, | 470 | UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7, |
| 466 | UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, | 471 | UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, |
| 472 | UPIU_QUERY_OPCODE_AGGREGATED_READ = 0x9, | ||
| 467 | }; | 473 | }; |
| 468 | 474 | ||
| 469 | /* bRefClkFreq attribute values */ | 475 | /* bRefClkFreq attribute values */ |
| @@ -235,11 +235,13 @@ struct ufs_query { · 234 unmodified lines | |||
| 235 | * @type: device management command type - Query, NOP OUT | 235 | * @type: device management command type - Query, NOP OUT |
| 236 | * @lock: lock to allow one command at a time | 236 | * @lock: lock to allow one command at a time |
| 237 | * @query: Device management query information | 237 | * @query: Device management query information |
| 238 | * @tag: tag of the reserved request in use | ||
| 238 | */ | 239 | */ |
| 239 | struct ufs_dev_cmd { | 240 | struct ufs_dev_cmd { |
| 240 | enum dev_cmd_type type; | 241 | enum dev_cmd_type type; |
| 241 | struct mutex lock; | 242 | struct mutex lock; |
| 242 | struct ufs_query query; | 243 | struct ufs_query query; |
| 244 | u8 tag; | ||
| 243 | }; | 245 | }; |
| 244 | 246 | ||
| 245 | /** | 247 | /** |
| @@ -954,9 +956,13 @@ enum ufshcd_mcq_opr { · 708 unmodified lines | |||
| 954 | * @ucdl_base_addr: UFS Command Descriptor base address | 956 | * @ucdl_base_addr: UFS Command Descriptor base address |
| 955 | * @utrdl_base_addr: UTP Transfer Request Descriptor base address | 957 | * @utrdl_base_addr: UTP Transfer Request Descriptor base address |
| 956 | * @utmrdl_base_addr: UTP Task Management Descriptor base address | 958 | * @utmrdl_base_addr: UTP Task Management Descriptor base address |
| 959 | * @devman_ucd_base_addr: UFS Command Descriptor base address for the reserved | ||
| 960 | * device management tag (has a larger response area) | ||
| 957 | * @ucdl_dma_addr: UFS Command Descriptor DMA address | 961 | * @ucdl_dma_addr: UFS Command Descriptor DMA address |
| 958 | * @utrdl_dma_addr: UTRDL DMA address | 962 | * @utrdl_dma_addr: UTRDL DMA address |
| 959 | * @utmrdl_dma_addr: UTMRDL DMA address | 963 | * @utmrdl_dma_addr: UTMRDL DMA address |
| 964 | * @devman_ucd_dma_addr: UFS Command Descriptor DMA address for the reserved | ||
| 965 | * device management tag | ||
| 960 | * @host: Scsi_Host instance of the driver | 966 | * @host: Scsi_Host instance of the driver |
| 961 | * @dev: device handle | 967 | * @dev: device handle |
| 962 | * @ufs_device_wlun: WLUN that controls the entire UFS device. | 968 | * @ufs_device_wlun: WLUN that controls the entire UFS device. |
| @@ -1098,11 +1104,13 @@ struct ufs_hba { · 135 unmodified lines | |||
| 1098 | struct utp_transfer_cmd_desc *ucdl_base_addr; | 1104 | struct utp_transfer_cmd_desc *ucdl_base_addr; |
| 1099 | struct utp_transfer_req_desc *utrdl_base_addr; | 1105 | struct utp_transfer_req_desc *utrdl_base_addr; |
| 1100 | struct utp_task_req_desc *utmrdl_base_addr; | 1106 | struct utp_task_req_desc *utmrdl_base_addr; |
| 1107 | struct utp_devman_cmd_desc *devman_ucd_base_addr; | ||
| 1101 | 1108 | ||
| 1102 | /* DMA memory reference */ | 1109 | /* DMA memory reference */ |
| 1103 | dma_addr_t ucdl_dma_addr; | 1110 | dma_addr_t ucdl_dma_addr; |
| 1104 | dma_addr_t utrdl_dma_addr; | 1111 | dma_addr_t utrdl_dma_addr; |
| 1105 | dma_addr_t utmrdl_dma_addr; | 1112 | dma_addr_t utmrdl_dma_addr; |
| 1113 | dma_addr_t devman_ucd_dma_addr; | ||
| 1106 | 1114 | ||
| 1107 | struct Scsi_Host *host; | 1115 | struct Scsi_Host *host; |
| 1108 | struct device *dev; | 1116 | struct device *dev; |
| @@ -1361,6 +1369,18 @@ static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba) · 252 unmodified lines | |||
| 1361 | return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba); | 1369 | return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba); |
| 1362 | } | 1370 | } |
| 1363 | 1371 | ||
| 1372 | /* | ||
| 1373 | * Two entries should be enough for the largest devman PRDT transfer (4 KiB), | ||
| 1374 | * like advanced RPMB. | ||
| 1375 | */ | ||
| 1376 | #define UFSHCD_DEVMAN_SG_ENTRIES 2 | ||
| 1377 | |||
| 1378 | static inline size_t ufshcd_get_devman_ucd_size(const struct ufs_hba *hba) | ||
| 1379 | { | ||
| 1380 | return sizeof(struct utp_devman_cmd_desc) + | ||
| 1381 | UFSHCD_DEVMAN_SG_ENTRIES * ufshcd_sg_entry_size(hba); | ||
| 1382 | } | ||
| 1383 | |||
| 1364 | /* Returns true if clocks can be gated. Otherwise false */ | 1384 | /* Returns true if clocks can be gated. Otherwise false */ |
| 1365 | static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) | 1385 | static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) |
| 1366 | { | 1386 | { |
| @@ -18,6 +18,8 @@ enum { · 17 unmodified lines | |||
| 18 | TASK_REQ_UPIU_SIZE_DWORDS = 8, | 18 | TASK_REQ_UPIU_SIZE_DWORDS = 8, |
| 19 | TASK_RSP_UPIU_SIZE_DWORDS = 8, | 19 | TASK_RSP_UPIU_SIZE_DWORDS = 8, |
| 20 | ALIGNED_UPIU_SIZE = 512, | 20 | ALIGNED_UPIU_SIZE = 512, |
| 21 | /* Larger response area, only for the devman UCD */ | ||
| 22 | ALIGNED_DEVMAN_RSP_SIZE = 4096, | ||
| 21 | }; | 23 | }; |
| 22 | 24 | ||
| 23 | /* UFSHCI Registers */ | 25 | /* UFSHCI Registers */ |
| @@ -501,6 +503,16 @@ struct utp_transfer_cmd_desc { · 477 unmodified lines | |||
| 501 | u8 prd_table[]; | 503 | u8 prd_table[]; |
| 502 | }; | 504 | }; |
| 503 | 505 | ||
| 506 | /* Dedicated UCD for the devman/reserved slot */ | ||
| 507 | struct utp_devman_cmd_desc { | ||
| 508 | u8 command_upiu[ALIGNED_UPIU_SIZE]; | ||
| 509 | u8 response_upiu[ALIGNED_DEVMAN_RSP_SIZE]; | ||
| 510 | u8 prd_table[]; | ||
| 511 | }; | ||
| 512 | |||
| 513 | static_assert(sizeof(struct utp_upiu_req) + QUERY_AGGREGATED_MAX_SIZE <= | ||
| 514 | ALIGNED_DEVMAN_RSP_SIZE); | ||
| 515 | |||
| 504 | /** | 516 | /** |
| 505 | * struct request_desc_header - Descriptor Header common to both UTRD and UTMRD | 517 | * struct request_desc_header - Descriptor Header common to both UTRD and UTMRD |
| 506 | */ | 518 | */ |