void IOQRollChkDiff_r10b::VerifyQPointers(SharedIOSQPtr iosq, SharedIOCQPtr iocq) { struct nvme_gen_cq iocqMetrics = iocq->GetQMetrics(); struct nvme_gen_sq iosqMetrics = iosq->GetQMetrics(); uint32_t expectedVal = (2 + MAX(iocq->GetNumEntries(), iosq->GetNumEntries())) % iocq->GetNumEntries(); if (iocqMetrics.head_ptr != expectedVal) { iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq", "head_ptr"), "CQ Metrics Head Pointer Inconsistent"); throw FrmwkEx(HERE, "Expected IO CQ.head_ptr = 0x%04X but actual " "IOCQ.head_ptr = 0x%04X", expectedVal, iocqMetrics.head_ptr); } expectedVal = (2 + MAX(iocq->GetNumEntries(), iosq->GetNumEntries())) % iosq->GetNumEntries(); if (iosqMetrics.tail_ptr != expectedVal) { iosq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iosq", "tail_ptr"), "SQ Metrics Tail Pointer Inconsistent"); throw FrmwkEx(HERE, "Expected IO SQ.tail_ptr = 0x%04X but actual " "IOSQ.tail_ptr = 0x%04X", expectedVal, iosqMetrics.tail_ptr); } }
void SQCQSizeMismatch_r10b::ReapVerifyOnCQ(SharedIOCQPtr iocq, SharedIOSQPtr iosq) { uint32_t numCE; uint32_t ceRemain; uint32_t numReaped; uint32_t isrCount; SharedMemBufferPtr ceMemIOCQ = SharedMemBufferPtr(new MemBuffer()); for (uint32_t nCmds = 1; nCmds < iocq->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 CreateIOCQ::Init(const SharedIOCQPtr iocq) { // Setup the PRP buffer based upon contig or non-contig memory int prpField = MASK_PRP1_PAGE; if (iocq->GetIsContig() == false) prpField |= MASK_PRP1_LIST; SetPrpBuffer((send_64b_bitmask)prpField, iocq->GetQBuffer(), iocq->GetQSize()); { // Handle DWORD 10 uint32_t dword10 = GetDword(10); // Handle q size dword10 &= ~0xffff0000; dword10 |= (((uint32_t)(iocq->GetNumEntries() - 1)) << 16); // Handle Q ID dword10 &= ~0x0000ffff; dword10 |= (uint32_t)iocq->GetQId(); SetDword(dword10, 10); } // Handle DWORD 10 { // Handle DWORD 11 uint32_t dword11 = GetDword(11); // Handle the PC bit if (iocq->GetIsContig()) dword11 |= 0x00000001; else dword11 &= ~0x00000001; // Handle IRQ support if (iocq->GetIrqEnabled()) { dword11 |= 0x00000002; dword11 &= ~0xffff0000; // clear it, then set it enum nvme_irq_type irq; uint16_t numIrqs; if (gCtrlrConfig->GetIrqScheme(irq, numIrqs) == false) throw FrmwkEx(HERE, "Unable to retrieve current IRQ scheme"); switch (irq) { case INT_MSI_MULTI: case INT_MSIX: dword11 |= (((uint32_t)iocq->GetIrqVector()) << 16); break; case INT_MSI_SINGLE: case INT_NONE: ; // Required to be zero break; default: throw FrmwkEx(HERE, "Unsupported IRQ scheme, what to do?"); } } else { dword11 &= ~0x00000002; dword11 &= ~0xffff0000; } SetDword(dword11, 11); } // Handle DWORD 11 }