@samitouri / QOSamiQemu / commits / 20c03709b3

hw/ufs: Populate cqe.task_tag for UFSHCI 4.1 tag decoding

In UFSHCI 4.1 the MCQ completion queue entry carries the request tag in the cqe.task_tag field (DW5), whereas 4.0 hosts derive it from the UTP command descriptor base address. The device reports version 4.1 in the VER register but left task_tag/lun zero in the completion path, so a 4.1-compliant host reads tag 0 for every completion and cannot match it to the outstanding request. Add the task_tag/lun/iid fields to UfsCqEntry per the UFSHCI 4.1 CQE layout and populate them from the request UPIU header. For example, the Linux ufshcd_mcq_get_tag() uses cqe.task_tag for version >= 4.1, so without this SCSI commands hung (e.g. INQUIRY to the device W-LUN) while device-management commands still completed. Signed-off-by: Jeuk Kim <jeuk20.kim@samsung.com>

Jeuk Kim committed Jun 26, 2026 at 17:04 UTC 20c03709b353d6c985bfa3174c4563d57ff47275
2 files changed +11 -1
hw/ufs/ufs.c
+6
@@ -520,6 +520,12 @@ static void ufs_mcq_process_cq(void *opaque)
520 req->cqe.prdt_off = cpu_to_le16(prdt_off);
521 req->cqe.status = status;
522 req->cqe.error = 0;
523 + /*
524 + * From UFSHCI 4.1 the host derives the request tag from cqe.task_tag
525 + * rather than decoding it from utp_addr.
526 + */
527 + req->cqe.task_tag = req->req_upiu.header.task_tag;
528 + req->cqe.lun = req->req_upiu.header.lun;
529
530 ret = ufs_addr_write(u, cq->addr + tail, &req->cqe, sizeof(req->cqe));
531 if (ret) {
include/block/ufs.h
+5 -1
@@ -1333,7 +1333,11 @@ typedef struct QEMU_PACKED UfsCqEntry {
1333 uint8_t status;
1334 uint8_t error;
1335 uint16_t rsvd1;
1336 - uint32_t rsvd2[3];
1336 + uint8_t task_tag;
1337 + uint8_t lun;
1338 + uint8_t iid_ext_iid;
1339 + uint8_t rsvd2;
1340 + uint32_t rsvd3[2];
1341 } UfsCqEntry;
1342
1343 static inline void _ufs_check_size(void)