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;
}
Exemple #3
0
void
PRP1PRP2_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    // Lookup objs which were created in a prior test within group
    string work;
    uint64_t i;
    
    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());

    LOG_NRM("Get log page to request firmware slot information");
    getLogPgCmd->SetNUMD(PRP1_ONLY_NUMD - 1); // 0-based
    getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID);
    getLogPgCmd->SetNSID(0xFFFFFFFF);    
    
    LOG_NRM("Set the offset into the buffer at 0x%04X", BUFFER_OFFSET);
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE,
        BUFFER_OFFSET, true);
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "prp1prp2", true);
}
Exemple #4
0
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;
}
Exemple #5
0
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);
}
Exemple #6
0
void
DeleteIOQContig_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Both test CreateIOQContigPoll_r10b & CreateIOQDiscontigPoll_r10b has
     *    run prior, or Both test CreateIOQContigIrq_r10b &
     *    CreateIOQDiscontigIrq_r10b has run prior
     * 2) An individual test within this group cannot run, the entire group
     *    must be executed every time. Each subsequent test relies on the prior.
     * \endverbatim
     */

    // 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))


    // According to spec, if one deletes the CQ before the SQ it's a "shall not"
    // statement which means it will have undefined behavior and thus there is
    // nothing to gain by attempting such action.
    LOG_NRM("Lookup IOSQ which was created in a prior test within group");
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_CONTIG_GROUP_ID))
    Queues::DeleteIOSQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms,
        iosq, asq, acq);


    LOG_NRM("Lookup IOCQ which was created in a prior test within group");
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_CONTIG_GROUP_ID))
    Queues::DeleteIOCQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms,
        iocq, asq, acq);
}
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
IllegalCreateQs_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */

    // Lookup objs which were created in a prior test within group
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID))
    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID))

    uint32_t numEntries = 2;
    uint8_t dword;
    uint32_t mask;
    uint32_t value;
    {
        LOG_NRM("Create IOCQ ID #%d but toxify its QID to 0", IOQ_ID);
        SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(mFd));
        iocq->Init(IOQ_ID, numEntries, true, 0);

        LOG_NRM("Form a Create IOCQ cmd");
        SharedCreateIOCQPtr iocqCmd = SharedCreateIOCQPtr(new CreateIOCQ());
        iocqCmd->Init(iocq);

        dword = 10;
        mask = 0xFFFF;
        value = 0;
        SendToxicCmd(asq, acq, iocqCmd, dword, mask, value, CESTAT_INVALID_QID);
    }
    {
        LOG_NRM("Create IOSQ ID #%d but toxify its QID to 0", IOQ_ID);
        SharedIOSQPtr iosq = SharedIOSQPtr(new IOSQ(mFd));
        iosq->Init(IOQ_ID, numEntries, IOQ_ID, 0);

        LOG_NRM("Form a Create IOSQ cmd");
        SharedCreateIOSQPtr iosqCmd = SharedCreateIOSQPtr(new CreateIOSQ());
        iosqCmd->Init(iosq);

        dword = 10;
        mask = 0xFFFF;
        value = 0;
        SendToxicCmd(asq, acq, iosqCmd, dword, mask, value, CESTAT_INVALID_QID);
    }
    {
        LOG_NRM("Create IOSQ ID #%d but wrongly associate to ACQ", IOQ_ID);
        SharedIOSQPtr iosq = SharedIOSQPtr(new IOSQ(mFd));
        iosq->Init(IOQ_ID, numEntries, IOQ_ID, 0);

        LOG_NRM("Form a Create IOSQ cmd");
        SharedCreateIOSQPtr iosqCmd = SharedCreateIOSQPtr(new CreateIOSQ());
        iosqCmd->Init(iosq);

        dword = 11;
        mask = 0xFFFF0000;
        value = 0;
        SendToxicCmd(asq, acq, iosqCmd, dword, mask, value, CESTAT_CQ_INVALID);
    }
}
bool
DeleteIOQDiscontigPoll_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) The ASQ & ACQ's have been created by the RsrcMngr for group lifetime
     * 2) All interrupts are disabled.
     * 3) CreateIOQDiscontigPoll_r10b test case has setup the Q's to delete
     * 4) CC.IOCQES and CC.IOSQES are already setup with correct values.
     * \endverbatim
     */

    uint64_t regVal;
    if (gRegisters->Read(CTLSPC_CAP, regVal) == false) {
        LOG_ERR("Unable to determine Q memory requirements");
        throw exception();
    } else if (regVal & CAP_CQR) {
        LOG_NRM("Unable to utilize discontig Q's, DUT requires contig");
        return true;
    }

    KernelAPI::DumpKernelMetrics(mFd,
        FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "before"));

    // 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))

    DeleteIOCQDiscontigPoll(asq, acq);
    DeleteIOSQDiscontigPoll(asq, acq);

    KernelAPI::DumpKernelMetrics(mFd,
        FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "after"));
    return true;
}
void
InvalidLogPageNVMSet_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    string work;
    // 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(BUFFER_SIZE, 0, true);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
    getLogPgCmd->SetNUMD(NUMD - 1); // 0-based
    getLogPgCmd->SetNSID(0xFFFFFFFF);
    list<uint32_t> invalidLIDs = GetInvalidLIDs();
    for (list<uint32_t>::iterator invalidLID = invalidLIDs.begin();
        invalidLID != invalidLIDs.end(); invalidLID++) {
        LOG_NRM("Processing for invalid LID = 0x%04X", *invalidLID);
        getLogPgCmd->SetLID(*invalidLID);

        work = str(boost::format("invalidLID.%d") % *invalidLID);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getLogPgCmd, work, true, CESTAT_INVAL_LOG_PAGE);
    }
}
void
MandatoryErrInfo_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    string work;
    uint64_t 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))

    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");
    getLogPgCmd->SetLID(ERRINFO_LID);

    // loop for all log entries supported by controller
    for (uint32_t numd = ERRINFO_NUMD; numd <= (X * ERRINFO_NUMD);
        numd += ERRINFO_NUMD) {
        LOG_NRM("Issue Get log page cmd with NUMD = %d and log entries = %d",
            numd, (numd/ERRINFO_NUMD));

        getLogPageMem->Init(GetLogPage::ERRINFO_DATA_SIZE * X, true);
        getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);
        getLogPgCmd->SetNUMD(numd - 1); // 0-based
        getLogPgCmd->SetNSID(0xFFFFFFFF);
        
        work = str(boost::format("logEnties%d") % (numd / ERRINFO_NUMD));
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getLogPgCmd, work, true);

        // Verify the buffer's non-retrieved log entries = 0x00.
        SharedMemBufferPtr cmdPayload = getLogPgCmd->GetRWPrpBuffer();
        uint32_t offset = (numd * 4);
        uint8_t *cmdPayloadBuff = (uint8_t *)cmdPayload->GetBuffer() + offset;
        for (; offset < (X * GetLogPage::ERRINFO_DATA_SIZE); offset++) {
            LOG_NRM("Verify data at offset = 0x%X", offset);
            if (*cmdPayloadBuff != 0x0) {
                throw FrmwkEx(HERE, "Invalid data at buffer offset = 0x%08X, "
                    "value = 0x%08X", cmdPayloadBuff, *cmdPayloadBuff);
            }
            cmdPayloadBuff++;
        }
    }
}
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
    string globalWork;
    //uint64_t i;
    
    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());

    LOG_NRM("Get log page to request firmware slot information");
    getLogPgCmd->SetNUMD(PRP1_ONLY_NUMD - 1); // 0-based
    getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID);
    getLogPgCmd->SetNSID(0xFFFFFFFF);
    
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE,
        BUFFER_OFFSET, true);
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);

    LOG_NRM("Issue GetLogPage cmd without setting reserved bits.");
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "rsvd.notset", true);

    LOG_NRM("Set all cmd's rsvd bits");
    uint32_t work = getLogPgCmd->GetDword(0);
    work |= 0x0000fc00;      // Set DW0_b15:10 bits
    getLogPgCmd->SetDword(work, 0);

    getLogPgCmd->SetDword(0xffffffff, 2);
    getLogPgCmd->SetDword(0xffffffff, 3);
    getLogPgCmd->SetDword(0xffffffff, 4);
    getLogPgCmd->SetDword(0xffffffff, 5);

    work = getLogPgCmd->GetDword(10);
    work |= 0xf0000000;      // Set DW10_b31:28 bits
    getLogPgCmd->SetDword(work, 10);

    getLogPgCmd->SetDword(0xffffffff, 11);
    getLogPgCmd->SetDword(0xffffffff, 12);
    getLogPgCmd->SetDword(0xffffffff, 13);
    getLogPgCmd->SetDword(0xffffffff, 14);
    getLogPgCmd->SetDword(0xffffffff, 15);

    LOG_NRM("Issue GetLogPage cmd after setting reserved bits.");
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "rsvd.set", 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
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;
    }
}
void
CIDAcceptedASQ_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    uint32_t isrCount;
    // 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("Verifying that the ACQ is empty");
    if (acq->ReapInquiry(isrCount, true) != 0) {
        acq->Dump(
            FileSystem::PrepDumpFile(mGrpName, mTestName, "acq",
            "notEmpty"), "Test assumption have not been met");
        throw FrmwkEx(HERE, 
            "The ACQ should not have any CE's waiting before testing");
    }

    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(CNS_Controller);
    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("Learn initial unique command id assigned by dnvme.");
    uint16_t currCID;
    asq->Send(idCmdCap, currCID);
    uint16_t prevCID = currCID;
    for (uint32_t nCmds = 0; nCmds < MAX_CMDS; nCmds++) {
        asq->Ring();
        LOG_NRM("Verify unique CID #%d for Cmd #%d", currCID, nCmds + 1);
        ReapVerifyCID(asq, acq, currCID);

        asq->Send(idCmdCap, currCID);
        if (currCID != (uint16_t)(prevCID + 1)) {
            asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq.fail"),
                "Dump Entire ASQ");
            acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"),
                "Dump Entire ACQ");
            throw FrmwkEx(HERE, "Current CID(%d) != prev + 1(%d)", currCID,
                prevCID);
        }

        prevCID = currCID;
    }
}
Exemple #17
0
void
NUMDIsAdhered_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    // Lookup objs which were created in a prior test within group
    string work;
    uint64_t i;
    
    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());

    LOG_NRM("Get log page to request firmware slot information");
    getLogPgCmd->SetNUMD(NUMDW_ADHERED - 1);  // 0-based
    getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID);
    getLogPgCmd->SetNSID(0xFFFFFFFF);
    
    LOG_NRM("Set the offset into the buffer at 0x%04X", BUFFER_OFFSET);
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());
    getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE,
        BUFFER_OFFSET, true, BUFFER_INIT_VAL);
    send_64b_bitmask prpReq =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        getLogPgCmd, "NUMD.adhered", true);

    LOG_NRM("Compare cmd buffer to verify the last half of buffer = 0xA5");
    SharedMemBufferPtr cmdPayload = getLogPgCmd->GetRWPrpBuffer();
    uint16_t offset = (NUMDW_ADHERED * 4);
    uint8_t *cmdPayloadBuff = (uint8_t *)cmdPayload->GetBuffer() + offset;
    for (; offset < (GetLogPage::FIRMSLOT_DATA_SIZE); offset++) {
        LOG_NRM("Verify data at offset = 0x%X", offset);
        if (*cmdPayloadBuff != BUFFER_INIT_VAL) {
            throw FrmwkEx(HERE, "NUMD not adhered at offset = 0x%08X, "
                "value = 0x%08X", cmdPayloadBuff, *cmdPayloadBuff);
        }
        cmdPayloadBuff++;
    }
}
void
InvalidFieldInCmd_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    string work;

    // 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 features cmd");
    SharedGetFeaturesPtr getFeaturesCmd =
        SharedGetFeaturesPtr(new GetFeatures());

    LOG_NRM("Form a vector of invalid FID's");
    vector<uint16_t> invalidFIDs;
    uint8_t invalFID;
    
    invalidFIDs.push_back(0x00);
    for (uint8_t invalFID = 0x0D; invalFID <= 0x7F; invalFID++)
        invalidFIDs.push_back(invalFID);

    if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_ONCS))
            & ONCS_SUP_RSRV)
       invalFID = 0x84;
    else
       invalFID = 0x81;  

    for (; invalFID <= 0xBF; invalFID++)
       invalidFIDs.push_back(invalFID);
       
    for (uint16_t i = 0; i < invalidFIDs.size(); i++) {
        if (invalidFIDs[i] == 0x81)
            continue;
        LOG_NRM("Issue get feat cmd using invalid FID = 0x%X", invalidFIDs[i]);
        getFeaturesCmd->SetFID(invalidFIDs[i]);
        work = str(boost::format("invalidFIDs.%xh") % invalidFIDs[i]);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            getFeaturesCmd, work, true, CESTAT_INVAL_FIELD);
    }
}
void
DeleteIOQDiscontig_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Both test CreateIOQContigPoll_r10b & CreateIOQDiscontigPoll_r10b has
     *    run prior, or Both test CreateIOQContigIrq_r10b &
     *    CreateIOQDiscontigIrq_r10b has run prior
     * 2) An individual test within this group cannot run, the entire group
     *    must be executed every time. Each subsequent test relies on the prior.
     * \endverbatim
     */
    uint64_t regVal;


    // DUT must support discontig memory backing a IOQ to run this test
    if (gRegisters->Read(CTLSPC_CAP, regVal) == false) {
        throw FrmwkEx(HERE, "Unable to determine Q memory requirements");
    } else if (regVal & CAP_CQR) {
        LOG_NRM("Unable to utilize discontig Q's, DUT requires contig");
        return;
    }

    // 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))

    // According to spec, if one deletes the CQ before the SQ it's a "shall not"
    // statement which means it will have undefined behavior and thus there is
    // nothing to gain by attempting such action.
    LOG_NRM("Lookup IOSQ which was created in a prior test within group");
    SharedIOSQPtr iosq =
        CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_DISCONTIG_GROUP_ID))
    Queues::DeleteIOSQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms,
        iosq, asq, acq);


    LOG_NRM("Lookup IOCQ which was created in a prior test within group");
    SharedIOCQPtr iocq =
        CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_DISCONTIG_GROUP_ID))
    Queues::DeleteIOCQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms,
        iocq, asq, acq);
}
Exemple #20
0
void
IOQRollChkDiff_r10b::IOQRollChkDiff(uint32_t numEntriesIOSQ,
    uint32_t numEntriesIOCQ)
{
    uint16_t uniqueId;

    // 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))

    SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName,
        mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, numEntriesIOCQ,
        false, IOCQ_CONTIG_GROUP_ID, false, 1);

    SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName,
        mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, numEntriesIOSQ,
        false, IOSQ_CONTIG_GROUP_ID, IOQ_ID, 0);

    LOG_NRM("(IOCQ Size, IOSQ Size)=(%d,%d)", iocq->GetNumEntries(),
        iosq->GetNumEntries());

    SharedWritePtr writeCmd = SetWriteCmd();

    LOG_NRM("Send #%d cmds to hdw via the contiguous IOSQ #%d",
        MAX(iosq->GetNumEntries(), iocq->GetNumEntries()) + 2,
        iosq->GetQId());
    for (uint32_t numEntries = 0; numEntries < (uint32_t)(MAX
        (iosq->GetNumEntries(), iocq->GetNumEntries()) + 2);
        numEntries++) {
        LOG_NRM("Processing #%d entries", numEntries);
        iosq->Send(writeCmd, uniqueId);
        iosq->Ring();
        ReapAndVerifyCE(iocq, (numEntries + 1) % iosq->GetNumEntries());
    }
    VerifyQPointers(iosq, iocq);

    LOG_NRM("Delete IOSQ before the IOCQ to comply with spec.");
    Queues::DeleteIOSQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms,
        iosq, asq, acq);
    Queues::DeleteIOCQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms,
        iocq, asq, acq);
}
void
ReadWriteToUnacquiredReservation::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
	LOG_NRM("Start ReadWriteToUnacquiredReservation::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));

	SharedWritePtr writeCmd = SharedWritePtr(new Write());
	SharedReadPtr readCmd = SharedReadPtr(new Read());

	SharedMemBufferPtr lbaWriteBuffer = SharedMemBufferPtr(new MemBuffer());
	SharedMemBufferPtr lbaReadBuffer = SharedMemBufferPtr(new MemBuffer());

	LOG_NRM("Create nvmeWrite Cmd and write 1 block of data to LBA 5, expecting 0:0x83 for HostB");
	lbaWriteBuffer->Init(512, true, 0xDD);
	writeCmd->SetPrpBuffer( (send_64b_bitmask)( MASK_PRP1_PAGE | MASK_PRP2_PAGE), lbaWriteBuffer);
	writeCmd->SetNSID(1);
	writeCmd->SetSLBA(5);
	writeCmd->SetNLB(0); // 0's based!
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, writeCmd, "write 0xDD's to LBA5 using hostB", true, CESTAT_RSRV_CONFLICT);

	LOG_NRM("Create nvmeRead Cmd and read back 1 block of data to LBA 5, expecting 0:0x83 for HostA");
	lbaReadBuffer->Init(512, true, 0x00);
	readCmd->SetPrpBuffer( (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE), lbaReadBuffer);
	readCmd->SetNSID(1);
	readCmd->SetSLBA(5);
	readCmd->SetNLB(0); // 0's based!
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, readCmd, "read from LBA5 using hostB", true, CESTAT_RSRV_CONFLICT);

    LOG_NRM("Completed ReadWriteToUnacquiredReservation::RunCoreTest")
}
Exemple #22
0
void
IllegalDeleteQs_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */

    // 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))

    SharedDeleteIOSQPtr deleteIOSQCmd = SharedDeleteIOSQPtr(new DeleteIOSQ());
    deleteIOSQCmd->SetWord(0x0, 10, 0); // Set illegal QID to Cmd DW10
    IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq,
    deleteIOSQCmd, "illegalDeleteIOSQ.invalidQId", true, CESTAT_INVALID_QID);

    SharedDeleteIOCQPtr deleteIOCQCmd = SharedDeleteIOCQPtr(new DeleteIOCQ());
    deleteIOSQCmd->SetWord(0x0, 10, 0); // Set illegal QID to Cmd DW10
    IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq,
    deleteIOCQCmd, "illegalDeleteIOCQ.invalidQId", true, CESTAT_INVALID_QID);
}
void
MandatorySMART_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    // 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))

    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint32_t nn = idCtrlrStruct->GetValue(IDCTRLRCAP_NN);
    if (nn == 0 )
        throw FrmwkEx(HERE, "Required to support >= 1 namespace");
    uint8_t logPageAttr = (uint8_t)idCtrlrStruct->GetValue(IDCTRLRCAP_LPA);

    LOG_NRM("Create get log page cmd and assoc some buffer memory");
    SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage());
    SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer());

    getLogPgCmd->SetLID(GetLogPage::LOGID_SMART_HEALTH);
    getLogPgCmd->SetNSID(0xFFFFFFFF);

    LOG_NRM("Issue cmd multiple times such that NUMD loops X=[0...512]");
    IssueGetLogPgCmdLessDwords(asq, acq, getLogPgCmd, getLogPageMem);

    LOG_NRM("If SMART supported per namspc, Reissue cmd for valid NSID's");
    if (logPageAttr) {
        for (uint32_t i = 1; i <= nn; i++) {
            LOG_NRM("Issue Get log page cmd with NSID = %u", i);
            getLogPgCmd->SetNSID(i);
            IssueGetLogPgCmdLessDwords(asq, acq, getLogPgCmd, getLogPageMem);
        }
    }
}
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
UnsupportRsvdFields_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    uint64_t maxIOQEntries = 2;

    // 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("Setup element sizes for the IOQ's");
    uint8_t iocqes = (gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_CQES) & 0xf);
    uint8_t iosqes = (gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_SQES) & 0xf);
    gCtrlrConfig->SetIOCQES(iocqes);
    gCtrlrConfig->SetIOSQES(iosqes);

    LOG_NRM("Create IOCQ");
    SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName, mTestName,
        CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false,
        IOCQ_GROUP_ID, true, 0);

    LOG_NRM("Create IOSQ");
    SharedIOSQPtr iosq = SharedIOSQPtr(new IOSQ(gDutFd));

    LOG_NRM("Allocate contiguous memory; IOSQ has ID=%d", IOQ_ID);
    iosq->Init(IOQ_ID, maxIOQEntries, IOQ_ID, 0);

    LOG_NRM("Form a Create IOSQ cmd to perform queue creation");
    SharedCreateIOSQPtr createIOSQCmd = SharedCreateIOSQPtr(new CreateIOSQ());
    createIOSQCmd->Init(iosq);

    LOG_NRM("Set all cmd's rsvd bits");
    uint32_t work = createIOSQCmd->GetDword(0);
    work |= 0x0000fc00;      // Set DW0_b15:10 bits
    createIOSQCmd->SetDword(work, 0);

    createIOSQCmd->SetDword(0xffffffff, 2);
    createIOSQCmd->SetDword(0xffffffff, 3);
    createIOSQCmd->SetDword(0xffffffff, 4);
    createIOSQCmd->SetDword(0xffffffff, 5);
    createIOSQCmd->SetDword(0xffffffff, 6);
    createIOSQCmd->SetDword(0xffffffff, 7);

    // DW11_b15:3
    work = createIOSQCmd->GetDword(11);
    work |= 0x0000fff8;
    createIOSQCmd->SetDword(work, 11);

    createIOSQCmd->SetDword(0xffffffff, 12);
    createIOSQCmd->SetDword(0xffffffff, 13);
    createIOSQCmd->SetDword(0xffffffff, 14);
    createIOSQCmd->SetDword(0xffffffff, 15);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        createIOSQCmd, "", true);

    WriteReadVerify(iosq, iocq);

    Queues::DeleteIOSQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
        asq, acq, "", false);
    Queues::DeleteIOCQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iocq,
        asq, acq, "", false);
}
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);
        }
    }
}
Exemple #27
0
void
InvalidMSIXIRQ_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Requires test createResources_r10b to execute 1st
     * \endverbatim
     */
    bool capable;
    uint16_t numIrqSupport;


    // Only allowed to execute if DUT supports MSI-X IRQ's
    if (gCtrlrConfig->IsMSIXCapable(capable, numIrqSupport) == false)
        throw FrmwkEx(HERE);
    else if (capable == false) {
        LOG_NRM("DUT does not support MSI-X IRQ's; unable to execute test");
        return;
    }

    if (gCtrlrConfig->SetState(ST_DISABLE) == false)
        throw FrmwkEx(HERE);

    LOG_NRM("Notify DUT we plan on using all IRQ's that it supports");
    if (gCtrlrConfig->SetIrqScheme(INT_MSIX, numIrqSupport) == false) {
        throw FrmwkEx(HERE,
            "Unable to use %d IRQ's, but DUT reports it supports",
            numIrqSupport);
    }

    gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET);
    if (gCtrlrConfig->SetState(ST_ENABLE) == false)
        throw FrmwkEx(HERE);

    // 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("Set legal IOCQ element size");
    gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_CQES) & 0xf);

    // This test expects the DUT to reject the usage of illegal/unsupported
    // MSIX IRQ vectors, thus they should never be used. In order to safely fool
    // dnvme's safeguards, thus preventing a kernel crash, we need to issue a
    // legal cmd and allow dnvme to do it job. Then just before ringing the
    // doorbell inject a toxic illegal MSIX IRQ vector, the guts of this test.
    // So lets prepare that "legal" cmd here and then corrupt/toxify it later.
    LOG_NRM("Last supported MSIX IRQ vec = %d", (numIrqSupport - 1));
    for (uint32_t i = numIrqSupport; i <= CtrlrConfig::MAX_MSIX_IRQ_VEC; i++) {
        // We must re-init the objects because a failed attempt at creating an
        // IOCQ forces dnvme to deconstruct the entire thing when it is reaped.
        LOG_NRM("Create the IOCQ and the cmd to issue to the DUT");
        SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(gDutFd));
        LOG_NRM("Allocate contiguous memory; IOCQ has ID=%d", IOQ_ID);
        iocq->Init(IOQ_ID, NUM_IOQ_ENTRY, true, (numIrqSupport - 1));
        SharedCreateIOCQPtr createIOCQCmd =
            SharedCreateIOCQPtr(new CreateIOCQ());
        createIOCQCmd->Init(iocq);
        SendToxicCmd(asq, acq, createIOCQCmd, i);
    }
}
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
ManyCmdSubmit_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     *  \endverbatim
     */
    uint32_t nCmds;
    uint32_t isrCount;
    uint32_t ceRemain;
    uint32_t numReaped;
    uint32_t numCE;
    uint16_t uniqueId;

    // 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 the max IOQ entries supported");
    uint64_t ctrlCapReg;
    if (gRegisters->Read(CTLSPC_CAP, ctrlCapReg) == false)
        throw FrmwkEx(HERE, "Unable to determine MQES");
    uint32_t maxIOQEntries = (uint32_t)(ctrlCapReg & CAP_MQES);
    maxIOQEntries += 1;     // convert to 1-based.

    LOG_NRM("Create contig IOQ's");
    SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName,
        mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries,
        false, IOCQ_CONTIG_GROUP_ID, true, 0);

    SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName,
        mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries,
        false, IOSQ_CONTIG_GROUP_ID, IOQ_ID, 0);

    SharedWritePtr writeCmd = SetWriteCmd();

    uint32_t increment = 1;
    for (uint32_t x = 1; x < maxIOQEntries; x += increment) {
        LOG_NRM("Sending #%d simultaneous NVM write cmds to IOSQ", x);
        // Issue x simultaneous NVM write cmds.
        for (nCmds = 1; nCmds <= x; nCmds++)
            iosq->Send(writeCmd, uniqueId);
        iosq->Ring();

        // Variable wait time w.r.t "x" and expect all CE's to arrive in CQ.
        if (iocq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(x),
            x, numCE, isrCount) == false) {
            iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                "iocq.reqpinq." + writeCmd->GetName()), "Dump Entire IOCQ");
            LogCEAndCQMetrics(iocq);
            throw FrmwkEx(HERE, "Unable to see CEs for issued cmds #%d", x);
        } else if (numCE != x) {
            iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                "iocq.reqpinq." + writeCmd->GetName()), "Dump Entire IOCQ");
            LogCEAndCQMetrics(iocq);
            throw FrmwkEx(HERE, "The IOCQ should only have #%d CE's as a result "
                "of #%d simultaneous cmds but found #%d", x, x, numCE);
        }

        SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer());
        if ((numReaped = iocq->Reap(ceRemain, ceMem, isrCount, x, true)) != x) {
            iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                "iocq.reap." + writeCmd->GetName()), "Dump Entire IOCQ");
            LogCEAndCQMetrics(iocq);
            throw FrmwkEx(HERE, "Unable to reap on IOCQ #%d. Reaped #%d of #%d",
                IOQ_ID, numReaped, x);
        }

        // Testing every cmd takes numerous hrs, so compromise.
        if ((maxIOQEntries - 1000) % x == 0)
            increment = 100;
        else if ((x % 1000) == 0)
            increment = 1000;
        else if ((maxIOQEntries - 100) % x == 0)
            increment = 10;
        else if ((x % 100) == 0)
            increment = 100;
        else if ((maxIOQEntries - 10) % x == 0)
            increment = 1;
        else if ((x % 10) == 0)
            increment = 10;

    }

    // Delete IOSQ before the IOCQ to comply with spec.
    Queues::DeleteIOSQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
        iosq, asq, acq);
    Queues::DeleteIOCQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
        iocq, asq, acq);
}
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);
}