bool CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw exception(); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw exception(); return true; }
void CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); gCtrlrConfig->SetIOSQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); }
void UnsupportRsvdFields_r11b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Create admin queues ACQ and ASQ for test lifetime"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); // Test async events without setting the rsvd bits in the cmd. TestAsyncEvents(acq, asq, false); // Test async events by setting the rsvd bits in the cmd. TestAsyncEvents(acq, asq, true); }
bool CreateACQASQ_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) This is the 1st within GrpBasicInit. * 2) The NVME device is disabled * 3) All interrupts are disabled. * \endverbatim */ KernelAPI::DumpKernelMetrics(mFd, FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "before")); // After disabling the defaults for AMS & CSS are fine, no need to modify if (gCtrlrConfig->SetMPS() == false) throw exception(); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw exception(); KernelAPI::DumpKernelMetrics(mFd, FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "after")); return true; }
void InvalidQID_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ string work; bool enableLog; uint64_t maxIOQEntries = 2; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Create admin queues ACQ and ASQ"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); // Calc X, max no. of IOCQ's DUT supports. uint32_t X = gInformative->GetFeaturesNumOfIOCQs(); LOG_NRM("Maximum num of IOCQ's DUT will support = %d", X); LOG_NRM("Setup element size for the IOCQ"); gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); LOG_NRM("Issue CreateIOCQ cmds with QID's ranging from %d to %d", (X + 1), MAX_IOQ_ID); list<uint32_t> illegalQIDs = GetIllegalQIDs(X + 1); for (list<uint32_t>::iterator qId = illegalQIDs.begin(); qId != illegalQIDs.end(); qId++) { LOG_NRM("Process each CreateIOCQCmd with iocq id #%d", *qId); SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(gDutFd)); iocq->Init(*qId, maxIOQEntries, true, 0); SharedCreateIOCQPtr createIOCQCmd = SharedCreateIOCQPtr(new CreateIOCQ()); createIOCQCmd->Init(iocq); work = str(boost::format("iocqId.%d") % *qId); enableLog = false; if ((*qId <= (X + 8)) || (*qId >= (MAX_IOQ_ID - 8))) enableLog = true; LOG_NRM("Send and reap cmd with CQ ID #%d", *qId); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, createIOCQCmd, work, enableLog, CESTAT_INVALID_QID); } }
void UnsupportRsvdFields_r11b::SendAsyncEventRequests(SharedASQPtr &asq, uint32_t nCmds, bool rsvd) { uint16_t uniqueId; string work; LOG_NRM("Create aync event request cmd"); SharedAsyncEventReqPtr asyncEventReqCmd = SharedAsyncEventReqPtr(new AsyncEventReq()); if (rsvd == true) { LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = asyncEventReqCmd->GetDword(0); work |= 0x00007c00; // Set DW0_b14:10 bits asyncEventReqCmd->SetDword(work, 0); for (uint32_t dw = 2; dw <= 15; dw++) asyncEventReqCmd->SetDword(0xffffffff, dw); } else { LOG_NRM("Reserved bits in the cmd are not set"); } for (uint32_t i = 0; i < nCmds; i++) { LOG_NRM("Send the async event request cmd to hdw via ASQ"); asq->Send(asyncEventReqCmd, uniqueId); work = str(boost::format("asyncEventReq.%d") % i); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq", work), "Before doorbell ring"); asq->Ring(); } }
void AdminQFull_r10b::AdminQFull(uint16_t numASQEntries, uint16_t numACQEntries, SharedIdentifyPtr idCmdCtrlr) { uint32_t numCE; uint32_t isrCount; uint16_t uniqueId; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); // Create Admin Q Objects for test lifetime SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(mFd))) acq->Init(numACQEntries); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(mFd))) asq->Init(numASQEntries); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); uint32_t nCmdsToSubmit = numASQEntries - 1; LOG_NRM("Send #%d cmds to hdw via ASQ", nCmdsToSubmit); for (uint32_t nCmds = 0; nCmds < nCmdsToSubmit; nCmds++) { LOG_NRM("Sending #%d of #%d Identify Cmds thru ASQ", nCmds + 1, nCmdsToSubmit); asq->Send(idCmdCtrlr, uniqueId); asq->Ring(); LOG_NRM("Wait for the CE to arrive in ACQ"); if (acq->ReapInquiryWaitSpecify(DEFAULT_CMD_WAIT_ms, (nCmds + 1), numCE, isrCount) == false) { // when asq size = acq size + 1, last CE will never arrive. if ((numASQEntries == numACQEntries + 1) && (nCmds == nCmdsToSubmit - 1)) { // Reap one element from IOCQ to make room for last CE. IO::ReapCE(acq, 1, isrCount, mGrpName, mTestName, "ACQCE", CESTAT_SUCCESS); if (acq->ReapInquiryWaitSpecify(DEFAULT_CMD_WAIT_ms, nCmds, numCE, isrCount) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq." + idCmdCtrlr->GetName()), "Dump entire ACQ"); throw FrmwkEx(HERE, "Unable to see last CE as expected"); } break; } acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq." + idCmdCtrlr->GetName()), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to see CE for issued cmd #%d", nCmds + 1); } else if (numCE != nCmds + 1) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq." + idCmdCtrlr->GetName()), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Missing last CE, #%d cmds of #%d received", nCmds + 1, numCE); } } }
void CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) This is the 1st within GrpBasicInit. * \endverbatim */ static uint32_t NumEntriesIOQ = 2; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); { uint64_t maxIOQEntries; // Determine the max IOQ entries supported if (gRegisters->Read(CTLSPC_CAP, maxIOQEntries) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); maxIOQEntries &= CAP_MQES; maxIOQEntries += 1; // convert to 1-based if (maxIOQEntries < (uint64_t)NumEntriesIOQ) { LOG_NRM("Changing number of Q elements from %d to %lld", NumEntriesIOQ, (unsigned long long)maxIOQEntries); NumEntriesIOQ = maxIOQEntries; } gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); Queues::CreateIOCQContigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, NumEntriesIOQ, true, IOCQ_GROUP_ID, true, 0); gCtrlrConfig->SetIOSQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); Queues::CreateIOSQContigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, NumEntriesIOQ, true, IOSQ_GROUP_ID, IOQ_ID, 0); } }
void CIDAcceptedIOSQ_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Create ACQ and ASQ objects which have test life time"); SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(gDutFd))) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(gDutFd))) asq->Init(5); IRQ::SetAnySchemeSpecifyNum(2); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); vector<SharedIOSQPtr> iosqs; SharedIOCQPtr iocq; InitTstRsrcs(asq, acq, iosqs, iocq); SharedWritePtr writeCmd = CreateWriteCmd(); LOG_NRM("Learn initial unique command id assigned by dnvme"); uint16_t curCID; vector <SharedIOSQPtr>::iterator iosq; for (iosq = iosqs.begin(); iosq != iosqs.end(); iosq++) (*iosq)->Send(writeCmd, curCID); uint16_t prevCID = curCID; for (uint32_t nCmds = 0; nCmds < MAX_CMDS; nCmds++) { for (iosq = iosqs.begin(); iosq != iosqs.end(); iosq++) { LOG_NRM("(nCmds, curCID, prevCID, SQ ID) = (%d, %d, %d, %d)", nCmds, curCID, prevCID, (*iosq)->GetQId()); (*iosq)->Ring(); ReapVerifyCID(*iosq, iocq, prevCID); (*iosq)->Send(writeCmd, curCID); if (curCID != (uint16_t)(prevCID + 1)) { (*iosq)->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iosq.fail." + (*iosq)->GetQId()), "Dump Entire IOSQ"); iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq.fail." + iocq->GetQId()), "Dump Entire IOCQ"); throw FrmwkEx(HERE, "curCID(%d) != (prevCID + 1)(%d)", curCID, (prevCID + 1)); } } prevCID = curCID; } }
void CIDAcceptedASQ_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ uint32_t isrCount; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Verifying that the ACQ is empty"); if (acq->ReapInquiry(isrCount, true) != 0) { acq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "acq", "notEmpty"), "Test assumption have not been met"); throw FrmwkEx(HERE, "The ACQ should not have any CE's waiting before testing"); } LOG_NRM("Create identify cmd and assoc some buffer memory"); SharedIdentifyPtr idCmdCap = SharedIdentifyPtr(new Identify()); LOG_NRM("Force identify to request ctrlr capabilities struct"); idCmdCap->SetCNS(CNS_Controller); SharedMemBufferPtr idMemCap = SharedMemBufferPtr(new MemBuffer()); idMemCap->InitAlignment(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_ALIGNMENT, false, 0); send_64b_bitmask idPrpCap = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdCap->SetPrpBuffer(idPrpCap, idMemCap); LOG_NRM("Learn initial unique command id assigned by dnvme."); uint16_t currCID; asq->Send(idCmdCap, currCID); uint16_t prevCID = currCID; for (uint32_t nCmds = 0; nCmds < MAX_CMDS; nCmds++) { asq->Ring(); LOG_NRM("Verify unique CID #%d for Cmd #%d", currCID, nCmds + 1); ReapVerifyCID(asq, acq, currCID); asq->Send(idCmdCap, currCID); if (currCID != (uint16_t)(prevCID + 1)) { asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq.fail"), "Dump Entire ASQ"); acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Current CID(%d) != prev + 1(%d)", currCID, prevCID); } prevCID = currCID; } }
void DeleteIOQDiscontigPoll_r10b::DeleteIOSQDiscontigPoll(SharedASQPtr asq, SharedACQPtr acq) { uint16_t numCE; LOG_NRM("Lookup IOSQ which was created in a prior test within group"); SharedIOSQPtr iosq = CAST_TO_IOSQ( gRsrcMngr->GetObj(IOSQ_DISCONTIG_POLL_GROUP_ID)) LOG_NRM("Create a Delete IOSQ cmd to perform the IOSQ deletion"); SharedDeleteIOSQPtr deleteIOSQCmd = SharedDeleteIOSQPtr(new DeleteIOSQ(mFd)); deleteIOSQCmd->Init(iosq); LOG_NRM("Send the Delete IOSQ cmd to hdw"); asq->Send(deleteIOSQCmd); asq->Dump(FileSystem::PrepLogFile(mGrpName, mTestName, "asq", "deleteIOSQCmd"), "Just B4 ringing SQ0 doorbell, dump entire SQ contents"); asq->Ring(); LOG_NRM("Wait for the CE to arrive in ACQ"); if (acq->ReapInquiryWaitSpecify(DEFAULT_CMD_WAIT_ms, 1, numCE) == false) { LOG_ERR("Unable to see completion of Delete IOSQ cmd"); acq->Dump( FileSystem::PrepLogFile(mGrpName, mTestName, "acq","deleteIOSQCmd"), "Unable to see any CE's in CQ0, dump entire CQ contents"); throw exception(); } acq->Dump(FileSystem::PrepLogFile(mGrpName, mTestName, "acq", "deleteIOSQCmd"), "Just B4 reaping CQ0, dump entire CQ contents"); { uint16_t ceRemain; uint16_t numReaped; LOG_NRM("Reaping CE from ACQ, requires memory to hold reaped CE"); SharedMemBufferPtr ceMemIOSQ = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = acq->Reap(ceRemain, ceMemIOSQ, numCE, true)) != 1) { LOG_ERR("Verified there was 1 CE, but reaping produced %d", numReaped); throw exception(); } LOG_NRM("The reaped identify CE is..."); ceMemIOSQ->Log(); } // Not explicitly necessary, but is more clean to free what is not needed gRsrcMngr->FreeObj(IOSQ_DISCONTIG_POLL_GROUP_ID); }
bool GrpAdminSetGetFeatCombo::RestoreState() { // For the majority of test groups this feature most likely won't be needed if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); if (RestoreArbitration(asq, acq) == false) { LOG_ERR("Arbitration restore failed"); return false; } if (RestorePowerState(asq, acq) == false) { LOG_ERR("Power state restore failed"); return false; } if (RestoreTMPTH(asq, acq) == false) { LOG_ERR("Temperature threshold restore failed"); return false; } if (RestoreTLER(asq, acq) == false) { LOG_ERR("Time limited error recovery restore failed"); return false; } if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_VWC) & BITMASK_VWC) == 0x1) { if (RestoreVolWrCache(asq, acq) == false) { LOG_ERR("Volatile write cache restore failed"); return false; } } LOG_NRM("System restore successful."); return true; }
void AcceptQPriority_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ uint64_t maxIOQEntries = 2; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Create admin queues ACQ and ASQ"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); LOG_NRM("Setup element sizes for the IOQ's"); gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); gCtrlrConfig->SetIOSQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); LOG_NRM("Create IOCQ with QID = %d", IOQ_ID); SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false, IOCQ_GROUP_ID, true, 0); for (uint8_t priority = 0; priority < PRIORITY_RANGE; priority++) { LOG_NRM("Create IOSQ with QID = %d and priority #%d", IOQ_ID, priority); SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false, IOSQ_GROUP_ID, IOQ_ID, priority); LOG_NRM("Delete IOSQ with QID = %d and priority #%d", IOQ_ID, priority); Queues::DeleteIOSQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, asq, acq, "", false); } }
/** * A function to issue consecutive admin cmd set format NVM cmds to a DUT. * @param format Pass formating instructions * @return true upon successful parsing, otherwise false. */ bool FormatDevice(Format &format) { try { // The objects to perform this work throw exceptions FileSystem::SetBaseDumpDir(false); // Log into GrpPending if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Prepare the admin Q's to setup this request"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(2); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(2); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); for (size_t i = 0; i < format.cmds.size(); i++) { LOG_NRM("Formatting namespace: %d", format.cmds[i].nsid); LOG_NRM(" FormatNVM:DW10.ses = 0x%02x", format.cmds[i].ses); LOG_NRM(" FormatNVM:DW10.pil = %c", format.cmds[i].pil ? 'T' :'F'); LOG_NRM(" FormatNVM:DW10.pi = 0x%02x", format.cmds[i].pi); LOG_NRM(" FormatNVM:DW10.ms = %c", format.cmds[i].ms ? 'T' : 'F'); LOG_NRM(" FormatNVM:DW10.lbaf = 0x%02x", format.cmds[i].lbaf); LOG_NRM("Create the cmd to carry this data to the DUT"); SharedFormatNVMPtr formatNVM = SharedFormatNVMPtr(new FormatNVM()); formatNVM->SetNSID(format.cmds[i].nsid); formatNVM->SetSES(format.cmds[i].ses); formatNVM->SetPIL(format.cmds[i].pil); formatNVM->SetPI(format.cmds[i].pi); formatNVM->SetMS(format.cmds[i].ms); formatNVM->SetLBAF(format.cmds[i].lbaf); IO::SendAndReapCmd("tnvme", "format", SYSTEMWIDE_CMD_WAIT_ms, asq, acq, formatNVM, "", true); } LOG_NRM("The operation succeeded to format device"); } catch (...) { LOG_ERR("Operation failed to format device"); gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY); return false; } gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY); return true; }
void CIDAcceptedASQ_r10b::ReapVerifyCID(SharedASQPtr asq, SharedACQPtr acq, uint16_t currCID) { uint32_t isrCount; uint32_t ceRemain; uint32_t numReaped; uint32_t numCE; if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to see CEs for issued cmd"); } SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true)) != 1) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to reap on ACQ"); } union CE *ce = (union CE *)ceMem->GetBuffer(); ProcessCE::Validate(*ce); // throws upon error if (ce->n.CID != currCID) { asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq.fail"), "Dump Entire ASQ"); acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Received CID %d but expected %d", ce->n.CID, currCID); } }
bool GrpAdminSetGetFeatCombo::SaveState() { LOG_NRM("Saving system state using getfeatures before group starts"); // Reset saved value to account for regression mArbitration = 0; mPowerState = 0; mTmpThreshold = 0; mTimeLimErrRec = 0; mVolWrCache = 0; mIrqCoalescing = 0; mWrAtomicity = 0; memset(mIvecConf, 0, sizeof(mIvecConf)); mAsyncEvent = 0; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); SaveArbitration(asq, acq); SavePowerState(asq, acq); SaveTMPTH(asq, acq); SaveTLER(asq, acq); if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_VWC) & BITMASK_VWC) == 0x1) { SaveVolWrCache(asq, acq); } SaveIRQCoalescing(asq, acq); SaveIvecConf(asq, acq); SaveWrAtomicity(asq, acq); SaveAsyncEvent(asq, acq); return true; }
void VerifyMaxEvents_r10b::SendAsyncEventRequests(SharedASQPtr &asq, uint32_t nCmds) { uint16_t uniqueId; string work; LOG_NRM("Create aync event request cmd"); SharedAsyncEventReqPtr asyncEventReqCmd = SharedAsyncEventReqPtr(new AsyncEventReq()); for (uint32_t i = 0; i < nCmds; i++) { LOG_NRM("Send the async event request cmd to hdw via ASQ"); asq->Send(asyncEventReqCmd, uniqueId); work = str(boost::format("asyncEventReq.%d") % i); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq", work), "Before doorbell ring"); asq->Ring(); } }
void AdminQRollChkDiff_r10b::VerifyQPointers(SharedACQPtr acq, SharedASQPtr asq) { union CE ce; struct nvme_gen_cq acqMetrics = acq->GetQMetrics(); struct nvme_gen_sq asqMetrics = asq->GetQMetrics(); // The CQ's metrics after reaping holds head_ptr plus 1 needed. Also Take // Q roll over into account. if (acqMetrics.head_ptr == 0) { ce = acq->PeekCE(acq->GetNumEntries() - 1); } else { ce = acq->PeekCE(acqMetrics.head_ptr - 1); } uint16_t expectedVal = (2 + MAX(acq->GetNumEntries(), asq->GetNumEntries())) % acq->GetNumEntries(); if (acqMetrics.head_ptr != expectedVal) { acq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "acq", "head_ptr"), "CQ Metrics Head Pointer Inconsistent"); throw FrmwkEx(HERE, "Expected ACQ.head_ptr = 0x%04X but actual " "ACQ.head_ptr = 0x%04X", expectedVal, acqMetrics.head_ptr); } expectedVal = (2 + MAX(acq->GetNumEntries(), asq->GetNumEntries())) % asq->GetNumEntries(); if (asqMetrics.tail_ptr != expectedVal) { asq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "asq", "tail_ptr"), "SQ Metrics Tail Pointer Inconsistent"); throw FrmwkEx(HERE, "Expected ASQ.tail_ptr = 0x%04X but actual " "ASQ.tail_ptr = 0x%04X", expectedVal, asqMetrics.tail_ptr); } if (ce.n.SQHD != expectedVal) { acq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "acq", "CE.SQHD"), "CE SQ Head Pointer Inconsistent"); throw FrmwkEx(HERE, "Expected CE.SQHD = 0x%04X in ACQ completion entry but actual " "CE.SQHD = 0x%04X", expectedVal, ce.n.SQHD); } }
/** * A function to send Set Features admin cmd to a device sending the identifier * 0x07 to set number of queues. This value, according to the spec, shall NOT * change between resets, i.e. only set this value after a power up. Failure to * conform results in undefined behavior. * "<STS:PXDS:AERUCES:CSTS>". * @param numQueues Pass a struct to source the desired values to send to hdw * @return true upon successful parsing, otherwise false. */ bool SetFeaturesNumberOfQueues(NumQueues &numQueues) { try { // The objects to perform this work throw exceptions LOG_NRM("Setting number of Q's; ncqr=0x%04X, nsqr=0x%04X", numQueues.ncqr, numQueues.nsqr); FileSystem::SetBaseDumpDir(false); // Log into GrpPending if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Prepare the admin Q's to setup this request"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(2); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(2); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); LOG_NRM("Create the cmd to carry this data to the DUT"); SharedSetFeaturesPtr sfNumOfQ = SharedSetFeaturesPtr(new SetFeatures()); sfNumOfQ->SetFID(BaseFeatures::FID_NUM_QUEUES); sfNumOfQ->SetNumberOfQueues(numQueues.ncqr, numQueues.nsqr); IO::SendAndReapCmd("tnvme", "queues", SYSTEMWIDE_CMD_WAIT_ms, asq, acq, sfNumOfQ, "", true); LOG_NRM("The operation succeeded to set number of queues"); } catch (...) { LOG_ERR("Operation failed to set number of queues"); gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY); return false; } gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY); return true; }
bool GrpAdminSetGetFeatCombo::SaveState() { LOG_NRM("Saving the current arbitration state before the group starts."); // Reset saved value to account for regression mArbitration = 0; mPowerState = 0; mTmpThreshold = 0; mTimeLimErrRec = 0; mVolWrCache = 0; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); SaveArbitration(asq, acq); SavePowerState(asq, acq); SaveTMPTH(asq, acq); SaveTLER(asq, acq); if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_VWC) & BITMASK_VWC) == 0x1) { SaveVolWrCache(asq, acq); } return true; }
void IllegalCreateQs_r10b::SendToxicCmd(SharedASQPtr asq, SharedACQPtr acq, SharedCmdPtr cmd, uint8_t dw, uint32_t mask, uint32_t val, CEStat status) { uint16_t uniqueId; uint32_t isrCnt; uint32_t numCE; string work; LOG_NRM("Send the cmd to hdw via ASQ"); asq->Send(cmd, uniqueId); work = str(boost::format("%s.pure.%d") % cmd->GetName().c_str() % uniqueId); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq" + cmd->GetName(), work), "Just B4 modifying, dump ASQ"); ASQCmdToxify(asq, dw, mask, val); work = str(boost::format("%s.toxic.%d") % cmd->GetName().c_str() % uniqueId); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq", work), "Just B4 ringing doorbell, dump ASQ"); asq->Ring(); LOG_NRM("Wait for the CE to arrive in CQ %d", acq->GetQId()); if (acq->ReapInquiryWaitSpecify(DEFAULT_CMD_WAIT_ms, 1, numCE, isrCnt) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"), "Dump Entire ACQ"); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq.fail"), "Dump Entire ASQ"); throw FrmwkEx(HERE, "Unable to see CEs for issued cmd"); } work = str(boost::format("acq.%d") % uniqueId); IO::ReapCE(acq, 1, isrCnt, mGrpName, mTestName, work, status); }
void IllegalCreateQs_r10b::ASQCmdToxify(SharedASQPtr asq, uint8_t dw, uint32_t mask, uint32_t val) { struct nvme_gen_sq asqMetrics = asq->GetQMetrics(); struct backdoor_inject inject; inject.q_id = asq->GetQId(); if (asqMetrics.tail_ptr_virt) inject.cmd_ptr = asqMetrics.tail_ptr_virt - 1; else inject.cmd_ptr = asq->GetNumEntries() - 1; inject.dword = dw; inject.value_mask = mask; inject.value = val; LOG_NRM("Inject toxic parameters: (qId, cmd_ptr, dword, mask, val) = " "(%d, %d, %d, %d, %d)", inject.q_id, inject.cmd_ptr, inject.dword, inject.value_mask, inject.value); asq->SetToxicCmdValue(inject); }
void InvalidMSIXIRQ_r10b::ASQCmdToxify(SharedASQPtr asq, uint16_t illegalIrqVec) { struct backdoor_inject inject; struct nvme_gen_sq asqMetrics = asq->GetQMetrics(); LOG_NRM("Attempt to utilize illegal IRQ vec %d", illegalIrqVec); if (asqMetrics.tail_ptr_virt) inject.cmd_ptr = (asqMetrics.tail_ptr_virt - 1); else inject.cmd_ptr = (asq->GetNumEntries() - 1); inject.q_id = asq->GetQId(); inject.dword = 11; inject.value_mask = 0xFFFF0000; inject.value = (illegalIrqVec << 16); LOG_NRM("Inject toxic parameters: (qId, cmd_ptr, dword, mask, val) = " "(%d, %d, %d, %d, %d)", inject.q_id, inject.cmd_ptr, inject.dword, inject.value_mask, inject.value); asq->SetToxicCmdValue(inject); }
void InvalidMSIXIRQ_r10b::SendToxicCmd(SharedASQPtr asq, SharedACQPtr acq, SharedCmdPtr cmd, uint16_t illegalIrqVec) { string work; uint16_t uniqueId; uint32_t isrCnt; uint32_t numCE; LOG_NRM("Send the cmd to hdw via ASQ with illegal IRQ vec %d", illegalIrqVec); asq->Send(cmd, uniqueId); work = str(boost::format("pure.%d") % illegalIrqVec); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq", work), "Just B4 modifying, dump ASQ"); ASQCmdToxify(asq, illegalIrqVec); work = str(boost::format("toxic.%d") % illegalIrqVec); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq", work), "Just B4 ringing doorbell, dump ASQ"); asq->Ring(); LOG_NRM("Wait for the CE to arrive in CQ %d", acq->GetQId()); if (acq->ReapInquiryWaitSpecify(DEFAULT_CMD_WAIT_ms, 1, numCE, isrCnt) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"), "Dump Entire ACQ"); asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq.fail"), "Dump Entire ASQ"); throw FrmwkEx(HERE, "Unable to see CEs for issued cmd"); } IO::ReapCE(acq, 1, isrCnt, mGrpName, mTestName, "acq", CESTAT_INVAL_INT_VEC); }
void CtrlrResetDefaults_r10b::VerifyCtrlrResetDefaults() { std::map<int, uint64_t> ctrlRegsMap; // Issue a cntl'r reset for a clean controller state to begin with if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); // Create ACQ and ASQ objects which have test life time SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(mFd))) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(mFd))) asq->Init(5); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); // Dump Controller space registers to known file before ctrlr reset KernelAPI::DumpCtrlrSpaceRegs(FileSystem:: PrepDumpFile(mGrpName, mTestName, "ctrlRegs", "beforeReset"), false); ModifyRWBitsOfCtrlrRegisters(ctrlRegsMap); // Issue a cntl'r reset. CC.EN transitions from 1 to 0 if (gCtrlrConfig->SetState(ST_DISABLE) == false) throw FrmwkEx(HERE); // Dump Controller space registers to known file after ctrlr reset KernelAPI::DumpCtrlrSpaceRegs(FileSystem:: PrepDumpFile(mGrpName, mTestName, "ctrlRegs", "afterReset"), false); ValidateCtrlrRWDefaultsAfterReset(ctrlRegsMap); }
bool CompareGolden(Golden &golden) { string work; try { // The objects to perform this work throw exceptions FileSystem::SetBaseDumpDir(false); // Log into GrpPending if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Prepare the admin Q's to setup this request"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(2); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(2); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); SharedIdentifyPtr idCmd = SharedIdentifyPtr(new Identify()); SharedMemBufferPtr idMem = SharedMemBufferPtr(new MemBuffer()); idMem->InitAlignment(Identify::IDEAL_DATA_SIZE, sizeof(uint64_t), true, 0); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmd->SetPrpBuffer(prpReq, idMem); for (size_t i = 0; i < golden.cmds.size(); i++) { LOG_NRM("Identify cmd #%ld", i); LOG_NRM(" Identify:DW1.nsid = 0x%02x", golden.cmds[i].nsid); LOG_NRM(" Identify.DW10.cns = %c", golden.cmds[i].cns ? 'T' : 'F'); LOG_NRM(" sizeof(Identify.raw) = %ld", golden.cmds[i].raw.size()); LOG_NRM("Formulate an identical idenitfy cmd to issue"); idCmd->SetCNS(golden.cmds[i].cns); idCmd->SetNSID(golden.cmds[i].nsid); idMem->InitAlignment(Identify::IDEAL_DATA_SIZE, sizeof(uint64_t), true, 0); work = str(boost::format("IdCmd%d") % i); IO::SendAndReapCmd("tnvme", "golden", SYSTEMWIDE_CMD_WAIT_ms, asq, acq, idCmd, work, false); if (idMem->Compare(golden.cmds[i].raw) == false) { idMem->Dump(FileSystem::PrepDumpFile("tnvme", "golden", "identify", "dut.miscompare"), "DUT data miscompare"); SharedMemBufferPtr userMem = SharedMemBufferPtr( new MemBuffer(golden.cmds[i].raw)); userMem->Dump(FileSystem::PrepDumpFile("tnvme", "golden", "identify", "cmdline.miscompare"), "Golden user data miscompare"); throw FrmwkEx(HERE, "Golden identify data miscompare"); } } LOG_NRM("The operation succeeded to compare golden data"); } catch (...) { LOG_ERR("Operation failed to compare golden data"); gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY); return false; } gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY); return true; }
void CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) This is the 1st within GrpNVMWriteReadCombo. * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); { uint64_t maxIOQEntries; // Determine the max IOQ entries supported if (gRegisters->Read(CTLSPC_CAP, maxIOQEntries) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); maxIOQEntries &= CAP_MQES; maxIOQEntries += 1; // convert to 1-based if (maxIOQEntries < (uint64_t)NumEntriesIOQ) { LOG_NRM("Changing number of Q elements from %d to %lld", NumEntriesIOQ, (unsigned long long)maxIOQEntries); NumEntriesIOQ = maxIOQEntries; } uint8_t iocqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); uint8_t iosqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); gCtrlrConfig->SetIOCQES(iocqes); gCtrlrConfig->SetIOSQES(iosqes); if (Queues::SupportDiscontigIOQ() == true) { SharedMemBufferPtr iocqBackedMem = SharedMemBufferPtr(new MemBuffer()); iocqBackedMem->InitOffset1stPage ((NumEntriesIOQ * (1 << iocqes)), 0, true); Queues::CreateIOCQDiscontigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOCQ_GROUP_ID, true, 0, iocqBackedMem); SharedMemBufferPtr iosqBackedMem = SharedMemBufferPtr(new MemBuffer()); iosqBackedMem->InitOffset1stPage ((NumEntriesIOQ * (1 << iosqes)), 0, true); Queues::CreateIOSQDiscontigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOSQ_GROUP_ID, IOQ_ID, 0, iosqBackedMem); } else { Queues::CreateIOCQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOCQ_GROUP_ID, true, 0); Queues::CreateIOSQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOSQ_GROUP_ID, IOQ_ID, 0); } } }
void FIDPwrMgmt_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ string work; union CE ce; struct nvme_gen_cq acqMetrics; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Create admin queues ACQ and ASQ for test lifetime"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); LOG_NRM("Create Get features and set features cmds"); SharedGetFeaturesPtr getFeaturesCmd = SharedGetFeaturesPtr(new GetFeatures()); SharedSetFeaturesPtr setFeaturesCmd = SharedSetFeaturesPtr(new SetFeatures()); LOG_NRM("Set and Get features PSD (FID = 0x%x)", BaseFeatures::FID_PWR_MGMT); getFeaturesCmd->SetFID(BaseFeatures::FID_PWR_MGMT); setFeaturesCmd->SetFID(BaseFeatures::FID_PWR_MGMT); uint8_t npss = gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_NPSS); // 0-based LOG_NRM("Number of power states supported by the ctrlr (NPSS) = %d", npss); uint8_t psMismatch = 0; for (uint16_t ps = 0; ps <= npss; ps++) { LOG_NRM("Set and Get features for PS # %d", ps); setFeaturesCmd->SetPowerManagementPS(ps); LOG_NRM("Issue set features cmd with PS = %d", ps); work = str(boost::format("ps.%d") % ps); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, setFeaturesCmd, work, true); acqMetrics = acq->GetQMetrics(); LOG_NRM("Issue get features cmd and check for ps = %d", ps); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getFeaturesCmd, work, false); ce = acq->PeekCE(acqMetrics.head_ptr); LOG_NRM("Power state descriptor using Get Features = %d", ce.t.dw0); if (ps != ce.t.dw0) { LOG_ERR("PSD get feat does not match set feat" "(expected, rcvd) = (%d, %d)", ps, ce.t.dw0); psMismatch = 0xFF; } } if (psMismatch) throw FrmwkEx(HERE, "Power state mismatched."); }
void ProtInfoIgnoreMeta_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) None. * \endverbatim */ string context; ConstSharedIdentifyPtr namSpcPtr; SharedIOSQPtr iosq; SharedIOCQPtr iocq; send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST); if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); LOG_NRM("Get all the supported meta namespaces"); vector<uint32_t> meta = gInformative->GetMetaNamespaces(); for (size_t i = 0; i < meta.size(); i++) { if (gCtrlrConfig->SetState(ST_DISABLE) == false) throw FrmwkEx(HERE); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); LOG_NRM("Create IOSQ and IOCQ with ID #%d", IOQ_ID); CreateIOQs(asq, acq, IOQ_ID, iosq, iocq); LOG_NRM("Get LBA format and lba data size for namespc #%d", meta[i]); namSpcPtr = gInformative->GetIdentifyCmdNamspc(meta[i]); LBAFormat lbaFormat = namSpcPtr->GetLBAFormat(); uint64_t lbaDataSize = (1 << lbaFormat.LBADS); LOG_NRM("Create a read cmd to read data from namspc %d", meta[i]); SharedReadPtr readCmd = SharedReadPtr(new Read()); LOG_NRM("Create memory to contain read payload"); SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer()); Informative::NamspcType nsType = gInformative->IdentifyNamespace(namSpcPtr); switch (nsType) { case Informative::NS_BARE: throw FrmwkEx(HERE, "Namspc type cannot be BARE."); case Informative::NS_METAS: readMem->Init(lbaDataSize); if (gRsrcMngr->SetMetaAllocSize(lbaFormat.MS) == false) throw FrmwkEx(HERE); readCmd->AllocMetaBuffer(); break; case Informative::NS_METAI: readMem->Init(lbaDataSize + lbaFormat.MS); break; case Informative::NS_E2ES: case Informative::NS_E2EI: throw FrmwkEx(HERE, "Deferring work to handle this case in future"); break; } readCmd->SetPrpBuffer(prpBitmask, readMem); readCmd->SetNSID(meta[i]); readCmd->SetNLB(0); // convert to 0-based value for (uint16_t protInfo = 0; protInfo <= 0x0f; protInfo++) { uint8_t work = readCmd->GetByte(12, 3); work &= ~0x3c; // PRINFO specific bits work |= (protInfo << 2); readCmd->SetByte(work, 12, 3); context = str(boost::format("ns%d.protInfo0x%02X") % (uint32_t)i % protInfo); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, readCmd, context, true); } } }
void FIDVolatileCash_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ string work; union CE ce; struct nvme_gen_cq acqMetrics; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Create admin queues ACQ and ASQ for test lifetime"); SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd)); acq->Init(5); SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); LOG_NRM("Create Get features and set features cmds"); SharedGetFeaturesPtr getFeaturesCmd = SharedGetFeaturesPtr(new GetFeatures()); SharedSetFeaturesPtr setFeaturesCmd = SharedSetFeaturesPtr(new SetFeatures()); LOG_NRM("Set and Get features for volatile write cache (FID = 0x%x)", BaseFeatures::FID_VOL_WR_CACHE); getFeaturesCmd->SetFID(BaseFeatures::FID_VOL_WR_CACHE); setFeaturesCmd->SetFID(BaseFeatures::FID_VOL_WR_CACHE); uint8_t wce = 0x0; // Disable volatile write cache LOG_NRM("Disable volatile wr cache # %d ", wce); setFeaturesCmd->SetVolatileWriteCacheWCE(wce); LOG_NRM("Issue set features cmd with WCE = %d", wce); work = str(boost::format("wce.%d") % wce); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, setFeaturesCmd, work, true); acqMetrics = acq->GetQMetrics(); LOG_NRM("Issue get features cmd & check wce = %d", wce); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getFeaturesCmd, work, false); ce = acq->PeekCE(acqMetrics.head_ptr); LOG_NRM("Get Features volatile wr cache = %d", ce.t.dw0); if (wce != ce.t.dw0) { throw FrmwkEx(HERE, "WCE get feat does not match set feat" "(expected, rcvd) = (%d, %d)", wce, ce.t.dw0); } wce = 0x1; // Enable volatile write cache LOG_NRM("Enable volatile wr cache # %d ", wce); setFeaturesCmd->SetVolatileWriteCacheWCE(wce); LOG_NRM("Issue set features cmd with WCE = %d", wce); work = str(boost::format("wce.%d") % wce); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, setFeaturesCmd, work, true); acqMetrics = acq->GetQMetrics(); LOG_NRM("Issue get features cmd & check wce = %d", wce); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getFeaturesCmd, work, false); ce = acq->PeekCE(acqMetrics.head_ptr); LOG_NRM("Get Features volatile wr cache = %d", ce.t.dw0); if (wce != ce.t.dw0) { throw FrmwkEx(HERE, "WCE get feat does not match set feat" "(expected, rcvd) = (%d, %d)", wce, ce.t.dw0); } }