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