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 ufs_wreg(ufs, ufs->cqdao[TEST_QID], cqhp);
170
171 return cqentry.status;
172 }
173
174 static enum UtpOcsCodes
ufs_send_transfer_request_sync(QUfs * ufs,uint8_t lun,const UtpTransferReqDesc * utrd)175 ufs_send_transfer_request_sync(QUfs *ufs, uint8_t lun,
176 const UtpTransferReqDesc *utrd)
177 {
178 if (ufs->support_mcq) {
179 return __ufs_send_transfer_request_mcq(ufs, lun, utrd);
180 }
181
182 return __ufs_send_transfer_request_doorbell(ufs, lun, utrd);
183 }
184
ufs_send_nop_out(QUfs * ufs,UtpUpiuRsp * rsp_out)185 static enum UtpOcsCodes ufs_send_nop_out(QUfs *ufs, UtpUpiuRsp *rsp_out)
186 {
187 int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
188 uint64_t req_upiu_addr =
189 ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
190 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
191
192 /* Build up request upiu */
193 UtpUpiuReq req_upiu = { 0 };
194 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_NOP_OUT;
195 req_upiu.header.task_tag = cmd_desc_slot;
196 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
197 sizeof(req_upiu));
198
199 /* Build up utp transfer request descriptor */
200 UtpTransferReqDesc utrd =
201 ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
202
203 /* Send Transfer Request */
204 enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
205
206 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
207 release_cmd_desc_slot(ufs, cmd_desc_slot);
208 return ret;
209 }
210
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)211 static enum UtpOcsCodes ufs_send_query(QUfs *ufs, uint8_t query_function,
212 uint8_t query_opcode, uint8_t idn,
213 uint8_t index, uint8_t selector,
214 uint32_t attr_value, UtpUpiuRsp *rsp_out)
215 {
216 int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
217 uint64_t req_upiu_addr =
218 ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
219 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
220
221 /* Build up request upiu */
222 UtpUpiuReq req_upiu = { 0 };
223 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_QUERY_REQ;
224 req_upiu.header.query_func = query_function;
225 req_upiu.header.task_tag = cmd_desc_slot;
226 /*
227 * QEMU UFS does not currently support Write descriptor,
228 * so the value of data_segment_length is always 0.
229 */
230 req_upiu.header.data_segment_length = 0;
231 req_upiu.qr.opcode = query_opcode;
232 req_upiu.qr.idn = idn;
233 req_upiu.qr.index = index;
234 req_upiu.qr.selector = selector;
235 req_upiu.qr.value = cpu_to_be32(attr_value);
236 req_upiu.qr.length = UFS_QUERY_DESC_MAX_SIZE;
237 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
238 sizeof(req_upiu));
239
240 /* Build up utp transfer request descriptor */
241 UtpTransferReqDesc utrd =
242 ufs_build_req_utrd(req_upiu_addr, UFS_UTP_NO_DATA_TRANSFER, 0);
243
244 /* Send Transfer Request */
245 enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, 0, &utrd);
246
247 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
248 release_cmd_desc_slot(ufs, cmd_desc_slot);
249 return ret;
250 }
251
252 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)253 ufs_send_scsi_command(QUfs *ufs, uint8_t lun, const uint8_t *cdb,
254 const uint8_t *data_in, size_t data_in_len,
255 uint8_t *data_out, size_t data_out_len,
256 UtpUpiuRsp *rsp_out)
257
258 {
259 /* Build up PRDT */
260 UfshcdSgEntry entries[MAX_PRD_ENTRY_COUNT] = {
261 0,
262 };
263 uint8_t flags;
264 uint16_t prd_table_length, i;
265 uint32_t data_direction, data_len;
266 int cmd_desc_slot = alloc_cmd_desc_slot(ufs);
267 uint64_t req_upiu_addr =
268 ufs->cmd_desc_addr + cmd_desc_slot * UTP_COMMAND_DESCRIPTOR_SIZE;
269 uint64_t prdt_addr = req_upiu_addr + UTP_PRDT_UPIU_OFFSET;
270
271 g_assert_true(data_in_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
272 g_assert_true(data_out_len < MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
273 if (data_in_len > 0) {
274 g_assert_nonnull(data_in);
275 data_direction = UFS_UTP_HOST_TO_DEVICE;
276 data_len = data_in_len;
277 flags = UFS_UPIU_CMD_FLAGS_WRITE;
278 } else if (data_out_len > 0) {
279 g_assert_nonnull(data_out);
280 data_direction = UFS_UTP_DEVICE_TO_HOST;
281 data_len = data_out_len;
282 flags = UFS_UPIU_CMD_FLAGS_READ;
283 } else {
284 data_direction = UFS_UTP_NO_DATA_TRANSFER;
285 data_len = 0;
286 flags = UFS_UPIU_CMD_FLAGS_NONE;
287 }
288 prd_table_length = DIV_ROUND_UP(data_len, PRD_ENTRY_DATA_SIZE);
289
290 qtest_memset(ufs->dev.bus->qts, ufs->data_buffer_addr, 0,
291 MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
292 if (data_in_len) {
293 qtest_memwrite(ufs->dev.bus->qts, ufs->data_buffer_addr, data_in,
294 data_in_len);
295 }
296
297 for (i = 0; i < prd_table_length; i++) {
298 entries[i].addr =
299 cpu_to_le64(ufs->data_buffer_addr + i * sizeof(UfshcdSgEntry));
300 if (i + 1 != prd_table_length) {
301 entries[i].size = cpu_to_le32(PRD_ENTRY_DATA_SIZE - 1);
302 } else {
303 entries[i].size = cpu_to_le32(
304 data_len - (PRD_ENTRY_DATA_SIZE * (prd_table_length - 1)) - 1);
305 }
306 }
307 qtest_memwrite(ufs->dev.bus->qts, prdt_addr, entries,
308 prd_table_length * sizeof(UfshcdSgEntry));
309
310 uint64_t rsp_upiu_addr = req_upiu_addr + UTP_RESPONSE_UPIU_OFFSET;
311
312 /* Build up request upiu */
313 UtpUpiuReq req_upiu = { 0 };
314 req_upiu.header.trans_type = UFS_UPIU_TRANSACTION_COMMAND;
315 req_upiu.header.flags = flags;
316 req_upiu.header.lun = lun;
317 req_upiu.header.task_tag = cmd_desc_slot;
318 req_upiu.sc.exp_data_transfer_len = cpu_to_be32(data_len);
319 memcpy(req_upiu.sc.cdb, cdb, UFS_CDB_SIZE);
320 qtest_memwrite(ufs->dev.bus->qts, req_upiu_addr, &req_upiu,
321 sizeof(req_upiu));
322
323 /* Build up utp transfer request descriptor */
324 UtpTransferReqDesc utrd =
325 ufs_build_req_utrd(req_upiu_addr, data_direction, prd_table_length);
326
327 /* Send Transfer Request */
328 enum UtpOcsCodes ret = ufs_send_transfer_request_sync(ufs, lun, &utrd);
329
330 qtest_memread(ufs->dev.bus->qts, rsp_upiu_addr, rsp_out, sizeof(*rsp_out));
331 if (data_out_len) {
332 qtest_memread(ufs->dev.bus->qts, ufs->data_buffer_addr, data_out,
333 data_out_len);
334 }
335 release_cmd_desc_slot(ufs, cmd_desc_slot);
336 return ret;
337 }
338
339 /**
340 * Initialize Ufs host controller and logical unit.
341 * After running this function, you can make a transfer request to the UFS.
342 */
ufs_init(QUfs * ufs,QGuestAllocator * alloc)343 static void ufs_init(QUfs *ufs, QGuestAllocator *alloc)
344 {
345 uint64_t end_time;
346 uint32_t nutrs;
347 uint32_t hcs, is, ucmdarg2, cap;
348 uint32_t hce = 0, ie = 0;
349 enum UtpOcsCodes ocs;
350 UtpUpiuRsp rsp_upiu;
351
352 ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
353 qpci_device_enable(&ufs->dev);
354
355 /* Start host controller initialization */
356 hce = FIELD_DP32(hce, HCE, HCE, 1);
357 ufs_wreg(ufs, A_HCE, hce);
358
359 /* Wait for device to reset */
360 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
361 do {
362 qtest_clock_step(ufs->dev.bus->qts, 100);
363 hce = FIELD_EX32(ufs_rreg(ufs, A_HCE), HCE, HCE);
364 } while (hce == 0 && g_get_monotonic_time() < end_time);
365 g_assert_cmpuint(hce, ==, 1);
366
367 /* Enable interrupt */
368 ie = FIELD_DP32(ie, IE, UCCE, 1);
369 ie = FIELD_DP32(ie, IE, UHESE, 1);
370 ie = FIELD_DP32(ie, IE, UHXSE, 1);
371 ie = FIELD_DP32(ie, IE, UPMSE, 1);
372 ufs_wreg(ufs, A_IE, ie);
373
374 /* Send DME_LINK_STARTUP uic command */
375 hcs = ufs_rreg(ufs, A_HCS);
376 g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
377
378 ufs_wreg(ufs, A_UCMDARG1, 0);
379 ufs_wreg(ufs, A_UCMDARG2, 0);
380 ufs_wreg(ufs, A_UCMDARG3, 0);
381 ufs_wreg(ufs, A_UICCMD, UFS_UIC_CMD_DME_LINK_STARTUP);
382
383 is = ufs_rreg(ufs, A_IS);
384 g_assert_true(FIELD_EX32(is, IS, UCCS));
385 ufs_wreg(ufs, A_IS, FIELD_DP32(0, IS, UCCS, 1));
386
387 ucmdarg2 = ufs_rreg(ufs, A_UCMDARG2);
388 g_assert_cmpuint(ucmdarg2, ==, 0);
389 is = ufs_rreg(ufs, A_IS);
390 g_assert_cmpuint(is, ==, 0);
391 hcs = ufs_rreg(ufs, A_HCS);
392 g_assert_true(FIELD_EX32(hcs, HCS, DP));
393 g_assert_true(FIELD_EX32(hcs, HCS, UTRLRDY));
394 g_assert_true(FIELD_EX32(hcs, HCS, UCRDY));
395
396 /* Check MCQ support */
397 cap = ufs_rreg(ufs, A_CAP);
398 ufs->support_mcq = FIELD_EX32(cap, CAP, MCQS);
399
400 /* Enable all interrupt functions */
401 ie = FIELD_DP32(ie, IE, UTRCE, 1);
402 ie = FIELD_DP32(ie, IE, UEE, 1);
403 ie = FIELD_DP32(ie, IE, UPMSE, 1);
404 ie = FIELD_DP32(ie, IE, UHXSE, 1);
405 ie = FIELD_DP32(ie, IE, UHESE, 1);
406 ie = FIELD_DP32(ie, IE, UTMRCE, 1);
407 ie = FIELD_DP32(ie, IE, UCCE, 1);
408 ie = FIELD_DP32(ie, IE, DFEE, 1);
409 ie = FIELD_DP32(ie, IE, HCFEE, 1);
410 ie = FIELD_DP32(ie, IE, SBFEE, 1);
411 ie = FIELD_DP32(ie, IE, CEFEE, 1);
412 if (ufs->support_mcq) {
413 ie = FIELD_DP32(ie, IE, CQEE, 1);
414 }
415 ufs_wreg(ufs, A_IE, ie);
416 ufs_wreg(ufs, A_UTRIACR, 0);
417
418 /* Enable transfer request */
419 ufs->cmd_desc_addr =
420 guest_alloc(alloc, UFS_MAX_CMD_DESC * UTP_COMMAND_DESCRIPTOR_SIZE);
421 ufs->data_buffer_addr =
422 guest_alloc(alloc, MAX_PRD_ENTRY_COUNT * PRD_ENTRY_DATA_SIZE);
423
424 if (ufs->support_mcq) {
425 uint32_t mcqcap, qid, qcfgptr, mcq_reg_offset;
426 uint32_t cqattr = 0, sqattr = 0;
427
428 mcqcap = ufs_rreg(ufs, A_MCQCAP);
429 qcfgptr = FIELD_EX32(mcqcap, MCQCAP, QCFGPTR);
430 ufs->maxq = FIELD_EX32(mcqcap, MCQCAP, MAXQ) + 1;
431 for (qid = 0; qid < ufs->maxq; ++qid) {
432 ufs->sqlba[qid] =
433 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
434 ufs->cqlba[qid] =
435 guest_alloc(alloc, QUEUE_SIZE * sizeof(UtpTransferReqDesc));
436 mcq_reg_offset = qcfgptr * 0x200 + qid * 0x40;
437
438 ufs_wreg(ufs, mcq_reg_offset + A_SQLBA,
439 ufs->sqlba[qid] & 0xffffffff);
440 ufs_wreg(ufs, mcq_reg_offset + A_SQUBA, ufs->sqlba[qid] >> 32);
441 ufs_wreg(ufs, mcq_reg_offset + A_CQLBA,
442 ufs->cqlba[qid] & 0xffffffff);
443 ufs_wreg(ufs, mcq_reg_offset + A_CQUBA, ufs->cqlba[qid] >> 32);
444
445 /* Enable Completion Queue */
446 cqattr = FIELD_DP32(cqattr, CQATTR, CQEN, 1);
447 cqattr = FIELD_DP32(cqattr, CQATTR, SIZE,
448 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
449 DWORD_BYTE);
450 ufs_wreg(ufs, mcq_reg_offset + A_CQATTR, cqattr);
451
452 /* Enable Submission Queue */
453 sqattr = FIELD_DP32(sqattr, SQATTR, SQEN, 1);
454 sqattr = FIELD_DP32(sqattr, SQATTR, SIZE,
455 QUEUE_SIZE * sizeof(UtpTransferReqDesc) /
456 DWORD_BYTE);
457 sqattr = FIELD_DP32(sqattr, SQATTR, CQID, qid);
458 ufs_wreg(ufs, mcq_reg_offset + A_SQATTR, sqattr);
459
460 /* Cache head & tail pointer */
461 ufs->sqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_SQDAO);
462 ufs->cqdao[qid] = ufs_rreg(ufs, mcq_reg_offset + A_CQDAO);
463 }
464 } else {
465 nutrs = FIELD_EX32(cap, CAP, NUTRS) + 1;
466 ufs->utrlba = guest_alloc(alloc, nutrs * sizeof(UtpTransferReqDesc));
467
468 ufs_wreg(ufs, A_UTRLBA, ufs->utrlba & 0xffffffff);
469 ufs_wreg(ufs, A_UTRLBAU, ufs->utrlba >> 32);
470 ufs_wreg(ufs, A_UTRLRSR, 1);
471 }
472
473 /* Send nop out to test transfer request */
474 ocs = ufs_send_nop_out(ufs, &rsp_upiu);
475 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
476
477 /* Set fDeviceInit flag via query request */
478 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
479 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
480 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
481 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
482 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
483
484 /* Wait for device to reset */
485 end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
486 do {
487 qtest_clock_step(ufs->dev.bus->qts, 100);
488 ocs =
489 ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
490 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
491 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
492 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
493 g_assert_cmpuint(rsp_upiu.header.response, ==,
494 UFS_COMMAND_RESULT_SUCCESS);
495 } while (be32_to_cpu(rsp_upiu.qr.value) != 0 &&
496 g_get_monotonic_time() < end_time);
497 g_assert_cmpuint(be32_to_cpu(rsp_upiu.qr.value), ==, 0);
498
499 ufs->enabled = true;
500 }
501
ufs_exit(QUfs * ufs,QGuestAllocator * alloc)502 static void ufs_exit(QUfs *ufs, QGuestAllocator *alloc)
503 {
504 if (ufs->enabled) {
505 if (ufs->support_mcq) {
506 for (uint32_t qid = 0; qid < ufs->maxq; ++qid) {
507 guest_free(alloc, ufs->sqlba[qid]);
508 guest_free(alloc, ufs->cqlba[qid]);
509 }
510 } else {
511 guest_free(alloc, ufs->utrlba);
512 }
513
514 guest_free(alloc, ufs->cmd_desc_addr);
515 guest_free(alloc, ufs->data_buffer_addr);
516 }
517
518 qpci_iounmap(&ufs->dev, ufs->bar);
519 }
520
ufs_get_driver(void * obj,const char * interface)521 static void *ufs_get_driver(void *obj, const char *interface)
522 {
523 QUfs *ufs = obj;
524
525 if (!g_strcmp0(interface, "pci-device")) {
526 return &ufs->dev;
527 }
528
529 fprintf(stderr, "%s not present in ufs\n", interface);
530 g_assert_not_reached();
531 }
532
ufs_create(void * pci_bus,QGuestAllocator * alloc,void * addr)533 static void *ufs_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
534 {
535 QUfs *ufs = g_new0(QUfs, 1);
536 QPCIBus *bus = pci_bus;
537
538 qpci_device_init(&ufs->dev, bus, addr);
539 ufs->obj.get_driver = ufs_get_driver;
540
541 return &ufs->obj;
542 }
543
ufstest_reg_read(void * obj,void * data,QGuestAllocator * alloc)544 static void ufstest_reg_read(void *obj, void *data, QGuestAllocator *alloc)
545 {
546 QUfs *ufs = obj;
547 uint32_t cap;
548
549 ufs->bar = qpci_iomap(&ufs->dev, 0, NULL);
550 qpci_device_enable(&ufs->dev);
551
552 cap = ufs_rreg(ufs, A_CAP);
553 g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTRS), ==, 31);
554 g_assert_cmpuint(FIELD_EX32(cap, CAP, NUTMRS), ==, 7);
555 g_assert_cmpuint(FIELD_EX32(cap, CAP, 64AS), ==, 1);
556
557 qpci_iounmap(&ufs->dev, ufs->bar);
558 }
559
ufstest_init(void * obj,void * data,QGuestAllocator * alloc)560 static void ufstest_init(void *obj, void *data, QGuestAllocator *alloc)
561 {
562 QUfs *ufs = obj;
563
564 uint8_t buf[4096] = { 0 };
565 const uint8_t report_luns_cdb[UFS_CDB_SIZE] = {
566 /* allocation length 4096 */
567 REPORT_LUNS, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x10, 0x00, 0x00, 0x00
569 };
570 const uint8_t test_unit_ready_cdb[UFS_CDB_SIZE] = {
571 TEST_UNIT_READY,
572 };
573 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
574 REQUEST_SENSE,
575 };
576 enum UtpOcsCodes ocs;
577 UtpUpiuRsp rsp_upiu;
578
579 ufs_init(ufs, alloc);
580
581 /* Check REPORT_LUNS */
582 ocs = ufs_send_scsi_command(ufs, 0, report_luns_cdb, NULL, 0, buf,
583 sizeof(buf), &rsp_upiu);
584 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
585 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
586 /* LUN LIST LENGTH should be 8, in big endian */
587 g_assert_cmpuint(buf[3], ==, 8);
588 /* There is one logical unit whose lun is 0 */
589 g_assert_cmpuint(buf[9], ==, 0);
590
591 /* Clear Unit Attention */
592 ocs = ufs_send_scsi_command(ufs, 0, request_sense_cdb, NULL, 0, buf,
593 sizeof(buf), &rsp_upiu);
594 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
595 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
596
597 /* Check TEST_UNIT_READY */
598 ocs = ufs_send_scsi_command(ufs, 0, test_unit_ready_cdb, NULL, 0, NULL, 0,
599 &rsp_upiu);
600 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
601 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, GOOD);
602
603 ufs_exit(ufs, alloc);
604 }
605
ufstest_read_write(void * obj,void * data,QGuestAllocator * alloc)606 static void ufstest_read_write(void *obj, void *data, QGuestAllocator *alloc)
607 {
608 QUfs *ufs = obj;
609 uint8_t read_buf[4096] = { 0 };
610 uint8_t write_buf[4096] = { 0 };
611 const uint8_t read_capacity_cdb[UFS_CDB_SIZE] = {
612 /* allocation length 4096 */
613 SERVICE_ACTION_IN_16,
614 SAI_READ_CAPACITY_16,
615 0x00,
616 0x00,
617 0x00,
618 0x00,
619 0x00,
620 0x00,
621 0x00,
622 0x00,
623 0x00,
624 0x00,
625 0x10,
626 0x00,
627 0x00,
628 0x00
629 };
630 const uint8_t request_sense_cdb[UFS_CDB_SIZE] = {
631 REQUEST_SENSE,
632 };
633 const uint8_t read_cdb[UFS_CDB_SIZE] = {
634 /* READ(10) to LBA 0, transfer length 1 */
635 READ_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
636 };
637 const uint8_t write_cdb[UFS_CDB_SIZE] = {
638 /* WRITE(10) to LBA 0, transfer length 1 */
639 WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
640 };
641 uint32_t block_size;
642 enum UtpOcsCodes ocs;
643 UtpUpiuRsp rsp_upiu;
644 const int test_lun = 1;
645
646 ufs_init(ufs, alloc);
647
648 /* Clear Unit Attention */
649 ocs = ufs_send_scsi_command(ufs, test_lun, request_sense_cdb, NULL, 0,
650 read_buf, sizeof(read_buf), &rsp_upiu);
651 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
652 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==, CHECK_CONDITION);
653
654 /* Read capacity */
655 ocs = ufs_send_scsi_command(ufs, test_lun, read_capacity_cdb, NULL, 0,
656 read_buf, sizeof(read_buf), &rsp_upiu);
657 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
658 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
659 UFS_COMMAND_RESULT_SUCCESS);
660 block_size = ldl_be_p(&read_buf[8]);
661 g_assert_cmpuint(block_size, ==, 4096);
662
663 /* Write data */
664 memset(write_buf, 0xab, block_size);
665 ocs = ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf, block_size,
666 NULL, 0, &rsp_upiu);
667 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
668 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
669 UFS_COMMAND_RESULT_SUCCESS);
670
671 /* Read data and verify */
672 ocs = ufs_send_scsi_command(ufs, test_lun, read_cdb, NULL, 0, read_buf,
673 block_size, &rsp_upiu);
674 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
675 g_assert_cmpuint(rsp_upiu.header.scsi_status, ==,
676 UFS_COMMAND_RESULT_SUCCESS);
677 g_assert_cmpint(memcmp(read_buf, write_buf, block_size), ==, 0);
678
679 ufs_exit(ufs, alloc);
680 }
681
ufstest_query_flag_request(void * obj,void * data,QGuestAllocator * alloc)682 static void ufstest_query_flag_request(void *obj, void *data,
683 QGuestAllocator *alloc)
684 {
685 QUfs *ufs = obj;
686
687 enum UtpOcsCodes ocs;
688 UtpUpiuRsp rsp_upiu;
689 ufs_init(ufs, alloc);
690
691 /* Read read-only flag */
692 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
693 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
694 UFS_QUERY_FLAG_IDN_FDEVICEINIT, 0, 0, 0, &rsp_upiu);
695 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
696 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
697 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_FLAG);
698 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_FLAG_IDN_FDEVICEINIT);
699 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
700
701 /* Flag Set, Clear, Toggle Test with fDeviceLifeSpanModeEn */
702 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
703 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
704 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
705 &rsp_upiu);
706 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
707 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
708 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
709
710 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
711 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
712 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
713 &rsp_upiu);
714 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
715 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
716 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
717
718 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
719 UFS_UPIU_QUERY_OPCODE_CLEAR_FLAG,
720 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
721 &rsp_upiu);
722 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
723 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
724 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
725
726 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
727 UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
728 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
729 &rsp_upiu);
730 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
731 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
732 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(1));
733
734 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
735 UFS_UPIU_QUERY_OPCODE_TOGGLE_FLAG,
736 UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE, 0, 0, 0,
737 &rsp_upiu);
738 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
739 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
740 g_assert_cmpuint(rsp_upiu.qr.value, ==, be32_to_cpu(0));
741
742 /* Read Write-only Flag (Intended Failure) */
743 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
744 UFS_UPIU_QUERY_OPCODE_READ_FLAG,
745 UFS_QUERY_FLAG_IDN_PURGE_ENABLE, 0, 0, 0, &rsp_upiu);
746 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
747 g_assert_cmpuint(rsp_upiu.header.response, ==,
748 UFS_QUERY_RESULT_NOT_READABLE);
749
750 /* Write Read-Only Flag (Intended Failure) */
751 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
752 UFS_UPIU_QUERY_OPCODE_SET_FLAG,
753 UFS_QUERY_FLAG_IDN_BUSY_RTC, 0, 0, 0, &rsp_upiu);
754 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
755 g_assert_cmpuint(rsp_upiu.header.response, ==,
756 UFS_QUERY_RESULT_NOT_WRITEABLE);
757
758 ufs_exit(ufs, alloc);
759 }
760
ufstest_query_attr_request(void * obj,void * data,QGuestAllocator * alloc)761 static void ufstest_query_attr_request(void *obj, void *data,
762 QGuestAllocator *alloc)
763 {
764 QUfs *ufs = obj;
765
766 enum UtpOcsCodes ocs;
767 UtpUpiuRsp rsp_upiu;
768 ufs_init(ufs, alloc);
769
770 /* Read Readable Attributes*/
771 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
772 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
773 UFS_QUERY_ATTR_IDN_BOOT_LU_EN, 0, 0, 0, &rsp_upiu);
774 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
775 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
776 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_ATTR);
777 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_ATTR_IDN_BOOT_LU_EN);
778 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
779
780 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
781 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
782 UFS_QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, 0, &rsp_upiu);
783 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
784 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
785 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
786
787 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
788 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
789 UFS_QUERY_ATTR_IDN_CASE_ROUGH_TEMP, 0, 0, 0,
790 &rsp_upiu);
791 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
792 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
793 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
794
795 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
796 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
797 UFS_QUERY_ATTR_IDN_HIGH_TEMP_BOUND, 0, 0, 0,
798 &rsp_upiu);
799 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
800 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
801 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(160));
802
803 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
804 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
805 UFS_QUERY_ATTR_IDN_LOW_TEMP_BOUND, 0, 0, 0,
806 &rsp_upiu);
807 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
808 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
809 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(60));
810
811 /* Write Writable Attributes & Read Again */
812 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
813 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
814 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x03,
815 &rsp_upiu);
816 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
817 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
818 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
819
820 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
821 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
822 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0x07, &rsp_upiu);
823 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
824 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
825 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07));
826
827 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
828 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
829 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &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, ==, cpu_to_be32(0x03));
833
834 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
835 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
836 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
837 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
838 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
839 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07));
840
841 /* Write Invalid Value (Intended Error) */
842 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
843 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
844 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x10,
845 &rsp_upiu);
846 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
847 g_assert_cmpuint(rsp_upiu.header.response, ==,
848 UFS_QUERY_RESULT_INVALID_VALUE);
849
850 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
851 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
852 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
853 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
854 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
855 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03));
856
857 /* Read Write-Only Attribute (Intended Error) */
858 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
859 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
860 UFS_QUERY_ATTR_IDN_SECONDS_PASSED, 0, 0, 0, &rsp_upiu);
861 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
862 g_assert_cmpuint(rsp_upiu.header.response, ==,
863 UFS_QUERY_RESULT_NOT_READABLE);
864
865 /* Write Read-Only Attribute (Intended Error) */
866 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
867 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
868 UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0x01, &rsp_upiu);
869 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
870 g_assert_cmpuint(rsp_upiu.header.response, ==,
871 UFS_QUERY_RESULT_NOT_WRITEABLE);
872
873 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
874 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
875 UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0, &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, ==, cpu_to_be32(0x00));
879
880 /* Reset Written Attributes */
881 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
882 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
883 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu);
884 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
885 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
886 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
887
888 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST,
889 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR,
890 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
891 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
892 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
893 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
894
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_ACTIVE_ICC_LVL, 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.value, ==, cpu_to_be32(0x00));
901
902 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
903 UFS_UPIU_QUERY_OPCODE_READ_ATTR,
904 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu);
905 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
906 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
907 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00));
908
909 ufs_exit(ufs, alloc);
910 }
911
ufstest_query_desc_request(void * obj,void * data,QGuestAllocator * alloc)912 static void ufstest_query_desc_request(void *obj, void *data,
913 QGuestAllocator *alloc)
914 {
915 QUfs *ufs = obj;
916
917 enum UtpOcsCodes ocs;
918 UtpUpiuRsp rsp_upiu;
919 ufs_init(ufs, alloc);
920
921 /* Write Descriptor is not supported yet */
922
923 /* Read Device Descriptor */
924 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
925 UFS_UPIU_QUERY_OPCODE_READ_DESC,
926 UFS_QUERY_DESC_IDN_DEVICE, 0, 0, 0, &rsp_upiu);
927 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
928 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
929 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_DESC);
930 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_DESC_IDN_DEVICE);
931 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceDescriptor));
932 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_DEVICE);
933
934 /* Read Configuration Descriptor is not supported yet*/
935
936 /* Read Unit Descriptor */
937 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
938 UFS_UPIU_QUERY_OPCODE_READ_DESC,
939 UFS_QUERY_DESC_IDN_UNIT, 0, 0, 0, &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.data[0], ==, sizeof(UnitDescriptor));
943 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
944 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 0);
945
946 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
947 UFS_UPIU_QUERY_OPCODE_READ_DESC,
948 UFS_QUERY_DESC_IDN_UNIT, 1, 0, 0, &rsp_upiu);
949 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
950 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
951 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor));
952 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
953 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 1);
954
955 ocs =
956 ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
957 UFS_UPIU_QUERY_OPCODE_READ_DESC, UFS_QUERY_DESC_IDN_UNIT,
958 UFS_UPIU_RPMB_WLUN, 0, 0, &rsp_upiu);
959 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
960 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
961 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(RpmbUnitDescriptor));
962 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT);
963 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, UFS_UPIU_RPMB_WLUN);
964
965 /* Read Interconnect Descriptor */
966 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
967 UFS_UPIU_QUERY_OPCODE_READ_DESC,
968 UFS_QUERY_DESC_IDN_INTERCONNECT, 0, 0, 0, &rsp_upiu);
969 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
970 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
971 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(InterconnectDescriptor));
972 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_INTERCONNECT);
973
974 /* Read String Descriptor */
975 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
976 UFS_UPIU_QUERY_OPCODE_READ_DESC,
977 UFS_QUERY_DESC_IDN_STRING, 0, 0, 0, &rsp_upiu);
978 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
979 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
980 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x12);
981 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
982
983 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
984 UFS_UPIU_QUERY_OPCODE_READ_DESC,
985 UFS_QUERY_DESC_IDN_STRING, 1, 0, 0, &rsp_upiu);
986 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
987 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
988 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x22);
989 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
990
991 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
992 UFS_UPIU_QUERY_OPCODE_READ_DESC,
993 UFS_QUERY_DESC_IDN_STRING, 4, 0, 0, &rsp_upiu);
994 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
995 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
996 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x0a);
997 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING);
998
999 /* Read Geometry Descriptor */
1000 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1001 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1002 UFS_QUERY_DESC_IDN_GEOMETRY, 0, 0, 0, &rsp_upiu);
1003 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1004 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1005 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(GeometryDescriptor));
1006 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_GEOMETRY);
1007
1008 /* Read Power Descriptor */
1009 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1010 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1011 UFS_QUERY_DESC_IDN_POWER, 0, 0, 0, &rsp_upiu);
1012 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS);
1013 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS);
1014 g_assert_cmpuint(rsp_upiu.qr.data[0], ==,
1015 sizeof(PowerParametersDescriptor));
1016 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_POWER);
1017
1018 /* Read Health Descriptor */
1019 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1020 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1021 UFS_QUERY_DESC_IDN_HEALTH, 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.data[0], ==, sizeof(DeviceHealthDescriptor));
1025 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_HEALTH);
1026
1027 /* Invalid Index (Intended Failure) */
1028 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1029 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1030 UFS_QUERY_DESC_IDN_UNIT, 4, 0, 0, &rsp_upiu);
1031 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1032 g_assert_cmpuint(rsp_upiu.header.response, ==,
1033 UFS_QUERY_RESULT_INVALID_INDEX);
1034
1035 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1036 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1037 UFS_QUERY_DESC_IDN_STRING, 5, 0, 0, &rsp_upiu);
1038 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1039 g_assert_cmpuint(rsp_upiu.header.response, ==,
1040 UFS_QUERY_RESULT_INVALID_INDEX);
1041
1042 /* Invalid Selector (Intended Failure) */
1043 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1044 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1045 UFS_QUERY_DESC_IDN_DEVICE, 0, 1, 0, &rsp_upiu);
1046 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1047 g_assert_cmpuint(rsp_upiu.header.response, ==,
1048 UFS_QUERY_RESULT_INVALID_SELECTOR);
1049
1050 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST,
1051 UFS_UPIU_QUERY_OPCODE_READ_DESC,
1052 UFS_QUERY_DESC_IDN_STRING, 0, 1, 0, &rsp_upiu);
1053 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR);
1054 g_assert_cmpuint(rsp_upiu.header.response, ==,
1055 UFS_QUERY_RESULT_INVALID_SELECTOR);
1056
1057 ufs_exit(ufs, alloc);
1058 }
1059
drive_destroy(void * path)1060 static void drive_destroy(void *path)
1061 {
1062 unlink(path);
1063 g_free(path);
1064 qos_invalidate_command_line();
1065 }
1066
drive_create(void)1067 static char *drive_create(void)
1068 {
1069 int fd, ret;
1070 char *t_path;
1071
1072 /* Create a temporary raw image */
1073 fd = g_file_open_tmp("qtest-ufs.XXXXXX", &t_path, NULL);
1074 g_assert_cmpint(fd, >=, 0);
1075 ret = ftruncate(fd, TEST_IMAGE_SIZE);
1076 g_assert_cmpint(ret, ==, 0);
1077 close(fd);
1078
1079 g_test_queue_destroy(drive_destroy, t_path);
1080 return t_path;
1081 }
1082
ufs_blk_test_setup(GString * cmd_line,void * arg)1083 static void *ufs_blk_test_setup(GString *cmd_line, void *arg)
1084 {
1085 char *tmp_path = drive_create();
1086
1087 g_string_append_printf(cmd_line,
1088 " -blockdev file,filename=%s,node-name=drv1 "
1089 "-device ufs-lu,bus=ufs0,drive=drv1,lun=1 ",
1090 tmp_path);
1091
1092 return arg;
1093 }
1094
ufs_register_nodes(void)1095 static void ufs_register_nodes(void)
1096 {
1097 const char *arch;
1098 QOSGraphEdgeOptions edge_opts = {
1099 .before_cmd_line = "-blockdev null-co,node-name=drv0,read-zeroes=on",
1100 .after_cmd_line = "-device ufs-lu,bus=ufs0,drive=drv0,lun=0",
1101 .extra_device_opts = "addr=04.0,id=ufs0"
1102 };
1103
1104 QOSGraphTestOptions io_test_opts = { .before = ufs_blk_test_setup,
1105 .edge.extra_device_opts =
1106 "mcq=false,nutrs=32,nutmrs=8" };
1107
1108 QOSGraphTestOptions mcq_test_opts = { .before = ufs_blk_test_setup,
1109 .edge.extra_device_opts =
1110 "mcq=true,mcq-maxq=1" };
1111
1112 add_qpci_address(&edge_opts, &(QPCIAddress){ .devfn = QPCI_DEVFN(4, 0) });
1113
1114 qos_node_create_driver("ufs", ufs_create);
1115 qos_node_consumes("ufs", "pci-bus", &edge_opts);
1116 qos_node_produces("ufs", "pci-device");
1117
1118 qos_add_test("reg-read", "ufs", ufstest_reg_read, NULL);
1119
1120 /*
1121 * Check architecture
1122 * TODO: Enable ufs io tests for ppc64
1123 */
1124 arch = qtest_get_arch();
1125 if (!strcmp(arch, "ppc64")) {
1126 g_test_message("Skipping ufs io tests for ppc64");
1127 return;
1128 }
1129 qos_add_test("init", "ufs", ufstest_init, NULL);
1130 qos_add_test("legacy-read-write", "ufs", ufstest_read_write, &io_test_opts);
1131 qos_add_test("mcq-read-write", "ufs", ufstest_read_write, &mcq_test_opts);
1132 qos_add_test("query-flag", "ufs", ufstest_query_flag_request,
1133 &io_test_opts);
1134 qos_add_test("query-attribute", "ufs", ufstest_query_attr_request,
1135 &io_test_opts);
1136 qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request,
1137 &io_test_opts);
1138 }
1139
1140 libqos_init(ufs_register_nodes);
1141