void AdminQRollChkDiff_r10b::VerifyCESQValues(SharedACQPtr acq, uint16_t expectedVal) { union CE ce; struct nvme_gen_cq acqMetrics = acq->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); } if (ce.n.SQID != 0) { acq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "acq", "CE.SQID"), "CE SQ ID Inconsistent"); throw FrmwkEx(HERE, "Expected CE.SQID = 0 in ACQ completion entry but actual " "CE.SQID = 0x%04X", ce.n.SQID); } 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); } }
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); } }
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; } }