master
c 1,737 lines 66 KB
Raw
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 #include "qemu/bswap.h"
18
19 #define DWORD_BYTE 4
20 /* Test images sizes in Bytes */
21 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
22 /* Timeout for various operations, in seconds. */
23 #define TIMEOUT_SECONDS 10
24 /* Maximum PRD entry count */
25 #define MAX_PRD_ENTRY_COUNT 10
26 #define PRD_ENTRY_DATA_SIZE 4096
27 /* Constants to build upiu */
28 #define UTP_COMMAND_DESCRIPTOR_SIZE 4096
29 #define UTP_RESPONSE_UPIU_OFFSET 1024
30 #define UTP_PRDT_UPIU_OFFSET 2048
31 #define UTRD_TEST_SLOT 0
32 #define UFS_MAX_CMD_DESC 32
33 /* Constants for MCQ */
34 #define TEST_QID 0
35 #define QUEUE_SIZE 32
36 #define UFS_MCQ_MAX_QNUM 32
37 #define ACPI_PCIHP_ADDR 0xae00
38 #define PCI_EJ_BASE 0x0008
39
40 typedef struct QUfs QUfs;
41
42 struct QUfs {
43 QOSGraphObject obj;
44 QPCIDevice dev;
45 QPCIBar bar;
46
47 DECLARE_BITMAP(cmd_desc_bitmap, UFS_MAX_CMD_DESC);
48 uint64_t cmd_desc_addr;
49 uint64_t data_buffer_addr;
50
51 bool enabled;
52 bool support_mcq;
53
54 /* for legacy doorbell mode */
55 uint64_t utrlba;
56
57 /* for mcq mode */
58 uint32_t maxq;
59 uint64_t sqlba[UFS_MCQ_MAX_QNUM];
60 uint64_t cqlba[UFS_MCQ_MAX_QNUM];
61 uint64_t sqdao[UFS_MCQ_MAX_QNUM];
62 uint64_t cqdao[UFS_MCQ_MAX_QNUM];
63 };
64
65 static inline uint32_t ufs_rreg(QUfs *ufs, size_t offset)
66 {
67 return qpci_io_readl(&ufs->dev, ufs->bar, offset);
68 }
69
70 static inline void ufs_wreg(QUfs *ufs, size_t offset, uint32_t value)
71 {
72 qpci_io_writel(&ufs->dev, ufs->bar, offset, value);
73 }
74
75 static int alloc_cmd_desc_slot(QUfs *ufs)
76 {
77 int slot = find_first_zero_bit(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC);
78 if (slot == UFS_MAX_CMD_DESC) {
79 g_assert_not_reached();
80 }
81 set_bit(slot, ufs->cmd_desc_bitmap);
82 return slot;
83 }
84
85 static void release_cmd_desc_slot(QUfs *ufs, int slot)
86 {
87 if (!test_bit(slot, ufs->cmd_desc_bitmap)) {
88 g_assert_not_reached();
89 }
90 clear_bit(slot, ufs->cmd_desc_bitmap);
91 }
92
93 static void ufs_wait_for_irq(QUfs *ufs)
94 {
95 uint64_t end_time;
96 uint32_t is;
97 /* Wait for device to reset as the linux driver does. */
98 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
99 do {
100 qtest_clock_step(ufs->dev.bus->qts, 100);
101 is = ufs_rreg(ufs, A_IS);
102 } while (is == 0 && g_get_monotonic_time() < end_time);
103 }
104
105 static UtpTransferReqDesc ufs_build_req_utrd(uint64_t command_desc_base_addr,
106 uint32_t data_direction,
107 uint16_t prd_table_length)
108 {
109 UtpTransferReqDesc req = { 0 };
110
111 req.header.dword_0 =
112 cpu_to_le32(1 << 28 | data_direction | UFS_UTP_REQ_DESC_INT_CMD);
113 req.header.dword_2 = cpu_to_le32(UFS_OCS_INVALID_COMMAND_STATUS);
114
115 req.command_desc_base_addr_hi = cpu_to_le32(command_desc_base_addr >> 32);
116 req.command_desc_base_addr_lo =
117 cpu_to_le32(command_desc_base_addr & 0xffffffff);
118 req.response_upiu_offset =
119 cpu_to_le16(UTP_RESPONSE_UPIU_OFFSET / sizeof(uint32_t));
120 req.response_upiu_length = cpu_to_le16(sizeof(UtpUpiuRsp));
121 req.prd_table_offset = cpu_to_le16(UTP_PRDT_UPIU_OFFSET / sizeof(uint32_t));
122 req.prd_table_length = cpu_to_le16(prd_table_length);
123 return req;
124 }
125
126 static enum UtpOcsCodes
127 __ufs_send_transfer_request_doorbell(QUfs *ufs, uint8_t lun,
128 const UtpTransferReqDesc *utrd)
129 {
130 uint64_t utrd_addr =
131 ufs->utrlba + UTRD_TEST_SLOT * sizeof(UtpTransferReqDesc);
132 UtpTransferReqDesc utrd_result;
133
134 qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
135
136 /* Ring the doorbell */
137 ufs_wreg(ufs, A_UTRLDBR, 1);
138 ufs_wait_for_irq(ufs);
139 g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, UTRCS));
140 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UTRCS, 1));
141
142 /* Handle completed command */
143 qtest_memread(ufs->dev.bus->qts, utrd_addr, &utrd_result,
144 sizeof(utrd_result));
145 return le32_to_cpu(utrd_result.header.dword_2) & 0xf;
146 }
147
148 static enum UtpOcsCodes
149 __ufs_send_transfer_request_mcq(QUfs *ufs, uint8_t lun,
150 const UtpTransferReqDesc *utrd)
151 {
152 uint32_t sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
153 uint64_t utrd_addr = ufs->sqlba[TEST_QID] + sqtp;
154 uint32_t cqhp;
155 uint64_t cqentry_addr;
156 UfsCqEntry cqentry;
157
158 qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
159
160 /* Insert a new entry into the submission queue */
161 sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
162 sqtp = (sqtp + sizeof(UfsSqEntry)) % (QUEUE_SIZE * sizeof(UfsSqEntry));
163 ufs_wreg(ufs, ufs->sqdao[TEST_QID] + 0x4, sqtp);
164 ufs_wait_for_irq(ufs);
165 g_assert_true(FIELD_EX32(ufs_rreg(ufs, A_IS), IS, CQES));
166 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, CQES, 1));
167
168 /* Handle the completed command from the completion queue */
169 cqhp = ufs_rreg(ufs, ufs->cqdao[TEST_QID]);
170 cqentry_addr = ufs->cqlba[TEST_QID] + cqhp;
171 qtest_memread(ufs->dev.bus->qts, cqentry_addr, &cqentry, sizeof(cqentry));
172 cqhp = (cqhp + sizeof(UfsCqEntry)) % (QUEUE_SIZE * sizeof(UfsCqEntry));
173 ufs_wreg(ufs, ufs->cqdao[TEST_QID], cqhp);
174
175 return cqentry.status;
176 }
177
178 static enum UtpOcsCodes
179 ufs_send_transfer_request_sync(QUfs *ufs, uint8_t lun,
180 const UtpTransferReqDesc *utrd)
181 {
182 if (ufs->support_mcq) {
183 return __ufs_send_transfer_request_mcq(ufs, lun, utrd);
184 }
185
186 return __ufs_send_transfer_request_doorbell(ufs, lun, utrd);
187 }
188
189 static enum UtpOcsCodes ufs_send_nop_out(QUfs *ufs, UtpUpiuRsp *rsp_out)
190 {
191 int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
192 uint64_t req_upiu_addr =
193 ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
194 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
195
196 /* Build up request upiu */
197 UtpUpiuReq req_upiu = { 0 };
198 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_NOP_OUT;
199 req_upiu.header.task_tag = cmd_desc_slot;
200 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
201 sizeof(req_upiu));
202
203 /* Build up utp transfer request descriptor */
204 UtpTransferReqDesc utrd =
205 ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
206
207 /* Send Transfer Request */
208 enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
209
210 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
211 release_cmd_desc_slot(ufs, cmd_desc_slot);
212 return ret;
213 }
214
215 static bool ufs_mcq_sq_has_space(QUfs *ufs)
216 {
217 uint32_t sqhp = ufs_rreg(ufs, ufs->sqdao[TEST_QID]);
218 uint32_t sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
219 uint32_t next_sqtp =
220 (sqtp + sizeof(UfsSqEntry)) % (QUEUE_SIZE * sizeof(UfsSqEntry));
221 return next_sqtp != sqhp;
222 }
223
224 static void
225 __ufs_send_transfer_request_mcq_async(QUfs *ufs, uint8_t lun,
226 const UtpTransferReqDesc *utrd)
227 {
228 uint32_t sqtp;
229 uint64_t utrd_addr;
230
231 /* Wait for SQ space */
232 while (!ufs_mcq_sq_has_space(ufs)) {
233 qtest_clock_step(ufs->dev.bus->qts, 100);
234 }
235
236 sqtp = ufs_rreg(ufs, ufs->sqdao[TEST_QID] + 0x4);
237 utrd_addr = ufs->sqlba[TEST_QID] + sqtp;
238 qtest_memwrite(ufs->dev.bus->qts, utrd_addr, utrd, sizeof(*utrd));
239 sqtp = (sqtp + sizeof(UfsSqEntry)) % (QUEUE_SIZE * sizeof(UfsSqEntry));
240 ufs_wreg(ufs, ufs->sqdao[TEST_QID] + 0x4, sqtp);
241 }
242
243 static int ufs_mcq_send_nop_out_async(QUfs *ufs)
244 {
245 int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
246 uint64_t req_upiu_addr =
247 ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
248
249 /* Build up request upiu */
250 UtpUpiuReq req_upiu = { 0 };
251 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_NOP_OUT;
252 req_upiu.header.task_tag = cmd_desc_slot;
253 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
254 sizeof(req_upiu));
255
256 /* Build up utp transfer request descriptor */
257 UtpTransferReqDesc utrd =
258 ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
259
260 /* Send Transfer Request */
261 __ufs_send_transfer_request_mcq_async(ufs, 0, &utrd);
262
263 return cmd_desc_slot;
264 }
265
266 static int ufs_mcq_poll_cq(QUfs *ufs, UfsCqEntry *cqe, uint16_t n_cqe)
267 {
268 uint32_t cqhp, cqtp;
269 uint64_t cqe_addr;
270 int ix = 0;
271
272 cqhp = ufs_rreg(ufs, ufs->cqdao[TEST_QID]);
273 cqtp = ufs_rreg(ufs, ufs->cqdao[TEST_QID] + 0x4);
274
275 while (cqhp != cqtp && ix < n_cqe) {
276 /* read completion entry */
277 cqe_addr = ufs->cqlba[TEST_QID] + cqhp;
278 qtest_memread(ufs->dev.bus->qts, cqe_addr, &cqe[ix], sizeof(cqe[ix]));
279
280 /* advance completion queue head pointer */
281 cqhp = (cqhp + sizeof(UfsCqEntry)) % (QUEUE_SIZE * sizeof(UfsCqEntry));
282 ix++;
283 }
284
285 ufs_wreg(ufs, ufs->cqdao[TEST_QID], cqhp);
286
287 return ix;
288 }
289
290 static enum UtpOcsCodes ufs_send_query(QUfs *ufs, uint8_t query_function,
291 uint8_t query_opcode, uint8_t idn,
292 uint8_t index, uint8_t selector,
293 uint32_t attr_value, UtpUpiuRsp *rsp_out)
294 {
295 int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
296 uint64_t req_upiu_addr =
297 ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
298 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
299
300 /* Build up request upiu */
301 UtpUpiuReq req_upiu = { 0 };
302 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_QUERY_REQ;
303 req_upiu.header.query_func = query_function;
304 req_upiu.header.task_tag = cmd_desc_slot;
305 /*
306 * QEMU UFS does not currently support Write descriptor,
307 * so the value of data_segment_length is always 0.
308 */
309 req_upiu.header.data_segment_length = 0;
310 req_upiu.qr.opcode = query_opcode;
311 req_upiu.qr.idn = idn;
312 req_upiu.qr.index = index;
313 req_upiu.qr.selector = selector;
314 req_upiu.qr.value = cpu_to_be32(attr_value);
315 req_upiu.qr.length = UFS_QUERY_DESC_MAX_SIZE;
316 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
317 sizeof(req_upiu));
318
319 /* Build up utp transfer request descriptor */
320 UtpTransferReqDesc utrd =
321 ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
322
323 /* Send Transfer Request */
324 enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
325
326 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
327 release_cmd_desc_slot(ufs, cmd_desc_slot);
328 return ret;
329 }
330
331 static enum UtpOcsCodes
332 ufs_send_scsi_command(QUfs *ufs, uint8_t lun, const uint8_t *cdb,
333 const uint8_t *data_in, size_t data_in_len,
334 uint8_t *data_out, size_t data_out_len,
335 UtpUpiuRsp *rsp_out)
336
337 {
338 /* Build up PRDT */
339 UfshcdSgEntry entries[MAX_PRD_ENTRY_COUNT] = {
340 0,
341 };
342 uint8_t flags;
343 uint16_t prd_table_length, i;
344 uint32_t data_direction, data_len;
345 int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
346 uint64_t req_upiu_addr =
347 ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
348 uint64_t prdt_addr = req_upiu_addr + UTP_PRDT_UPIU_OFFSET;
349
350 g_assert_true(data_in_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
351 g_assert_true(data_out_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
352 if (data_in_len > 0) {
353 g_assert_nonnull(data_in);
354 data_direction = UFS_UTP_HOST_TO_DEVICE;
355 data_len = data_in_len;
356 flags = UFS_UPIU_CMD_FLAGS_WRITE;
357 } else if (data_out_len > 0) {
358 g_assert_nonnull(data_out);
359 data_direction = UFS_UTP_DEVICE_TO_HOST;
360 data_len = data_out_len;
361 flags = UFS_UPIU_CMD_FLAGS_READ;
362 } else {
363 data_direction = UFS_UTP_NO_DATA_TRANSFER;
364 data_len = 0;
365 flags = UFS_UPIU_CMD_FLAGS_NONE;
366 }
367 prd_table_length = DIV_ROUND_UP(data_len, PRD_ENTRY_DATA_SIZE);
368
369 qtest_memset(ufs->dev.bus->qts, ufs->data_buffer_addr, 0,
370 MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
371 if (data_in_len) {
372 qtest_memwrite(ufs->dev.bus->qts, ufs->data_buffer_addr, data_in,
373 data_in_len);
374 }
375
376 for (i = 0; i < prd_table_length; i++) {
377 entries[i].addr =
378 cpu_to_le64(ufs->data_buffer_addr + i * sizeof(UfshcdSgEntry));
379 if (i + 1 != prd_table_length) {
380 entries[i].size = cpu_to_le32(PRD_ENTRY_DATA_SIZE - 1);
381 } else {
382 entries[i].size = cpu_to_le32(
383 data_len - (PRD_ENTRY_DATA_SIZE * (prd_table_length - 1)) - 1);
384 }
385 }
386 qtest_memwrite(ufs->dev.bus->qts, prdt_addr, entries,
387 prd_table_length * sizeof(UfshcdSgEntry));
388
389 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
390
391 /* Build up request upiu */
392 UtpUpiuReq req_upiu = { 0 };
393 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_COMMAND;
394 req_upiu.header.flags = flags;
395 req_upiu.header.lun = lun;
396 req_upiu.header.task_tag = cmd_desc_slot;
397 req_upiu.sc.exp_data_transfer_len = cpu_to_be32(data_len);
398 memcpy(req_upiu.sc.cdb, cdb, UFS_CDB_SIZE);
399 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
400 sizeof(req_upiu));
401
402 /* Build up utp transfer request descriptor */
403 UtpTransferReqDesc utrd =
404 ufs_build_req_utrd(req_upiu_addr, data_direction, prd_table_length);
405
406 /* Send Transfer Request */
407 enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, lun, &utrd);
408
409 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
410 if (data_out_len) {
411 qtest_memread(ufs->dev.bus->qts, ufs->data_buffer_addr, data_out,
412 data_out_len);
413 }
414 release_cmd_desc_slot(ufs, cmd_desc_slot);
415 return ret;
416 }
417
418 /**
419 * Initialize Ufs host controller and logical unit.
420 * After running this function, you can make a transfer request to the UFS.
421 */
422 static void ufs_init(QUfs *ufs, QGuestAllocator *alloc)
423 {
424 uint64_t end_time;
425 uint32_t nutrs;
426 uint32_t hcs, is, ucmdarg2, cap;
427 uint32_t hce = 0, ie = 0;
428 enum UtpOcsCodes ocs;
429 UtpUpiuRsp rsp_upiu;
430
431 ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
432 qpci_device_enable(&ufs->dev);
433
434 /* Start host controller initialization */
435 hce = FIELD_DP32(hce, HCE, HCE, 1);
436 ufs_wreg(ufs, A_HCE, hce);
437
438 /* Wait for device to reset */
439 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
440 do {
441 qtest_clock_step(ufs->dev.bus->qts, 100);
442 hce = FIELD_EX32(ufs_rreg(ufs, A_HCE), HCE, HCE);
443 } while (hce == 0 && g_get_monotonic_time() < end_time);
444 g_assert_cmpuint(hce, ==, 1);
445
446 /* Enable interrupt */
447 ie = FIELD_DP32(ie, IE, UCCE, 1);
448 ie = FIELD_DP32(ie, IE, UHESE, 1);
449 ie = FIELD_DP32(ie, IE, UHXSE, 1);
450 ie = FIELD_DP32(ie, IE, UPMSE, 1);
451 ufs_wreg(ufs, A_IE, ie);
452
453 /* Send DME_LINK_STARTUP uic command */
454 hcs = ufs_rreg(ufs, A_HCS);
455 g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
456
457 ufs_wreg(ufs, A_UCMDARG1, 0);
458 ufs_wreg(ufs, A_UCMDARG2, 0);
459 ufs_wreg(ufs, A_UCMDARG3, 0);
460 ufs_wreg(ufs, A_UICCMD, UFS_UIC_CMD_DME_LINK_STARTUP);
461
462 is = ufs_rreg(ufs, A_IS);
463 g_assert_true(FIELD_EX32(is, IS, UCCS));
464 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UCCS, 1));
465
466 ucmdarg2 = ufs_rreg(ufs, A_UCMDARG2);
467 g_assert_cmpuint(ucmdarg2, ==, 0);
468 is = ufs_rreg(ufs, A_IS);
469 g_assert_cmpuint(is, ==, 0);
470 hcs = ufs_rreg(ufs, A_HCS);
471 g_assert_true(FIELD_EX32(hcs, HCS, DP));
472 g_assert_true(FIELD_EX32(hcs, HCS, UTRLRDY));
473 g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
474
475 /* Check MCQ support */
476 cap = ufs_rreg(ufs, A_CAP);
477 ufs->support_mcq = FIELD_EX32(cap, CAP, MCQS);
478
479 /* Enable all interrupt functions */
480 ie = FIELD_DP32(ie, IE, UTRCE, 1);
481 ie = FIELD_DP32(ie, IE, UEE, 1);
482 ie = FIELD_DP32(ie, IE, UPMSE, 1);
483 ie = FIELD_DP32(ie, IE, UHXSE, 1);
484 ie = FIELD_DP32(ie, IE, UHESE, 1);
485 ie = FIELD_DP32(ie, IE, UTMRCE, 1);
486 ie = FIELD_DP32(ie, IE, UCCE, 1);
487 ie = FIELD_DP32(ie, IE, DFEE, 1);
488 ie = FIELD_DP32(ie, IE, HCFEE, 1);
489 ie = FIELD_DP32(ie, IE, SBFEE, 1);
490 ie = FIELD_DP32(ie, IE, CEFEE, 1);
491 if (ufs->support_mcq) {
492 ie = FIELD_DP32(ie, IE, CQEE, 1);
493 }
494 ufs_wreg(ufs, A_IE, ie);
495 ufs_wreg(ufs, A_UTRIACR, 0);
496
497 /* Enable transfer request */
498 bitmap_zero(ufs->cmd_desc_bitmap, UFS_MAX_CMD_DESC);
499 ufs->cmd_desc_addr =
500 guest_alloc(alloc, UFS_MAX_CMD_DESC * UTP_COMMAND_DESCRIPTOR_SIZE);
501 ufs->data_buffer_addr =
502 guest_alloc(alloc, MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
503
504 if (ufs->support_mcq) {
505 uint32_t mcqcap, qid, qcfgptr, mcq_reg_offset;
506 uint32_t cqattr = 0, sqattr = 0;
507
508 mcqcap = ufs_rreg(ufs, A_MCQCAP);
509 qcfgptr = FIELD_EX32(mcqcap, MCQCAP, QCFGPTR);
510 ufs->maxq = FIELD_EX32(mcqcap, MCQCAP, MAXQ) + 1;
511 for (qid = 0; qid < ufs->maxq; ++qid) {
512 ufs->sqlba[qid] =
513 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
514 ufs->cqlba[qid] =
515 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
516 mcq_reg_offset = qcfgptr * 0x200 + qid * 0x40;
517
518 ufs_wreg(ufs, mcq_reg_offset + A_SQLBA,
519 ufs->sqlba[qid] & 0xffffffff);
520 ufs_wreg(ufs, mcq_reg_offset + A_SQUBA, ufs->sqlba[qid] >> 32);
521 ufs_wreg(ufs, mcq_reg_offset + A_CQLBA,
522 ufs->cqlba[qid] & 0xffffffff);
523 ufs_wreg(ufs, mcq_reg_offset + A_CQUBA, ufs->cqlba[qid] >> 32);
524
525 /* Enable Completion Queue */
526 cqattr = FIELD_DP32(cqattr, CQATTR, CQEN, 1);
527 cqattr = FIELD_DP32(cqattr, CQATTR, SIZE,
528 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
529 DWORD_BYTE);
530 ufs_wreg(ufs, mcq_reg_offset + A_CQATTR, cqattr);
531
532 /* Enable Submission Queue */
533 sqattr = FIELD_DP32(sqattr, SQATTR, SQEN, 1);
534 sqattr = FIELD_DP32(sqattr, SQATTR, SIZE,
535 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
536 DWORD_BYTE);
537 sqattr = FIELD_DP32(sqattr, SQATTR, CQID, qid);
538 ufs_wreg(ufs, mcq_reg_offset + A_SQATTR, sqattr);
539
540 /* Cache head & tail pointer */
541 ufs->sqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_SQDAO);
542 ufs->cqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_CQDAO);
543 }
544 } else {
545 nutrs = FIELD_EX32(cap, CAP, NUTRS) + 1;
546 ufs->utrlba = guest_alloc(alloc, nutrs * sizeof(UtpTransferReqDesc));
547
548 ufs_wreg(ufs, A_UTRLBA, ufs->utrlba & 0xffffffff);
549 ufs_wreg(ufs, A_UTRLBAU, ufs->utrlba >> 32);
550 ufs_wreg(ufs, A_UTRLRSR, 1);
551 }
552
553 /* Send nop out to test transfer request */
554 ocs = ufs_send_nop_out(ufs, &rsp_upiu);
555 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
556
557 /* Set fDeviceInit flag via query request */
558 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
559 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
560 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
561 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
562 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
563
564 /* Wait for device to reset */
565 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
566 do {
567 qtest_clock_step(ufs->dev.bus->qts, 100);
568 ocs =
569 ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
570 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
571 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
572 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
573 g_assert_cmpuint(rsp_upiu.header.response, ==,
574 UFS_COMMAND_RESULT_SUCCESS);
575 } while (be32_to_cpu(rsp_upiu.qr.value) != 0 &&
576 g_get_monotonic_time() < end_time);
577 g_assert_cmpuint(be32_to_cpu(rsp_upiu.qr.value), ==, 0);
578
579 ufs->enabled = true;
580 }
581
582 static void ufs_exit(QUfs *ufs, QGuestAllocator *alloc)
583 {
584 if (ufs->enabled) {
585 if (ufs->support_mcq) {
586 for (uint32_t qid = 0; qid < ufs->maxq; ++qid) {
587 guest_free(alloc, ufs->sqlba[qid]);
588 guest_free(alloc, ufs->cqlba[qid]);
589 }
590 } else {
591 guest_free(alloc, ufs->utrlba);
592 }
593
594 guest_free(alloc, ufs->cmd_desc_addr);
595 guest_free(alloc, ufs->data_buffer_addr);
596 }
597
598 qpci_iounmap(&ufs->dev, ufs->bar);
599 }
600
601 static void *ufs_get_driver(void *obj, const char *interface)
602 {
603 QUfs *ufs = obj;
604
605 if (!g_strcmp0(interface, "pci-device")) {
606 return &ufs->dev;
607 }
608
609 fprintf(stderr, "%s not present in ufs\n", interface);
610 g_assert_not_reached();
611 }
612
613 static void *ufs_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
614 {
615 QUfs *ufs = g_new0(QUfs, 1);
616 QPCIBus *bus = pci_bus;
617
618 qpci_device_init(&ufs->dev, bus, addr);
619 ufs->obj.get_driver = ufs_get_driver;
620
621 return &ufs->obj;
622 }
623
624 static void ufstest_reg_read(void *obj, void *data, QGuestAllocator *alloc)
625 {
626 QUfs *ufs = obj;
627 uint32_t cap;
628
629 ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
630 qpci_device_enable(&ufs->dev);
631
632 cap = ufs_rreg(ufs, A_CAP);
633 g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTRS), ==, 31);
634 g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTMRS), ==, 7);
635 g_assert_cmpuint(FIELD_EX32(cap, CAP, 64AS), ==, 1);
636
637 qpci_iounmap(&ufs->dev, ufs->bar);
638 }
639
640 static void ufstest_acpi_eject(void *obj, void *data, QGuestAllocator *alloc)
641 {
642 QUfs *ufs = obj;
643 QTestState *qts = ufs->dev.bus->qts;
644
645 qtest_outl(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << 4);
646 qtest_qmp_assert_success(qts, "{ 'execute': 'query-status' }");
647 g_usleep(3 * G_USEC_PER_SEC);
648 qtest_qmp_assert_success(qts, "{ 'execute': 'query-status' }");
649 }
650
651 static void ufstest_init(void *obj, void *data, QGuestAllocator *alloc)
652 {
653 QUfs *ufs = obj;
654
655 uint8_t buf[4096] = { 0 };
656 const uint8_t report_luns_cdb[UFS_CDB_SIZE] = {
657 /* allocation length 4096 */
658 REPORT_LUNS, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x10, 0x00, 0x00, 0x00
660 };
661 const uint8_t test_unit_ready_cdb[UFS_CDB_SIZE] = {
662 TEST_UNIT_READY,
663 };
664 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
665 REQUEST_SENSE,
666 };
667 enum UtpOcsCodes ocs;
668 UtpUpiuRsp rsp_upiu;
669
670 ufs_init(ufs, alloc);
671
672 /* Check REPORT_LUNS */
673 ocs = ufs_send_scsi_command(ufs, 0, report_luns_cdb, NULL, 0, buf,
674 sizeof(buf), &rsp_upiu);
675 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
676 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
677 /* LUN LIST LENGTH should be 8, in big endian */
678 g_assert_cmpuint(buf[3], ==, 8);
679 /* There is one logical unit whose lun is 0 */
680 g_assert_cmpuint(buf[9], ==, 0);
681
682 /* Clear Unit Attention */
683 ocs = ufs_send_scsi_command(ufs, 0, request_sense_cdb, NULL, 0, buf,
684 sizeof(buf), &rsp_upiu);
685 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
686 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
687
688 /* Check TEST_UNIT_READY */
689 ocs = ufs_send_scsi_command(ufs, 0, test_unit_ready_cdb, NULL, 0, NULL, 0,
690 &rsp_upiu);
691 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
692 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
693
694 ufs_exit(ufs, alloc);
695 }
696
697 static void ufstest_read_write(void *obj, void *data, QGuestAllocator *alloc)
698 {
699 QUfs *ufs = obj;
700 uint8_t read_buf[4096] = { 0 };
701 uint8_t write_buf[4096] = { 0 };
702 const uint8_t read_capacity_cdb[UFS_CDB_SIZE] = {
703 /* allocation length 4096 */
704 SERVICE_ACTION_IN_16,
705 SAI_READ_CAPACITY_16,
706 0x00,
707 0x00,
708 0x00,
709 0x00,
710 0x00,
711 0x00,
712 0x00,
713 0x00,
714 0x00,
715 0x00,
716 0x10,
717 0x00,
718 0x00,
719 0x00
720 };
721 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
722 REQUEST_SENSE,
723 };
724 const uint8_t read_cdb[UFS_CDB_SIZE] = {
725 /* READ(10) to LBA 0, transfer length 1 */
726 READ_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
727 };
728 const uint8_t write_cdb[UFS_CDB_SIZE] = {
729 /* WRITE(10) to LBA 0, transfer length 1 */
730 WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
731 };
732 uint32_t block_size;
733 enum UtpOcsCodes ocs;
734 UtpUpiuRsp rsp_upiu;
735 const int test_lun = 1;
736
737 ufs_init(ufs, alloc);
738
739 /* Clear Unit Attention */
740 ocs = ufs_send_scsi_command(ufs, test_lun, request_sense_cdb, NULL, 0,
741 read_buf, sizeof(read_buf), &rsp_upiu);
742 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
743 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
744
745 /* Read capacity */
746 ocs = ufs_send_scsi_command(ufs, test_lun, read_capacity_cdb, NULL, 0,
747 read_buf, sizeof(read_buf), &rsp_upiu);
748 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
749 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
750 UFS_COMMAND_RESULT_SUCCESS);
751 block_size = ldl_be_p(&read_buf[8]);
752 g_assert_cmpuint(block_size, ==, 4096);
753
754 /* Write data */
755 memset(write_buf, 0xab, block_size);
756 ocs = ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf, block_size,
757 NULL, 0, &rsp_upiu);
758 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
759 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
760 UFS_COMMAND_RESULT_SUCCESS);
761
762 /* Read data and verify */
763 ocs = ufs_send_scsi_command(ufs, test_lun, read_cdb, NULL, 0, read_buf,
764 block_size, &rsp_upiu);
765 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
766 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
767 UFS_COMMAND_RESULT_SUCCESS);
768 g_assert_cmpint(memcmp(read_buf, write_buf, block_size), ==, 0);
769
770 ufs_exit(ufs, alloc);
771 }
772
773 static void ufstest_mcq_cq_wraparound(void *obj, void *data,
774 QGuestAllocator *alloc)
775 {
776 QUfs *ufs = obj;
777 UfsCqEntry cqe[QUEUE_SIZE];
778 const int num_requests = QUEUE_SIZE;
779 int i, completed = 0;
780
781 ufs_init(ufs, alloc);
782
783 /* Ensure MCQ is supported */
784 g_assert_true(ufs->support_mcq);
785
786 for (i = 0; i < num_requests; ++i) {
787 ufs_mcq_send_nop_out_async(ufs);
788 }
789
790 while (completed != num_requests) {
791 int n_cqe = ufs_mcq_poll_cq(ufs, cqe, ARRAY_SIZE(cqe));
792 if (!n_cqe) {
793 break;
794 }
795
796 for (i = 0; i < n_cqe; ++i) {
797 uint64_t ucdba;
798 uint64_t rsp_upiu_addr;
799 UtpUpiuRsp rsp_upiu;
800 uint8_t tag;
801
802 g_assert_cmpuint(cqe[i].status, ==, UFS_OCS_SUCCESS);
803
804 ucdba = le64_to_cpu(cqe[i].utp_addr) & MAKE_64BIT_MASK(7, 57);
805 rsp_upiu_addr = ucdba + UTP_RESPONSE_UPIU_OFFSET;
806 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, &rsp_upiu,
807 sizeof(rsp_upiu));
808
809 tag = rsp_upiu.header.task_tag;
810 release_cmd_desc_slot(ufs, tag);
811 }
812
813 completed += n_cqe;
814 }
815
816 g_assert_cmpint(completed, ==, num_requests);
817 ufs_exit(ufs, alloc);
818 }
819
820 static void ufstest_query_flag_request(void *obj, void *data,
821 QGuestAllocator *alloc)
822 {
823 QUfs *ufs = obj;
824
825 enum UtpOcsCodes ocs;
826 UtpUpiuRsp rsp_upiu;
827 ufs_init(ufs, alloc);
828
829 /* Read read-only flag */
830 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
831 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
832 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
833 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
834 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
835 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_FLAG);
836 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_FLAG_IDN_FDEVICEINIT);
837 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
838
839 /* Flag Set, Clear, Toggle Test with fDeviceLifeSpanModeEn */
840 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
841 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
842 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
843 &rsp_upiu);
844 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
845 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
846 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
847
848 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
849 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
850 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
851 &rsp_upiu);
852 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
853 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
854 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
855
856 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
857 UFS_UPIU_QUERY_OPCODE_CLEAR_FLAG,
858 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
859 &rsp_upiu);
860 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
861 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
862 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
863
864 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
865 UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
866 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
867 &rsp_upiu);
868 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
869 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
870 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
871
872 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
873 UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
874 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
875 &rsp_upiu);
876 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
877 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
878 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
879
880 /* Read Write-only Flag (Intended Failure) */
881 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
882 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
883 UFS_QUERY_FLAG_IDN_PURGE_ENABLE, 0, 0, 0, &rsp_upiu);
884 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
885 g_assert_cmpuint(rsp_upiu.header.response, ==,
886 UFS_QUERY_RESULT_NOT_READABLE);
887
888 /* Write Read-Only Flag (Intended Failure) */
889 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
890 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
891 UFS_QUERY_FLAG_IDN_BUSY_RTC, 0, 0, 0, &rsp_upiu);
892 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
893 g_assert_cmpuint(rsp_upiu.header.response, ==,
894 UFS_QUERY_RESULT_NOT_WRITEABLE);
895
896 ufs_exit(ufs, alloc);
897 }
898
899 static void ufstest_query_attr_request(void *obj, void *data,
900 QGuestAllocator *alloc)
901 {
902 QUfs *ufs = obj;
903
904 enum UtpOcsCodes ocs;
905 UtpUpiuRsp rsp_upiu;
906 ufs_init(ufs, alloc);
907
908 /* Read Readable Attributes*/
909 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
910 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
911 UFS_QUERY_ATTR_IDN_BOOT_LU_EN, 0, 0, 0, &rsp_upiu);
912 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
913 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
914 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_ATTR);
915 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_ATTR_IDN_BOOT_LU_EN);
916 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
917
918 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
919 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
920 UFS_QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, 0, &rsp_upiu);
921 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
922 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
923 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
924
925 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
926 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
927 UFS_QUERY_ATTR_IDN_CASE_ROUGH_TEMP, 0, 0, 0,
928 &rsp_upiu);
929 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
930 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
931 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
932
933 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
934 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
935 UFS_QUERY_ATTR_IDN_HIGH_TEMP_BOUND, 0, 0, 0,
936 &rsp_upiu);
937 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
938 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
939 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(160));
940
941 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
942 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
943 UFS_QUERY_ATTR_IDN_LOW_TEMP_BOUND, 0, 0, 0,
944 &rsp_upiu);
945 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
946 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
947 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(60));
948
949 /* Write Writable Attributes & Read Again */
950 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
951 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
952 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x03,
953 &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_WRITE_REQUEST,
959 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
960 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0x07, &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 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
966 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
967 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
968 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
969 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
970 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
971
972 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
973 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
974 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
975 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
976 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
977 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07));
978
979 /* Write Invalid Value (Intended Error) */
980 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
981 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
982 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x10,
983 &rsp_upiu);
984 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
985 g_assert_cmpuint(rsp_upiu.header.response, ==,
986 UFS_QUERY_RESULT_INVALID_VALUE);
987
988 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
989 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
990 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
991 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
992 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
993 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
994
995 /* Read Write-Only Attribute (Intended Error) */
996 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
997 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
998 UFS_QUERY_ATTR_IDN_SECONDS_PASSED, 0, 0, 0, &rsp_upiu);
999 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1000 g_assert_cmpuint(rsp_upiu.header.response, ==,
1001 UFS_QUERY_RESULT_NOT_READABLE);
1002
1003 /* Write Read-Only Attribute (Intended Error) */
1004 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1005 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
1006 UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0x01, &rsp_upiu);
1007 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1008 g_assert_cmpuint(rsp_upiu.header.response, ==,
1009 UFS_QUERY_RESULT_NOT_WRITEABLE);
1010
1011 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1012 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
1013 UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0, &rsp_upiu);
1014 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1015 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1016 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1017
1018 /* Reset Written Attributes */
1019 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1020 UFS_UPIU_QUERY_OPCODE_WRITE_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_WRITE_REQUEST,
1027 UFS_UPIU_QUERY_OPCODE_WRITE_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 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1034 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
1035 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
1036 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1037 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1038 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1039
1040 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1041 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
1042 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
1043 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1044 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1045 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
1046
1047 ufs_exit(ufs, alloc);
1048 }
1049
1050 static void ufstest_query_desc_request(void *obj, void *data,
1051 QGuestAllocator *alloc)
1052 {
1053 QUfs *ufs = obj;
1054
1055 enum UtpOcsCodes ocs;
1056 UtpUpiuRsp rsp_upiu;
1057 ufs_init(ufs, alloc);
1058
1059 /* Write Descriptor is not supported yet */
1060
1061 /* Read Device Descriptor */
1062 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1063 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1064 UFS_QUERY_DESC_IDN_DEVICE, 0, 0, 0, &rsp_upiu);
1065 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1066 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1067 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_DESC);
1068 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_DESC_IDN_DEVICE);
1069 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceDescriptor));
1070 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_DEVICE);
1071
1072 /* Read Configuration Descriptor is not supported yet*/
1073
1074 /* Read Unit Descriptor */
1075 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1076 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1077 UFS_QUERY_DESC_IDN_UNIT, 0, 0, 0, &rsp_upiu);
1078 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1079 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1080 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor));
1081 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
1082 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 0);
1083
1084 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1085 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1086 UFS_QUERY_DESC_IDN_UNIT, 1, 0, 0, &rsp_upiu);
1087 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1088 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1089 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor));
1090 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
1091 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 1);
1092
1093 ocs =
1094 ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1095 UFS_UPIU_QUERY_OPCODE_READ_DESC, UFS_QUERY_DESC_IDN_UNIT,
1096 UFS_UPIU_RPMB_WLUN, 0, 0, &rsp_upiu);
1097 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1098 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1099 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(RpmbUnitDescriptor));
1100 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
1101 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, UFS_UPIU_RPMB_WLUN);
1102
1103 /* Read Interconnect Descriptor */
1104 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1105 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1106 UFS_QUERY_DESC_IDN_INTERCONNECT, 0, 0, 0, &rsp_upiu);
1107 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1108 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1109 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(InterconnectDescriptor));
1110 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_INTERCONNECT);
1111
1112 /* Read String Descriptor */
1113 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1114 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1115 UFS_QUERY_DESC_IDN_STRING, 0, 0, 0, &rsp_upiu);
1116 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1117 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1118 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x12);
1119 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
1120
1121 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1122 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1123 UFS_QUERY_DESC_IDN_STRING, 1, 0, 0, &rsp_upiu);
1124 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1125 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1126 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x22);
1127 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
1128
1129 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1130 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1131 UFS_QUERY_DESC_IDN_STRING, 4, 0, 0, &rsp_upiu);
1132 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1133 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1134 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x0a);
1135 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
1136
1137 /* Read Geometry Descriptor */
1138 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1139 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1140 UFS_QUERY_DESC_IDN_GEOMETRY, 0, 0, 0, &rsp_upiu);
1141 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1142 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1143 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(GeometryDescriptor));
1144 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_GEOMETRY);
1145
1146 /* Read Power Descriptor */
1147 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1148 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1149 UFS_QUERY_DESC_IDN_POWER, 0, 0, 0, &rsp_upiu);
1150 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1151 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1152 g_assert_cmpuint(rsp_upiu.qr.data[0], ==,
1153 sizeof(PowerParametersDescriptor));
1154 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_POWER);
1155
1156 /* Read Health Descriptor */
1157 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1158 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1159 UFS_QUERY_DESC_IDN_HEALTH, 0, 0, 0, &rsp_upiu);
1160 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1161 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1162 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceHealthDescriptor));
1163 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_HEALTH);
1164
1165 /* Invalid Index (Intended Failure) */
1166 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1167 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1168 UFS_QUERY_DESC_IDN_UNIT, 4, 0, 0, &rsp_upiu);
1169 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1170 g_assert_cmpuint(rsp_upiu.header.response, ==,
1171 UFS_QUERY_RESULT_INVALID_INDEX);
1172
1173 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1174 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1175 UFS_QUERY_DESC_IDN_STRING, 5, 0, 0, &rsp_upiu);
1176 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1177 g_assert_cmpuint(rsp_upiu.header.response, ==,
1178 UFS_QUERY_RESULT_INVALID_INDEX);
1179
1180 /* Invalid Selector (Intended Failure) */
1181 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1182 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1183 UFS_QUERY_DESC_IDN_DEVICE, 0, 1, 0, &rsp_upiu);
1184 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1185 g_assert_cmpuint(rsp_upiu.header.response, ==,
1186 UFS_QUERY_RESULT_INVALID_SELECTOR);
1187
1188 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1189 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1190 UFS_QUERY_DESC_IDN_STRING, 0, 1, 0, &rsp_upiu);
1191 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1192 g_assert_cmpuint(rsp_upiu.header.response, ==,
1193 UFS_QUERY_RESULT_INVALID_SELECTOR);
1194
1195 ufs_exit(ufs, alloc);
1196 }
1197
1198 static void ufstest_wb_init(void *obj, void *data, QGuestAllocator *alloc)
1199 {
1200 QUfs *ufs = obj;
1201 enum UtpOcsCodes ocs;
1202 UtpUpiuRsp rsp_upiu;
1203 uint8_t *desc;
1204 uint32_t value;
1205
1206 ufs_init(ufs, alloc);
1207
1208 /* Read Device Descriptor */
1209 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1210 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1211 UFS_QUERY_DESC_IDN_DEVICE, 0, 0, 0, &rsp_upiu);
1212 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1213 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1214 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_DESC);
1215 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_DESC_IDN_DEVICE);
1216 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceDescriptor));
1217 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_DEVICE);
1218
1219 /* Check Write Booster Supportability */
1220 desc = rsp_upiu.qr.data;
1221
1222 value = lduw_be_p(desc + UFS_DEVICE_DESC_PARAM_EXT_WB_SUP);
1223 g_assert_cmpuint(value, ==, WB_RESIZE | WB_FIFO | WB_PINNED);
1224
1225 value = ldl_be_p(desc + UFS_DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
1226 g_assert_cmpuint(value & UFS_DEV_WB_SUPPORT, ==, UFS_DEV_WB_SUPPORT);
1227
1228 /* Read Geometry Descriptor */
1229 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1230 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1231 UFS_QUERY_DESC_IDN_GEOMETRY, 0, 0, 0, &rsp_upiu);
1232 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1233 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1234 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(GeometryDescriptor));
1235 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_GEOMETRY);
1236
1237 /* Check Write Booster Configuration */
1238 desc = rsp_upiu.qr.data;
1239
1240 value = ldl_be_p(desc + UFS_GEOMETRY_DESC_PARAM_WB_MAX_ALLOC_UNITS);
1241 g_assert_cmpuint(value, ==, 1024);
1242
1243 value = desc[UFS_GEOMETRY_DESC_PARAM_WB_MAX_WB_LUNS];
1244 g_assert_cmpuint(value, ==, 1);
1245
1246 value = desc[UFS_GEOMETRY_DESC_PARAM_WB_BUFF_CAP_ADJ];
1247 g_assert_cmpuint(value, ==, 3);
1248
1249 value = desc[UFS_GEOMETRY_DESC_PARAM_WB_SUP_RED_TYPE];
1250 g_assert_cmpuint(value, ==, 1);
1251
1252 value = desc[UFS_GEOMETRY_DESC_PARAM_WB_SUP_WB_TYPE];
1253 g_assert_cmpuint(value, ==, 1);
1254
1255 ufs_exit(ufs, alloc);
1256 }
1257
1258 static void ufstest_wb_read_write(void *obj, void *data, QGuestAllocator *alloc)
1259 {
1260 QUfs *ufs = obj;
1261 uint8_t read_buf[4096] = { 0 };
1262 uint8_t write_buf[4096] = { 0 };
1263 const uint8_t read_capacity_cdb[UFS_CDB_SIZE] = {
1264 /* allocation length 4096 */
1265 SERVICE_ACTION_IN_16,
1266 SAI_READ_CAPACITY_16,
1267 0x00,
1268 0x00,
1269 0x00,
1270 0x00,
1271 0x00,
1272 0x00,
1273 0x00,
1274 0x00,
1275 0x00,
1276 0x00,
1277 0x10,
1278 0x00,
1279 0x00,
1280 0x00
1281 };
1282 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
1283 REQUEST_SENSE,
1284 };
1285 const uint8_t write_cdb[UFS_CDB_SIZE] = {
1286 /* WRITE(10) to LBA 0, transfer length 1 */
1287 WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
1288 };
1289 uint32_t block_size;
1290 enum UtpOcsCodes ocs;
1291 UtpUpiuRsp rsp_upiu;
1292 const int test_lun = 1;
1293 uint64_t end_time;
1294
1295 ufs_init(ufs, alloc);
1296
1297 /* Clear Unit Attention */
1298 ocs = ufs_send_scsi_command(ufs, test_lun, request_sense_cdb, NULL, 0,
1299 read_buf, sizeof(read_buf), &rsp_upiu);
1300 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1301 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
1302
1303 /* Read capacity */
1304 ocs = ufs_send_scsi_command(ufs, test_lun, read_capacity_cdb, NULL, 0,
1305 read_buf, sizeof(read_buf), &rsp_upiu);
1306 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1307 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
1308 UFS_COMMAND_RESULT_SUCCESS);
1309 block_size = ldl_be_p(&read_buf[8]);
1310 g_assert_cmpuint(block_size, ==, 4096);
1311
1312 /* Check available buffer size */
1313 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1314 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
1315 UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE, 0, 0, 0,
1316 &rsp_upiu);
1317 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1318 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1319 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_ATTR);
1320 g_assert_cmpuint(rsp_upiu.qr.idn, ==,
1321 UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE);
1322 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0xA));
1323
1324 /* Enable WB */
1325 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1326 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
1327 UFS_QUERY_FLAG_IDN_WB_EN, 0, 0, 0, &rsp_upiu);
1328 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1329 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1330 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
1331
1332 /* Write data */
1333 for (int i = 0; i < 256; i++) {
1334 memset(write_buf, 0xab, block_size);
1335 ocs = ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf,
1336 block_size, NULL, 0, &rsp_upiu);
1337 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1338 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
1339 UFS_COMMAND_RESULT_SUCCESS);
1340 }
1341
1342 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
1343 do {
1344 qtest_clock_step(ufs->dev.bus->qts, 100);
1345
1346 /* Check available buffer size */
1347 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1348 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
1349 UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE, 0, 0, 0,
1350 &rsp_upiu);
1351 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1352 g_assert_cmpuint(rsp_upiu.header.response, ==,
1353 UFS_COMMAND_RESULT_SUCCESS);
1354 g_assert_cmpuint(rsp_upiu.qr.opcode, ==,
1355 UFS_UPIU_QUERY_OPCODE_READ_ATTR);
1356 g_assert_cmpuint(rsp_upiu.qr.idn, ==,
1357 UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE);
1358 } while (rsp_upiu.qr.value == cpu_to_be32(0xA) &&
1359 g_get_monotonic_time() < end_time);
1360
1361 /* Check available buffer size */
1362 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x9));
1363
1364 ufs_exit(ufs, alloc);
1365 }
1366
1367 static void drive_destroy(void *path)
1368 {
1369 unlink(path);
1370 g_free(path);
1371 qos_invalidate_command_line();
1372 }
1373
1374 static char *drive_create(void)
1375 {
1376 int fd, ret;
1377 char *t_path;
1378
1379 /* Create a temporary raw image */
1380 fd = g_file_open_tmp("qtest-ufs.XXXXXX", &t_path, NULL);
1381 g_assert_cmpint(fd, >=, 0);
1382 ret = ftruncate(fd, TEST_IMAGE_SIZE);
1383 g_assert_cmpint(ret, ==, 0);
1384 close(fd);
1385
1386 g_test_queue_destroy(drive_destroy, t_path);
1387 return t_path;
1388 }
1389
1390 static void *ufs_blk_test_setup(GString *cmd_line, void *arg)
1391 {
1392 char *tmp_path = drive_create();
1393
1394 g_string_append_printf(cmd_line,
1395 " -blockdev file,filename=%s,node-name=drv1 "
1396 "-device ufs-lu,bus=ufs0,drive=drv1,lun=1 ",
1397 tmp_path);
1398
1399 return arg;
1400 }
1401
1402 /*
1403 * Helper to read a single HID attribute value.
1404 * Returns the host-endian attribute value; asserts OCS success.
1405 */
1406 static uint32_t ufs_hid_read_attr(QUfs *ufs, uint8_t idn)
1407 {
1408 enum UtpOcsCodes ocs;
1409 UtpUpiuRsp rsp;
1410
1411 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1412 UFS_UPIU_QUERY_OPCODE_READ_ATTR, idn, 0, 0, 0, &rsp);
1413 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1414 g_assert_cmpuint(rsp.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1415 return be32_to_cpu(rsp.qr.value);
1416 }
1417
1418 /*
1419 * Helper to write a single HID attribute value.
1420 * Asserts OCS success.
1421 */
1422 static void ufs_hid_write_attr(QUfs *ufs, uint8_t idn, uint32_t value)
1423 {
1424 enum UtpOcsCodes ocs;
1425 UtpUpiuRsp rsp;
1426
1427 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1428 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR, idn, 0, 0, value,
1429 &rsp);
1430 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1431 g_assert_cmpuint(rsp.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1432 }
1433
1434 static uint32_t ufs_hid_wait_leave_state(QUfs *ufs, uint32_t from)
1435 {
1436 uint64_t end_time =
1437 g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
1438 uint32_t state;
1439
1440 do {
1441 qtest_clock_step(ufs->dev.bus->qts, 100);
1442 state = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1443 } while (state == from && g_get_monotonic_time() < end_time);
1444
1445 return state;
1446 }
1447
1448 static uint32_t ufs_hid_wait_state(QUfs *ufs, uint32_t expected)
1449 {
1450 uint64_t end_time =
1451 g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
1452 uint32_t state;
1453
1454 do {
1455 qtest_clock_step(ufs->dev.bus->qts, 100);
1456 state = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1457 } while (state != expected && g_get_monotonic_time() < end_time);
1458
1459 g_assert_cmpuint(state, ==, expected);
1460 return state;
1461 }
1462
1463 static void ufs_hid_wait_progress_complete(QUfs *ufs)
1464 {
1465 uint64_t end_time =
1466 g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
1467 uint32_t val;
1468
1469 do {
1470 qtest_clock_step(ufs->dev.bus->qts, 100);
1471 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_PROG_RATIO);
1472 } while (val != 100 && g_get_monotonic_time() < end_time);
1473
1474 g_assert_cmpuint(val, ==, 100);
1475 }
1476
1477 static void ufstest_hid(void *obj, void *data, QGuestAllocator *alloc)
1478 {
1479 QUfs *ufs = obj;
1480 uint32_t val;
1481 enum UtpOcsCodes ocs;
1482 UtpUpiuRsp rsp;
1483 const int test_lun = 1;
1484 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
1485 REQUEST_SENSE,
1486 };
1487 const uint8_t write_cdb[UFS_CDB_SIZE] = {
1488 /* WRITE(10) to LBA 0, transfer length 8 sectors = 1 fragment */
1489 WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00
1490 };
1491 uint8_t write_buf[4096];
1492 uint8_t read_buf[4096];
1493 int i;
1494
1495 ufs_init(ufs, alloc);
1496
1497 /* Clear Unit Attention */
1498 ufs_send_scsi_command(ufs, test_lun, request_sense_cdb, NULL, 0, read_buf,
1499 sizeof(read_buf), &rsp);
1500
1501 /*
1502 * 1. Verify HID default attribute values
1503 */
1504 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP);
1505 g_assert_cmpuint(val, ==, UFS_HID_OP_DISABLE);
1506
1507 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE);
1508 g_assert_cmpuint(val, ==, 0xFFFFFFFF);
1509
1510 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_SIZE);
1511 g_assert_cmpuint(val, ==, 0xFFFFFFFF);
1512
1513 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_PROG_RATIO);
1514 g_assert_cmpuint(val, ==, 0);
1515
1516 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1517 g_assert_cmpuint(val, ==, UFS_HID_STATE_IDLE);
1518
1519 /*
1520 * 2. Verify read-only attributes reject writes
1521 */
1522 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1523 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
1524 UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE, 0, 0, 0x100, &rsp);
1525 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1526 g_assert_cmpuint(rsp.header.response, ==, UFS_QUERY_RESULT_NOT_WRITEABLE);
1527
1528 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1529 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
1530 UFS_QUERY_ATTR_IDN_HID_PROG_RATIO, 0, 0, 50, &rsp);
1531 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1532 g_assert_cmpuint(rsp.header.response, ==, UFS_QUERY_RESULT_NOT_WRITEABLE);
1533
1534 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1535 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
1536 UFS_QUERY_ATTR_IDN_HID_STATE, 0, 0, 0x01, &rsp);
1537 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1538 g_assert_cmpuint(rsp.header.response, ==, UFS_QUERY_RESULT_NOT_WRITEABLE);
1539
1540 /*
1541 * 3. Verify invalid bDefragOperation value is rejected
1542 */
1543 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
1544 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
1545 UFS_QUERY_ATTR_IDN_DEFRAG_OP, 0, 0, 0x03, &rsp);
1546 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1547 g_assert_cmpuint(rsp.header.response, ==, UFS_QUERY_RESULT_INVALID_VALUE);
1548
1549 /*
1550 * 4. dHIDSize is writable and readable
1551 */
1552 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_HID_SIZE, 0x100);
1553 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_SIZE);
1554 g_assert_cmpuint(val, ==, 0x100);
1555
1556 /* Restore default */
1557 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_HID_SIZE, 0xFFFFFFFF);
1558
1559 /*
1560 * 5. Analysis with no fragments -> Defrag Not Required, then reading
1561 * bHIDState in a terminal state auto-resets HID to Idle.
1562 */
1563 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP, UFS_HID_OP_ANALYSIS);
1564
1565 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1566 g_assert_cmpuint(val, ==, UFS_HID_STATE_ANALYSIS_IN_PROGRESS);
1567
1568 /* Idle handler advances analysis; first non-analysis read is decisive */
1569 val = ufs_hid_wait_leave_state(ufs, UFS_HID_STATE_ANALYSIS_IN_PROGRESS);
1570 g_assert_cmpuint(val, ==, UFS_HID_STATE_DEFRAG_NOT_REQUIRED);
1571
1572 /* Reading Not Required auto-reset to Idle */
1573 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1574 g_assert_cmpuint(val, ==, UFS_HID_STATE_IDLE);
1575
1576 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE);
1577 g_assert_cmpuint(val, ==, 0xFFFFFFFF);
1578
1579 /*
1580 * 6. Generate fragmentation via SCSI WRITE, then analyze (analysis
1581 * only): the machine settles at Defrag Required.
1582 */
1583 memset(write_buf, 0xab, sizeof(write_buf));
1584 for (i = 0; i < 4; i++) {
1585 ocs = ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf,
1586 sizeof(write_buf), NULL, 0, &rsp);
1587 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1588 }
1589
1590 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP, UFS_HID_OP_ANALYSIS);
1591
1592 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1593 g_assert_cmpuint(val, ==, UFS_HID_STATE_ANALYSIS_IN_PROGRESS);
1594
1595 val = ufs_hid_wait_leave_state(ufs, UFS_HID_STATE_ANALYSIS_IN_PROGRESS);
1596 g_assert_cmpuint(val, ==, UFS_HID_STATE_DEFRAG_REQUIRED);
1597
1598 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP);
1599 g_assert_cmpuint(val, ==, UFS_HID_OP_DISABLE);
1600
1601 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE);
1602 g_assert_cmpuint(val, >, 0);
1603
1604 /*
1605 * 7. Disable resets to Idle from any state
1606 */
1607 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP, UFS_HID_OP_DISABLE);
1608
1609 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1610 g_assert_cmpuint(val, ==, UFS_HID_STATE_IDLE);
1611
1612 /*
1613 * 8. Partial defrag cycle: dHIDSize limits the requested defrag size,
1614 * and reading bHIDProgressRatio at 100% resets the HID attributes.
1615 */
1616 for (i = 0; i < 4; i++) {
1617 ocs = ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf,
1618 sizeof(write_buf), NULL, 0, &rsp);
1619 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1620 }
1621
1622 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_HID_SIZE, 2);
1623 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP, UFS_HID_OP_DEFRAG);
1624
1625 /* Should start in Analysis In Progress */
1626 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1627 g_assert_cmpuint(val, ==, UFS_HID_STATE_ANALYSIS_IN_PROGRESS);
1628
1629 ufs_hid_wait_progress_complete(ufs);
1630
1631 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE);
1632 g_assert_cmpuint(val, ==, 0xFFFFFFFF);
1633
1634 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP);
1635 g_assert_cmpuint(val, ==, UFS_HID_OP_DISABLE);
1636
1637 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_PROG_RATIO);
1638 g_assert_cmpuint(val, ==, 0);
1639
1640 /*
1641 * Re-analyze after the partial defrag. There were 8 fragments before
1642 * defrag, and dHIDSize limited the completed operation to 2.
1643 */
1644 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP, UFS_HID_OP_ANALYSIS);
1645
1646 val = ufs_hid_wait_leave_state(ufs, UFS_HID_STATE_ANALYSIS_IN_PROGRESS);
1647 g_assert_cmpuint(val, ==, UFS_HID_STATE_DEFRAG_REQUIRED);
1648
1649 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE);
1650 g_assert_cmpuint(val, ==, 6);
1651
1652 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP, UFS_HID_OP_DISABLE);
1653 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_HID_SIZE, 0xFFFFFFFF);
1654
1655 /*
1656 * 9. Full defrag cycle: reading bHIDState in Completed state returns
1657 * Completed once and resets HID attributes to Idle/default values.
1658 */
1659 ufs_hid_write_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP, UFS_HID_OP_DEFRAG);
1660
1661 val = ufs_hid_wait_state(ufs, UFS_HID_STATE_DEFRAG_COMPLETED);
1662 g_assert_cmpuint(val, ==, UFS_HID_STATE_DEFRAG_COMPLETED);
1663
1664 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_STATE);
1665 g_assert_cmpuint(val, ==, UFS_HID_STATE_IDLE);
1666
1667 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_DEFRAG_OP);
1668 g_assert_cmpuint(val, ==, UFS_HID_OP_DISABLE);
1669
1670 val = ufs_hid_read_attr(ufs, UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE);
1671 g_assert_cmpuint(val, ==, 0xFFFFFFFF);
1672
1673 ufs_exit(ufs, alloc);
1674 }
1675
1676 static void ufs_register_nodes(void)
1677 {
1678 const char *arch;
1679 QOSGraphEdgeOptions edge_opts = {
1680 .before_cmd_line = "-blockdev null-co,node-name=drv0,read-zeroes=on",
1681 .after_cmd_line = "-device ufs-lu,bus=ufs0,drive=drv0,lun=0",
1682 .extra_device_opts = "addr=04.0,id=ufs0"
1683 };
1684
1685 QOSGraphTestOptions io_test_opts = { .before = ufs_blk_test_setup,
1686 .edge.extra_device_opts =
1687 "mcq=false,nutrs=32,nutmrs=8" };
1688
1689 QOSGraphTestOptions mcq_test_opts = { .before = ufs_blk_test_setup,
1690 .edge.extra_device_opts =
1691 "mcq=true,mcq-maxq=1" };
1692
1693 QOSGraphTestOptions wb_test_opts = { .before = ufs_blk_test_setup,
1694 .edge.extra_device_opts =
1695 "mcq=false,nutrs=32,nutmrs=8,"
1696 "wb-max-size=1024,"
1697 "wb-min-size=256" };
1698 QOSGraphTestOptions acpi_eject_test_opts = { .subprocess = true };
1699
1700 add_qpci_address(&edge_opts, &(QPCIAddress){ .devfn = QPCI_DEVFN(4, 0) });
1701
1702 qos_node_create_driver("ufs", ufs_create);
1703 qos_node_consumes("ufs", "pci-bus", &edge_opts);
1704 qos_node_produces("ufs", "pci-device");
1705
1706 qos_add_test("reg-read", "ufs", ufstest_reg_read, NULL);
1707
1708 /*
1709 * Check architecture
1710 * TODO: Enable ufs io tests for ppc64
1711 */
1712 arch = qtest_get_arch();
1713 if (!strcmp(arch, "ppc64")) {
1714 g_test_message("Skipping ufs io tests for ppc64");
1715 return;
1716 }
1717 if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) {
1718 qos_add_test("acpi-eject", "ufs", ufstest_acpi_eject,
1719 &acpi_eject_test_opts);
1720 }
1721 qos_add_test("init", "ufs", ufstest_init, NULL);
1722 qos_add_test("legacy-read-write", "ufs", ufstest_read_write, &io_test_opts);
1723 qos_add_test("mcq-read-write", "ufs", ufstest_read_write, &mcq_test_opts);
1724 qos_add_test("mcq-cq-wraparound", "ufs", ufstest_mcq_cq_wraparound,
1725 &mcq_test_opts);
1726 qos_add_test("query-flag", "ufs", ufstest_query_flag_request,
1727 &io_test_opts);
1728 qos_add_test("query-attribute", "ufs", ufstest_query_attr_request,
1729 &io_test_opts);
1730 qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request,
1731 &io_test_opts);
1732 qos_add_test("wb-init", "ufs", ufstest_wb_init, &wb_test_opts);
1733 qos_add_test("wb-read-write", "ufs", ufstest_wb_read_write, &wb_test_opts);
1734 qos_add_test("hid", "ufs", ufstest_hid, &io_test_opts);
1735 }
1736
1737 libqos_init(ufs_register_nodes);