void QIDVariations_r10b::ReapVerifyOnCQ(SharedIOCQPtr iocq, SharedIOSQPtr iosq) { uint32_t numCE; uint32_t ceRemain; uint32_t numReaped; uint32_t isrCount; LOG_NRM("Reap and verify CE."); SharedMemBufferPtr ceMemIOCQ = SharedMemBufferPtr(new MemBuffer()); for (uint32_t nCmds = 1; nCmds < iosq->GetNumEntries(); nCmds++) { LOG_NRM("Wait for the CE to arrive in IOCQ"); if (iocq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount) == false) { iocq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq", "reapInq"), "Unable to see any CE's in IOCQ, dump entire CQ contents"); throw FrmwkEx(HERE, "Unable to see completion of cmd"); } LOG_NRM("The CQ's metrics B4 reaping holds head_ptr needed"); struct nvme_gen_cq iocqMetrics = iocq->GetQMetrics(); KernelAPI::LogCQMetrics(iocqMetrics); if ((numReaped = iocq->Reap(ceRemain, ceMemIOCQ, isrCount, 1, true)) != 1) { iocq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq", "reap"), "Unable to see any CE's in IOCQ, dump entire CQ contents"); throw FrmwkEx(HERE, "Verified there was 1 CE, but reaping failed"); } LOG_NRM("The reaped CE is..."); iocq->LogCE(iocqMetrics.head_ptr); union CE ce = iocq->PeekCE(iocqMetrics.head_ptr); ProcessCE::Validate(ce); // throws upon error if (ce.n.SQID != iosq->GetQId()) { iocq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq", "sqId"), "Wrong SQID in the CE of IOCQ, dump entire CQ contents"); throw FrmwkEx(HERE, "Invalid SQID %d in CE, expected SQID", ce.n.SQID, iosq->GetQId()); } } }
void CreateIOSQ::Init(const SharedIOSQPtr iosq) { // Setup the PRP buffer based upon contig or non-contig memory int prpField = MASK_PRP1_PAGE; if (iosq->GetIsContig() == false) prpField |= MASK_PRP1_LIST; SetPrpBuffer((send_64b_bitmask)prpField, iosq->GetQBuffer(), iosq->GetQSize()); { // Handle DWORD 10 uint32_t dword10 = GetDword(10); // Handle q size dword10 &= ~0xffff0000; dword10 |= (((uint32_t)iosq->GetNumEntries()) << 16); // Handle Q ID dword10 &= ~0x0000ffff; dword10 |= (uint32_t)iosq->GetQId(); SetDword(dword10, 10); } // Handle DWORD 10 { // Handle DWORD 11 uint32_t dword11 = GetDword(11); // Handle the PC bit if (iosq->GetIsContig()) dword11 |= 0x00000001; else dword11 &= ~0x00000001; // Handle Q priority dword11 &= ~0x00000006; dword11 |= (((uint32_t)iosq->GetPriority()) << 1); // Handle CQ ID dword11 &= ~0xffff0000; dword11 |= (((uint32_t)iosq->GetCqId()) << 16); SetDword(dword11, 11); } // Handle DWORD 11 }
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); } }