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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 /* Write Writable Attributes & Read Again */ 788 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST, 789 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR, 790 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x03, 791 &rsp_upiu); 792 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 793 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 794 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03)); 795 796 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST, 797 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR, 798 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0x07, &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(0x07)); 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_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu); 806 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 807 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 808 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03)); 809 810 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 811 UFS_UPIU_QUERY_OPCODE_READ_ATTR, 812 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu); 813 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 814 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 815 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x07)); 816 817 /* Write Invalid Value (Intended Error) */ 818 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST, 819 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR, 820 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0x10, 821 &rsp_upiu); 822 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR); 823 g_assert_cmpuint(rsp_upiu.header.response, ==, 824 UFS_QUERY_RESULT_INVALID_VALUE); 825 826 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 827 UFS_UPIU_QUERY_OPCODE_READ_ATTR, 828 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu); 829 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 830 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 831 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x03)); 832 833 /* Read Write-Only Attribute (Intended Error) */ 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_SECONDS_PASSED, 0, 0, 0, &rsp_upiu); 837 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR); 838 g_assert_cmpuint(rsp_upiu.header.response, ==, 839 UFS_QUERY_RESULT_NOT_READABLE); 840 841 /* Write Read-Only Attribute (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_POWER_MODE, 0, 0, 0x01, &rsp_upiu); 845 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR); 846 g_assert_cmpuint(rsp_upiu.header.response, ==, 847 UFS_QUERY_RESULT_NOT_WRITEABLE); 848 849 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 850 UFS_UPIU_QUERY_OPCODE_READ_ATTR, 851 UFS_QUERY_ATTR_IDN_POWER_MODE, 0, 0, 0, &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, ==, cpu_to_be32(0x00)); 855 856 /* Reset Written Attributes */ 857 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST, 858 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR, 859 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &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, ==, cpu_to_be32(0x00)); 863 864 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST, 865 UFS_UPIU_QUERY_OPCODE_WRITE_ATTR, 866 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu); 867 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 868 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 869 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00)); 870 871 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 872 UFS_UPIU_QUERY_OPCODE_READ_ATTR, 873 UFS_QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, 0, &rsp_upiu); 874 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 875 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 876 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00)); 877 878 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 879 UFS_UPIU_QUERY_OPCODE_READ_ATTR, 880 UFS_QUERY_ATTR_IDN_EE_CONTROL, 0, 0, 0, &rsp_upiu); 881 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 882 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 883 g_assert_cmpuint(rsp_upiu.qr.value, ==, cpu_to_be32(0x00)); 884 885 ufs_exit(ufs, alloc); 886 } 887 888 static void ufstest_query_desc_request(void *obj, void *data, 889 QGuestAllocator *alloc) 890 { 891 QUfs *ufs = obj; 892 893 enum UtpOcsCodes ocs; 894 UtpUpiuRsp rsp_upiu; 895 ufs_init(ufs, alloc); 896 897 /* Write Descriptor is not supported yet */ 898 899 /* Read Device Descriptor */ 900 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 901 UFS_UPIU_QUERY_OPCODE_READ_DESC, 902 UFS_QUERY_DESC_IDN_DEVICE, 0, 0, 0, &rsp_upiu); 903 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 904 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 905 g_assert_cmpuint(rsp_upiu.qr.opcode, ==, UFS_UPIU_QUERY_OPCODE_READ_DESC); 906 g_assert_cmpuint(rsp_upiu.qr.idn, ==, UFS_QUERY_DESC_IDN_DEVICE); 907 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceDescriptor)); 908 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_DEVICE); 909 910 /* Read Configuration Descriptor is not supported yet*/ 911 912 /* Read Unit Descriptor */ 913 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 914 UFS_UPIU_QUERY_OPCODE_READ_DESC, 915 UFS_QUERY_DESC_IDN_UNIT, 0, 0, 0, &rsp_upiu); 916 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 917 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 918 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor)); 919 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT); 920 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 0); 921 922 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 923 UFS_UPIU_QUERY_OPCODE_READ_DESC, 924 UFS_QUERY_DESC_IDN_UNIT, 1, 0, 0, &rsp_upiu); 925 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 926 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 927 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(UnitDescriptor)); 928 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT); 929 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, 1); 930 931 ocs = 932 ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 933 UFS_UPIU_QUERY_OPCODE_READ_DESC, UFS_QUERY_DESC_IDN_UNIT, 934 UFS_UPIU_RPMB_WLUN, 0, 0, &rsp_upiu); 935 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 936 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 937 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(RpmbUnitDescriptor)); 938 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_UNIT); 939 g_assert_cmpuint(rsp_upiu.qr.data[2], ==, UFS_UPIU_RPMB_WLUN); 940 941 /* Read Interconnect Descriptor */ 942 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 943 UFS_UPIU_QUERY_OPCODE_READ_DESC, 944 UFS_QUERY_DESC_IDN_INTERCONNECT, 0, 0, 0, &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.data[0], ==, sizeof(InterconnectDescriptor)); 948 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_INTERCONNECT); 949 950 /* Read String Descriptor */ 951 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 952 UFS_UPIU_QUERY_OPCODE_READ_DESC, 953 UFS_QUERY_DESC_IDN_STRING, 0, 0, 0, &rsp_upiu); 954 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 955 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 956 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x12); 957 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING); 958 959 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 960 UFS_UPIU_QUERY_OPCODE_READ_DESC, 961 UFS_QUERY_DESC_IDN_STRING, 1, 0, 0, &rsp_upiu); 962 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 963 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 964 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x22); 965 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING); 966 967 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 968 UFS_UPIU_QUERY_OPCODE_READ_DESC, 969 UFS_QUERY_DESC_IDN_STRING, 4, 0, 0, &rsp_upiu); 970 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 971 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 972 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 0x0a); 973 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_STRING); 974 975 /* Read Geometry Descriptor */ 976 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 977 UFS_UPIU_QUERY_OPCODE_READ_DESC, 978 UFS_QUERY_DESC_IDN_GEOMETRY, 0, 0, 0, &rsp_upiu); 979 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 980 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 981 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(GeometryDescriptor)); 982 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_GEOMETRY); 983 984 /* Read Power Descriptor */ 985 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 986 UFS_UPIU_QUERY_OPCODE_READ_DESC, 987 UFS_QUERY_DESC_IDN_POWER, 0, 0, 0, &rsp_upiu); 988 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 989 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 990 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, 991 sizeof(PowerParametersDescriptor)); 992 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_POWER); 993 994 /* Read Health Descriptor */ 995 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 996 UFS_UPIU_QUERY_OPCODE_READ_DESC, 997 UFS_QUERY_DESC_IDN_HEALTH, 0, 0, 0, &rsp_upiu); 998 g_assert_cmpuint(ocs, ==, UFS_OCS_SUCCESS); 999 g_assert_cmpuint(rsp_upiu.header.response, ==, UFS_COMMAND_RESULT_SUCCESS); 1000 g_assert_cmpuint(rsp_upiu.qr.data[0], ==, sizeof(DeviceHealthDescriptor)); 1001 g_assert_cmpuint(rsp_upiu.qr.data[1], ==, UFS_QUERY_DESC_IDN_HEALTH); 1002 1003 /* Invalid Index (Intended Failure) */ 1004 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 1005 UFS_UPIU_QUERY_OPCODE_READ_DESC, 1006 UFS_QUERY_DESC_IDN_UNIT, 4, 0, 0, &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_INVALID_INDEX); 1010 1011 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 1012 UFS_UPIU_QUERY_OPCODE_READ_DESC, 1013 UFS_QUERY_DESC_IDN_STRING, 5, 0, 0, &rsp_upiu); 1014 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR); 1015 g_assert_cmpuint(rsp_upiu.header.response, ==, 1016 UFS_QUERY_RESULT_INVALID_INDEX); 1017 1018 /* Invalid Selector (Intended Failure) */ 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_DEVICE, 0, 1, 0, &rsp_upiu); 1022 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR); 1023 g_assert_cmpuint(rsp_upiu.header.response, ==, 1024 UFS_QUERY_RESULT_INVALID_SELECTOR); 1025 1026 ocs = ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, 1027 UFS_UPIU_QUERY_OPCODE_READ_DESC, 1028 UFS_QUERY_DESC_IDN_STRING, 0, 1, 0, &rsp_upiu); 1029 g_assert_cmpuint(ocs, ==, UFS_OCS_INVALID_CMD_TABLE_ATTR); 1030 g_assert_cmpuint(rsp_upiu.header.response, ==, 1031 UFS_QUERY_RESULT_INVALID_SELECTOR); 1032 1033 ufs_exit(ufs, alloc); 1034 } 1035 1036 static void drive_destroy(void *path) 1037 { 1038 unlink(path); 1039 g_free(path); 1040 qos_invalidate_command_line(); 1041 } 1042 1043 static char *drive_create(void) 1044 { 1045 int fd, ret; 1046 char *t_path; 1047 1048 /* Create a temporary raw image */ 1049 fd = g_file_open_tmp("qtest-ufs.XXXXXX", &t_path, NULL); 1050 g_assert_cmpint(fd, >=, 0); 1051 ret = ftruncate(fd, TEST_IMAGE_SIZE); 1052 g_assert_cmpint(ret, ==, 0); 1053 close(fd); 1054 1055 g_test_queue_destroy(drive_destroy, t_path); 1056 return t_path; 1057 } 1058 1059 static void *ufs_blk_test_setup(GString *cmd_line, void *arg) 1060 { 1061 char *tmp_path = drive_create(); 1062 1063 g_string_append_printf(cmd_line, 1064 " -blockdev file,filename=%s,node-name=drv1 " 1065 "-device ufs-lu,bus=ufs0,drive=drv1,lun=1 ", 1066 tmp_path); 1067 1068 return arg; 1069 } 1070 1071 static void ufs_register_nodes(void) 1072 { 1073 const char *arch; 1074 QOSGraphEdgeOptions edge_opts = { 1075 .before_cmd_line = "-blockdev null-co,node-name=drv0,read-zeroes=on", 1076 .after_cmd_line = "-device ufs-lu,bus=ufs0,drive=drv0,lun=0", 1077 .extra_device_opts = "addr=04.0,id=ufs0" 1078 }; 1079 1080 QOSGraphTestOptions io_test_opts = { .before = ufs_blk_test_setup, 1081 .edge.extra_device_opts = 1082 "mcq=false,nutrs=32,nutmrs=8" }; 1083 1084 QOSGraphTestOptions mcq_test_opts = { .before = ufs_blk_test_setup, 1085 .edge.extra_device_opts = 1086 "mcq=true,mcq-maxq=1" }; 1087 1088 add_qpci_address(&edge_opts, &(QPCIAddress){ .devfn = QPCI_DEVFN(4, 0) }); 1089 1090 qos_node_create_driver("ufs", ufs_create); 1091 qos_node_consumes("ufs", "pci-bus", &edge_opts); 1092 qos_node_produces("ufs", "pci-device"); 1093 1094 qos_add_test("reg-read", "ufs", ufstest_reg_read, NULL); 1095 1096 /* 1097 * Check architecture 1098 * TODO: Enable ufs io tests for ppc64 1099 */ 1100 arch = qtest_get_arch(); 1101 if (!strcmp(arch, "ppc64")) { 1102 g_test_message("Skipping ufs io tests for ppc64"); 1103 return; 1104 } 1105 qos_add_test("init", "ufs", ufstest_init, NULL); 1106 qos_add_test("legacy-read-write", "ufs", ufstest_read_write, &io_test_opts); 1107 qos_add_test("mcq-read-write", "ufs", ufstest_read_write, &mcq_test_opts); 1108 qos_add_test("query-flag", "ufs", ufstest_query_flag_request, 1109 &io_test_opts); 1110 qos_add_test("query-attribute", "ufs", ufstest_query_attr_request, 1111 &io_test_opts); 1112 qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request, 1113 &io_test_opts); 1114 } 1115 1116 libqos_init(ufs_register_nodes); 1117