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 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::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); }
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); } } }
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; }
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 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; } }
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; }
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; }
/** * 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 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); }
void PRPLessPageDiscontig_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None * \endverbatim */ string work; bool enableLog; if (Queues::SupportDiscontigIOQ() == false) { LOG_WARN("DUT must support discontig Q's for this test."); return; } uint64_t ctrlCapReg; LOG_NRM("Determine the max IOQ entries supported"); if (gRegisters->Read(CTLSPC_CAP, ctrlCapReg) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); uint32_t maxIOQEntries = (ctrlCapReg & CAP_MQES); maxIOQEntries += 1; // convert to 1-based LOG_NRM("Compute memory page size from CC.MPS."); uint8_t mps; if (gCtrlrConfig->GetMPS(mps) == false) throw FrmwkEx(HERE, "Unable to get MPS value from CC."); uint64_t capMPS = (uint64_t)(1 << (mps + 12)); LOG_NRM("Determine element sizes for the IOCQ's"); uint8_t iocqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); uint32_t Y = ((capMPS / (1 << iocqes)) - 1); if (maxIOQEntries < Y) { LOG_WARN("Desired to support >= %d elements in IOCQ for this test", Y); return; } LOG_NRM("Determine element sizes for the IOSQ's"); uint8_t iosqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); uint32_t Z = ((capMPS / (1 << iosqes)) - 1); LOG_NRM("Computed memory page size from CC.MPS = %ld", capMPS); LOG_NRM("Max IOQ entries supported CAP.MQES = %d", maxIOQEntries); LOG_NRM("Number of IOCQ elements = %d", Y); LOG_NRM("Number of IOSQ elements = %d", Z); 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); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); Informative::Namspc namspcData = gInformative->Get1stBareMetaE2E(); LBAFormat lbaFormat = namspcData.idCmdNamspc->GetLBAFormat(); uint64_t lbaDataSize = namspcData.idCmdNamspc->GetLBADataSize(); LOG_NRM("Setup element sizes for the IOQ's"); gCtrlrConfig->SetIOCQES(iocqes); gCtrlrConfig->SetIOSQES(iosqes); LOG_NRM("Create discontig IOSQ and IOCQ with IDs 1"); SharedMemBufferPtr iocqBackedMem = SharedMemBufferPtr(new MemBuffer()); iocqBackedMem->InitOffset1stPage((Y * (1 << iocqes)), 0, true); SharedIOCQPtr iocq = Queues::CreateIOCQDiscontigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, Y, false, IOCQ_GROUP_ID, true, 0, iocqBackedMem); SharedMemBufferPtr iosqBackedMem = SharedMemBufferPtr(new MemBuffer()); iosqBackedMem->InitOffset1stPage((Z * (1 << iosqes)), 0,true); SharedIOSQPtr iosq = Queues::CreateIOSQDiscontigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, Z, false, IOSQ_GROUP_ID, IOQ_ID, 0, iosqBackedMem); SharedWritePtr writeCmd = SharedWritePtr(new Write()); SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer()); SharedReadPtr readCmd = SharedReadPtr(new Read()); SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer()); send_64b_bitmask prpBitmask = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST); switch (namspcData.type) { case Informative::NS_BARE: writeMem->Init(lbaDataSize); readMem->Init(lbaDataSize); break; case Informative::NS_METAS: writeMem->Init(lbaDataSize); readMem->Init(lbaDataSize); if (gRsrcMngr->SetMetaAllocSize(lbaFormat.MS) == false) throw FrmwkEx(HERE); writeCmd->AllocMetaBuffer(); readCmd->AllocMetaBuffer(); break; case Informative::NS_METAI: writeMem->Init(lbaDataSize + lbaFormat.MS); 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; } writeCmd->SetPrpBuffer(prpBitmask, writeMem); writeCmd->SetNSID(namspcData.id); writeCmd->SetNLB(0); readCmd->SetPrpBuffer(prpBitmask, readMem); readCmd->SetNSID(namspcData.id); readCmd->SetNLB(0); // Fill the IOSQ and roll over for (int64_t X = 1; X <= (iosq->GetNumEntries() + 1); X++) { LOG_NRM("Processing #%ld of %d cmds", X, (iosq->GetNumEntries() + 1)); switch (namspcData.type) { case Informative::NS_BARE: writeMem->SetDataPattern(DATAPAT_INC_32BIT, X); break; case Informative::NS_METAS: writeMem->SetDataPattern(DATAPAT_INC_32BIT, X); writeCmd->SetMetaDataPattern(DATAPAT_INC_32BIT, X); break; case Informative::NS_METAI: writeMem->SetDataPattern(DATAPAT_INC_32BIT, X); break; case Informative::NS_E2ES: case Informative::NS_E2EI: throw FrmwkEx(HERE, "Deferring work to handle this case in future"); break; } enableLog = false; if ((X <= 8) || (X >= (X - 8))) enableLog = true; work = str(boost::format("X.%d") % X); IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, iocq, writeCmd, work, enableLog); IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, iocq, readCmd, work, enableLog); VerifyDataPat(readCmd, writeCmd); } }
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 VerifyEventQueueing_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ uint32_t isrCount; uint32_t ceRemain; uint32_t numReaped; uint32_t numCE; 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("Ring doorbell for IOSQ #1"); InvalidSQWriteDoorbell(); LOG_NRM("Delay 5 sec"); sleep(5); LOG_NRM("Verify no CE's exist in ACQ"); if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount) == true) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.0rinq"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "0 CE's expected in ACQ but found %d CE's", numCE); } LOG_NRM("Issue one async event "); SendAsyncEventRequests(asq, 1); LOG_NRM("verify CE exists in ACQ for invalid SQID doorbell write"); if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.1rinq"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "1 CE expected in ACQ but found %d CEs", numCE); } SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true)) != 1) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.1reap"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to reap on ACQ"); } union CE *ce = (union CE *)ceMem->GetBuffer(); if (ce->n.async.asyncEventType != EVENT_TYPE_ERROR_STS) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.sts"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Invalid async event error status, " "(Expected : Received) :: (%d : %d)", EVENT_TYPE_ERROR_STS, ce->n.async.asyncEventType); } else if (ce->n.async.asyncEventInfo != ERR_STS_INVALID_SQ) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.sc"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Invalid async event info, " "(Expected : Received) :: (%d : %d)", ERR_STS_INVALID_SQ, ce->n.async.asyncEventInfo); } }
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 MaxQSizeExceed_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ string work; bool enableLog; uint64_t ctrlCapReg; LOG_NRM("Determine the max IOQ entries supported"); if (gRegisters->Read(CTLSPC_CAP, ctrlCapReg) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); uint32_t maxIOQEntries = (ctrlCapReg & CAP_MQES); maxIOQEntries += 1; // convert to 1 - based. 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 size for the IOCQ"); gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); LOG_NRM("Create IOCQ with illegal Q entries ranging from 0x%04X to 0x10000", maxIOQEntries + 1); list<uint32_t> illegalQSizes = GetIllegalQSizes(maxIOQEntries); for (list<uint32_t>::iterator qSize = illegalQSizes.begin(); qSize != illegalQSizes.end(); qSize++) { LOG_NRM("Process CreateIOCQ Cmd with qSize #0x%04X", *qSize); SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(gDutFd)); iocq->Init(IOQ_ID, *qSize, true, 0); SharedCreateIOCQPtr createIOCQCmd = SharedCreateIOCQPtr(new CreateIOCQ()); createIOCQCmd->Init(iocq); work = str(boost::format("qSize.%04Xh") % *qSize); enableLog = false; if ((*qSize <= (maxIOQEntries + 8)) || (*qSize >= (0xFFFF - 8))) enableLog = true; LOG_NRM("Send n reap ACQ for CreateIOCQCmd; qSize #0x%04X", *qSize); IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, createIOCQCmd, work, enableLog, CESTAT_MAX_Q_SIZE_EXCEED); } }
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); } }
bool SetFeaturesNumberOfQueues(Queues &queues, int fd) { uint16_t numCE; uint16_t ceRemain; uint16_t numReaped; try { // The objects to perform this work throw exceptions LOG_NRM("Setting number of Q's; ncqr=0x%04X, nsqr=0x%04X", queues.ncqr, queues.nsqr); if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw exception(); LOG_NRM("Prepare the admin Q's to setup this request"); SharedACQPtr acq = SharedACQPtr(new ACQ(fd)); acq->Init(2); SharedASQPtr asq = SharedASQPtr(new ASQ(fd)); asq->Init(2); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw exception(); LOG_NRM("Create the cmd to carry this data to the DUT"); SharedSetFeaturesPtr sfNumOfQ = SharedSetFeaturesPtr(new SetFeatures(fd)); sfNumOfQ->SetFID(BaseFeatures::FID_NUM_QUEUES); sfNumOfQ->SetNumberOfQueues(queues.ncqr, queues.nsqr); LOG_NRM("Send the cmd to the ASQ, wait for it to complete"); asq->Send(sfNumOfQ); asq->Ring(); if (acq->ReapInquiryWaitSpecify(2000, 1, numCE) == false) { LOG_ERR("Unable to see completion of Set Features cmd"); throw exception(); } else if (numCE != 1) { LOG_ERR("The ACQ should only have 1 CE as a result of a cmd"); throw exception(); } LOG_NRM("The CQ's metrics before reaping holds head_ptr needed"); struct nvme_gen_cq acqMetrics = acq->GetQMetrics(); KernelAPI::LogCQMetrics(acqMetrics); LOG_NRM("Reaping CE from ACQ, requires memory to hold reaped CE"); SharedMemBufferPtr ceMemIOCQ = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = acq->Reap(ceRemain, ceMemIOCQ, numCE, true)) != 1) { LOG_ERR("Verified there was 1 CE, but reaping produced %d", numReaped); throw exception(); } LOG_NRM("The reaped get features CE is..."); acq->LogCE(acqMetrics.head_ptr); union CE ce = acq->PeekCE(acqMetrics.head_ptr); if (ce.n.status != 0) { LOG_ERR("CE shows cmd failed: status = 0x%02X", ce.n.status); throw exception(); } printf("The operation succeeded to set number of queues\n"); } catch (...) { printf("Operation failed to set number of queues\n"); return false; } return true; }
void PRPOffsetDualPgMultiBlk_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ string work; int64_t X; bool enableLog; 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(mFd))) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(mFd))) asq->Init(5); IRQ::SetAnySchemeSpecifyNum(2); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); SharedIOCQPtr iocq; SharedIOSQPtr iosq; InitTstRsrcs(asq, acq, iosq, iocq); LOG_NRM("Compute memory page size from CC.MPS."); uint8_t mpsRegVal; if (gCtrlrConfig->GetMPS(mpsRegVal) == false) throw FrmwkEx(HERE, "Unable to get MPS value from CC."); uint64_t ccMPS = (uint64_t)(1 << (mpsRegVal + 12)); LOG_NRM("Get namspc and determine LBA size"); Informative::Namspc namspcData = gInformative->Get1stBareMetaE2E(); send_64b_bitmask prpBitmask = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); LBAFormat lbaFormat = namspcData.idCmdNamspc->GetLBAFormat(); uint64_t lbaDataSize = (1 << lbaFormat.LBADS); LOG_NRM("LBA data size is %ld.", lbaDataSize); LOG_NRM("Seeking max data xfer size for chosen namspc"); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); uint32_t maxDtXferSz = idCmdCtrlr->GetMaxDataXferSize(); SharedWritePtr writeCmd = SharedWritePtr(new Write()); writeCmd->SetNSID(namspcData.id); SharedReadPtr readCmd = SharedReadPtr(new Read()); readCmd->SetNSID(namspcData.id); SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer()); SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer()); switch (namspcData.type) { case Informative::NS_BARE: X = ccMPS - lbaDataSize; break; case Informative::NS_METAS: X = ccMPS - lbaDataSize; LOG_NRM("Allocating separate meta data buffer."); if (gRsrcMngr->SetMetaAllocSize( lbaFormat.MS * ((2 * ccMPS) / lbaDataSize)) == false) { throw FrmwkEx(HERE, "Unable to allocate Meta buffers."); } writeCmd->AllocMetaBuffer(); readCmd->AllocMetaBuffer(); break; case Informative::NS_METAI: X = ccMPS - (lbaDataSize + lbaFormat.MS); break; case Informative::NS_E2ES: case Informative::NS_E2EI: throw FrmwkEx(HERE, "Deferring work to handle this case in future"); break; } if (X < 0) { LOG_WARN("CC.MPS < lba data size(LBADS); Can't run test."); return; } DataPattern dataPat; uint64_t wrVal; uint64_t Y; for (int64_t pgOff = 0; pgOff <= X; pgOff += 4) { switch (namspcData.type) { case Informative::NS_BARE: case Informative::NS_METAS: Y = ((2 * ccMPS) - pgOff) / lbaDataSize; break; case Informative::NS_METAI: Y = ((2 * ccMPS) - pgOff) / (lbaDataSize + lbaFormat.MS); break; case Informative::NS_E2ES: case Informative::NS_E2EI: throw FrmwkEx(HERE, "Deferring work to handle this case in future"); break; } for (uint64_t nLBAs = 1; nLBAs <= Y; nLBAs++) { LOG_NRM("Sending LBA #%ld of #%ld", nLBAs, Y); if ((maxDtXferSz != 0) && (maxDtXferSz < (lbaDataSize * nLBAs))) { // If the total data xfer exceeds the maximum data xfer // allowed then we break from the inner loop and continue // test with next offset (outer loop). LOG_WARN("Data xfer size exceeds max allowed, continuing.."); break; } if ((nLBAs % 2) != 0) { dataPat = DATAPAT_INC_32BIT; wrVal = pgOff + nLBAs; } else { dataPat = DATAPAT_CONST_16BIT; wrVal = pgOff + nLBAs; } uint64_t metabufSz = nLBAs * lbaFormat.MS; switch (namspcData.type) { case Informative::NS_BARE: writeMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false); readMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false); break; case Informative::NS_METAS: writeMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false); readMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false); writeCmd->SetMetaDataPattern(dataPat, wrVal, 0, metabufSz); break; case Informative::NS_METAI: writeMem->InitOffset1stPage( ((lbaDataSize + lbaFormat.MS) * nLBAs), pgOff, false); readMem->InitOffset1stPage( ((lbaDataSize + lbaFormat.MS) * nLBAs), pgOff, false); break; case Informative::NS_E2ES: case Informative::NS_E2EI: throw FrmwkEx(HERE, "Deferring work to handle this case in future"); break; } work = str(boost::format("pgOff.%d.nlba.%d") % pgOff % nLBAs); writeCmd->SetPrpBuffer(prpBitmask, writeMem); writeMem->SetDataPattern(dataPat, wrVal); writeCmd->SetNLB(nLBAs - 1); // convert to 0 based. enableLog = false; if ((pgOff <= 8) || (pgOff >= (X - 8))) enableLog = true; IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, iocq, writeCmd, work, enableLog); readCmd->SetPrpBuffer(prpBitmask, readMem); readCmd->SetNLB(nLBAs - 1); // convert to 0 based. IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, iocq, readCmd, work, enableLog); VerifyDataPat(readCmd, dataPat, wrVal, metabufSz); } } }
void VerifyMasking_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ uint32_t isrCount; uint32_t ceRemain; uint32_t numReaped; uint32_t numCE; LOG_NRM("Issue Identify.AERL to get Async Event Req Limit (AERL)"); uint8_t nAerlimit = gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_AERL) + 1; // Convert to 1-based. 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(nAerlimit + 1); // one extra space than Q full condition SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(nAerlimit + 1); // one extra space than Q full condition // 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("Issue %d async event requests", nAerlimit); SendAsyncEventRequests(asq, nAerlimit); for (uint8_t nAer = 1; nAer <= nAerlimit; nAer++) { LOG_NRM("Ring doorbell for IOSQ #1"); InvalidSQWriteDoorbell(); sleep(5); if (nAer == 1) { LOG_NRM("Verify only 1 CE exists for invalid SQID doorbell write"); if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.reapinq1"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "1 CE expected in but found %d CEs", numCE); } SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true)) != 1) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.reap1"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to reap on ACQ"); } union CE *ce = (union CE *)ceMem->GetBuffer(); if (ce->n.async.asyncEventType != EVENT_TYPE_ERROR_STS) { throw FrmwkEx(HERE, "Invalid async event error status, " "(Expected : Received) :: (%d : %d)", EVENT_TYPE_ERROR_STS, ce->n.async.asyncEventType); } else if (ce->n.async.asyncEventInfo != ERR_STS_INVALID_SQ) { throw FrmwkEx(HERE, "Invalid async event info, " "(Expected : Received) :: (%d : %d)", ERR_STS_INVALID_SQ, ce->n.async.asyncEventInfo); } } else { LOG_NRM("Verify only 1 CE exists for %d cmds as " "async events are masked (GetLogPage not called)", nAer); if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 2, numCE, isrCount) == true) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail.reapinq2"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "1 CE expected but found %d CEs", numCE); } } } }
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); LOG_NRM("Issue DeleteIOSQ traversing through all combinations of DW10.QID"); SharedDeleteIOSQPtr deleteIOSQCmd = SharedDeleteIOSQPtr(new DeleteIOSQ()); list<uint32_t> illegalQIDs = GetIllegalQIDs(1); for (list<uint32_t>::iterator qId = illegalQIDs.begin(); qId != illegalQIDs.end(); qId++) { LOG_NRM("Sending 1st deleteIOSQ cmd for QId #%d", *qId); work = str(boost::format("1st.IOQID.%d") % *qId); enableLog = false; if ((*qId <= 8) || (*qId >= (MAX_IOQ_ID - 8))) enableLog = true; deleteIOSQCmd->SetWord(*qId, 10, 0); // Set IO QID using Cmd DW10 IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, deleteIOSQCmd, work, enableLog, CESTAT_INVALID_QID); } 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/IOSQ pair 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); SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false, IOCQ_GROUP_ID, IOQ_ID, 0); LOG_NRM("Send DeleteIOSQ and expect success for QID = 1"); work = str(boost::format("2nd.IOQID.1")); deleteIOSQCmd->SetWord(1, 10, 0); // Set IO QID = 1 using Cmd DW10 IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, deleteIOSQCmd, work, true); LOG_NRM("Again issue DeleteIOSQ through all combinations of DW10.QID"); illegalQIDs = GetIllegalQIDs(2); for (list<uint32_t>::iterator qId = illegalQIDs.begin(); qId != illegalQIDs.end(); qId++) { LOG_NRM("Sending 2nd deleteIOSQ cmd for QId #%d", *qId); work = str(boost::format("2nd.IOQID.%d") % *qId); enableLog = false; if ((*qId <= 8) || (*qId >= (MAX_IOQ_ID - 8))) enableLog = true; deleteIOSQCmd->SetWord(*qId, 10, 0); // Set IO QID using Cmd DW10 IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, deleteIOSQCmd, work, enableLog, CESTAT_INVALID_QID); } }
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 AdminQRollChkDiff_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none. * \endverbatim */ uint16_t mACQSize = MIN_ADMIN_Q_SIZE; // Start ACQ with min size. uint16_t mASQSize = MAX_ADMIN_Q_SIZE; uint16_t loopCnt = 0; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); while (1) { LOG_NRM("(ASQSize, ACQSize, Loop Cnt) = (%d, %d, %d)", mASQSize, mACQSize, loopCnt++); // Issue cntl'r disable completely for every iteration. 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(gDutFd))) acq->Init(mACQSize); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(gDutFd))) asq->Init(mASQSize); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); 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(true); 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("Submit Idtfy cmds to fill & roll over the Q (Q_SIZE plus 2)."); for (uint16_t nsubmitTimes = 0; nsubmitTimes < MAX(asq->GetNumEntries(), acq->GetNumEntries()) + 2; nsubmitTimes++) { LOG_NRM("Sending #%d times of %d", (nsubmitTimes + 1), (acq->GetNumEntries() + 2)); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdCap, "AdminQRollChkDiff", false); VerifyCESQValues(acq, (nsubmitTimes + 1) % asq->GetNumEntries()); } // Verify final Q pointers after all the cmds are submitted and reaped VerifyQPointers(acq, asq); if (mACQSize >= MAX_ADMIN_Q_SIZE) { break; } // If the test requires incremental sizes then edit here. mACQSize = MAX_ADMIN_Q_SIZE; // Assign MAX Q Size of ACQ. mASQSize = MIN_ADMIN_Q_SIZE; } }
void VerifyMaxEvents_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ uint32_t isrCount; uint32_t ceRemain; uint32_t numReaped; uint32_t numCE; LOG_NRM("Issue Identify.AERL to get Async Event Req Limit (AERL)"); uint8_t nAerlimit = gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_AERL) + 1; // Convert to 1-based. 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(nAerlimit + 2); // one extra space than Q full condition SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd)); asq->Init(nAerlimit + 2); // one extra space than Q full condition // 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("Issue one more than %d (async event req limit)", nAerlimit); SendAsyncEventRequests(asq, (nAerlimit + 1)); LOG_NRM("Delay 5 sec"); sleep(5); if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail1"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "1 CE's expected in ACQ but found %d CE's", numCE); } SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true)) != 1) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail2"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to reap on ACQ"); } LOG_NRM("verify SC = Async Event Limit Exceeded"); union CE *ce = (union CE *)ceMem->GetBuffer(); ProcessCE::Validate(*ce, CESTAT_ASYNC_REQ_EXCEED); for (uint8_t nAer = 0; nAer < nAerlimit; nAer++) { LOG_NRM("Ring doorbell for IOSQ #1"); InvalidSQWriteDoorbell(); sleep(1); LOG_NRM("verify CE exists in ACQ for invalid SQID doorbell write"); if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail4"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "1 CE expected in ACQ but found %d CEs", numCE); } SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true)) != 1) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail5"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to reap on ACQ"); } union CE *ce = (union CE *)ceMem->GetBuffer(); if (ce->n.async.asyncEventType != EVENT_TYPE_ERROR_STS) { throw FrmwkEx(HERE, "Invalid async event error status, " "(Expected : Received) :: (%d : %d)", EVENT_TYPE_ERROR_STS, ce->n.async.asyncEventType); } else if (ce->n.async.asyncEventInfo != ERR_STS_INVALID_SQ) { throw FrmwkEx(HERE, "Invalid async event info, " "(Expected : Received) :: (%d : %d)", ERR_STS_INVALID_SQ, ce->n.async.asyncEventInfo); } LOG_NRM("Associated Log page = %d", ce->n.async.assocLogPage); ReadLogPage(acq, asq, ce->n.async.assocLogPage); } }
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 FunctionalityMeta_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ string work; bool enableLog; ConstSharedIdentifyPtr namSpcPtr; SharedIOSQPtr iosq; SharedIOCQPtr iocq; uint64_t maxWrBlks; 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); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); uint32_t maxDtXferSz = idCmdCtrlr->GetMaxDataXferSize(); if (maxDtXferSz == 0) maxDtXferSz = MAX_DATA_TX_SIZE; LOG_NRM("Prepare cmds to be send through Q's."); SharedWritePtr writeCmd = SharedWritePtr(new Write()); SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer()); SharedReadPtr readCmd = SharedReadPtr(new Read()); SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer()); SharedFlushPtr flushCmd = SharedFlushPtr(new Flush()); DataPattern dataPat[] = { DATAPAT_INC_8BIT, DATAPAT_CONST_8BIT, DATAPAT_INC_16BIT, DATAPAT_CONST_16BIT, DATAPAT_INC_32BIT, DATAPAT_CONST_32BIT }; uint64_t dpArrSize = sizeof(dataPat) / sizeof(dataPat[0]); send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST); LOG_NRM("Seeking all meta namspc's."); vector<uint32_t> meta = gInformative->GetMetaNamespaces(); for (size_t i = 0; i < meta.size(); i++) { LOG_NRM("Processing meta namspc id #%d of %ld", meta[i], meta.size()); 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); uint64_t ncap = namSpcPtr->GetValue(IDNAMESPC_NCAP); uint64_t metaBuffSz = 0; LOG_NRM("Set read and write buffers based on the namspc type"); switch (gInformative->IdentifyNamespace(namSpcPtr)) { case Informative::NS_BARE: throw FrmwkEx(HERE, "Namspc type cannot be BARE."); case Informative::NS_METAS: maxWrBlks = maxDtXferSz / lbaDataSize; metaBuffSz = maxWrBlks * lbaFormat.MS; if (gRsrcMngr->SetMetaAllocSize(metaBuffSz) == false) throw FrmwkEx(HERE); LOG_NRM("Max rd/wr blks %ld using separate meta buff of ncap %ld", maxWrBlks, ncap); writeMem->Init(maxWrBlks * lbaDataSize); readMem->Init(maxWrBlks * lbaDataSize); writeCmd->AllocMetaBuffer(); readCmd->AllocMetaBuffer(); break; case Informative::NS_METAI: maxWrBlks = maxDtXferSz / (lbaDataSize + lbaFormat.MS); LOG_NRM("Max rd/wr blks %ld using integrated meta buff of ncap %ld", maxWrBlks, ncap); writeMem->Init(maxWrBlks * (lbaDataSize + lbaFormat.MS)); readMem->Init(maxWrBlks * (lbaDataSize + lbaFormat.MS)); break; case Informative::NS_E2ES: case Informative::NS_E2EI: throw FrmwkEx(HERE, "Deferring work to handle this case in future"); break; } writeCmd->SetPrpBuffer(prpBitmask, writeMem); writeCmd->SetNSID(meta[i]); writeCmd->SetNLB(maxWrBlks - 1); // 0 based value. readCmd->SetPrpBuffer(prpBitmask, readMem); readCmd->SetNSID(meta[i]); readCmd->SetNLB(maxWrBlks - 1); // 0 based value. flushCmd->SetNSID(meta[i]); for (uint64_t sLBA = 0; sLBA < maxWrBlks/*(ncap - 1)*/; sLBA += maxWrBlks) { LOG_NRM("Processing at #%ld blk of %ld", sLBA, (ncap -1)); if ((sLBA + maxWrBlks) >= ncap) { maxWrBlks = ncap - sLBA; LOG_NRM("Resize max write blocks to #%ld", maxWrBlks); ResizeDataBuf(readCmd, writeCmd, namSpcPtr, maxWrBlks, prpBitmask); metaBuffSz = maxWrBlks * lbaFormat.MS; } LOG_NRM("Sending #%ld blks starting at #%ld", maxWrBlks, sLBA); for (uint64_t nLBA = 0; nLBA < maxWrBlks; nLBA++) { writeMem->SetDataPattern(dataPat[nLBA % dpArrSize], (sLBA + nLBA + 1), (nLBA * lbaDataSize), lbaDataSize); writeCmd->SetMetaDataPattern(dataPat[nLBA % dpArrSize], (sLBA + nLBA + 1), (nLBA * lbaFormat.MS), lbaFormat.MS); } writeCmd->SetSLBA(sLBA); readCmd->SetSLBA(sLBA); enableLog = false; if ((sLBA <= maxWrBlks) || (sLBA >= (ncap - 2 * maxWrBlks))) enableLog = true; work = str(boost::format("metaID.%d.SLBA.%ld") % meta[i] % sLBA); LOG_NRM("Sending write and read commands through ioq's"); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, writeCmd, work, enableLog); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, flushCmd, work, enableLog); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, readCmd, work, enableLog); VerifyDataPat(readCmd, writeCmd, metaBuffSz); } } }