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 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 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 1060 static void drive_destroy(void *path) 1061 { 1062 unlink(path); 1063 g_free(path); 1064 qos_invalidate_command_line(); 1065 } 1066 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 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 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