Commit 4da9629dd6 for qemu.org

commit 4da9629dd63c9d92056608b9bbea446004f55431
Author: Stanley Jhu <stanleyjhu@google.com>
Date:   Fri Oct 23 19:38:27 2026 +0800

    tests/qtest/ufs-test: Add TMR and async MCQ SCSI submission helpers

    Add ufs_send_tmr() and ufs_mcq_send_scsi_cmd_async() helper functions
    in preparation for UTMRL task management and QOM fault injection unit
    tests.

    Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
    Reviewed-by: Jeuk Kim <jeuk20.kim@samsung.com>
    Signed-off-by: Jeuk Kim <jeuk20.kim@samsung.com>

diff --git a/tests/qtest/ufs-test.c b/tests/qtest/ufs-test.c
index e8993e8c24..2914723430 100644
--- a/tests/qtest/ufs-test.c
+++ b/tests/qtest/ufs-test.c
@@ -1899,6 +1899,59 @@ static void ufstest_hid(void *obj, void *data, QGuestAllocator *alloc)
     ufs_exit(ufs, alloc);
 }

+static G_GNUC_UNUSED void ufs_send_tmr(QUfs *ufs, uint64_t utmrlba, int slot,
+                         uint8_t tm_func, uint8_t lun,
+                         uint32_t task_tag,
+                         UtpTaskReqDesc *utrd_out)
+{
+    uint64_t desc_addr = utmrlba + slot * sizeof(UtpTaskReqDesc);
+    UtpTaskReqDesc desc = { 0 };
+
+    desc.header.dword_0 = cpu_to_le32(UFS_UTP_REQ_DESC_INT_CMD);
+    desc.header.dword_2 = cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS);
+
+    desc.upiu_req.req_header.trans_type = UFS_UPIU_TRANSACTION_TASK_REQ;
+    desc.upiu_req.req_header.query_func = tm_func;
+    desc.upiu_req.req_header.lun = lun;
+    desc.upiu_req.req_header.task_tag = 0x10 + slot;
+    desc.upiu_req.input_param1 = cpu_to_be32(lun);
+    desc.upiu_req.input_param2 = cpu_to_be32(task_tag);
+
+    qtest_memwrite(ufs->dev.bus->qts, desc_addr, &desc, sizeof(desc));
+
+    ufs_wreg(ufs, A_UTMRLDBR, 1 << slot);
+    ufs_wait_for_irq(ufs);
+    g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTMRCS));
+    ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTMRCS, 1));
+    g_assert_cmpuint(ufs_rreg(ufs, A_UTMRLDBR) & (1 << slot), ==, 0);
+
+    qtest_memread(ufs->dev.bus->qts, desc_addr, utrd_out, sizeof(*utrd_out));
+}
+
+static G_GNUC_UNUSED int ufs_mcq_send_scsi_cmd_async(QUfs *ufs, uint8_t lun,
+                                       const uint8_t *cdb)
+{
+    int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
+    uint64_t req_upiu_addr =
+        ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
+    UtpUpiuReq req_upiu = { 0 };
+    UtpTransferReqDesc utrd;
+
+    req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_COMMAND;
+    req_upiu.header.flags = UFS_UPIU_CMD_FLAGS_NONE;
+    req_upiu.header.lun = lun;
+    req_upiu.header.task_tag = cmd_desc_slot;
+    memcpy(req_upiu.sc.cdb, cdb, UFS_CDB_SIZE);
+    qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
+                   sizeof(req_upiu));
+
+    utrd = ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
+    __ufs_send_transfer_request_mcq_async(ufs, lun, &utrd);
+
+    return cmd_desc_slot;
+}
+
+
 static void ufs_register_nodes(void)
 {
     const char *arch;