예제 #1
0
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);
}
예제 #2
0
void
InvalidQID_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    bool enableLog;
    uint64_t maxIOQEntries = 2;

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

    LOG_NRM("Create admin queues ACQ and ASQ");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    // Calc X, max no. of IOCQ's DUT supports.
    uint32_t X = gInformative->GetFeaturesNumOfIOCQs();
    LOG_NRM("Maximum num of IOCQ's DUT will support = %d", X);

    LOG_NRM("Setup element size for the IOCQ");
    gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_CQES) & 0xf);

    LOG_NRM("Issue CreateIOCQ cmds with QID's ranging from %d to %d",
        (X + 1), MAX_IOQ_ID);

    list<uint32_t> illegalQIDs = GetIllegalQIDs(X + 1);
    for (list<uint32_t>::iterator qId = illegalQIDs.begin();
        qId != illegalQIDs.end(); qId++) {
        LOG_NRM("Process each CreateIOCQCmd with iocq id #%d", *qId);
        SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(gDutFd));
        iocq->Init(*qId, maxIOQEntries, true, 0);
        SharedCreateIOCQPtr createIOCQCmd =
            SharedCreateIOCQPtr(new CreateIOCQ());
        createIOCQCmd->Init(iocq);

        work = str(boost::format("iocqId.%d") % *qId);
        enableLog = false;
        if ((*qId <= (X + 8)) || (*qId >= (MAX_IOQ_ID - 8)))
            enableLog = true;

        LOG_NRM("Send and reap cmd with CQ ID #%d", *qId);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            createIOCQCmd, work, enableLog, CESTAT_INVALID_QID);
    }
}
예제 #3
0
void
UnsupportRsvdFields_r11b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) none
     *  \endverbatim
     */
    if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
        throw FrmwkEx(HERE);

    LOG_NRM("Create admin queues ACQ and ASQ for test lifetime");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    // Test async events without setting the rsvd bits in the cmd.
    TestAsyncEvents(acq, asq, false);

    // Test async events by setting the rsvd bits in the cmd.
    TestAsyncEvents(acq, asq, true);

}
예제 #4
0
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);
        }
    }
}
예제 #5
0
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;
}
예제 #6
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;
}
예제 #7
0
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);
    }
}
예제 #8
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;
    }
}
예제 #9
0
bool
GrpAdminSetGetFeatCombo::RestoreState()
{
    // For the majority of test groups this feature most likely won't be needed
     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);

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

    if (RestoreArbitration(asq, acq) == false) {
        LOG_ERR("Arbitration restore failed");
        return false;
    }

    if (RestorePowerState(asq, acq) == false) {
        LOG_ERR("Power state restore failed");
        return false;
    }

    if (RestoreTMPTH(asq, acq) == false) {
        LOG_ERR("Temperature threshold restore failed");
        return false;
    }

    if (RestoreTLER(asq, acq) == false) {
        LOG_ERR("Time limited error recovery restore failed");
        return false;
    }

    if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_VWC)
        & BITMASK_VWC) == 0x1) {
        if (RestoreVolWrCache(asq, acq) == false) {
            LOG_ERR("Volatile write cache restore failed");
            return false;
        }
    }

    LOG_NRM("System restore successful.");
    return true;
}
예제 #10
0
void
AcceptQPriority_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    uint64_t maxIOQEntries = 2;

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

    LOG_NRM("Create admin queues ACQ and ASQ");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    LOG_NRM("Setup element sizes for the IOQ's");
    gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_CQES) & 0xf);
    gCtrlrConfig->SetIOSQES(gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_SQES) & 0xf);

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

    for (uint8_t priority = 0; priority < PRIORITY_RANGE; priority++) {
        LOG_NRM("Create IOSQ with QID = %d and priority #%d", IOQ_ID, priority);
        SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName,
            mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries,
            false, IOSQ_GROUP_ID, IOQ_ID, priority);

        LOG_NRM("Delete IOSQ with QID = %d and priority #%d", IOQ_ID, priority);
        Queues::DeleteIOSQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
            asq, acq, "", false);
    }
}
예제 #11
0
/**
 * A function to issue consecutive admin cmd set format NVM cmds to a DUT.
 * @param format Pass formating instructions
 * @return true upon successful parsing, otherwise false.
 */
bool
FormatDevice(Format &format)
{
    try {   // The objects to perform this work throw exceptions
        FileSystem::SetBaseDumpDir(false);   // Log into GrpPending
        if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
            throw FrmwkEx(HERE);

        LOG_NRM("Prepare the admin Q's to setup this request");
        SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
        acq->Init(2);
        SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
        asq->Init(2);
        gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET);
        if (gCtrlrConfig->SetState(ST_ENABLE) == false)
            throw FrmwkEx(HERE);

        for (size_t i = 0; i < format.cmds.size(); i++) {
            LOG_NRM("Formatting namespace: %d", format.cmds[i].nsid);
            LOG_NRM("  FormatNVM:DW10.ses = 0x%02x", format.cmds[i].ses);
            LOG_NRM("  FormatNVM:DW10.pil = %c", format.cmds[i].pil ? 'T' :'F');
            LOG_NRM("  FormatNVM:DW10.pi = 0x%02x", format.cmds[i].pi);
            LOG_NRM("  FormatNVM:DW10.ms = %c", format.cmds[i].ms ? 'T' : 'F');
            LOG_NRM("  FormatNVM:DW10.lbaf = 0x%02x", format.cmds[i].lbaf);

            LOG_NRM("Create the cmd to carry this data to the DUT");
            SharedFormatNVMPtr formatNVM =
                SharedFormatNVMPtr(new FormatNVM());
            formatNVM->SetNSID(format.cmds[i].nsid);
            formatNVM->SetSES(format.cmds[i].ses);
            formatNVM->SetPIL(format.cmds[i].pil);
            formatNVM->SetPI(format.cmds[i].pi);
            formatNVM->SetMS(format.cmds[i].ms);
            formatNVM->SetLBAF(format.cmds[i].lbaf);

            IO::SendAndReapCmd("tnvme", "format", SYSTEMWIDE_CMD_WAIT_ms,
                asq, acq, formatNVM, "", true);
        }
        LOG_NRM("The operation succeeded to format device");
    } catch (...) {
        LOG_ERR("Operation failed to format device");
        gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY);
        return false;
    }

    gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY);
    return true;
}
bool
GrpAdminSetGetFeatCombo::SaveState()
{
    LOG_NRM("Saving system state using getfeatures before group starts");

    // Reset saved value to account for regression
    mArbitration = 0;
    mPowerState = 0;
    mTmpThreshold = 0;
    mTimeLimErrRec = 0;
    mVolWrCache = 0;
    mIrqCoalescing = 0;
    mWrAtomicity = 0;
    memset(mIvecConf, 0, sizeof(mIvecConf));
    mAsyncEvent = 0;

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

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

    SaveArbitration(asq, acq);
    SavePowerState(asq, acq);
    SaveTMPTH(asq, acq);
    SaveTLER(asq, acq);

    if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_VWC)
        & BITMASK_VWC) == 0x1) {
        SaveVolWrCache(asq, acq);
    }
    SaveIRQCoalescing(asq, acq);
    SaveIvecConf(asq, acq);
    SaveWrAtomicity(asq, acq);
    SaveAsyncEvent(asq, acq);
    return true;
}
예제 #13
0
/**
 * A function to send Set Features admin cmd to a device sending the identifier
 * 0x07 to set number of queues. This value, according to the spec, shall NOT
 * change between resets, i.e. only set this value after a power up. Failure to
 * conform results in undefined behavior.
 * "<STS:PXDS:AERUCES:CSTS>".
 * @param numQueues Pass a struct to source the desired values to send to hdw
 * @return true upon successful parsing, otherwise false.
 */
bool
SetFeaturesNumberOfQueues(NumQueues &numQueues)
{
    try {   // The objects to perform this work throw exceptions

        LOG_NRM("Setting number of Q's; ncqr=0x%04X, nsqr=0x%04X",
            numQueues.ncqr, numQueues.nsqr);

        FileSystem::SetBaseDumpDir(false);   // Log into GrpPending
        if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
            throw FrmwkEx(HERE);

        LOG_NRM("Prepare the admin Q's to setup this request");
        SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
        acq->Init(2);
        SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
        asq->Init(2);
        gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET);
        if (gCtrlrConfig->SetState(ST_ENABLE) == false)
            throw FrmwkEx(HERE);

        LOG_NRM("Create the cmd to carry this data to the DUT");
        SharedSetFeaturesPtr sfNumOfQ =
            SharedSetFeaturesPtr(new SetFeatures());
        sfNumOfQ->SetFID(BaseFeatures::FID_NUM_QUEUES);
        sfNumOfQ->SetNumberOfQueues(numQueues.ncqr, numQueues.nsqr);

        IO::SendAndReapCmd("tnvme", "queues", SYSTEMWIDE_CMD_WAIT_ms,
            asq, acq, sfNumOfQ, "", true);
        LOG_NRM("The operation succeeded to set number of queues");
    } catch (...) {
        LOG_ERR("Operation failed to set number of queues");
        gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY);
        return false;
    }

    gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY);
    return true;
}
예제 #14
0
bool
GrpAdminSetGetFeatCombo::SaveState()
{
    LOG_NRM("Saving the current arbitration state before the group starts.");

    // Reset saved value to account for regression
    mArbitration = 0;
    mPowerState = 0;
    mTmpThreshold = 0;
    mTimeLimErrRec = 0;
    mVolWrCache = 0;

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

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

    SaveArbitration(asq, acq);
    SavePowerState(asq, acq);
    SaveTMPTH(asq, acq);
    SaveTLER(asq, acq);

    if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_VWC)
        & BITMASK_VWC) == 0x1) {
        SaveVolWrCache(asq, acq);
    }
    return true;
}
예제 #15
0
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);
}
예제 #16
0
void
PRPLessPageDiscontig_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None
     * \endverbatim
     */
    string work;
    bool enableLog;

    if (Queues::SupportDiscontigIOQ() == false) {
        LOG_WARN("DUT must support discontig Q's for this test.");
        return;
    }

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

    LOG_NRM("Compute memory page size from CC.MPS.");
    uint8_t mps;
    if (gCtrlrConfig->GetMPS(mps) == false)
        throw FrmwkEx(HERE, "Unable to get MPS value from CC.");
    uint64_t capMPS = (uint64_t)(1 << (mps + 12));

    LOG_NRM("Determine element sizes for the IOCQ's");
    uint8_t iocqes = (gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_CQES) & 0xf);
    uint32_t Y = ((capMPS / (1 << iocqes)) - 1);
    if (maxIOQEntries < Y) {
        LOG_WARN("Desired to support >= %d elements in IOCQ for this test", Y);
        return;
    }

    LOG_NRM("Determine element sizes for the IOSQ's");
    uint8_t iosqes = (gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_SQES) & 0xf);
    uint32_t Z = ((capMPS / (1 << iosqes)) - 1);

    LOG_NRM("Computed memory page size from CC.MPS = %ld", capMPS);
    LOG_NRM("Max IOQ entries supported CAP.MQES = %d", maxIOQEntries);
    LOG_NRM("Number of IOCQ elements = %d", Y);
    LOG_NRM("Number of IOSQ elements = %d", Z);

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

    LOG_NRM("Create admin queues ACQ and ASQ");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);     // throws upon error

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

    Informative::Namspc namspcData = gInformative->Get1stBareMetaE2E();
    LBAFormat lbaFormat = namspcData.idCmdNamspc->GetLBAFormat();
    uint64_t lbaDataSize = namspcData.idCmdNamspc->GetLBADataSize();

    LOG_NRM("Setup element sizes for the IOQ's");
    gCtrlrConfig->SetIOCQES(iocqes);
    gCtrlrConfig->SetIOSQES(iosqes);

    LOG_NRM("Create discontig IOSQ and IOCQ with IDs 1");
    SharedMemBufferPtr iocqBackedMem = SharedMemBufferPtr(new MemBuffer());
    iocqBackedMem->InitOffset1stPage((Y * (1 << iocqes)), 0, true);
    SharedIOCQPtr iocq = Queues::CreateIOCQDiscontigToHdw(mGrpName, mTestName,
        DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, Y, false, IOCQ_GROUP_ID,
        true, 0, iocqBackedMem);

    SharedMemBufferPtr iosqBackedMem = SharedMemBufferPtr(new MemBuffer());
    iosqBackedMem->InitOffset1stPage((Z * (1 << iosqes)), 0,true);
    SharedIOSQPtr iosq = Queues::CreateIOSQDiscontigToHdw(mGrpName, mTestName,
        DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, Z, false, IOSQ_GROUP_ID,
        IOQ_ID, 0, iosqBackedMem);

    SharedWritePtr writeCmd = SharedWritePtr(new Write());
    SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());

    SharedReadPtr readCmd = SharedReadPtr(new Read());
    SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());

    send_64b_bitmask prpBitmask = (send_64b_bitmask)(MASK_PRP1_PAGE |
        MASK_PRP2_PAGE | MASK_PRP2_LIST);

    switch (namspcData.type) {
    case Informative::NS_BARE:
        writeMem->Init(lbaDataSize);
        readMem->Init(lbaDataSize);
        break;
    case Informative::NS_METAS:
        writeMem->Init(lbaDataSize);
        readMem->Init(lbaDataSize);
        if (gRsrcMngr->SetMetaAllocSize(lbaFormat.MS) == false)
            throw FrmwkEx(HERE);
        writeCmd->AllocMetaBuffer();
        readCmd->AllocMetaBuffer();
        break;
    case Informative::NS_METAI:
        writeMem->Init(lbaDataSize + lbaFormat.MS);
        readMem->Init(lbaDataSize + lbaFormat.MS);
        break;
    case Informative::NS_E2ES:
    case Informative::NS_E2EI:
        throw FrmwkEx(HERE, "Deferring work to handle this case in future");
        break;
    }

    writeCmd->SetPrpBuffer(prpBitmask, writeMem);
    writeCmd->SetNSID(namspcData.id);
    writeCmd->SetNLB(0);

    readCmd->SetPrpBuffer(prpBitmask, readMem);
    readCmd->SetNSID(namspcData.id);
    readCmd->SetNLB(0);

    // Fill the IOSQ and roll over
    for (int64_t X = 1; X <= (iosq->GetNumEntries() + 1); X++) {
        LOG_NRM("Processing #%ld of %d cmds", X, (iosq->GetNumEntries() + 1));
        switch (namspcData.type) {
        case Informative::NS_BARE:
            writeMem->SetDataPattern(DATAPAT_INC_32BIT, X);
            break;
        case Informative::NS_METAS:
            writeMem->SetDataPattern(DATAPAT_INC_32BIT, X);
            writeCmd->SetMetaDataPattern(DATAPAT_INC_32BIT, X);
            break;
        case Informative::NS_METAI:
            writeMem->SetDataPattern(DATAPAT_INC_32BIT, X);
            break;
        case Informative::NS_E2ES:
        case Informative::NS_E2EI:
            throw FrmwkEx(HERE, "Deferring work to handle this case in future");
            break;
        }

        enableLog = false;
        if ((X <= 8) || (X >= (X - 8)))
            enableLog = true;

        work = str(boost::format("X.%d") % X);
        IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq,
            iocq, writeCmd, work, enableLog);

        IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq,
            iocq, readCmd, work, enableLog);

        VerifyDataPat(readCmd, writeCmd);
    }
}
예제 #17
0
void
FIDPwrMgmt_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    union CE ce;
    struct nvme_gen_cq acqMetrics;

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

    LOG_NRM("Create admin queues ACQ and ASQ for test lifetime");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    LOG_NRM("Create Get features and set features cmds");
    SharedGetFeaturesPtr getFeaturesCmd =
        SharedGetFeaturesPtr(new GetFeatures());
    SharedSetFeaturesPtr setFeaturesCmd =
        SharedSetFeaturesPtr(new SetFeatures());

    LOG_NRM("Set and Get features PSD (FID = 0x%x)", BaseFeatures::FID_PWR_MGMT);
    getFeaturesCmd->SetFID(BaseFeatures::FID_PWR_MGMT);
    setFeaturesCmd->SetFID(BaseFeatures::FID_PWR_MGMT);

    uint8_t npss = gInformative->GetIdentifyCmdCtrlr()->
                   GetValue(IDCTRLRCAP_NPSS); // 0-based

    LOG_NRM("Number of power states supported by the ctrlr (NPSS) = %d", npss);

    uint8_t psMismatch = 0;
    for (uint16_t ps = 0; ps <= npss; ps++) {
        LOG_NRM("Set and Get features for PS # %d", ps);
        setFeaturesCmd->SetPowerManagementPS(ps);
        LOG_NRM("Issue set features cmd with PS = %d", ps);

        work = str(boost::format("ps.%d") % ps);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
                           setFeaturesCmd, work, true);

        acqMetrics = acq->GetQMetrics();

        LOG_NRM("Issue get features cmd and check for ps = %d", ps);
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
                           getFeaturesCmd, work, false);

        ce = acq->PeekCE(acqMetrics.head_ptr);
        LOG_NRM("Power state descriptor using Get Features = %d", ce.t.dw0);
        if (ps != ce.t.dw0) {
            LOG_ERR("PSD get feat does not match set feat"
                    "(expected, rcvd) = (%d, %d)", ps, ce.t.dw0);
            psMismatch = 0xFF;
        }
    }

    if (psMismatch)
        throw FrmwkEx(HERE, "Power state mismatched.");
}
예제 #18
0
void
VerifyEventQueueing_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) none
     *  \endverbatim
     */
    uint32_t isrCount;
    uint32_t ceRemain;
    uint32_t numReaped;
    uint32_t numCE;

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

    LOG_NRM("Create admin queues ACQ and ASQ for test lifetime");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    LOG_NRM("Ring doorbell for IOSQ #1");
    InvalidSQWriteDoorbell();

    LOG_NRM("Delay 5 sec");
    sleep(5);

    LOG_NRM("Verify no CE's exist in ACQ");
    if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount)
        == true) {
        acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
            "acq.fail.0rinq"), "Dump Entire ACQ");
        throw FrmwkEx(HERE, "0 CE's expected in ACQ but found %d CE's", numCE);
    }

    LOG_NRM("Issue one async event ");
    SendAsyncEventRequests(asq, 1);

    LOG_NRM("verify CE exists in ACQ for invalid SQID doorbell write");
    if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount)
        == false) {
        acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
            "acq.fail.1rinq"), "Dump Entire ACQ");
        throw FrmwkEx(HERE, "1 CE expected in ACQ but found %d CEs", numCE);
    }

    SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer());
    if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true))
        != 1) {
        acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
            "acq.fail.1reap"), "Dump Entire ACQ");
        throw FrmwkEx(HERE, "Unable to reap on ACQ");
    }

    union CE *ce = (union CE *)ceMem->GetBuffer();
    if (ce->n.async.asyncEventType != EVENT_TYPE_ERROR_STS) {
        acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
            "acq.fail.sts"), "Dump Entire ACQ");
        throw FrmwkEx(HERE, "Invalid async event error status, "
            "(Expected : Received) :: (%d : %d)", EVENT_TYPE_ERROR_STS,
            ce->n.async.asyncEventType);
    } else if (ce->n.async.asyncEventInfo != ERR_STS_INVALID_SQ) {
        acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
            "acq.fail.sc"), "Dump Entire ACQ");
        throw FrmwkEx(HERE, "Invalid async event info, "
            "(Expected : Received) :: (%d : %d)", ERR_STS_INVALID_SQ,
            ce->n.async.asyncEventInfo);
    }
}
예제 #19
0
void
ProtInfoIgnoreMeta_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) None.
     * \endverbatim
     */
    string context;
    ConstSharedIdentifyPtr namSpcPtr;
    SharedIOSQPtr iosq;
    SharedIOCQPtr iocq;
    send_64b_bitmask prpBitmask = (send_64b_bitmask)
        (MASK_PRP1_PAGE | MASK_PRP2_PAGE | MASK_PRP2_LIST);

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

    LOG_NRM("Get all the supported meta namespaces");
    vector<uint32_t> meta = gInformative->GetMetaNamespaces();
    for (size_t i = 0; i < meta.size(); i++) {
        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);

        LOG_NRM("Create a read cmd to read data from namspc %d", meta[i]);
        SharedReadPtr readCmd = SharedReadPtr(new Read());

        LOG_NRM("Create memory to contain read payload");
        SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());

        Informative::NamspcType
            nsType = gInformative->IdentifyNamespace(namSpcPtr);
        switch (nsType) {
        case Informative::NS_BARE:
            throw FrmwkEx(HERE, "Namspc type cannot be BARE.");
        case Informative::NS_METAS:
            readMem->Init(lbaDataSize);
            if (gRsrcMngr->SetMetaAllocSize(lbaFormat.MS) == false)
                throw FrmwkEx(HERE);
            readCmd->AllocMetaBuffer();
            break;
        case Informative::NS_METAI:
            readMem->Init(lbaDataSize + lbaFormat.MS);
            break;
        case Informative::NS_E2ES:
        case Informative::NS_E2EI:
            throw FrmwkEx(HERE, "Deferring work to handle this case in future");
            break;
        }

        readCmd->SetPrpBuffer(prpBitmask, readMem);
        readCmd->SetNSID(meta[i]);
        readCmd->SetNLB(0);    // convert to 0-based value

        for (uint16_t protInfo = 0; protInfo <= 0x0f; protInfo++) {
            uint8_t work = readCmd->GetByte(12, 3);
            work &= ~0x3c;  // PRINFO specific bits
            work |= (protInfo << 2);
            readCmd->SetByte(work, 12, 3);

            context = str(boost::format("ns%d.protInfo0x%02X") %
                (uint32_t)i % protInfo);
            IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, readCmd, context, true);
        }
    }
}
예제 #20
0
void
MaxQSizeExceed_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    bool enableLog;

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

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

    LOG_NRM("Create admin queues ACQ and ASQ");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    LOG_NRM("Setup element size for the IOCQ");
    gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_CQES) & 0xf);

    LOG_NRM("Create IOCQ with illegal Q entries ranging from 0x%04X to 0x10000",
        maxIOQEntries + 1);
    list<uint32_t> illegalQSizes = GetIllegalQSizes(maxIOQEntries);
    for (list<uint32_t>::iterator qSize = illegalQSizes.begin();
        qSize != illegalQSizes.end(); qSize++) {
        LOG_NRM("Process CreateIOCQ Cmd with qSize #0x%04X", *qSize);
        SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(gDutFd));
        iocq->Init(IOQ_ID, *qSize, true, 0);
        SharedCreateIOCQPtr createIOCQCmd =
            SharedCreateIOCQPtr(new CreateIOCQ());
        createIOCQCmd->Init(iocq);

        work = str(boost::format("qSize.%04Xh") % *qSize);
        enableLog = false;
        if ((*qSize <= (maxIOQEntries + 8)) || (*qSize >= (0xFFFF - 8)))
            enableLog = true;

        LOG_NRM("Send n reap ACQ for CreateIOCQCmd; qSize #0x%04X", *qSize);
        IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq,
            createIOCQCmd, work, enableLog, CESTAT_MAX_Q_SIZE_EXCEED);
    }
}
예제 #21
0
void
FIDVolatileCash_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    union CE ce;
    struct nvme_gen_cq acqMetrics;

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

    LOG_NRM("Create admin queues ACQ and ASQ for test lifetime");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    LOG_NRM("Create Get features and set features cmds");
    SharedGetFeaturesPtr getFeaturesCmd =
        SharedGetFeaturesPtr(new GetFeatures());
    SharedSetFeaturesPtr setFeaturesCmd =
        SharedSetFeaturesPtr(new SetFeatures());

    LOG_NRM("Set and Get features for volatile write cache (FID = 0x%x)",
        BaseFeatures::FID_VOL_WR_CACHE);
    getFeaturesCmd->SetFID(BaseFeatures::FID_VOL_WR_CACHE);
    setFeaturesCmd->SetFID(BaseFeatures::FID_VOL_WR_CACHE);

    uint8_t wce = 0x0; // Disable volatile write cache
    LOG_NRM("Disable volatile wr cache # %d ", wce);
    setFeaturesCmd->SetVolatileWriteCacheWCE(wce);
    LOG_NRM("Issue set features cmd with WCE = %d", wce);

    work = str(boost::format("wce.%d") % wce);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
        asq, acq, setFeaturesCmd, work, true);

    acqMetrics = acq->GetQMetrics();

    LOG_NRM("Issue get features cmd & check wce = %d", wce);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
        asq, acq, getFeaturesCmd, work, false);

    ce = acq->PeekCE(acqMetrics.head_ptr);
    LOG_NRM("Get Features volatile wr cache = %d", ce.t.dw0);
    if (wce != ce.t.dw0) {
        throw FrmwkEx(HERE, "WCE get feat does not match set feat"
            "(expected, rcvd) = (%d, %d)", wce, ce.t.dw0);
    }

    wce = 0x1; // Enable volatile write cache
    LOG_NRM("Enable volatile wr cache # %d ", wce);
    setFeaturesCmd->SetVolatileWriteCacheWCE(wce);
    LOG_NRM("Issue set features cmd with WCE = %d", wce);

    work = str(boost::format("wce.%d") % wce);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
        asq, acq, setFeaturesCmd, work, true);

    acqMetrics = acq->GetQMetrics();

    LOG_NRM("Issue get features cmd & check wce = %d", wce);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
        asq, acq, getFeaturesCmd, work, false);

    ce = acq->PeekCE(acqMetrics.head_ptr);
    LOG_NRM("Get Features volatile wr cache = %d", ce.t.dw0);
    if (wce != ce.t.dw0) {
        throw FrmwkEx(HERE, "WCE get feat does not match set feat"
            "(expected, rcvd) = (%d, %d)", wce, ce.t.dw0);
    }
}
예제 #22
0
bool SetFeaturesNumberOfQueues(Queues &queues, int fd)
{
    uint16_t numCE;
    uint16_t ceRemain;
    uint16_t numReaped;

    try {   // The objects to perform this work throw exceptions
        LOG_NRM("Setting number of Q's; ncqr=0x%04X, nsqr=0x%04X",
            queues.ncqr, queues.nsqr);
        if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
            throw exception();

        LOG_NRM("Prepare the admin Q's to setup this request");
        SharedACQPtr acq = SharedACQPtr(new ACQ(fd));
        acq->Init(2);
        SharedASQPtr asq = SharedASQPtr(new ASQ(fd));
        asq->Init(2);
        if (gCtrlrConfig->SetState(ST_ENABLE) == false)
            throw exception();

        LOG_NRM("Create the cmd to carry this data to the DUT");
        SharedSetFeaturesPtr sfNumOfQ =
            SharedSetFeaturesPtr(new SetFeatures(fd));
        sfNumOfQ->SetFID(BaseFeatures::FID_NUM_QUEUES);
        sfNumOfQ->SetNumberOfQueues(queues.ncqr, queues.nsqr);

        LOG_NRM("Send the cmd to the ASQ, wait for it to complete");
        asq->Send(sfNumOfQ);
        asq->Ring();
        if (acq->ReapInquiryWaitSpecify(2000, 1, numCE) == false) {
            LOG_ERR("Unable to see completion of Set Features cmd");
            throw exception();
        } else if (numCE != 1) {
            LOG_ERR("The ACQ should only have 1 CE as a result of a cmd");
            throw exception();
        }

        LOG_NRM("The CQ's metrics before reaping holds head_ptr needed");
        struct nvme_gen_cq acqMetrics = acq->GetQMetrics();
        KernelAPI::LogCQMetrics(acqMetrics);

        LOG_NRM("Reaping CE from ACQ, requires memory to hold reaped CE");
        SharedMemBufferPtr ceMemIOCQ = SharedMemBufferPtr(new MemBuffer());
        if ((numReaped = acq->Reap(ceRemain, ceMemIOCQ, numCE, true)) != 1) {
            LOG_ERR("Verified there was 1 CE, but reaping produced %d",
                numReaped);
            throw exception();
        }
        LOG_NRM("The reaped get features CE is...");
        acq->LogCE(acqMetrics.head_ptr);

        union CE ce = acq->PeekCE(acqMetrics.head_ptr);
        if (ce.n.status != 0) {
            LOG_ERR("CE shows cmd failed: status = 0x%02X", ce.n.status);
            throw exception();
        }
        printf("The operation succeeded to set number of queues\n");
    } catch (...) {
        printf("Operation failed to set number of queues\n");
        return false;
    }

    return true;
}
void
PRPOffsetDualPgMultiBlk_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    int64_t X;
    bool enableLog;

    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(mFd)))
    acq->Init(5);
    SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(mFd)))
    asq->Init(5);

    IRQ::SetAnySchemeSpecifyNum(2);     // throws upon error

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

    SharedIOCQPtr iocq;
    SharedIOSQPtr iosq;
    InitTstRsrcs(asq, acq, iosq, iocq);

    LOG_NRM("Compute memory page size from CC.MPS.");
    uint8_t mpsRegVal;
    if (gCtrlrConfig->GetMPS(mpsRegVal) == false)
        throw FrmwkEx(HERE, "Unable to get MPS value from CC.");
    uint64_t ccMPS = (uint64_t)(1 << (mpsRegVal + 12));

    LOG_NRM("Get namspc and determine LBA size");
    Informative::Namspc namspcData = gInformative->Get1stBareMetaE2E();
    send_64b_bitmask prpBitmask =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    LBAFormat lbaFormat = namspcData.idCmdNamspc->GetLBAFormat();
    uint64_t lbaDataSize = (1 << lbaFormat.LBADS);
    LOG_NRM("LBA data size is %ld.", lbaDataSize);

    LOG_NRM("Seeking max data xfer size for chosen namspc");
    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    uint32_t maxDtXferSz = idCmdCtrlr->GetMaxDataXferSize();

    SharedWritePtr writeCmd = SharedWritePtr(new Write());
    writeCmd->SetNSID(namspcData.id);

    SharedReadPtr readCmd = SharedReadPtr(new Read());
    readCmd->SetNSID(namspcData.id);

    SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());
    SharedMemBufferPtr readMem = SharedMemBufferPtr(new MemBuffer());

    switch (namspcData.type) {
    case Informative::NS_BARE:
        X =  ccMPS - lbaDataSize;
        break;
    case Informative::NS_METAS:
        X =  ccMPS - lbaDataSize;
        LOG_NRM("Allocating separate meta data buffer.");
        if (gRsrcMngr->SetMetaAllocSize(
            lbaFormat.MS * ((2 * ccMPS) / lbaDataSize)) == false) {
            throw FrmwkEx(HERE, "Unable to allocate Meta buffers.");
        }
        writeCmd->AllocMetaBuffer();
        readCmd->AllocMetaBuffer();
        break;
    case Informative::NS_METAI:
        X =  ccMPS - (lbaDataSize + lbaFormat.MS);
        break;
    case Informative::NS_E2ES:
    case Informative::NS_E2EI:
        throw FrmwkEx(HERE, "Deferring work to handle this case in future");
        break;
    }
    if (X < 0) {
        LOG_WARN("CC.MPS < lba data size(LBADS); Can't run test.");
        return;
    }

    DataPattern dataPat;
    uint64_t wrVal;
    uint64_t Y;

    for (int64_t pgOff = 0; pgOff <= X; pgOff += 4) {
        switch (namspcData.type) {
        case Informative::NS_BARE:
        case Informative::NS_METAS:
            Y = ((2 * ccMPS) - pgOff) / lbaDataSize;
            break;
        case Informative::NS_METAI:
            Y = ((2 * ccMPS) - pgOff) / (lbaDataSize + lbaFormat.MS);
            break;
        case Informative::NS_E2ES:
        case Informative::NS_E2EI:
            throw FrmwkEx(HERE, "Deferring work to handle this case in future");
            break;
        }
        for (uint64_t nLBAs = 1; nLBAs <= Y; nLBAs++) {
            LOG_NRM("Sending LBA #%ld of #%ld", nLBAs, Y);
            if ((maxDtXferSz != 0) && (maxDtXferSz < (lbaDataSize * nLBAs))) {
                // If the total data xfer exceeds the maximum data xfer
                // allowed then we break from the inner loop and continue
                // test with next offset (outer loop).
                LOG_WARN("Data xfer size exceeds max allowed, continuing..");
                break;
            }
            if ((nLBAs % 2) != 0) {
                dataPat = DATAPAT_INC_32BIT;
                wrVal = pgOff + nLBAs;
            } else {
                dataPat = DATAPAT_CONST_16BIT;
                wrVal = pgOff + nLBAs;
            }

            uint64_t metabufSz = nLBAs * lbaFormat.MS;
            switch (namspcData.type) {
            case Informative::NS_BARE:
                writeMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff,
                    false);
                readMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false);
                break;
            case Informative::NS_METAS:
                writeMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff,
                    false);
                readMem->InitOffset1stPage((lbaDataSize * nLBAs), pgOff, false);
                writeCmd->SetMetaDataPattern(dataPat, wrVal, 0, metabufSz);
                break;
            case Informative::NS_METAI:
                writeMem->InitOffset1stPage(
                    ((lbaDataSize + lbaFormat.MS) * nLBAs), pgOff, false);
                readMem->InitOffset1stPage(
                    ((lbaDataSize + lbaFormat.MS) * nLBAs), pgOff, false);
                break;
            case Informative::NS_E2ES:
            case Informative::NS_E2EI:
                throw FrmwkEx(HERE,
                    "Deferring work to handle this case in future");
                break;
            }
            work = str(boost::format("pgOff.%d.nlba.%d") % pgOff % nLBAs);
            writeCmd->SetPrpBuffer(prpBitmask, writeMem);
            writeMem->SetDataPattern(dataPat, wrVal);
            writeCmd->SetNLB(nLBAs - 1); // convert to 0 based.

            enableLog = false;
            if ((pgOff <= 8) || (pgOff >= (X - 8)))
                enableLog = true;

            IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq,
                iocq, writeCmd, work, enableLog);

            readCmd->SetPrpBuffer(prpBitmask, readMem);
            readCmd->SetNLB(nLBAs - 1); // convert to 0 based.

            IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq,
                iocq, readCmd, work, enableLog);

            VerifyDataPat(readCmd, dataPat, wrVal, metabufSz);
        }
    }
}
예제 #24
0
void
VerifyMasking_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) none
     *  \endverbatim
     */
    uint32_t isrCount;
    uint32_t ceRemain;
    uint32_t numReaped;
    uint32_t numCE;

    LOG_NRM("Issue Identify.AERL to get Async Event Req Limit (AERL)");
    uint8_t nAerlimit = gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_AERL) + 1; // Convert to 1-based.

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

    LOG_NRM("Create admin queues ACQ and ASQ for test lifetime");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(nAerlimit + 1); // one extra space than Q full condition

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(nAerlimit + 1); // one extra space than Q full condition

    // 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("Issue %d async event requests", nAerlimit);
    SendAsyncEventRequests(asq, nAerlimit);

    for (uint8_t nAer = 1; nAer <= nAerlimit; nAer++) {
        LOG_NRM("Ring doorbell for IOSQ #1");
        InvalidSQWriteDoorbell();
        sleep(5);
        if (nAer == 1) {
            LOG_NRM("Verify only 1 CE exists for invalid SQID doorbell write");
            if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE,
                isrCount) == false) {
                acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                    "acq.fail.reapinq1"), "Dump Entire ACQ");
                throw FrmwkEx(HERE, "1 CE expected in but found %d CEs", numCE);
            }
            SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer());
            if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true))
                != 1) {
                acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                    "acq.fail.reap1"), "Dump Entire ACQ");
                throw FrmwkEx(HERE, "Unable to reap on ACQ");
            }

            union CE *ce = (union CE *)ceMem->GetBuffer();
            if (ce->n.async.asyncEventType != EVENT_TYPE_ERROR_STS) {
                throw FrmwkEx(HERE, "Invalid async event error status, "
                    "(Expected : Received) :: (%d : %d)", EVENT_TYPE_ERROR_STS,
                    ce->n.async.asyncEventType);
            } else if (ce->n.async.asyncEventInfo != ERR_STS_INVALID_SQ) {
                throw FrmwkEx(HERE, "Invalid async event info, "
                    "(Expected : Received) :: (%d : %d)", ERR_STS_INVALID_SQ,
                    ce->n.async.asyncEventInfo);
            }
        } else {
            LOG_NRM("Verify only 1 CE exists for %d cmds as "
                "async events are masked (GetLogPage not called)", nAer);
            if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 2, numCE,
                isrCount) == true) {
                acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                    "acq.fail.reapinq2"), "Dump Entire ACQ");
                throw FrmwkEx(HERE, "1 CE expected but found %d CEs", numCE);
            }
        }
    }
}
예제 #25
0
void
InvalidQID_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
    string work;
    bool enableLog;
    uint64_t maxIOQEntries = 2;

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

    LOG_NRM("Create admin queues ACQ and ASQ");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(5);

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(5);

    // All queues will use identical IRQ vector
    IRQ::SetAnySchemeSpecifyNum(1);

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

    LOG_NRM("Issue DeleteIOSQ traversing through all combinations of DW10.QID");
    SharedDeleteIOSQPtr deleteIOSQCmd = SharedDeleteIOSQPtr(new DeleteIOSQ());

    list<uint32_t> illegalQIDs = GetIllegalQIDs(1);
    for (list<uint32_t>::iterator qId = illegalQIDs.begin();
        qId != illegalQIDs.end(); qId++) {
        LOG_NRM("Sending 1st deleteIOSQ cmd for QId #%d", *qId);
        work = str(boost::format("1st.IOQID.%d") % *qId);
        enableLog = false;
        if ((*qId <= 8) || (*qId >= (MAX_IOQ_ID - 8)))
            enableLog = true;

        deleteIOSQCmd->SetWord(*qId, 10, 0); // Set IO QID using Cmd DW10
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            deleteIOSQCmd, work, enableLog, CESTAT_INVALID_QID);
    }

    LOG_NRM("Setup element sizes for the IOQ's");
    gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_CQES) & 0xf);
    gCtrlrConfig->SetIOSQES(gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_SQES) & 0xf);

    LOG_NRM("Create IOCQ/IOSQ pair with QID = %d", IOQ_ID);
    SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName, mTestName,
        CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false,
        IOCQ_GROUP_ID, true, 0);
    SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName, mTestName,
        CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false,
        IOCQ_GROUP_ID, IOQ_ID, 0);

    LOG_NRM("Send DeleteIOSQ and expect success for QID = 1");
    work = str(boost::format("2nd.IOQID.1"));
    deleteIOSQCmd->SetWord(1, 10, 0); // Set IO QID = 1 using Cmd DW10
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        deleteIOSQCmd, work, true);

    LOG_NRM("Again issue DeleteIOSQ through all combinations of DW10.QID");
    illegalQIDs = GetIllegalQIDs(2);
    for (list<uint32_t>::iterator qId = illegalQIDs.begin();
        qId != illegalQIDs.end(); qId++) {
        LOG_NRM("Sending 2nd deleteIOSQ cmd for QId #%d", *qId);
        work = str(boost::format("2nd.IOQID.%d") % *qId);
        enableLog = false;
        if ((*qId <= 8) || (*qId >= (MAX_IOQ_ID - 8)))
            enableLog = true;

        deleteIOSQCmd->SetWord(*qId, 10, 0); // Set IO QID using Cmd DW10
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
            deleteIOSQCmd, work, enableLog, CESTAT_INVALID_QID);
    }
}
예제 #26
0
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);
        }
    }
}
예제 #27
0
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;
    }
}
예제 #28
0
void
VerifyMaxEvents_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) none
     *  \endverbatim
     */
    uint32_t isrCount;
    uint32_t ceRemain;
    uint32_t numReaped;
    uint32_t numCE;

    LOG_NRM("Issue Identify.AERL to get Async Event Req Limit (AERL)");
    uint8_t nAerlimit = gInformative->GetIdentifyCmdCtrlr()->
        GetValue(IDCTRLRCAP_AERL) + 1; // Convert to 1-based.

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

    LOG_NRM("Create admin queues ACQ and ASQ for test lifetime");
    SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
    acq->Init(nAerlimit + 2); // one extra space than Q full condition

    SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
    asq->Init(nAerlimit + 2); // one extra space than Q full condition

    // 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("Issue one more than %d (async event req limit)", nAerlimit);
    SendAsyncEventRequests(asq, (nAerlimit + 1));

    LOG_NRM("Delay 5 sec");
    sleep(5);

    if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount)
        == false) {
        acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail1"),
            "Dump Entire ACQ");
        throw FrmwkEx(HERE, "1 CE's expected in ACQ but found %d CE's", numCE);
    }

    SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer());
    if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true)) != 1) {
        acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail2"),
            "Dump Entire ACQ");
        throw FrmwkEx(HERE, "Unable to reap on ACQ");
    }

    LOG_NRM("verify SC = Async Event Limit Exceeded");
    union CE *ce = (union CE *)ceMem->GetBuffer();
    ProcessCE::Validate(*ce, CESTAT_ASYNC_REQ_EXCEED);

    for (uint8_t nAer = 0; nAer < nAerlimit; nAer++) {
        LOG_NRM("Ring doorbell for IOSQ #1");
        InvalidSQWriteDoorbell();
        sleep(1);
        LOG_NRM("verify CE exists in ACQ for invalid SQID doorbell write");
        if (acq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(1), 1, numCE, isrCount)
            == false) {
            acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                "acq.fail4"), "Dump Entire ACQ");
            throw FrmwkEx(HERE, "1 CE expected in ACQ but found %d CEs", numCE);
        }

        SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer());
        if ((numReaped = acq->Reap(ceRemain, ceMem, isrCount, numCE, true))
            != 1) {
            acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName,
                "acq.fail5"), "Dump Entire ACQ");
            throw FrmwkEx(HERE, "Unable to reap on ACQ");
        }

        union CE *ce = (union CE *)ceMem->GetBuffer();
        if (ce->n.async.asyncEventType != EVENT_TYPE_ERROR_STS) {
            throw FrmwkEx(HERE, "Invalid async event error status, "
                "(Expected : Received) :: (%d : %d)", EVENT_TYPE_ERROR_STS,
                ce->n.async.asyncEventType);
        } else if (ce->n.async.asyncEventInfo != ERR_STS_INVALID_SQ) {
            throw FrmwkEx(HERE, "Invalid async event info, "
                "(Expected : Received) :: (%d : %d)", ERR_STS_INVALID_SQ,
                ce->n.async.asyncEventInfo);
        }
        LOG_NRM("Associated Log page = %d", ce->n.async.assocLogPage);
        ReadLogPage(acq, asq, ce->n.async.assocLogPage);
    }
}
예제 #29
0
bool
CompareGolden(Golden &golden)
{
    string work;

    try {   // The objects to perform this work throw exceptions
        FileSystem::SetBaseDumpDir(false);   // Log into GrpPending
        if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false)
            throw FrmwkEx(HERE);

        LOG_NRM("Prepare the admin Q's to setup this request");
        SharedACQPtr acq = SharedACQPtr(new ACQ(gDutFd));
        acq->Init(2);
        SharedASQPtr asq = SharedASQPtr(new ASQ(gDutFd));
        asq->Init(2);
        gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET);
        if (gCtrlrConfig->SetState(ST_ENABLE) == false)
            throw FrmwkEx(HERE);

        SharedIdentifyPtr idCmd = SharedIdentifyPtr(new Identify());
        SharedMemBufferPtr idMem = SharedMemBufferPtr(new MemBuffer());
        idMem->InitAlignment(Identify::IDEAL_DATA_SIZE, sizeof(uint64_t), true, 0);
        send_64b_bitmask prpReq =
            (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
        idCmd->SetPrpBuffer(prpReq, idMem);

        for (size_t i = 0; i < golden.cmds.size(); i++) {
            LOG_NRM("Identify cmd #%ld", i);
            LOG_NRM("  Identify:DW1.nsid = 0x%02x", golden.cmds[i].nsid);
            LOG_NRM("  Identify.DW10.cns = %c", golden.cmds[i].cns ? 'T' : 'F');
            LOG_NRM("  sizeof(Identify.raw) = %ld", golden.cmds[i].raw.size());

            LOG_NRM("Formulate an identical idenitfy cmd to issue");
            idCmd->SetCNS(golden.cmds[i].cns);
            idCmd->SetNSID(golden.cmds[i].nsid);

            idMem->InitAlignment(Identify::IDEAL_DATA_SIZE, sizeof(uint64_t),
                true, 0);
            work = str(boost::format("IdCmd%d") % i);
            IO::SendAndReapCmd("tnvme", "golden", SYSTEMWIDE_CMD_WAIT_ms, asq,
                acq, idCmd, work, false);

            if (idMem->Compare(golden.cmds[i].raw) == false) {
                idMem->Dump(FileSystem::PrepDumpFile("tnvme", "golden",
                    "identify", "dut.miscompare"), "DUT data miscompare");
                SharedMemBufferPtr userMem = SharedMemBufferPtr(
                    new MemBuffer(golden.cmds[i].raw));
                userMem->Dump(FileSystem::PrepDumpFile("tnvme", "golden",
                    "identify", "cmdline.miscompare"),
                    "Golden user data miscompare");
                throw FrmwkEx(HERE, "Golden identify data miscompare");
            }
        }

        LOG_NRM("The operation succeeded to compare golden data");
    } catch (...) {
        LOG_ERR("Operation failed to compare golden data");
        gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY);
        return false;
    }

    gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY);
    return true;
}
예제 #30
0
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);
        }
    }
}