Test::RunType CreateResources_r11::RunnableCoreTest(bool preserve) { /////////////////////////////////////////////////////////////////////////// // All code contained herein must never permanently modify the state or // configuration of the DUT. Permanence is defined as state or configuration // changes that will not be restored after a cold hard reset. /////////////////////////////////////////////////////////////////////////// ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr(); uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS); uint64_t mic = idCtrlrCap->GetValue(IDCTRLRCAP_MIC); if((mic & MIC_SUP_PCI_PORTS) == 0) { LOG_NRM("Reporting only one PCI port is supported (mic)%ld", mic); return RUN_FALSE; } else { if ((oncs & ONCS_SUP_RSRV) == 0) { LOG_NRM("Reporting Reservations not supported (oncs)%ld", oncs); return RUN_FALSE; } } preserve = preserve; // Suppress compiler error/warning return RUN_TRUE; // This test is never destructive }
Test::RunType UnsupportRsvdFields_r11b::RunnableCoreTest(bool preserve) { /////////////////////////////////////////////////////////////////////////// // All code contained herein must never permanently modify the state or // configuration of the DUT. Permanence is defined as state or configuration // changes that will not be restored after a cold hard reset. /////////////////////////////////////////////////////////////////////////// ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr(); uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS); if ((oncs & ONCS_SUP_DSM_CMD) == 0) { LOG_NRM("Reporting not supoorted (oncs)%ld", oncs); return RUN_FALSE; } LOG_NRM("Reporting runnable (oncs)%ld", oncs); if (gCmdLine.rsvdfields == false) return RUN_FALSE; // Optional rsvd fields test skipped. preserve = preserve; // Suppress compiler error/warning return RUN_TRUE; // This test is never destructive }
void UnsupportRrvdFields_r10b::ReadLogPage(SharedACQPtr &acq, SharedASQPtr &asq, uint8_t logId) { string work; LOG_NRM("Reading log page with LID = %d to clear the event mask", logId); ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint8_t X = idCtrlrStruct->GetValue(IDCTRLRCAP_ELPE) + 1; LOG_NRM("Identify controller ELPE = %d (1-based)", X); LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); LOG_NRM("Create memory buffer for log page to request error information"); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); LOG_NRM("Get log page to request error information logId = %d", logId); getLogPgCmd->SetLID(logId); getLogPageMem->Init(GetLogPage::ERRINFO_DATA_SIZE * X, true); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); getLogPgCmd->SetNUMD((GetLogPage::ERRINFO_DATA_SIZE * X / 4) - 1); //0-based work = str(boost::format("ErrorLog%d") % (uint32_t)logId); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true); }
void PRP1PRP2_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ LOG_NRM("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("Determine if DUT has atleast one namespace support"); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0) throw FrmwkEx(HERE, "Required to support >= 1 namespace"); LOG_NRM("Form identify namespace cmd and associate some buffer"); SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify()); idCmdNamSpc->SetCNS(false); idCmdNamSpc->SetNSID(1); SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer()); idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_OFFSET, true); LOG_NRM("Allow PRP1 and PRP2"); send_64b_bitmask idPrpNamSpc = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "prp1Prp2", true); }
void UnsupportRsvdFields_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ LOG_NRM("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("Determine if DUT has atleast one namespace support"); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0) throw FrmwkEx(HERE, "Required to support >= 1 namespace"); LOG_NRM("Form identify namespace cmd and associate some buffer"); SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify()); idCmdNamSpc->SetCNS(0); idCmdNamSpc->SetNSID(1); SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer()); idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_OFFSET, true); LOG_NRM("Allow PRP1 and PRP2"); send_64b_bitmask idPrpNamSpc = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdnone.set", true); LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = idCmdNamSpc->GetDword(0); work |= 0x0000fc00; // Set DW0_b15:10 bits idCmdNamSpc->SetDword(work, 0); idCmdNamSpc->SetDword(0xffffffff, 2); idCmdNamSpc->SetDword(0xffffffff, 3); idCmdNamSpc->SetDword(0xffffffff, 4); idCmdNamSpc->SetDword(0xffffffff, 5); work = idCmdNamSpc->GetDword(10); work |= 0xfffffffe; // Set DW10_b31:1 bits idCmdNamSpc->SetDword(work, 10); idCmdNamSpc->SetDword(0xffffffff, 11); idCmdNamSpc->SetDword(0xffffffff, 12); idCmdNamSpc->SetDword(0xffffffff, 13); idCmdNamSpc->SetDword(0xffffffff, 14); idCmdNamSpc->SetDword(0xffffffff, 15); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdall.set", true); }
void LBAOutOfRangeBare_r12::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ uint64_t nsze; char work[256]; ConstSharedIdentifyPtr namSpcPtr; // Lookup objs which were created in a prior test within group SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); vector<uint32_t> bare = gInformative->GetBareNamespaces(); for (size_t i = 0; i < bare.size(); i++) { namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]); if (namSpcPtr->isZeroFilled()) { LOG_NRM("Namespace %lu is inactive", i); } else { nsze = namSpcPtr->GetValue(IDNAMESPC_NSZE); LOG_NRM("Create memory to contain write payload"); SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer()); uint64_t lbaDataSize = namSpcPtr->GetLBADataSize(); writeMem->Init(WR_NUM_BLKS * lbaDataSize); LOG_NRM("Create a write cmd to write data to namspc %d", bare[i]); SharedWritePtr writeCmd = SharedWritePtr(new Write()); send_64b_bitmask prpBitmask = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST); writeCmd->SetPrpBuffer(prpBitmask, writeMem); writeCmd->SetNSID(bare[i]); writeCmd->SetNLB(WR_NUM_BLKS - 1); // convert to 0-based value LOG_NRM( "Issue cmd where 1st block starts at LBA (Identify.NSZE-2)"); snprintf(work, sizeof(work), "nsze-2.%01d", (uint32_t)i); writeCmd->SetSLBA(nsze - 2); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, writeCmd, work, true); LOG_NRM( "Issue cmd where 1st block starts at LBA (Identify.NSZE-1)"); snprintf(work, sizeof(work), "nsze-1.%d01d", (uint32_t)i); writeCmd->SetSLBA(nsze - 1); SendCmdToHdw(iosq, iocq, writeCmd, work); LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE)"); snprintf(work, sizeof(work), "nsze.%01d", (uint32_t)i); writeCmd->SetSLBA(nsze); SendCmdToHdw(iosq, iocq, writeCmd, work); } } }
bool LBAOutOfRangeBare_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ uint64_t nsze; ConstSharedIdentifyPtr namSpcPtr; // Lookup objs which were created in a prior test within group SharedIOSQPtr iosqContig = CAST_TO_IOSQ( gRsrcMngr->GetObj(IOSQ_CONTIG_GROUP_ID)) SharedIOCQPtr iocqContig = CAST_TO_IOCQ( gRsrcMngr->GetObj(IOCQ_CONTIG_GROUP_ID)) vector<uint32_t> bare = gInformative->GetBareNamespaces(); for (size_t i = 1; i < bare.size(); i++) { namSpcPtr = gInformative->GetIdentifyCmdNamspc(i); if (namSpcPtr == Identify::NullIdentifyPtr) { LOG_ERR("Identify namspc struct #%d doesn't exist", bare[i]); throw exception(); } nsze = namSpcPtr->GetValue(IDNAMESPC_NSZE); LOG_NRM("Create memory to contain read payload"); SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer()); uint64_t lbaDataSize = namSpcPtr->GetLBADataSize(); readMem->Init(RD_NUM_BLKS * lbaDataSize); LOG_NRM("Create a read cmd to read data from namspc %d", bare[i]); SharedReadPtr readCmd = SharedReadPtr(new Read(mFd)); send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST); readCmd->SetPrpBuffer(prpBitmask, readMem); readCmd->SetNSID(bare[i]); readCmd->SetNLB(RD_NUM_BLKS - 1); // convert to 0-based value LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE-2)"); readCmd->SetSLBA(nsze - 2); IO::SendCmdToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosqContig, iocqContig, readCmd, "nsze-2", true); LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE-1)"); readCmd->SetSLBA(nsze - 1); SendCmdToHdw(iosqContig, iocqContig, readCmd, "nsze-1"); LOG_NRM("Issue cmd where 1st block starts at LBA (Identify.NSZE)"); readCmd->SetSLBA(nsze); SendCmdToHdw(iosqContig, iocqContig, readCmd, "nsze"); } return true; }
void InvalidNamspc_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ uint64_t inc, i; string work; uint32_t numCE; uint32_t isrCountB4; LOG_NRM("Lookup objs which were created in a prior test within group"); SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); if ((numCE = iocq->ReapInquiry(isrCountB4, true)) != 0) { iocq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq", "notEmpty"), "Test assumption have not been met"); throw FrmwkEx(HERE, "Require 0 CE's within CQ %d, not upheld, found %d", iocq->GetQId(), numCE); } LOG_NRM("Setup write cmd's values that won't change per namspc"); SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer()); uint64_t lbaDataSize = 512; writeMem->Init(lbaDataSize); SharedWritePtr writeCmd = SharedWritePtr(new Write()); send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST); writeCmd->SetPrpBuffer(prpBitmask, writeMem); writeCmd->SetNLB(0); // convert to 0-based value writeCmd->SetSLBA(0); LOG_NRM("For all namspc's issue cmd to an illegal namspc"); ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN); if (nn == 0 ) { throw FrmwkEx(HERE, "Required to support >= 1 namespace"); } for (i = (nn + 1), inc = 1; i <= 0xffffffff; i += (2 * inc), inc += 1327) { LOG_NRM("Issue flush cmd with illegal namspc ID=%llu", (unsigned long long)i); writeCmd->SetNSID(i); work = str(boost::format("namspc%d") % i); SendCmdToHdw(iosq, iocq, writeCmd, work); } }
void IOSQ::Init(uint16_t qId, uint32_t numEntries, uint16_t cqId, uint8_t priority) { uint8_t entrySize; uint64_t work; LOG_NRM("IOSQ::Init (qId,numEntry,cqId,prior) = (%d,%d,%d,%d)", qId, numEntries, cqId, priority); switch (priority) { case 0: case 1: case 2: case 3: mPriority = priority; break; default: throw FrmwkEx(HERE, "Illegal priority value, can't fit within 2 bits"); } if (gCtrlrConfig->GetIOSQES(entrySize) == false) throw FrmwkEx(HERE, "Unable to learn IOSQ entry size"); // Nothing to gain by specifying an element size which the DUT doesn't // support, the outcome is undefined, might succeed in crashing the kernel ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr(); uint64_t value = idCtrlrCap->GetValue(IDCTRLRCAP_SQES); uint8_t maxElemSize = (uint8_t)((value >> 4) & 0x0f); uint8_t minElemSize = (uint8_t)((value >> 0) & 0x0f); if ((entrySize < minElemSize) || (entrySize > maxElemSize)) { throw FrmwkEx(HERE, "Reg CC.IOSQES yields a bad element size: 0x%04X", (1 << entrySize)); } // Detect if doing something that looks suspicious/incorrect/illegal if (gRegisters->Read(CTLSPC_CAP, work) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); work &= CAP_MQES; work += 1; // convert to 1-based if ((work + 1) < (uint64_t)numEntries) { LOG_WARN("Creating Q with %d entries, but DUT only allows %d", numEntries, (uint32_t)(work + 1)); } SQ::Init(qId, (1 << entrySize), numEntries, cqId); }
Test::RunType VerifyNUSE_r10b::RunnableCoreTest(bool preserve) { /////////////////////////////////////////////////////////////////////////// // All code contained herein must never permanently modify the state or // configuration of the DUT. Permanence is defined as state or configuration // changes that will not be restored after a cold hard reset. /////////////////////////////////////////////////////////////////////////// ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr(); uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS); if ((oncs & ONCS_SUP_DSM_CMD) == 0) return RUN_FALSE; return ((preserve == true) ? RUN_FALSE : RUN_TRUE); // Test is destructive }
void UnsupportRsvdFields_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); SharedFlushPtr flushCmd = SharedFlushPtr(new Flush()); ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr(); for (uint64_t i = 1; i <= idCtrlr->GetValue(IDCTRLRCAP_NN); i++) { LOG_NRM("Processing namspc %ld", i); flushCmd->SetNSID(i); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, flushCmd, "none.set", true); LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = flushCmd->GetDword(0); work |= 0x0000fc00; // Set DW0_b15:10 bits flushCmd->SetDword(work, 0); flushCmd->SetDword(0xffffffff, 2); flushCmd->SetDword(0xffffffff, 3); flushCmd->SetDword(0xffffffff, 4); flushCmd->SetDword(0xffffffff, 5); flushCmd->SetDword(0xffffffff, 6); flushCmd->SetDword(0xffffffff, 7); flushCmd->SetDword(0xffffffff, 8); flushCmd->SetDword(0xffffffff, 9); flushCmd->SetDword(0xffffffff, 10); flushCmd->SetDword(0xffffffff, 11); flushCmd->SetDword(0xffffffff, 12); flushCmd->SetDword(0xffffffff, 13); flushCmd->SetDword(0xffffffff, 14); flushCmd->SetDword(0xffffffff, 15); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, flushCmd, "all.set", true); } }
Test::RunType CreateAndAttachMaxNamespacesAndVerify::RunnableCoreTest(bool preserve) { /////////////////////////////////////////////////////////////////////////// // All code contained herein must never permanently modify the state or // configuration of the DUT. Permanence is defined as state or configuration // changes that will not be restored after a cold hard reset. /////////////////////////////////////////////////////////////////////////// ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr(); uint64_t oacs = idCtrlrCap->GetValue(IDCTRLRCAP_OACS); if ((oacs & OACS_SUP_NSMANAGEMENT_CMD) == 0) { LOG_NRM("Reporting Namespace Management not supported (oacs) 0x%02x", (uint32_t) oacs); return RUN_FALSE; } preserve = preserve; // Suppress compiler error/warning return RUN_TRUE; // This test is never destruct }
void UnsupportRsvdFields_r11b::ReadLogPage(SharedACQPtr &acq, SharedASQPtr &asq, uint8_t logId) { string work; LOG_NRM("Reading log page with LID = %d to clear the event mask", logId); ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint16_t elpeVal = idCtrlrStruct->GetValue(IDCTRLRCAP_ELPE) + 1; LOG_NRM("Identify controller ELPE = %d (1-based)", elpeVal); uint16_t totalBytes = elpeVal * GetLogPage::ERRINFO_DATA_SIZE; LOG_NRM("Total bytes available for error info log page: %d", totalBytes); uint8_t mps; if (!gCtrlrConfig->GetMPS(mps)) throw FrmwkEx(HERE, "Failed to retrieve CC.MPS value"); uint32_t twoPages = 2 * (1 << (mps + 12)); LOG_NRM("Size of two memory pages (i.e. PRP1 & PRP2): %d bytes", twoPages); // PRP2 cannot be pointer to PRP list, so don't ask for more than 2 pages if (totalBytes > twoPages) { LOG_NRM("Can only utilize two memory pages; reducing total bytes"); totalBytes = twoPages; } uint16_t totalDwords = totalBytes / 4; LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); LOG_NRM("Create memory buffer for log page to request error information"); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); LOG_NRM("Get log page to request error information logId = %d", logId); getLogPgCmd->SetLID(logId); getLogPageMem->Init(totalBytes, true); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); getLogPgCmd->SetNUMD(totalDwords - 1); //0-based work = str(boost::format("ErrorLog%d") % (uint32_t)logId); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true); }
void GetLogPage::SetNUMD(uint16_t numDW) { uint64_t errLogPgEntries; uint64_t numDWAvail; LOG_NRM("Setting NUMD 0x%04X", numDW); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); errLogPgEntries = idCmdCtrlr->GetValue(IDCTRLRCAP_ELPE); numDWAvail = ((errLogPgEntries * ERRINFO_DATA_SIZE) / sizeof(uint32_t)); if (numDWAvail > numDW) { // per the spec this action is undef'd, so don't allow it LOG_ERR("Request %d DWORDS > %lld available yields undef'd results", numDW, (unsigned long long)numDWAvail); throw exception(); } uint16_t curVal = GetWord(10, 1); curVal &= ~NUMD_BITMASK; curVal |= (numDW & NUMD_BITMASK); SetWord(curVal, 10, 1); }
void Identify_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) This is the 1st within GrpNVMCompareCmd. * * NOTE: To validate whether a DUT is suppose to support or not support an * optional feature, the cmd line option --golden should be used. * The reason this test is present as the 1st within any optional * grouping of tests is to force a development team to make a * decision as to whether these tests should be included or skipped * based upon their specific hdw requirements. This way nothing will * be missed by accident. The assumption is that every optional * feature is support until told otherwise by the cmd line option * --skiptest. * \endverbatim */ ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr(); uint64_t oncs = idCtrlrCap->GetValue(IDCTRLRCAP_ONCS); if ((oncs & ONCS_SUP_DSM_CMD) == 0) throw FrmwkEx(HERE, "Optional feature not supported, see this source"); }
void UnsupportRsvdFields_r12::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ LOG_NRM("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("Determine if DUT has atleast one namespace support"); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0) throw FrmwkEx(HERE, "Required to support >= 1 namespace"); LOG_NRM("Form identify namespace cmd and associate some buffer"); SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify()); idCmdNamSpc->SetCNS(CNS_Namespace); idCmdNamSpc->SetNSID(1); SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer()); idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_OFFSET, true); LOG_NRM("Allow PRP1 and PRP2"); send_64b_bitmask idPrpNamSpc = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdnone.set", true); LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = idCmdNamSpc->GetDword(0); work |= 0x00003c00; // Set DW0_b13:10 bits idCmdNamSpc->SetDword(work, 0); idCmdNamSpc->SetDword(0xffffffff, 2); idCmdNamSpc->SetDword(0xffffffff, 3); idCmdNamSpc->SetDword(0xffffffff, 4); idCmdNamSpc->SetDword(0xffffffff, 5); work = idCmdNamSpc->GetDword(10); //work |= 0xfffffffc; // Set DW10_b31:2 bits work |= 0x0000ff00; // Set DW10_b31:8 bits idCmdNamSpc->SetDword(work, 10); idCmdNamSpc->SetDword(0xffffffff, 11); idCmdNamSpc->SetDword(0xffffffff, 12); idCmdNamSpc->SetDword(0xffffffff, 13); idCmdNamSpc->SetDword(0xffffffff, 14); idCmdNamSpc->SetDword(0xffffffff, 15); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdall.set", true); LOG_NRM("Set CNS field reserved coded value"); uint32_t cdw10 = idCmdNamSpc->GetDword(10); //work = cdw10 | 0x3; //idCmdNamSpc->SetDword(work, 10); const uint32_t cnsNonRsvdVal[] = { 0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x13 }; const uint32_t cnsNonRevdValCnt = sizeof(cnsNonRsvdVal) / sizeof(uint32_t); /*IO::SendAndReapCmdNot(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdall.val.set", true, CESTAT_SUCCESS); */ for (uint32_t cnsVal = 0; cnsVal <= 0xff; cnsVal++){ uint32_t idx = 0; while ((idx < cnsNonRevdValCnt) && (cnsVal != cnsNonRsvdVal[idx])){ ++idx; } if (idx == cnsNonRevdValCnt) { work = cdw10 | cnsVal; idCmdNamSpc->SetDword(work, 10); IO::SendAndReapCmdNot(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdall.val.set", true, CESTAT_SUCCESS); } } }
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); } } }
void InvalidNamspc_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ string work; uint64_t inc, i; // 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("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); getLogPageMem->InitOffset1stPage(GetLogPage::SMART_DATA_SIZE, 0, true); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); getLogPgCmd->SetLID(SMART_HEALTH_INFO_LID); getLogPgCmd->SetNUMD(SMART_NUMD - 1); // 0 - based ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN); if (nn == 0 ) throw FrmwkEx(HERE, "Required to support >= 1 namespace"); uint8_t logPageAttr = (uint8_t)idCtrlrStruct->GetValue(IDCTRLRCAP_LPA); // bits 7:1 are reserved, need bit 0 uint8_t suppSmartPerNamspc = logPageAttr & 0x1; if(suppSmartPerNamspc > 0) { LOG_NRM("IDCTRLRCAP_LPA bit0 is set. Per Namespace Smart Pages supported") } else { LOG_NRM("IDCTRLRCAP_LPA bit0 is not set. Per Namespace Smart Pages is not supported") } // for all illegal nsid's verify get log page cmd. for (i = (nn + 1), inc = 1; i < 0xffffffff; i += (2 * inc), inc += 1327) { LOG_NRM("Issue Get log page cmd with illegal namspc ID = 0x%llX", (unsigned long long)i); getLogPgCmd->SetNSID(i); work = str(boost::format("namspc%d") % i); // Determine the status based on the per namespace mask bit. // While the 1.1+ spec requires the device to return invalid field // the 1.0 spec does NOT require the device to return SUCCESS and // a global log page no matter what value of NSID is provided // Instead only the global 0xFFFFFFFF NSID MUST be supported IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true, CESTAT_INVAL_NAMSPC); } // If per namespc smart log is supported, check all legal nn. if (suppSmartPerNamspc) { for (i = 1; i <= nn; i++) { LOG_NRM("Issue Get log page cmd with legal namspc ID = 0x%llX (per namespace smart log supported)", (unsigned long long)i); getLogPgCmd->SetNSID(i); work = str(boost::format("namspc%d") % i); // Determine the status based on the per namespace mask bit. IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true); } } // GetLogPage of NSID == 0 is not expected to pass when LPA bit 0 is not set // The only requirement is that 0xFFFFFFFF is supported, not that the NSID field // is completely ignored and a global page is always returned... /* else { i = 0; getLogPgCmd->SetNSID(i); work = str(boost::format("namspc%d") % i); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true); } */ // If name space is 0xffffffff, then we should get the global log info. i = 0xffffffff; getLogPgCmd->SetNSID(i); work = str(boost::format("namspc%d") % i); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true); }
void CreateAndAttachMaxNamespacesAndVerify::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ LOG_NRM("Start CreateAndAttachMaxNamespacesAndVerify::RunCoreTest"); SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)); SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)); //uint8_t keyToRegister[16]; //uint32_t memAlignment = sysconf(_SC_PAGESIZE); //CEStat retStat; send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE); uint8_t userBuffer[4096]; if (userBuffer == 0){} // Suppress unused variable warning const uint32_t *namespaceIdListBuffer32BitPtr = NULL; const uint16_t *controllerIdListBuffer16BitPtr; ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr(); uint32_t identifyControllerMaxNSID = (uint32_t)idCtrlrCap->GetValue(IDCTRLRCAP_NN); // BUGBUG large assumption that NVMCAP values will not be larger than 64bit num bytes, which is 16384 PETAbytes // BUGBUG Also assume we need to create on GB multiples uint64_t identifyControllerUnallocatedCapacity = idCtrlrCap->GetValue(IDCTRLRCAP_UNVMCAP_LOWER); uint64_t identifyControllerTotalCapacity = idCtrlrCap->GetValue(IDCTRLRCAP_TNVMCAP_LOWER); uint64_t individualNamespaceCapacityInGB = (uint64_t) floor( identifyControllerUnallocatedCapacity / 1024.0 / 1024.0 / 1024.0 / identifyControllerMaxNSID); // In GB units uint64_t individualNamespaceCapacity = individualNamespaceCapacityInGB * 1024 * 1024 * 1024 / 512; // In 512B LBA units uint32_t newlyCreatedNSID = 0; if( identifyControllerUnallocatedCapacity != identifyControllerTotalCapacity) { LOG_NRM("TNVMCAP != UNVMCAP, which points to a namespace being allocated but the previous test should have deleted all"); } LOG_NRM("Create Identify Command To Get All Present NSIDs"); SharedIdentifyPtr identifyCmd = SharedIdentifyPtr(new Identify()); SharedMemBufferPtr identifyControllerStruct = SharedMemBufferPtr(new MemBuffer()); identifyControllerStruct->Init(4096, true, 0x0); SharedMemBufferPtr identifyNamespaceStruct = SharedMemBufferPtr(new MemBuffer()); identifyNamespaceStruct->Init(4096, true, 0x0); SharedMemBufferPtr identifyNamespaceList = SharedMemBufferPtr(new MemBuffer()); identifyNamespaceList->Init(4096, true, 0x0); SharedMemBufferPtr identifyControllerList = SharedMemBufferPtr(new MemBuffer()); identifyControllerList->Init(4096, true, 0x0); // Figure 86 in 1.2 spec CNS NSID CNTID Returns // CNS_Namespace 0x00 X - (Identify Namespace from NSID X. If attached, receive struct, else all 0's, else invalid namespace ID) // CNS_Controller 0x01 - - (Identify Controller struct) // CNS_NamespaceListAttached 0x02 Y - (Identify Namespace LIST, starting at NSID Y and in an increasing order) // CNS_NamespaceListSubsystem 0x10 Z - (Identify Namespace LIST, starting at NSID Z present in subsystem that may or may not be attached) // CNS_NamespaceStructSubsystem 0x11 X - (Identify Namespace from NSID A. If attached or not, receive the struct, else invalid namespace ID) // CNS_ControllerListAttachedToNSID 0x12 X A (Controller List that are attached to NSID X, starting with CNTID greater than A) // CNS_ControllerListSubsystem 0x13 - B (Controller List present in subsystem starting with CNTID greater than B) LOG_NRM("First ensure there are no namespaces present, as this test depends on deleteAllNamespacesAndVerify to complete successfully"); // See 8.11 in 1.2 spec for describing the process this test is following identifyCmd->SetPrpBuffer(prpBitmask, identifyNamespaceList); identifyCmd->SetNSID( 0 ); identifyCmd->SetCNS( CNS_NamespaceListSubsystem ); // Get all NSIDs attached (or not) to controllers identifyCmd->SetCNTID(0); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Reading back (up to) 1024 NSIDs attached to this controller (CNS=2). Command should pass, with 0 NSIDs to be returned", false, CESTAT_SUCCESS); namespaceIdListBuffer32BitPtr = (uint32_t*) identifyCmd->GetROPrpBuffer(); if( namespaceIdListBuffer32BitPtr[0] != 0) { throw FrmwkEx(HERE, "Before creating any namespaces, subsystem was expected to have no NSIDs active and present, but Identify CNS=0x10 returned at least one NSID."); } LOG_NRM("No namespaces are active, test can continue. Pull back the controller list to be used to attach all NSIDs to all controllers on subsystem"); identifyCmd->SetPrpBuffer(prpBitmask, identifyControllerList); identifyCmd->SetNSID( 0 ); identifyCmd->SetCNS( CNS_ControllerListSubsystem ); // Get all controllers in this subsystem identifyCmd->SetCNTID(0); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Reading back what controllers are on this subsystem (CNS=0x13), should find at LEAST one.", false, CESTAT_SUCCESS); controllerIdListBuffer16BitPtr = (uint16_t*) identifyCmd->GetROPrpBuffer(); if( controllerIdListBuffer16BitPtr[0] == 0) { throw FrmwkEx(HERE, "Before creating any namespaces, subsystem was expected to have at least one controller ID present, but found zero."); } SharedNamespaceAttachPtr namespaceAttachCmd = SharedNamespaceAttachPtr(new NamespaceAttach() ); /* //BUGBUG APL is returning an improper list (Ctrlr IDs 1/2 wheras they ID themselves as actually 0/1) for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) { userBuffer[bufferIndex]=0; } userBuffer[0] = 2; // 2 Controllers userBuffer[4] = 1; // 1st (byte 2) is 0 and 2nd (byte 4) is 1 to match APL identifyControllerList->InitAlignment(4096, 4096, false, 0, userBuffer); LOG_NRM("Controller list hardcoded to 0/1 for the time being... BUGBUG"); // END BUG BUG */ // Set attach namespace buffer to be the full controller list, to attach all new NSIDs to to all on this subsystem namespaceAttachCmd->SetPrpBuffer(prpBitmask, identifyControllerList); LOG_NRM("Create Namespace Management to create all namespaces before attaching to all contollers"); SharedNamespaceManagementPtr namespaceManagementCmd = SharedNamespaceManagementPtr(new NamespaceManagement() ); SharedMemBufferPtr managementBuffer = SharedMemBufferPtr(new MemBuffer() ); NamespaceManagementCreateStruct nscreate; nscreate.NSZE = individualNamespaceCapacity; nscreate.NCAP = individualNamespaceCapacity; nscreate.FLBAS = 0; nscreate.DPS = 0; nscreate.NMIC = 1; //NamespaceManagementCreateStruct nscreate( individualNamespaceCapacity, individualNamespaceCapacity, 0, 0, 1 ); // BUGBUG we are going to assume a 512B size and barenamespace as FLBAS=0... otherwise we need to determine what format via namespace structs... //CreateNamespaceManagementStructure( individualNamespaceCapacity, individualNamespaceCapacity, 0, 0, 1, userBuffer); LOG_NRM("Each of the %d namespaces will be of 0x%llx size", identifyControllerMaxNSID, (long long unsigned int) individualNamespaceCapacity); nscreate.print(); managementBuffer->InitAlignment(384, 4096, false, 0x0, (uint8_t*) &nscreate); // Contains namespace struct info for namespace management to consume (384B) namespaceManagementCmd->SetPrpBuffer(prpBitmask, managementBuffer); namespaceAttachCmd->SetSEL( 0 ); namespaceAttachCmd->SetNSID( 0 ); LOG_NRM("Start main loop over valid NSIDs to create/attach them."); for(uint64_t currentNamespaceIdToCreate = 0; currentNamespaceIdToCreate < identifyControllerMaxNSID; currentNamespaceIdToCreate++ ) { // Get the current // Create this namespace using 1/NNth amount of the total available space. namespaceManagementCmd->SetSEL(0); namespaceManagementCmd->SetNSID(0); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceManagementCmd, "Creating namespace that is 1/NNth size of total NVM capacity, 512B bare LBAs.", false, CESTAT_SUCCESS); newlyCreatedNSID = (acq->PeekCEwithCID( namespaceManagementCmd->GetCID() ) ).t.dw0; LOG_NRM("Newly created NS has NSID of 0x%llu", (long long unsigned) newlyCreatedNSID); // ID this namespace and see if it is all 0s. Namespace should be created but 'inactive'. identifyCmd->SetCNS(CNS_Namespace ); // Standard Namespace ID, should also be attached to this controller identifyCmd->SetNSID( newlyCreatedNSID ); // identifyCmd->SetCNTID(0); identifyCmd->SetPrpBuffer(prpBitmask, identifyNamespaceStruct); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Read Identify Controller struct from created NSID, expecting it to be all 0's since it has not yet attached", false, CESTAT_SUCCESS); // Currently fails on FW for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) { if ( identifyCmd->GetROPrpBuffer()[bufferIndex] != 0) { throw FrmwkEx(HERE, "Expected Identify Namespace to returned all zero buffer as namespace should be inactive and non-attached"); } } // Now attach the drive to all controllers on the subsystem namespaceAttachCmd->SetNSID( newlyCreatedNSID ); namespaceAttachCmd->SetSEL(0); // Should already have the ControllerList associated with the NamespaceAttach command IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceAttachCmd, "Attaching NSID to all controllers on subsystem", false, CESTAT_SUCCESS); // Reread this NS struct back and make sure the values match what we had requested... IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Read Identify Controller struct from created NSID, expecting non-zero since it is now attached", false, CESTAT_SUCCESS); // First ensure the buffer is not completely non-zero bool identifyNamespaceBufferIsZeroFilled = true; for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) { if ( identifyCmd->GetROPrpBuffer()[bufferIndex] != 0) { identifyNamespaceBufferIsZeroFilled = false; break; } } if( identifyNamespaceBufferIsZeroFilled == true) { throw FrmwkEx(HERE, "Expected Identify Namespace to returned a non-zero buffer as namespace should now be attached"); } // Now check a couple fields (BUGBUG should check all!) IdNamespcStruct *currentNamespaceStruct = (IdNamespcStruct*) identifyCmd->GetROPrpBuffer(); if(currentNamespaceStruct->NSZE != individualNamespaceCapacity) { LOG_NRM("Namespace NSZE 0x%llx != what was passed to namespaceManagement 0x%08llx", (long long unsigned) currentNamespaceStruct->NSZE, (long long unsigned) individualNamespaceCapacity); throw FrmwkEx(HERE, "Newly created namespace's NSZE does not match what was sent to namespaceManagement"); } if(currentNamespaceStruct->NCAP != individualNamespaceCapacity) { LOG_NRM("Namespace NCAP 0x%llx != what was passed to namespaceManagement 0x%08llx", (long long unsigned) currentNamespaceStruct->NCAP, (long long unsigned) individualNamespaceCapacity); throw FrmwkEx(HERE, "Newly created namespace's NCAP does not match what was sent to namespaceManagement"); } // Repull the Identify Controller information and make sure the UNVMCAP values have decreased the amount we just allocatd for this create namespace identifyCmd->SetCNS(CNS_Controller); identifyCmd->SetNSID(0); identifyCmd->SetCNTID(0); identifyCmd->SetPrpBuffer(prpBitmask, identifyControllerStruct); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Pull Identify Controller to check usage sizes have changed.", false, CESTAT_SUCCESS); IdCtrlrCapStruct *currentControllerStruct = (IdCtrlrCapStruct*) identifyCmd->GetROPrpBuffer(); uint64_t expectedNVMCAP = identifyControllerTotalCapacity - (individualNamespaceCapacity * (currentNamespaceIdToCreate+1) * 512); if(currentControllerStruct->UNVMCAP_LOWER != expectedNVMCAP) { LOG_NRM("Expecting UNVMCAP to decrease by last allocated namespace. UNVMCAP = 0x%llx expecting 0x%llx", (long long unsigned) currentControllerStruct->UNVMCAP_LOWER, (long long unsigned) expectedNVMCAP); throw FrmwkEx(HERE, "Identify Controller UNVMCAP is not adjusted after creating a namespace of 1/NNth size"); } // Try to retry the attachment again and ensure a proper fail case IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceAttachCmd, "Attaching an already attached NSID to all controllers again to check fail case", false, CESTAT_NS_ALREADY_ATTACHED); } // At this point we can double sanity check. // 1) Controller should state 0 bytes available // 2) Should be Cntrl.NN namespaces active and attached to all controllers on the subsystem LOG_NRM("Completed CreateAndAttachMaxNamespacesAndVerify::RunCoreTest"); }
void UnsupportRsvdFields_r11b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); SharedDatasetMgmtPtr datasetMgmtCmd = SharedDatasetMgmtPtr(new DatasetMgmt()); uint16_t timeout; if (gCmdLine.setAD) timeout = 1000; else timeout = 1; ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr(); for (uint64_t i = 1; i <= idCtrlr->GetValue(IDCTRLRCAP_NN); i++) { LOG_NRM("Processing namspc %ld", i); datasetMgmtCmd->SetNSID(i); LOG_NRM("Create memory to contain 1 dataset range def"); SharedMemBufferPtr rangeMem = SharedMemBufferPtr(new MemBuffer()); rangeMem->Init(sizeof(RangeDef), true); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); datasetMgmtCmd->SetPrpBuffer(prpReq, rangeMem); LOG_NRM("Setup generic range def guidelines"); RangeDef *rangeDef = (RangeDef *)rangeMem->GetBuffer(); rangeDef->length = 1; if (gCmdLine.setAD) datasetMgmtCmd->SetAD(true); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(timeout), iosq, iocq, datasetMgmtCmd, "none.set", true); LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = datasetMgmtCmd->GetDword(0); work |= 0x00007c00; // Set DW0_b14:10 bits datasetMgmtCmd->SetDword(work, 0); datasetMgmtCmd->SetDword(0xffffffff, 2); datasetMgmtCmd->SetDword(0xffffffff, 3); datasetMgmtCmd->SetDword(0xffffffff, 4); datasetMgmtCmd->SetDword(0xffffffff, 5); datasetMgmtCmd->SetDword(0xffffffff, 8); datasetMgmtCmd->SetDword(0xffffffff, 9); work = datasetMgmtCmd->GetDword(10); work |= 0xffffff00; // Set DW10_b31:8 bits datasetMgmtCmd->SetDword(work, 10); work = datasetMgmtCmd->GetDword(11); work |= 0xfffffff8; // Set DW11_b31:3 bits if (gCmdLine.setAD) work |= 0x4; // Set Bit2 AD=1 (Deallocate) datasetMgmtCmd->SetDword(work, 11); datasetMgmtCmd->SetDword(0xffffffff, 12); datasetMgmtCmd->SetDword(0xffffffff, 13); datasetMgmtCmd->SetDword(0xffffffff, 14); datasetMgmtCmd->SetDword(0xffffffff, 15); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(timeout), iosq, iocq, datasetMgmtCmd, "all.set", true); } }
void UnsupportRsvdFields_r12::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ CE ce; vector<uint32_t> activeNamespaces; string work; LOG_NRM("Admin queue setup"); SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)); SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)); LOG_NRM("Test proper"); LOG_NRM("Form identify cmd for namespace list and associate some buffer"); SharedIdentifyPtr idCmdNamSpcList = SharedIdentifyPtr(new Identify()); idCmdNamSpcList->SetCNS(CNS_NamespaceListActive); idCmdNamSpcList->SetNSID(0); SharedMemBufferPtr idMemNamSpcList = SharedMemBufferPtr(new MemBuffer()); idMemNamSpcList->InitAlignment(NAMSPC_LIST_SIZE * NAMSPC_ENTRY_SIZE); send_64b_bitmask idPrpNamSpc = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdNamSpcList->SetPrpBuffer(idPrpNamSpc, idMemNamSpcList); LOG_NRM("Sending Identify command CNS.%02Xh", CNS_NamespaceListActive); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpcList, "namspcList", true); LOG_NRM("Reading in active Namespaces."); const uint8_t *data = &((idCmdNamSpcList->GetROPrpBuffer())[0]); while ((*((uint32_t *)data) & 0xffff) != 0x0000){ uint32_t nsid = (*((uint32_t *)data) & 0xffff); LOG_NRM("Found active NSID: %08X", nsid); activeNamespaces.push_back(nsid); data += 4; } // Lookup objs which were created in a prior test within group SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr(); for (size_t i = 0; i < activeNamespaces.size(); i++) { LOG_NRM("Processing namspc %ld", i); SharedFlushPtr flushCmd = SharedFlushPtr(new Flush()); flushCmd->SetNSID(activeNamespaces[i]); ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, flushCmd, "none.set", true); if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){ throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, " "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC); } if (ce.n.reserved != 0){ throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X", ce.n.reserved); } else if(ce.n.cmdSpec != 0){ throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X", ce.n.cmdSpec); } LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = flushCmd->GetDword(0); work |= 0x00003c00; // Set DW0_b13:10 bits flushCmd->SetDword(work, 0); flushCmd->SetDword(0xffffffff, 2); flushCmd->SetDword(0xffffffff, 3); flushCmd->SetDword(0xffffffff, 4); flushCmd->SetDword(0xffffffff, 5); flushCmd->SetDword(0xffffffff, 6); flushCmd->SetDword(0xffffffff, 7); flushCmd->SetDword(0xffffffff, 8); flushCmd->SetDword(0xffffffff, 9); flushCmd->SetDword(0xffffffff, 10); flushCmd->SetDword(0xffffffff, 11); flushCmd->SetDword(0xffffffff, 12); flushCmd->SetDword(0xffffffff, 13); flushCmd->SetDword(0xffffffff, 14); flushCmd->SetDword(0xffffffff, 15); ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,flushCmd, "all.set", true); if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){ throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, " "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC); } if (ce.n.reserved != 0){ throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X", ce.n.reserved); } else if(ce.n.cmdSpec != 0){ throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X", ce.n.cmdSpec); } } // This highestNSID could provide a case where it issues to an inactive NSID // In the case of an inactive NSID the error status would be Invalid Field /*uint32_t highestNSID = 0; for (uint32_t i = 0; i < activeNamespaces.size(); i++){ if (activeNamespaces[i] > highestNSID) highestNSID = activeNamespaces[i]; } if (highestNSID != 0xffffffff){ SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush()); invalidFlushCmd->SetNSID(highestNSID + 1); // Could be Invalid Field or Invalid Namespace or Format IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, invalidFlushCmd, "none.set", true, CESTAT_INVAL_NAMSPC); }*/ ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN); // Issuing flush cmd with a few invalid NSIDs int count = 0; for (uint64_t i = 0; pow(2, i) <= 0xffffffff; i++) { if (pow(2, i) <= nn) continue; LOG_NRM("Issue flush cmd with illegal namspc ID=%llu", (unsigned long long)i); SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush()); invalidFlushCmd->SetNSID(pow(2, i)); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, invalidFlushCmd, "Flush.Invalid", true, CESTAT_INVAL_NAMSPC); count++; } LOG_NRM("Ran with: %d invalid NSIDs", count); }
void StartingLBABare_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ string work; bool enableLog; ConstSharedIdentifyPtr namSpcPtr; // Lookup objs which were created in a prior test within group SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); 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()); send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST); SharedReadPtr readCmd = SharedReadPtr(new Read()); SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer()); 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]); LOG_NRM("Seeking all bare namspc's."); vector<uint32_t> bare = gInformative->GetBareNamespaces(); for (size_t i = 0; i < bare.size(); i++) { LOG_NRM("Processing for BARE name space id #%d", bare[i]); namSpcPtr = gInformative->GetIdentifyCmdNamspc(bare[i]); uint64_t ncap = namSpcPtr->GetValue(IDNAMESPC_NCAP); uint64_t lbaDataSize = namSpcPtr->GetLBADataSize(); uint64_t maxWrBlks = maxDtXferSz / lbaDataSize; writeMem->Init(maxWrBlks * lbaDataSize); writeCmd->SetPrpBuffer(prpBitmask, writeMem); writeCmd->SetNSID(bare[i]); writeCmd->SetNLB(maxWrBlks - 1); // 0 based value. readMem->Init(maxWrBlks * lbaDataSize); readCmd->SetPrpBuffer(prpBitmask, readMem); readCmd->SetNSID(bare[i]); readCmd->SetNLB(maxWrBlks - 1); // 0 based value. for (uint64_t nWrBlks = 0; nWrBlks < (ncap - 1); nWrBlks += maxWrBlks) { LOG_NRM("Sending #%ld blks of #%ld", nWrBlks, (ncap -1)); for (uint64_t nLBA = 0; nLBA < maxWrBlks; nLBA++) { writeMem->SetDataPattern(dataPat[nLBA % dpArrSize], (nWrBlks + nLBA + 1), (nLBA * lbaDataSize), lbaDataSize); } writeCmd->SetSLBA(nWrBlks); readCmd->SetSLBA(nWrBlks); enableLog = false; if ((nWrBlks <= maxWrBlks) || (nWrBlks >= (ncap - 2 * maxWrBlks))) enableLog = true; work = str(boost::format("NSID.%d.SLBA.%ld") % bare[i] % nWrBlks); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, writeCmd, work, enableLog); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, readCmd, work, enableLog); VerifyDataPat(readCmd, writeMem); } } }