xref: /openbmc/qemu/tests/qtest/ufs-test.c (revision 0c2fd08dc88d7cc7755ad67bd3248ac748e87f2c)
1 /*
2  * QTest testcase for UFS
3  *
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include "qemu/module.h"
11 #include "libqtest.h"
12 #include "libqos/qgraph.h"
13 #include "libqos/pci.h"
14 #include "scsi/constants.h"
15 #include "block/ufs.h"
16 #include "qemu/bitmap.h"
17 
18 #define DWORD_BYTE 4
19 /* Test images sizes in Bytes */
20 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
21 /* Timeout for various operations, in seconds. */
22 #define TIMEOUT_SECONDS 10
23 /* Maximum PRD entry count */
24 #define MAX_PRD_ENTRY_COUNT 10
25 #define PRD_ENTRY_DATA_SIZE 4096
26 /* Constants to build upiu */
27 #define UTP_COMMAND_DESCRIPTOR_SIZE 4096
28 #define UTP_RESPONSE_UPIU_OFFSET 1024
29 #define UTP_PRDT_UPIU_OFFSET 2048
30 #define UTRD_TEST_SLOT 0
31 #define UFS_MAX_CMD_DESC 32
32 /* Constants for MCQ */
33 #define TEST_QID 0
34 #define QUEUE_SIZE 32
35 #define UFS_MCQ_MAX_QNUM 32
36 
37 typedef struct QUfs QUfs;
38 
39 struct QUfs {
40     QOSGraphObject obj;
41     QPCIDevice dev;
42     QPCIBar bar;
43 
44     DECLARE_BITMAP(cmd_desc_bitmap, UFS_MAX_CMD_DESC);
45     uint64_t cmd_desc_addr;
46     uint64_t data_buffer_addr;
47 
48     bool enabled;
49     bool support_mcq;
50 
51     /* for legacy doorbell mode */
52     uint64_t utrlba;
53 
54     /* for mcq mode */
55     uint32_t maxq;
56     uint64_t sqlba[UFS_MCQ_MAX_QNUM];
57     uint64_t cqlba[UFS_MCQ_MAX_QNUM];
58     uint64_t sqdao[UFS_MCQ_MAX_QNUM];
59     uint64_t cqdao[UFS_MCQ_MAX_QNUM];
60 };
61 
ufs_rreg(QUfs * ufs,size_t offset)62 static inline uint32_t ufs_rreg(QUfs *ufs, size_t offset)
63 {
64     return qpci_io_readl(&ufs->dev, ufs->bar, offset);
65 }
66 
ufs_wreg(QUfs * ufs,size_t offset,uint32_t value)67 static inline void ufs_wreg(QUfs *ufs, size_t offset, uint32_t value)
68 {
69     qpci_io_writel(&ufs->dev, ufs->bar, offset, value);
70 }
71 
alloc_cmd_desc_slot(QUfs * ufs)72 static int alloc_cmd_desc_slot(QUfs *ufs)
73 {
74     int slot = find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC);
75     if (slot == UFS_MAX_CMD_DESC) {
76         g_assert_not_reached();
77     }
78     set_bit(slot, ufs->cmd_desc_bitmap);
79     return slot;
80 }
81 
release_cmd_desc_slot(QUfs * ufs,int slot)82 static void release_cmd_desc_slot(QUfs *ufs, int slot)
83 {
84     if (!test_bit(slot, ufs->cmd_desc_bitmap)) {
85         g_assert_not_reached();
86     }
87     clear_bit(slot, ufs->cmd_desc_bitmap);
88 }
89 
ufs_wait_for_irq(QUfs * ufs)90 static void ufs_wait_for_irq(QUfs *ufs)
91 {
92     uint64_t end_time;
93     uint32_t is;
94     /* Wait for device to reset as the linux driver does. */
95     end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
96     do {
97         qtest_clock_step(ufs->dev.bus->qts, 100);
98         is = ufs_rreg(ufs, A_IS);
99     } while (is == 0 && g_get_monotonic_time() < end_time);
100 }
101 
ufs_build_req_utrd(uint64_t command_desc_base_addr,uint32_t data_direction,uint16_t prd_table_length)102 static UtpTransferReqDesc ufs_build_req_utrd(uint64_t command_desc_base_addr,
103                                              uint32_t data_direction,
104                                              uint16_t prd_table_length)
105 {
106     UtpTransferReqDesc req = { 0 };
107 
108     req.header.dword_0 =
109         cpu_to_le32(1 << 28 | data_direction | UFS_UTP_REQ_DESC_INT_CMD);
110     req.header.dword_2 = cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS);
111 
112     req.command_desc_base_addr_hi = cpu_to_le32(command_desc_base_addr >> 32);
113     req.command_desc_base_addr_lo =
114         cpu_to_le32(command_desc_base_addr & 0xffffffff);
115     req.response_upiu_offset =
116         cpu_to_le16(UTP_RESPONSE_UPIU_OFFSET / sizeof(uint32_t));
117     req.response_upiu_length = cpu_to_le16(sizeof(UtpUpiuRsp));
118     req.prd_table_offset = cpu_to_le16(UTP_PRDT_UPIU_OFFSET / sizeof(uint32_t));
119     req.prd_table_length = cpu_to_le16(prd_table_length);
120     return req;
121 }
122 
123 static enum UtpOcsCodes
__ufs_send_transfer_request_doorbell(QUfs * ufs,uint8_t lun,const UtpTransferReqDesc * utrd)124 __ufs_send_transfer_request_doorbell(QUfs *ufs, uint8_t lun,
125                                      const UtpTransferReqDesc *utrd)
126 {
127     uint64_t utrd_addr =
128         ufs->utrlba + UTRD_TEST_SLOT * sizeof(UtpTransferReqDesc);
129     UtpTransferReqDesc utrd_result;
130 
131     qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
132 
133     /* Ring the doorbell */
134     ufs_wreg(ufs, A_UTRLDBR, 1);
135     ufs_wait_for_irq(ufs);
136     g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTRCS));
137     ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTRCS, 1));
138 
139     /* Handle completed command */
140     qtest_memread(ufs->dev.bus->qts, utrd_addr, &utrd_result,
141                   sizeof(utrd_result));
142     return le32_to_cpu(utrd_result.header.dword_2) & 0xf;
143 }
144 
145 static enum UtpOcsCodes
__ufs_send_transfer_request_mcq(QUfs * ufs,uint8_t lun,const UtpTransferReqDesc * utrd)146 __ufs_send_transfer_request_mcq(QUfs *ufs, uint8_t lun,
147                                 const UtpTransferReqDesc *utrd)
148 {
149     uint32_t sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
150     uint64_t utrd_addr = ufs->sqlba[TEST_QID] + sqtp;
151     uint32_t cqhp;
152     uint64_t cqentry_addr;
153     UfsCqEntry cqentry;
154 
155     qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
156 
157     /* Insert a new entry into the submission queue */
158     sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
159     sqtp = (sqtp + sizeof(UfsSqEntry)) % (QUEUE_SIZE * sizeof(UfsSqEntry));
160     ufs_wreg(ufs, ufs->sqdao[TEST_QID] + 0x4, sqtp);
161     ufs_wait_for_irq(ufs);
162     g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, CQES));
163     ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, CQES, 1));
164 
165     /* Handle the completed command from the completion queue */
166     cqhp = ufs_rreg(ufs, ufs->cqdao[TEST_QID]);
167     cqentry_addr = ufs->cqlba[TEST_QID] + cqhp;
168     qtest_memread(ufs->dev.bus->qts, cqentry_addr, &cqentry, sizeof(cqentry));
169     cqhp = (cqhp + sizeof(UfsCqEntry)) % (QUEUE_SIZE * sizeof(UfsCqEntry));
170     ufs_wreg(ufs, ufs->cqdao[TEST_QID], cqhp);
171 
172     return cqentry.status;
173 }
174 
175 static enum UtpOcsCodes
ufs_send_transfer_request_sync(QUfs * ufs,uint8_t lun,const UtpTransferReqDesc * utrd)176 ufs_send_transfer_request_sync(QUfs *ufs, uint8_t lun,
177                                const UtpTransferReqDesc *utrd)
178 {
179     if (ufs->support_mcq) {
180         return __ufs_send_transfer_request_mcq(ufs, lun, utrd);
181     }
182 
183     return __ufs_send_transfer_request_doorbell(ufs, lun, utrd);
184 }
185 
ufs_send_nop_out(QUfs * ufs,UtpUpiuRsp * rsp_out)186 static enum UtpOcsCodes ufs_send_nop_out(QUfs *ufs, UtpUpiuRsp *rsp_out)
187 {
188     int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
189     uint64_t req_upiu_addr =
190         ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
191     uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
192 
193     /* Build up request upiu */
194     UtpUpiuReq req_upiu = { 0 };
195     req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_NOP_OUT;
196     req_upiu.header.task_tag = cmd_desc_slot;
197     qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
198                    sizeof(req_upiu));
199 
200     /* Build up utp transfer request descriptor */
201     UtpTransferReqDesc utrd =
202         ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
203 
204     /* Send Transfer Request */
205     enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
206 
207     qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
208     release_cmd_desc_slot(ufs, cmd_desc_slot);
209     return ret;
210 }
211 
ufs_mcq_sq_has_space(QUfs * ufs)212 static bool ufs_mcq_sq_has_space(QUfs *ufs)
213 {
214     uint32_t sqhp = ufs_rreg(ufs, ufs->sqdao[TEST_QID]);
215     uint32_t sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
216     uint32_t next_sqtp =
217         (sqtp + sizeof(UfsSqEntry)) % (QUEUE_SIZE * sizeof(UfsSqEntry));
218     return next_sqtp != sqhp;
219 }
220 
221 static void
__ufs_send_transfer_request_mcq_async(QUfs * ufs,uint8_t lun,const UtpTransferReqDesc * utrd)222 __ufs_send_transfer_request_mcq_async(QUfs *ufs, uint8_t lun,
223                                       const UtpTransferReqDesc *utrd)
224 {
225     uint32_t sqtp;
226     uint64_t utrd_addr;
227 
228     /* Wait for SQ space */
229     while (!ufs_mcq_sq_has_space(ufs)) {
230         qtest_clock_step(ufs->dev.bus->qts, 100);
231     }
232 
233     sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
234     utrd_addr = ufs->sqlba[TEST_QID] + sqtp;
235     qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
236     sqtp = (sqtp + sizeof(UfsSqEntry)) % (QUEUE_SIZE * sizeof(UfsSqEntry));
237     ufs_wreg(ufs, ufs->sqdao[TEST_QID] + 0x4, sqtp);
238 }
239 
ufs_mcq_send_nop_out_async(QUfs * ufs)240 static int ufs_mcq_send_nop_out_async(QUfs *ufs)
241 {
242     int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
243     uint64_t req_upiu_addr =
244         ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
245 
246     /* Build up request upiu */
247     UtpUpiuReq req_upiu = { 0 };
248     req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_NOP_OUT;
249     req_upiu.header.task_tag = cmd_desc_slot;
250     qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
251                    sizeof(req_upiu));
252 
253     /* Build up utp transfer request descriptor */
254     UtpTransferReqDesc utrd =
255         ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
256 
257     /* Send Transfer Request */
258     __ufs_send_transfer_request_mcq_async(ufs, 0, &utrd);
259 
260     return cmd_desc_slot;
261 }
262 
ufs_mcq_poll_cq(QUfs * ufs,UfsCqEntry * cqe,uint16_t n_cqe)263 static int ufs_mcq_poll_cq(QUfs *ufs, UfsCqEntry *cqe, uint16_t n_cqe)
264 {
265     uint32_t cqhp, cqtp;
266     uint64_t cqe_addr;
267     int ix = 0;
268 
269     cqhp = ufs_rreg(ufs, ufs->cqdao[TEST_QID]);
270     cqtp = ufs_rreg(ufs, ufs->cqdao[TEST_QID] + 0x4);
271 
272     while (cqhp != cqtp && ix < n_cqe) {
273         /* read completion entry */
274         cqe_addr = ufs->cqlba[TEST_QID] + cqhp;
275         qtest_memread(ufs->dev.bus->qts, cqe_addr, &cqe[ix], sizeof(cqe[ix]));
276 
277         /* advance completion queue head pointer */
278         cqhp = (cqhp + sizeof(UfsCqEntry)) % (QUEUE_SIZE * sizeof(UfsCqEntry));
279         ix++;
280     }
281 
282     ufs_wreg(ufs, ufs->cqdao[TEST_QID], cqhp);
283 
284     return ix;
285 }
286 
ufs_send_query(QUfs * ufs,uint8_t query_function,uint8_t query_opcode,uint8_t idn,uint8_t index,uint8_t selector,uint32_t attr_value,UtpUpiuRsp * rsp_out)287 static enum UtpOcsCodes ufs_send_query(QUfs *ufs, uint8_t query_function,
288                                        uint8_t query_opcode, uint8_t idn,
289                                        uint8_t index, uint8_t selector,
290                                        uint32_t attr_value, UtpUpiuRsp *rsp_out)
291 {
292     int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
293     uint64_t req_upiu_addr =
294         ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
295     uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
296 
297     /* Build up request upiu */
298     UtpUpiuReq req_upiu = { 0 };
299     req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_QUERY_REQ;
300     req_upiu.header.query_func = query_function;
301     req_upiu.header.task_tag = cmd_desc_slot;
302     /*
303      * QEMU UFS does not currently support Write descriptor,
304      * so the value of data_segment_length is always 0.
305      */
306     req_upiu.header.data_segment_length = 0;
307     req_upiu.qr.opcode = query_opcode;
308     req_upiu.qr.idn = idn;
309     req_upiu.qr.index = index;
310     req_upiu.qr.selector = selector;
311     req_upiu.qr.value = cpu_to_be32(attr_value);
312     req_upiu.qr.length = UFS_QUERY_DESC_MAX_SIZE;
313     qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
314                    sizeof(req_upiu));
315 
316     /* Build up utp transfer request descriptor */
317     UtpTransferReqDesc utrd =
318         ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
319 
320     /* Send Transfer Request */
321     enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
322 
323     qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
324     release_cmd_desc_slot(ufs, cmd_desc_slot);
325     return ret;
326 }
327 
328 static enum UtpOcsCodes
ufs_send_scsi_command(QUfs * ufs,uint8_t lun,const uint8_t * cdb,const uint8_t * data_in,size_t data_in_len,uint8_t * data_out,size_t data_out_len,UtpUpiuRsp * rsp_out)329 ufs_send_scsi_command(QUfs *ufs, uint8_t lun, const uint8_t *cdb,
330                       const uint8_t *data_in, size_t data_in_len,
331                       uint8_t *data_out, size_t data_out_len,
332                       UtpUpiuRsp *rsp_out)
333 
334 {
335     /* Build up PRDT */
336     UfshcdSgEntry entries[MAX_PRD_ENTRY_COUNT] = {
337         0,
338     };
339     uint8_t flags;
340     uint16_t prd_table_length, i;
341     uint32_t data_direction, data_len;
342     int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
343     uint64_t req_upiu_addr =
344         ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
345     uint64_t prdt_addr = req_upiu_addr + UTP_PRDT_UPIU_OFFSET;
346 
347     g_assert_true(data_in_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
348     g_assert_true(data_out_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
349     if (data_in_len > 0) {
350         g_assert_nonnull(data_in);
351         data_direction = UFS_UTP_HOST_TO_DEVICE;
352         data_len = data_in_len;
353         flags = UFS_UPIU_CMD_FLAGS_WRITE;
354     } else if (data_out_len > 0) {
355         g_assert_nonnull(data_out);
356         data_direction = UFS_UTP_DEVICE_TO_HOST;
357         data_len = data_out_len;
358         flags = UFS_UPIU_CMD_FLAGS_READ;
359     } else {
360         data_direction = UFS_UTP_NO_DATA_TRANSFER;
361         data_len = 0;
362         flags = UFS_UPIU_CMD_FLAGS_NONE;
363     }
364     prd_table_length = DIV_ROUND_UP(data_len, PRD_ENTRY_DATA_SIZE);
365 
366     qtest_memset(ufs->dev.bus->qts, ufs->data_buffer_addr, 0,
367                  MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
368     if (data_in_len) {
369         qtest_memwrite(ufs->dev.bus->qts, ufs->data_buffer_addr, data_in,
370                        data_in_len);
371     }
372 
373     for (i = 0; i < prd_table_length; i++) {
374         entries[i].addr =
375             cpu_to_le64(ufs->data_buffer_addr + i * sizeof(UfshcdSgEntry));
376         if (i + 1 != prd_table_length) {
377             entries[i].size = cpu_to_le32(PRD_ENTRY_DATA_SIZE - 1);
378         } else {
379             entries[i].size = cpu_to_le32(
380                 data_len - (PRD_ENTRY_DATA_SIZE * (prd_table_length - 1)) - 1);
381         }
382     }
383     qtest_memwrite(ufs->dev.bus->qts, prdt_addr, entries,
384                    prd_table_length * sizeof(UfshcdSgEntry));
385 
386     uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
387 
388     /* Build up request upiu */
389     UtpUpiuReq req_upiu = { 0 };
390     req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_COMMAND;
391     req_upiu.header.flags = flags;
392     req_upiu.header.lun = lun;
393     req_upiu.header.task_tag = cmd_desc_slot;
394     req_upiu.sc.exp_data_transfer_len = cpu_to_be32(data_len);
395     memcpy(req_upiu.sc.cdb, cdb, UFS_CDB_SIZE);
396     qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
397                    sizeof(req_upiu));
398 
399     /* Build up utp transfer request descriptor */
400     UtpTransferReqDesc utrd =
401         ufs_build_req_utrd(req_upiu_addr, data_direction, prd_table_length);
402 
403     /* Send Transfer Request */
404     enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, lun, &utrd);
405 
406     qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
407     if (data_out_len) {
408         qtest_memread(ufs->dev.bus->qts, ufs->data_buffer_addr, data_out,
409                       data_out_len);
410     }
411     release_cmd_desc_slot(ufs, cmd_desc_slot);
412     return ret;
413 }
414 
415 /**
416  * Initialize Ufs host controller and logical unit.
417  * After running this function, you can make a transfer request to the UFS.
418  */
ufs_init(QUfs * ufs,QGuestAllocator * alloc)419 static void ufs_init(QUfs *ufs, QGuestAllocator *alloc)
420 {
421     uint64_t end_time;
422     uint32_t nutrs;
423     uint32_t hcs, is, ucmdarg2, cap;
424     uint32_t hce = 0, ie = 0;
425     enum UtpOcsCodes ocs;
426     UtpUpiuRsp rsp_upiu;
427 
428     ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
429     qpci_device_enable(&ufs->dev);
430 
431     /* Start host controller initialization */
432     hce = FIELD_DP32(hce, HCE, HCE, 1);
433     ufs_wreg(ufs, A_HCE, hce);
434 
435     /* Wait for device to reset */
436     end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
437     do {
438         qtest_clock_step(ufs->dev.bus->qts, 100);
439         hce = FIELD_EX32(ufs_rreg(ufs, A_HCE), HCE, HCE);
440     } while (hce == 0 && g_get_monotonic_time() < end_time);
441     g_assert_cmpuint(hce, ==, 1);
442 
443     /* Enable interrupt */
444     ie = FIELD_DP32(ie, IE, UCCE, 1);
445     ie = FIELD_DP32(ie, IE, UHESE, 1);
446     ie = FIELD_DP32(ie, IE, UHXSE, 1);
447     ie = FIELD_DP32(ie, IE, UPMSE, 1);
448     ufs_wreg(ufs, A_IE, ie);
449 
450     /* Send DME_LINK_STARTUP uic command */
451     hcs = ufs_rreg(ufs, A_HCS);
452     g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
453 
454     ufs_wreg(ufs, A_UCMDARG1, 0);
455     ufs_wreg(ufs, A_UCMDARG2, 0);
456     ufs_wreg(ufs, A_UCMDARG3, 0);
457     ufs_wreg(ufs, A_UICCMD, UFS_UIC_CMD_DME_LINK_STARTUP);
458 
459     is = ufs_rreg(ufs, A_IS);
460     g_assert_true(FIELD_EX32(is, IS, UCCS));
461     ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UCCS, 1));
462 
463     ucmdarg2 = ufs_rreg(ufs, A_UCMDARG2);
464     g_assert_cmpuint(ucmdarg2, ==, 0);
465     is = ufs_rreg(ufs, A_IS);
466     g_assert_cmpuint(is, ==, 0);
467     hcs = ufs_rreg(ufs, A_HCS);
468     g_assert_true(FIELD_EX32(hcs, HCS, DP));
469     g_assert_true(FIELD_EX32(hcs, HCS, UTRLRDY));
470     g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
471 
472     /* Check MCQ support */
473     cap = ufs_rreg(ufs, A_CAP);
474     ufs->support_mcq = FIELD_EX32(cap, CAP, MCQS);
475 
476     /* Enable all interrupt functions */
477     ie = FIELD_DP32(ie, IE, UTRCE, 1);
478     ie = FIELD_DP32(ie, IE, UEE, 1);
479     ie = FIELD_DP32(ie, IE, UPMSE, 1);
480     ie = FIELD_DP32(ie, IE, UHXSE, 1);
481     ie = FIELD_DP32(ie, IE, UHESE, 1);
482     ie = FIELD_DP32(ie, IE, UTMRCE, 1);
483     ie = FIELD_DP32(ie, IE, UCCE, 1);
484     ie = FIELD_DP32(ie, IE, DFEE, 1);
485     ie = FIELD_DP32(ie, IE, HCFEE, 1);
486     ie = FIELD_DP32(ie, IE, SBFEE, 1);
487     ie = FIELD_DP32(ie, IE, CEFEE, 1);
488     if (ufs->support_mcq) {
489         ie = FIELD_DP32(ie, IE, CQEE, 1);
490     }
491     ufs_wreg(ufs, A_IE, ie);
492     ufs_wreg(ufs, A_UTRIACR, 0);
493 
494     /* Enable transfer request */
495     bitmap_zero(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC);
496     ufs->cmd_desc_addr =
497         guest_alloc(alloc, UFS_MAX_CMD_DESC * UTP_COMMAND_DESCRIPTOR_SIZE);
498     ufs->data_buffer_addr =
499         guest_alloc(alloc, MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
500 
501     if (ufs->support_mcq) {
502         uint32_t mcqcap, qid, qcfgptr, mcq_reg_offset;
503         uint32_t cqattr = 0, sqattr = 0;
504 
505         mcqcap = ufs_rreg(ufs, A_MCQCAP);
506         qcfgptr = FIELD_EX32(mcqcap, MCQCAP, QCFGPTR);
507         ufs->maxq = FIELD_EX32(mcqcap, MCQCAP, MAXQ) + 1;
508         for (qid = 0; qid < ufs->maxq; ++qid) {
509             ufs->sqlba[qid] =
510                 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
511             ufs->cqlba[qid] =
512                 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
513             mcq_reg_offset = qcfgptr * 0x200 + qid * 0x40;
514 
515             ufs_wreg(ufs, mcq_reg_offset + A_SQLBA,
516                      ufs->sqlba[qid] & 0xffffffff);
517             ufs_wreg(ufs, mcq_reg_offset + A_SQUBA, ufs->sqlba[qid] >> 32);
518             ufs_wreg(ufs, mcq_reg_offset + A_CQLBA,
519                      ufs->cqlba[qid] & 0xffffffff);
520             ufs_wreg(ufs, mcq_reg_offset + A_CQUBA, ufs->cqlba[qid] >> 32);
521 
522             /* Enable Completion Queue */
523             cqattr = FIELD_DP32(cqattr, CQATTR, CQEN, 1);
524             cqattr = FIELD_DP32(cqattr, CQATTR, SIZE,
525                                 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
526                                     DWORD_BYTE);
527             ufs_wreg(ufs, mcq_reg_offset + A_CQATTR, cqattr);
528 
529             /* Enable Submission Queue */
530             sqattr = FIELD_DP32(sqattr, SQATTR, SQEN, 1);
531             sqattr = FIELD_DP32(sqattr, SQATTR, SIZE,
532                                 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
533                                     DWORD_BYTE);
534             sqattr = FIELD_DP32(sqattr, SQATTR, CQID, qid);
535             ufs_wreg(ufs, mcq_reg_offset + A_SQATTR, sqattr);
536 
537             /* Cache head & tail pointer */
538             ufs->sqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_SQDAO);
539             ufs->cqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_CQDAO);
540         }
541     } else {
542         nutrs = FIELD_EX32(cap, CAP, NUTRS) + 1;
543         ufs->utrlba = guest_alloc(alloc, nutrs * sizeof(UtpTransferReqDesc));
544 
545         ufs_wreg(ufs, A_UTRLBA, ufs->utrlba & 0xffffffff);
546         ufs_wreg(ufs, A_UTRLBAU, ufs->utrlba >> 32);
547         ufs_wreg(ufs, A_UTRLRSR, 1);
548     }
549 
550     /* Send nop out to test transfer request */
551     ocs = ufs_send_nop_out(ufs, &rsp_upiu);
552     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
553 
554     /* Set fDeviceInit flag via query request */
555     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
556                          UFS_UPIU_QUERY_OPCODE_SET_FLAG,
557                          UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
558     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
559     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
560 
561     /* Wait for device to reset */
562     end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
563     do {
564         qtest_clock_step(ufs->dev.bus->qts, 100);
565         ocs =
566             ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
567                            UFS_UPIU_QUERY_OPCODE_READ_FLAG,
568                            UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
569         g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
570         g_assert_cmpuint(rsp_upiu.header.response, ==,
571                          UFS_COMMAND_RESULT_SUCCESS);
572     } while (be32_to_cpu(rsp_upiu.qr.value) != 0 &&
573              g_get_monotonic_time() < end_time);
574     g_assert_cmpuint(be32_to_cpu(rsp_upiu.qr.value), ==, 0);
575 
576     ufs->enabled = true;
577 }
578 
ufs_exit(QUfs * ufs,QGuestAllocator * alloc)579 static void ufs_exit(QUfs *ufs, QGuestAllocator *alloc)
580 {
581     if (ufs->enabled) {
582         if (ufs->support_mcq) {
583             for (uint32_t qid = 0; qid < ufs->maxq; ++qid) {
584                 guest_free(alloc, ufs->sqlba[qid]);
585                 guest_free(alloc, ufs->cqlba[qid]);
586             }
587         } else {
588             guest_free(alloc, ufs->utrlba);
589         }
590 
591         guest_free(alloc, ufs->cmd_desc_addr);
592         guest_free(alloc, ufs->data_buffer_addr);
593     }
594 
595     qpci_iounmap(&ufs->dev, ufs->bar);
596 }
597 
ufs_get_driver(void * obj,const char * interface)598 static void *ufs_get_driver(void *obj, const char *interface)
599 {
600     QUfs *ufs = obj;
601 
602     if (!g_strcmp0(interface, "pci-device")) {
603         return &ufs->dev;
604     }
605 
606     fprintf(stderr, "%s not present in ufs\n", interface);
607     g_assert_not_reached();
608 }
609 
ufs_create(void * pci_bus,QGuestAllocator * alloc,void * addr)610 static void *ufs_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
611 {
612     QUfs *ufs = g_new0(QUfs, 1);
613     QPCIBus *bus = pci_bus;
614 
615     qpci_device_init(&ufs->dev, bus, addr);
616     ufs->obj.get_driver = ufs_get_driver;
617 
618     return &ufs->obj;
619 }
620 
ufstest_reg_read(void * obj,void * data,QGuestAllocator * alloc)621 static void ufstest_reg_read(void *obj, void *data, QGuestAllocator *alloc)
622 {
623     QUfs *ufs = obj;
624     uint32_t cap;
625 
626     ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
627     qpci_device_enable(&ufs->dev);
628 
629     cap = ufs_rreg(ufs, A_CAP);
630     g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTRS), ==, 31);
631     g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTMRS), ==, 7);
632     g_assert_cmpuint(FIELD_EX32(cap, CAP, 64AS), ==, 1);
633 
634     qpci_iounmap(&ufs->dev, ufs->bar);
635 }
636 
ufstest_init(void * obj,void * data,QGuestAllocator * alloc)637 static void ufstest_init(void *obj, void *data, QGuestAllocator *alloc)
638 {
639     QUfs *ufs = obj;
640 
641     uint8_t buf[4096] = { 0 };
642     const uint8_t report_luns_cdb[UFS_CDB_SIZE] = {
643         /* allocation length 4096 */
644         REPORT_LUNS, 0x00, 0x00, 0x00, 0x00, 0x00,
645         0x00,        0x00, 0x10, 0x00, 0x00, 0x00
646     };
647     const uint8_t test_unit_ready_cdb[UFS_CDB_SIZE] = {
648         TEST_UNIT_READY,
649     };
650     const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
651         REQUEST_SENSE,
652     };
653     enum UtpOcsCodes ocs;
654     UtpUpiuRsp rsp_upiu;
655 
656     ufs_init(ufs, alloc);
657 
658     /* Check REPORT_LUNS */
659     ocs = ufs_send_scsi_command(ufs, 0, report_luns_cdb, NULL, 0, buf,
660                                 sizeof(buf), &rsp_upiu);
661     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
662     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
663     /* LUN LIST LENGTH should be 8, in big endian */
664     g_assert_cmpuint(buf[3], ==, 8);
665     /* There is one logical unit whose lun is 0 */
666     g_assert_cmpuint(buf[9], ==, 0);
667 
668     /* Clear Unit Attention */
669     ocs = ufs_send_scsi_command(ufs, 0, request_sense_cdb, NULL, 0, buf,
670                                 sizeof(buf), &rsp_upiu);
671     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
672     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
673 
674     /* Check TEST_UNIT_READY */
675     ocs = ufs_send_scsi_command(ufs, 0, test_unit_ready_cdb, NULL, 0, NULL, 0,
676                                 &rsp_upiu);
677     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
678     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
679 
680     ufs_exit(ufs, alloc);
681 }
682 
ufstest_read_write(void * obj,void * data,QGuestAllocator * alloc)683 static void ufstest_read_write(void *obj, void *data, QGuestAllocator *alloc)
684 {
685     QUfs *ufs = obj;
686     uint8_t read_buf[4096] = { 0 };
687     uint8_t write_buf[4096] = { 0 };
688     const uint8_t read_capacity_cdb[UFS_CDB_SIZE] = {
689         /* allocation length 4096 */
690         SERVICE_ACTION_IN_16,
691         SAI_READ_CAPACITY_16,
692         0x00,
693         0x00,
694         0x00,
695         0x00,
696         0x00,
697         0x00,
698         0x00,
699         0x00,
700         0x00,
701         0x00,
702         0x10,
703         0x00,
704         0x00,
705         0x00
706     };
707     const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
708         REQUEST_SENSE,
709     };
710     const uint8_t read_cdb[UFS_CDB_SIZE] = {
711         /* READ(10) to LBA 0, transfer length 1 */
712         READ_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
713     };
714     const uint8_t write_cdb[UFS_CDB_SIZE] = {
715         /* WRITE(10) to LBA 0, transfer length 1 */
716         WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
717     };
718     uint32_t block_size;
719     enum UtpOcsCodes ocs;
720     UtpUpiuRsp rsp_upiu;
721     const int test_lun = 1;
722 
723     ufs_init(ufs, alloc);
724 
725     /* Clear Unit Attention */
726     ocs = ufs_send_scsi_command(ufs, test_lun, request_sense_cdb, NULL, 0,
727                                 read_buf, sizeof(read_buf), &rsp_upiu);
728     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
729     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
730 
731     /* Read capacity */
732     ocs = ufs_send_scsi_command(ufs, test_lun, read_capacity_cdb, NULL, 0,
733                                 read_buf, sizeof(read_buf), &rsp_upiu);
734     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
735     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
736                      UFS_COMMAND_RESULT_SUCCESS);
737     block_size = ldl_be_p(&read_buf[8]);
738     g_assert_cmpuint(block_size, ==, 4096);
739 
740     /* Write data */
741     memset(write_buf, 0xab, block_size);
742     ocs = ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf, block_size,
743                                 NULL, 0, &rsp_upiu);
744     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
745     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
746                      UFS_COMMAND_RESULT_SUCCESS);
747 
748     /* Read data and verify */
749     ocs = ufs_send_scsi_command(ufs, test_lun, read_cdb, NULL, 0, read_buf,
750                                 block_size, &rsp_upiu);
751     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
752     g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
753                      UFS_COMMAND_RESULT_SUCCESS);
754     g_assert_cmpint(memcmp(read_buf, write_buf, block_size), ==, 0);
755 
756     ufs_exit(ufs, alloc);
757 }
758 
ufstest_mcq_cq_wraparound(void * obj,void * data,QGuestAllocator * alloc)759 static void ufstest_mcq_cq_wraparound(void *obj, void *data,
760                                       QGuestAllocator *alloc)
761 {
762     QUfs *ufs = obj;
763     UfsCqEntry cqe[QUEUE_SIZE];
764     const int num_requests = QUEUE_SIZE;
765     int i, completed = 0;
766 
767     ufs_init(ufs, alloc);
768 
769     /* Ensure MCQ is supported */
770     g_assert_true(ufs->support_mcq);
771 
772     for (i = 0; i < num_requests; ++i) {
773         ufs_mcq_send_nop_out_async(ufs);
774     }
775 
776     while (completed != num_requests) {
777         int n_cqe = ufs_mcq_poll_cq(ufs, cqe, ARRAY_SIZE(cqe));
778         if (!n_cqe) {
779             break;
780         }
781 
782         for (i = 0; i < n_cqe; ++i) {
783             uint64_t ucdba;
784             uint64_t rsp_upiu_addr;
785             UtpUpiuRsp rsp_upiu;
786             uint8_t tag;
787 
788             g_assert_cmpuint(cqe[i].status, ==, UFS_OCS_SUCCESS);
789 
790             ucdba = le64_to_cpu(cqe[i].utp_addr) & MAKE_64BIT_MASK(7, 57);
791             rsp_upiu_addr = ucdba + UTP_RESPONSE_UPIU_OFFSET;
792             qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, &rsp_upiu,
793                           sizeof(rsp_upiu));
794 
795             tag = rsp_upiu.header.task_tag;
796             release_cmd_desc_slot(ufs, tag);
797         }
798 
799         completed += n_cqe;
800     }
801 
802     g_assert_cmpint(completed, ==, num_requests);
803     ufs_exit(ufs, alloc);
804 }
805 
ufstest_query_flag_request(void * obj,void * data,QGuestAllocator * alloc)806 static void ufstest_query_flag_request(void *obj, void *data,
807                                        QGuestAllocator *alloc)
808 {
809     QUfs *ufs = obj;
810 
811     enum UtpOcsCodes ocs;
812     UtpUpiuRsp rsp_upiu;
813     ufs_init(ufs, alloc);
814 
815     /* Read read-only flag */
816     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
817                          UFS_UPIU_QUERY_OPCODE_READ_FLAG,
818                          UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
819     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
820     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
821     g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_FLAG);
822     g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_FLAG_IDN_FDEVICEINIT);
823     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
824 
825     /* Flag Set, Clear, Toggle Test with fDeviceLifeSpanModeEn */
826     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
827                          UFS_UPIU_QUERY_OPCODE_READ_FLAG,
828                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
829                          &rsp_upiu);
830     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
831     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
832     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
833 
834     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
835                          UFS_UPIU_QUERY_OPCODE_SET_FLAG,
836                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
837                          &rsp_upiu);
838     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
839     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
840     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
841 
842     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
843                          UFS_UPIU_QUERY_OPCODE_CLEAR_FLAG,
844                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
845                          &rsp_upiu);
846     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
847     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
848     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
849 
850     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
851                          UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
852                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
853                          &rsp_upiu);
854     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
855     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
856     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
857 
858     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
859                          UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
860                          UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
861                          &rsp_upiu);
862     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
863     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
864     g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
865 
866     /* Read Write-only Flag (Intended Failure) */
867     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
868                          UFS_UPIU_QUERY_OPCODE_READ_FLAG,
869                          UFS_QUERY_FLAG_IDN_PURGE_ENABLE, 0, 0, 0, &rsp_upiu);
870     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
871     g_assert_cmpuint(rsp_upiu.header.response, ==,
872                      UFS_QUERY_RESULT_NOT_READABLE);
873 
874     /* Write Read-Only Flag (Intended Failure) */
875     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
876                          UFS_UPIU_QUERY_OPCODE_SET_FLAG,
877                          UFS_QUERY_FLAG_IDN_BUSY_RTC, 0, 0, 0, &rsp_upiu);
878     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
879     g_assert_cmpuint(rsp_upiu.header.response, ==,
880                      UFS_QUERY_RESULT_NOT_WRITEABLE);
881 
882     ufs_exit(ufs, alloc);
883 }
884 
ufstest_query_attr_request(void * obj,void * data,QGuestAllocator * alloc)885 static void ufstest_query_attr_request(void *obj, void *data,
886                                        QGuestAllocator *alloc)
887 {
888     QUfs *ufs = obj;
889 
890     enum UtpOcsCodes ocs;
891     UtpUpiuRsp rsp_upiu;
892     ufs_init(ufs, alloc);
893 
894     /* Read Readable Attributes*/
895     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
896                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
897                          UFS_QUERY_ATTR_IDN_BOOT_LU_EN, 0, 0, 0, &rsp_upiu);
898     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
899     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
900     g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_ATTR);
901     g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_ATTR_IDN_BOOT_LU_EN);
902     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
903 
904     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
905                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
906                          UFS_QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, 0, &rsp_upiu);
907     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
908     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
909     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
910 
911     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
912                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
913                          UFS_QUERY_ATTR_IDN_CASE_ROUGH_TEMP, 0, 0, 0,
914                          &rsp_upiu);
915     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
916     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
917     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
918 
919     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
920                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
921                          UFS_QUERY_ATTR_IDN_HIGH_TEMP_BOUND, 0, 0, 0,
922                          &rsp_upiu);
923     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
924     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
925     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(160));
926 
927     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
928                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
929                          UFS_QUERY_ATTR_IDN_LOW_TEMP_BOUND, 0, 0, 0,
930                          &rsp_upiu);
931     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
932     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
933     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(60));
934 
935     /* Write Writable Attributes & Read Again */
936     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
937                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
938                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x03,
939                          &rsp_upiu);
940     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
941     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
942     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
943 
944     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
945                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
946                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0x07, &rsp_upiu);
947     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
948     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
949     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07));
950 
951     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
952                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
953                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
954     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
955     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
956     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
957 
958     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
959                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
960                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
961     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
962     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
963     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07));
964 
965     /* Write Invalid Value (Intended Error) */
966     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
967                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
968                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x10,
969                          &rsp_upiu);
970     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
971     g_assert_cmpuint(rsp_upiu.header.response, ==,
972                      UFS_QUERY_RESULT_INVALID_VALUE);
973 
974     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
975                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
976                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
977     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
978     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
979     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
980 
981     /* Read Write-Only Attribute (Intended Error) */
982     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
983                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
984                          UFS_QUERY_ATTR_IDN_SECONDS_PASSED, 0, 0, 0, &rsp_upiu);
985     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
986     g_assert_cmpuint(rsp_upiu.header.response, ==,
987                      UFS_QUERY_RESULT_NOT_READABLE);
988 
989     /* Write Read-Only Attribute (Intended Error) */
990     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
991                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
992                          UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0x01, &rsp_upiu);
993     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
994     g_assert_cmpuint(rsp_upiu.header.response, ==,
995                      UFS_QUERY_RESULT_NOT_WRITEABLE);
996 
997     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
998                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
999                          UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0, &rsp_upiu);
1000     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1001     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1002     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1003 
1004     /* Reset Written Attributes */
1005     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1006                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
1007                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
1008     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1009     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1010     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1011 
1012     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1013                          UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
1014                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
1015     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1016     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1017     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1018 
1019     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1020                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
1021                          UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
1022     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1023     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1024     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1025 
1026     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1027                          UFS_UPIU_QUERY_OPCODE_READ_ATTR,
1028                          UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
1029     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1030     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1031     g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1032 
1033     ufs_exit(ufs, alloc);
1034 }
1035 
ufstest_query_desc_request(void * obj,void * data,QGuestAllocator * alloc)1036 static void ufstest_query_desc_request(void *obj, void *data,
1037                                        QGuestAllocator *alloc)
1038 {
1039     QUfs *ufs = obj;
1040 
1041     enum UtpOcsCodes ocs;
1042     UtpUpiuRsp rsp_upiu;
1043     ufs_init(ufs, alloc);
1044 
1045     /* Write Descriptor is not supported yet */
1046 
1047     /* Read Device Descriptor */
1048     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1049                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1050                          UFS_QUERY_DESC_IDN_DEVICE, 0, 0, 0, &rsp_upiu);
1051     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1052     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1053     g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_DESC);
1054     g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_DESC_IDN_DEVICE);
1055     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceDescriptor));
1056     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_DEVICE);
1057 
1058     /* Read Configuration Descriptor is not supported yet*/
1059 
1060     /* Read Unit Descriptor */
1061     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1062                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1063                          UFS_QUERY_DESC_IDN_UNIT, 0, 0, 0, &rsp_upiu);
1064     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1065     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1066     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor));
1067     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
1068     g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 0);
1069 
1070     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1071                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1072                          UFS_QUERY_DESC_IDN_UNIT, 1, 0, 0, &rsp_upiu);
1073     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1074     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1075     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor));
1076     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
1077     g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 1);
1078 
1079     ocs =
1080         ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1081                        UFS_UPIU_QUERY_OPCODE_READ_DESC, UFS_QUERY_DESC_IDN_UNIT,
1082                        UFS_UPIU_RPMB_WLUN, 0, 0, &rsp_upiu);
1083     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1084     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1085     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(RpmbUnitDescriptor));
1086     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
1087     g_assert_cmpuint(rsp_upiu.qr.data[2], ==, UFS_UPIU_RPMB_WLUN);
1088 
1089     /* Read Interconnect Descriptor */
1090     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1091                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1092                          UFS_QUERY_DESC_IDN_INTERCONNECT, 0, 0, 0, &rsp_upiu);
1093     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1094     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1095     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(InterconnectDescriptor));
1096     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_INTERCONNECT);
1097 
1098     /* Read String Descriptor */
1099     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1100                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1101                          UFS_QUERY_DESC_IDN_STRING, 0, 0, 0, &rsp_upiu);
1102     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1103     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1104     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x12);
1105     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
1106 
1107     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1108                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1109                          UFS_QUERY_DESC_IDN_STRING, 1, 0, 0, &rsp_upiu);
1110     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1111     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1112     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x22);
1113     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
1114 
1115     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1116                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1117                          UFS_QUERY_DESC_IDN_STRING, 4, 0, 0, &rsp_upiu);
1118     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1119     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1120     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x0a);
1121     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
1122 
1123     /* Read Geometry Descriptor */
1124     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1125                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1126                          UFS_QUERY_DESC_IDN_GEOMETRY, 0, 0, 0, &rsp_upiu);
1127     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1128     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1129     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(GeometryDescriptor));
1130     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_GEOMETRY);
1131 
1132     /* Read Power Descriptor */
1133     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1134                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1135                          UFS_QUERY_DESC_IDN_POWER, 0, 0, 0, &rsp_upiu);
1136     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1137     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1138     g_assert_cmpuint(rsp_upiu.qr.data[0], ==,
1139                      sizeof(PowerParametersDescriptor));
1140     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_POWER);
1141 
1142     /* Read Health Descriptor */
1143     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1144                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1145                          UFS_QUERY_DESC_IDN_HEALTH, 0, 0, 0, &rsp_upiu);
1146     g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1147     g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1148     g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceHealthDescriptor));
1149     g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_HEALTH);
1150 
1151     /* Invalid Index (Intended Failure) */
1152     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1153                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1154                          UFS_QUERY_DESC_IDN_UNIT, 4, 0, 0, &rsp_upiu);
1155     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1156     g_assert_cmpuint(rsp_upiu.header.response, ==,
1157                      UFS_QUERY_RESULT_INVALID_INDEX);
1158 
1159     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1160                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1161                          UFS_QUERY_DESC_IDN_STRING, 5, 0, 0, &rsp_upiu);
1162     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1163     g_assert_cmpuint(rsp_upiu.header.response, ==,
1164                      UFS_QUERY_RESULT_INVALID_INDEX);
1165 
1166     /* Invalid Selector (Intended Failure) */
1167     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1168                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1169                          UFS_QUERY_DESC_IDN_DEVICE, 0, 1, 0, &rsp_upiu);
1170     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1171     g_assert_cmpuint(rsp_upiu.header.response, ==,
1172                      UFS_QUERY_RESULT_INVALID_SELECTOR);
1173 
1174     ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1175                          UFS_UPIU_QUERY_OPCODE_READ_DESC,
1176                          UFS_QUERY_DESC_IDN_STRING, 0, 1, 0, &rsp_upiu);
1177     g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1178     g_assert_cmpuint(rsp_upiu.header.response, ==,
1179                      UFS_QUERY_RESULT_INVALID_SELECTOR);
1180 
1181     ufs_exit(ufs, alloc);
1182 }
1183 
drive_destroy(void * path)1184 static void drive_destroy(void *path)
1185 {
1186     unlink(path);
1187     g_free(path);
1188     qos_invalidate_command_line();
1189 }
1190 
drive_create(void)1191 static char *drive_create(void)
1192 {
1193     int fd, ret;
1194     char *t_path;
1195 
1196     /* Create a temporary raw image */
1197     fd = g_file_open_tmp("qtest-ufs.XXXXXX", &t_path, NULL);
1198     g_assert_cmpint(fd, >=, 0);
1199     ret = ftruncate(fd, TEST_IMAGE_SIZE);
1200     g_assert_cmpint(ret, ==, 0);
1201     close(fd);
1202 
1203     g_test_queue_destroy(drive_destroy, t_path);
1204     return t_path;
1205 }
1206 
ufs_blk_test_setup(GString * cmd_line,void * arg)1207 static void *ufs_blk_test_setup(GString *cmd_line, void *arg)
1208 {
1209     char *tmp_path = drive_create();
1210 
1211     g_string_append_printf(cmd_line,
1212                            " -blockdev file,filename=%s,node-name=drv1 "
1213                            "-device ufs-lu,bus=ufs0,drive=drv1,lun=1 ",
1214                            tmp_path);
1215 
1216     return arg;
1217 }
1218 
ufs_register_nodes(void)1219 static void ufs_register_nodes(void)
1220 {
1221     const char *arch;
1222     QOSGraphEdgeOptions edge_opts = {
1223         .before_cmd_line = "-blockdev null-co,node-name=drv0,read-zeroes=on",
1224         .after_cmd_line = "-device ufs-lu,bus=ufs0,drive=drv0,lun=0",
1225         .extra_device_opts = "addr=04.0,id=ufs0"
1226     };
1227 
1228     QOSGraphTestOptions io_test_opts = { .before = ufs_blk_test_setup,
1229                                          .edge.extra_device_opts =
1230                                              "mcq=false,nutrs=32,nutmrs=8" };
1231 
1232     QOSGraphTestOptions mcq_test_opts = { .before = ufs_blk_test_setup,
1233                                           .edge.extra_device_opts =
1234                                               "mcq=true,mcq-maxq=1" };
1235 
1236     add_qpci_address(&edge_opts, &(QPCIAddress){ .devfn = QPCI_DEVFN(4, 0) });
1237 
1238     qos_node_create_driver("ufs", ufs_create);
1239     qos_node_consumes("ufs", "pci-bus", &edge_opts);
1240     qos_node_produces("ufs", "pci-device");
1241 
1242     qos_add_test("reg-read", "ufs", ufstest_reg_read, NULL);
1243 
1244     /*
1245      * Check architecture
1246      * TODO: Enable ufs io tests for ppc64
1247      */
1248     arch = qtest_get_arch();
1249     if (!strcmp(arch, "ppc64")) {
1250         g_test_message("Skipping ufs io tests for ppc64");
1251         return;
1252     }
1253     qos_add_test("init", "ufs", ufstest_init, NULL);
1254     qos_add_test("legacy-read-write", "ufs", ufstest_read_write, &io_test_opts);
1255     qos_add_test("mcq-read-write", "ufs", ufstest_read_write, &mcq_test_opts);
1256     qos_add_test("mcq-cq-wraparound", "ufs", ufstest_mcq_cq_wraparound,
1257                  &mcq_test_opts);
1258     qos_add_test("query-flag", "ufs", ufstest_query_flag_request,
1259                  &io_test_opts);
1260     qos_add_test("query-attribute", "ufs", ufstest_query_attr_request,
1261                  &io_test_opts);
1262     qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request,
1263                  &io_test_opts);
1264 }
1265 
1266 libqos_init(ufs_register_nodes);
1267