Example #1
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);
}
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);
}
Example #3
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;
}
void
UnsupportRsvdFields_r12::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    CE ce;
    vector<uint32_t> activeNamespaces;
    string work;
    LOG_NRM("Admin queue setup");

    SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID));
    SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID));
    LOG_NRM("Test proper");


    LOG_NRM("Form identify cmd for namespace list and associate some buffer");
    SharedIdentifyPtr idCmdNamSpcList = SharedIdentifyPtr(new Identify());
    idCmdNamSpcList->SetCNS(CNS_NamespaceListActive);
    idCmdNamSpcList->SetNSID(0);

    SharedMemBufferPtr idMemNamSpcList = SharedMemBufferPtr(new MemBuffer());
    idMemNamSpcList->InitAlignment(NAMSPC_LIST_SIZE * NAMSPC_ENTRY_SIZE);

    send_64b_bitmask idPrpNamSpc =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    idCmdNamSpcList->SetPrpBuffer(idPrpNamSpc, idMemNamSpcList);

    LOG_NRM("Sending Identify command CNS.%02Xh", CNS_NamespaceListActive);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpcList, "namspcList", true);

    LOG_NRM("Reading in active Namespaces.");
    const uint8_t *data = &((idCmdNamSpcList->GetROPrpBuffer())[0]);

    while ((*((uint32_t *)data) & 0xffff) != 0x0000){
        uint32_t nsid = (*((uint32_t *)data) & 0xffff);
        LOG_NRM("Found active NSID: %08X", nsid);
        activeNamespaces.push_back(nsid);
        data += 4;
    }

    // Lookup objs which were created in a prior test within group
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr();

    for (size_t i = 0; i < activeNamespaces.size(); i++) {
        LOG_NRM("Processing namspc %ld", i);
        SharedFlushPtr flushCmd = SharedFlushPtr(new Flush());
        flushCmd->SetNSID(activeNamespaces[i]);

        ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,
            flushCmd, "none.set", true);
        if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){
            throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, "
                    "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC);
        }

        if (ce.n.reserved != 0){
            throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X",
                    ce.n.reserved);
        } else if(ce.n.cmdSpec != 0){
            throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X",
                    ce.n.cmdSpec);
        }

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

        flushCmd->SetDword(0xffffffff, 2);
        flushCmd->SetDword(0xffffffff, 3);
        flushCmd->SetDword(0xffffffff, 4);
        flushCmd->SetDword(0xffffffff, 5);
        flushCmd->SetDword(0xffffffff, 6);
        flushCmd->SetDword(0xffffffff, 7);
        flushCmd->SetDword(0xffffffff, 8);
        flushCmd->SetDword(0xffffffff, 9);
        flushCmd->SetDword(0xffffffff, 10);
        flushCmd->SetDword(0xffffffff, 11);
        flushCmd->SetDword(0xffffffff, 12);
        flushCmd->SetDword(0xffffffff, 13);
        flushCmd->SetDword(0xffffffff, 14);
        flushCmd->SetDword(0xffffffff, 15);

        ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1),
                iosq, iocq,flushCmd, "all.set", true);
        if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){
            throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, "
                    "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC);
        }

        if (ce.n.reserved != 0){
            throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X",
                    ce.n.reserved);
        } else if(ce.n.cmdSpec != 0){
            throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X",
                    ce.n.cmdSpec);
        }
    }

    // This highestNSID could provide a case where it issues to an inactive NSID
    // In the case of an inactive NSID the error status would be Invalid Field
    /*uint32_t highestNSID = 0;
    for (uint32_t i = 0; i < activeNamespaces.size(); i++){
        if (activeNamespaces[i] > highestNSID)
            highestNSID = activeNamespaces[i];
    }

    if (highestNSID != 0xffffffff){
        SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush());
        invalidFlushCmd->SetNSID(highestNSID + 1);
        // Could be Invalid Field or Invalid Namespace or Format
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,
            invalidFlushCmd, "none.set", true, CESTAT_INVAL_NAMSPC);
    }*/
    ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr();
    uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN);
    // Issuing flush cmd with a few invalid NSIDs
    int count = 0;
    for (uint64_t i = 0; pow(2, i) <= 0xffffffff; i++) {
        if (pow(2, i) <= nn)
            continue;
        LOG_NRM("Issue flush cmd with illegal namspc ID=%llu",
                (unsigned long long)i);
        SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush());
        invalidFlushCmd->SetNSID(pow(2, i));
        IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
                iocq, invalidFlushCmd, "Flush.Invalid", true, CESTAT_INVAL_NAMSPC);
        count++;
    }
    LOG_NRM("Ran with: %d invalid NSIDs", count);
}
void
CreateAndAttachMaxNamespacesAndVerify::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * None.
     * \endverbatim
     */
	LOG_NRM("Start CreateAndAttachMaxNamespacesAndVerify::RunCoreTest");

	SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
	SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));
	SharedASQPtr   asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID));
	SharedACQPtr   acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID));
	//uint8_t keyToRegister[16];
	//uint32_t memAlignment = sysconf(_SC_PAGESIZE);
	//CEStat retStat;
	send_64b_bitmask prpBitmask = (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE);
	uint8_t userBuffer[4096];
    if (userBuffer == 0){} // Suppress unused variable warning

    const uint32_t *namespaceIdListBuffer32BitPtr = NULL;
    const uint16_t *controllerIdListBuffer16BitPtr;

    ConstSharedIdentifyPtr idCtrlrCap = gInformative->GetIdentifyCmdCtrlr();
    uint32_t identifyControllerMaxNSID = (uint32_t)idCtrlrCap->GetValue(IDCTRLRCAP_NN);

    // BUGBUG large assumption that NVMCAP values will not be larger than 64bit num bytes, which is 16384 PETAbytes
    // BUGBUG Also assume we need to create on GB multiples

    uint64_t identifyControllerUnallocatedCapacity = idCtrlrCap->GetValue(IDCTRLRCAP_UNVMCAP_LOWER);
    uint64_t identifyControllerTotalCapacity       = idCtrlrCap->GetValue(IDCTRLRCAP_TNVMCAP_LOWER);

    uint64_t individualNamespaceCapacityInGB       = (uint64_t) floor( identifyControllerUnallocatedCapacity / 1024.0 / 1024.0 / 1024.0 / identifyControllerMaxNSID); // In GB units
    uint64_t individualNamespaceCapacity = individualNamespaceCapacityInGB * 1024 * 1024 * 1024 / 512; // In 512B LBA units
    uint32_t newlyCreatedNSID = 0;

    if( identifyControllerUnallocatedCapacity != identifyControllerTotalCapacity) {
    	LOG_NRM("TNVMCAP != UNVMCAP, which points to a namespace being allocated but the previous test should have deleted all");
    }

	LOG_NRM("Create Identify Command To Get All Present NSIDs");
	SharedIdentifyPtr identifyCmd = SharedIdentifyPtr(new Identify());
    SharedMemBufferPtr identifyControllerStruct = SharedMemBufferPtr(new MemBuffer());
    identifyControllerStruct->Init(4096, true, 0x0);
    SharedMemBufferPtr identifyNamespaceStruct = SharedMemBufferPtr(new MemBuffer());
    identifyNamespaceStruct->Init(4096, true, 0x0);
    SharedMemBufferPtr identifyNamespaceList = SharedMemBufferPtr(new MemBuffer());
    identifyNamespaceList->Init(4096, true, 0x0);
    SharedMemBufferPtr identifyControllerList = SharedMemBufferPtr(new MemBuffer());
    identifyControllerList->Init(4096, true, 0x0);

    // Figure 86 in 1.2 spec               CNS  NSID CNTID Returns
    // CNS_Namespace                      0x00    X     -   (Identify Namespace from NSID X. If attached, receive struct, else all 0's, else invalid namespace ID)
    // CNS_Controller                     0x01    -     -   (Identify Controller struct)
    // CNS_NamespaceListAttached          0x02    Y     -   (Identify Namespace LIST, starting at NSID Y and in an increasing order)
    // CNS_NamespaceListSubsystem         0x10    Z     -   (Identify Namespace LIST, starting at NSID Z present in subsystem that may or may not be attached)
    // CNS_NamespaceStructSubsystem       0x11    X     -   (Identify Namespace from NSID A. If attached or not, receive the struct, else invalid namespace ID)
    // CNS_ControllerListAttachedToNSID   0x12    X     A   (Controller List that are attached to NSID X, starting with CNTID greater than A)
    // CNS_ControllerListSubsystem        0x13    -     B   (Controller List present in subsystem starting with CNTID greater than B)

    LOG_NRM("First ensure there are no namespaces present, as this test depends on deleteAllNamespacesAndVerify to complete successfully");
	// See 8.11 in 1.2 spec for describing the process this test is following
	identifyCmd->SetPrpBuffer(prpBitmask, identifyNamespaceList);
	identifyCmd->SetNSID( 0 );
	identifyCmd->SetCNS(  CNS_NamespaceListSubsystem ); // Get all NSIDs attached (or not) to controllers
    identifyCmd->SetCNTID(0);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Reading back (up to) 1024 NSIDs attached to this controller (CNS=2). Command should pass, with 0 NSIDs to be returned", false, CESTAT_SUCCESS);
    namespaceIdListBuffer32BitPtr = (uint32_t*) identifyCmd->GetROPrpBuffer();
    if( namespaceIdListBuffer32BitPtr[0] != 0) {
    	throw FrmwkEx(HERE, "Before creating any namespaces, subsystem was expected to have no NSIDs active and present, but Identify CNS=0x10 returned at least one NSID.");
    }

    LOG_NRM("No namespaces are active, test can continue. Pull back the controller list to be used to attach all NSIDs to all controllers on subsystem");
	identifyCmd->SetPrpBuffer(prpBitmask, identifyControllerList);
	identifyCmd->SetNSID( 0 );
	identifyCmd->SetCNS(  CNS_ControllerListSubsystem ); // Get all controllers in this subsystem
	identifyCmd->SetCNTID(0);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Reading back what controllers are on this subsystem (CNS=0x13), should find at LEAST one.", false, CESTAT_SUCCESS);
    controllerIdListBuffer16BitPtr = (uint16_t*) identifyCmd->GetROPrpBuffer();
    if( controllerIdListBuffer16BitPtr[0] == 0) {
    	throw FrmwkEx(HERE, "Before creating any namespaces, subsystem was expected to have at least one controller ID present, but found zero.");
    }

    SharedNamespaceAttachPtr namespaceAttachCmd = SharedNamespaceAttachPtr(new NamespaceAttach() );
    /*
    //BUGBUG APL is returning an improper list (Ctrlr IDs 1/2 wheras they ID themselves as actually 0/1)
    for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) {
    	userBuffer[bufferIndex]=0;
    }
    userBuffer[0] = 2; // 2 Controllers
    userBuffer[4] = 1; // 1st (byte 2) is 0 and 2nd (byte 4) is 1 to match APL
    identifyControllerList->InitAlignment(4096, 4096, false, 0, userBuffer);
    LOG_NRM("Controller list hardcoded to 0/1 for the time being... BUGBUG");
    // END BUG BUG
    */
    // Set attach namespace buffer to be the full controller list, to attach all new NSIDs to to all on this subsystem
    namespaceAttachCmd->SetPrpBuffer(prpBitmask, identifyControllerList);

	LOG_NRM("Create Namespace Management to create all namespaces before attaching to all contollers");
    SharedNamespaceManagementPtr namespaceManagementCmd = SharedNamespaceManagementPtr(new NamespaceManagement() );
    SharedMemBufferPtr managementBuffer = SharedMemBufferPtr(new MemBuffer() );

    NamespaceManagementCreateStruct nscreate;
    nscreate.NSZE = individualNamespaceCapacity;
    nscreate.NCAP = individualNamespaceCapacity;
    nscreate.FLBAS = 0;
    nscreate.DPS   = 0;
    nscreate.NMIC  = 1;

    //NamespaceManagementCreateStruct nscreate( individualNamespaceCapacity, individualNamespaceCapacity, 0, 0, 1 );
    // BUGBUG we are going to assume a 512B size and barenamespace as FLBAS=0... otherwise we need to determine what format via namespace structs...
    //CreateNamespaceManagementStructure( individualNamespaceCapacity, individualNamespaceCapacity, 0, 0, 1, userBuffer);
    LOG_NRM("Each of the %d namespaces will be of 0x%llx size", identifyControllerMaxNSID, (long long unsigned int) individualNamespaceCapacity);
    nscreate.print();

    managementBuffer->InitAlignment(384, 4096, false, 0x0, (uint8_t*) &nscreate); // Contains namespace struct info for namespace management to consume (384B)
    namespaceManagementCmd->SetPrpBuffer(prpBitmask, managementBuffer);
    namespaceAttachCmd->SetSEL( 0 );
    namespaceAttachCmd->SetNSID( 0 );

	LOG_NRM("Start main loop over valid NSIDs to create/attach them.");
	for(uint64_t currentNamespaceIdToCreate = 0; currentNamespaceIdToCreate < identifyControllerMaxNSID; currentNamespaceIdToCreate++ ) {
		// Get the current
		// Create this namespace using 1/NNth amount of the total available space.
	    namespaceManagementCmd->SetSEL(0);
	    namespaceManagementCmd->SetNSID(0);
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceManagementCmd, "Creating namespace that is 1/NNth size of total NVM capacity, 512B bare LBAs.", false, CESTAT_SUCCESS);
	    newlyCreatedNSID = (acq->PeekCEwithCID( namespaceManagementCmd->GetCID() ) ).t.dw0;
	    LOG_NRM("Newly created NS has NSID of 0x%llu", (long long unsigned) newlyCreatedNSID);

		// ID this namespace and see if it is all 0s. Namespace should be created but 'inactive'.
		identifyCmd->SetCNS(CNS_Namespace ); // Standard Namespace ID, should also be attached to this controller
		identifyCmd->SetNSID( newlyCreatedNSID ); //
	    identifyCmd->SetCNTID(0);
		identifyCmd->SetPrpBuffer(prpBitmask, identifyNamespaceStruct);
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Read Identify Controller struct from created NSID, expecting it to be all 0's since it has not yet attached", false, CESTAT_SUCCESS);
	    // Currently fails on FW
	    for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) {
    		if ( identifyCmd->GetROPrpBuffer()[bufferIndex] != 0) {
    			throw FrmwkEx(HERE, "Expected Identify Namespace to returned all zero buffer as namespace should be inactive and non-attached");
    		}
    	}

	    // Now attach the drive to all controllers on the subsystem
	    namespaceAttachCmd->SetNSID( newlyCreatedNSID );
	    namespaceAttachCmd->SetSEL(0);
	    // Should already have the ControllerList associated with the NamespaceAttach command
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceAttachCmd, "Attaching NSID to all controllers on subsystem", false, CESTAT_SUCCESS);

	    // Reread this NS struct back and make sure the values match what we had requested...
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Read Identify Controller struct from created NSID, expecting non-zero since it is now attached", false, CESTAT_SUCCESS);
	    // First ensure the buffer is not completely non-zero
	    bool identifyNamespaceBufferIsZeroFilled = true;
	    for(uint32_t bufferIndex = 0; bufferIndex < 4096; bufferIndex++) {
    		if ( identifyCmd->GetROPrpBuffer()[bufferIndex] != 0) {
    			identifyNamespaceBufferIsZeroFilled = false;
    			break;
    		}
    	}
	    if( identifyNamespaceBufferIsZeroFilled == true) {
	    	throw FrmwkEx(HERE, "Expected Identify Namespace to returned a non-zero buffer as namespace should now be attached");
	    }

	    // Now check a couple fields (BUGBUG should check all!)
	    IdNamespcStruct *currentNamespaceStruct = (IdNamespcStruct*) identifyCmd->GetROPrpBuffer();
	    if(currentNamespaceStruct->NSZE != individualNamespaceCapacity) {
	    	LOG_NRM("Namespace NSZE 0x%llx != what was passed to namespaceManagement 0x%08llx", (long long unsigned) currentNamespaceStruct->NSZE, (long long unsigned) individualNamespaceCapacity);
	    	throw FrmwkEx(HERE, "Newly created namespace's NSZE does not match what was sent to namespaceManagement");
	    }
	    if(currentNamespaceStruct->NCAP != individualNamespaceCapacity) {
	    	LOG_NRM("Namespace NCAP 0x%llx != what was passed to namespaceManagement 0x%08llx", (long long unsigned) currentNamespaceStruct->NCAP, (long long unsigned) individualNamespaceCapacity);
	    	throw FrmwkEx(HERE, "Newly created namespace's NCAP does not match what was sent to namespaceManagement");
	    }

	    // Repull the Identify Controller information and make sure the UNVMCAP values have decreased the amount we just allocatd for this create namespace
	    identifyCmd->SetCNS(CNS_Controller);
	    identifyCmd->SetNSID(0);
	    identifyCmd->SetCNTID(0);
	    identifyCmd->SetPrpBuffer(prpBitmask, identifyControllerStruct);
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, identifyCmd, "Pull Identify Controller to check usage sizes have changed.", false, CESTAT_SUCCESS);
	    IdCtrlrCapStruct *currentControllerStruct = (IdCtrlrCapStruct*) identifyCmd->GetROPrpBuffer();
	    uint64_t expectedNVMCAP = identifyControllerTotalCapacity - (individualNamespaceCapacity * (currentNamespaceIdToCreate+1) * 512);
	    if(currentControllerStruct->UNVMCAP_LOWER != expectedNVMCAP) {
	    	LOG_NRM("Expecting UNVMCAP to decrease by last allocated namespace. UNVMCAP = 0x%llx expecting 0x%llx", (long long unsigned) currentControllerStruct->UNVMCAP_LOWER, (long long unsigned) expectedNVMCAP);
	    	throw FrmwkEx(HERE, "Identify Controller UNVMCAP is not adjusted after creating a namespace of 1/NNth size");
	    }

	    // Try to retry the attachment again and ensure a proper fail case
	    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, namespaceAttachCmd, "Attaching an already attached NSID to all controllers again to check fail case", false, CESTAT_NS_ALREADY_ATTACHED);
	}

	// At this point we can double sanity check.
	// 1) Controller should state 0 bytes available
	// 2) Should be Cntrl.NN namespaces active and attached to all controllers on the subsystem

    LOG_NRM("Completed CreateAndAttachMaxNamespacesAndVerify::RunCoreTest");
}
Example #6
0
void
VerifyNUSE_r10b::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */
    string work;

    LOG_NRM("Lookup Q'S 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))
    SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID));
    SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID));

    LOG_NRM("Search for 1st bare/meta or e2e namespace.");
    Informative::Namspc namspcData = gInformative->Get1stBareMetaE2E();
    uint64_t ncap = namspcData.idCmdNamspc->GetValue(IDNAMESPC_NCAP);
    LBAFormat lbaFormat = namspcData.idCmdNamspc->GetLBAFormat();
    uint64_t lbaDataSize = namspcData.idCmdNamspc->GetLBADataSize();
    LOG_NRM("For namespace ID #%d; NCAP = 0x%08lX; LBA Size (B): %lu; NCAP*LBA "
        "Size (GB): %.2f", namspcData.id, ncap, lbaDataSize,
        ncap * lbaDataSize / 1e9);

    LOG_NRM("Create dataset mgmt cmd to be used subsequently");
    SharedDatasetMgmtPtr datasetMgmtCmd =
        SharedDatasetMgmtPtr(new DatasetMgmt());
    SharedMemBufferPtr rangeMem = SharedMemBufferPtr(new MemBuffer());
    rangeMem->Init((NUM_RANGES * sizeof(RangeDef)), true);

    send_64b_bitmask prpBitmask =
            (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    datasetMgmtCmd->SetNSID(namspcData.id);
    datasetMgmtCmd->SetNR(NUM_RANGES - 1);  // convert to 0-based
    datasetMgmtCmd->SetPrpBuffer(prpBitmask, rangeMem);
    datasetMgmtCmd->SetAD(true);

    LOG_NRM("Deallocate every LBA in namespace ID #%d", namspcData.id);
    RangeDef *rangePtr = (RangeDef *)rangeMem->GetBuffer();
    rangePtr->slba = 0;
    rangePtr->length = ncap;

    const double deallocRate = 1.6e8; // bytes / ms
    work = str(boost::format("deallocate.%08Xh") % ncap);
    IO::SendAndReapCmd(mGrpName, mTestName, ncap * lbaDataSize / deallocRate
        + 10000, iosq, iocq, datasetMgmtCmd, work, true);

    LOG_NRM("Create identify cmd & assoc some buffer memory");
    SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify());
    LOG_NRM("Force identify to request namespace struct");
    idCmdNamSpc->SetCNS(CNS_Namespace);
    idCmdNamSpc->SetNSID(namspcData.id);
    SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer());
    idMemNamSpc->InitAlignment(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_ALIGNMENT,
        true, 0);
    send_64b_bitmask idPrpNamSpc =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc);

    work = str(boost::format("IdentifyNamspc.nsid.%d.lba.all") % namspcData.id);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, work, true);

    LOG_NRM("Verify namespace utilization is zero after de-allocation.");
    uint64_t nuse = idCmdNamSpc->GetValue(IDNAMESPC_NUSE);
    uint64_t nsfeat = idCmdNamSpc->GetValue(IDNAMESPC_NSFEAT);
    if (nuse != 0x0 && ((nsfeat & 0x1) == 0x1)) {
        throw FrmwkEx(HERE, "Expected namspc utilization = 0x0 but found "
            "namspc utilization = 0x%08X", nuse);
    }

    LOG_NRM("Write data pattern and issue a single block to LBA 0");
    SharedWritePtr writeCmd = SharedWritePtr(new Write());
    SharedMemBufferPtr writeMem = SharedMemBufferPtr(new MemBuffer());

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

    prpBitmask = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE |
        MASK_PRP2_LIST);
    writeCmd->SetPrpBuffer(prpBitmask, writeMem);
    writeCmd->SetNSID(namspcData.id);
    writeCmd->SetNLB(0);

    work = str(boost::format("write.nsid.%d.nlba.0") % namspcData.id);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq,
        iocq, writeCmd, work, true);

    work = str(boost::format("IdentifyNamspc.nsid.%d.nlba.0") % namspcData.id);
    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, work, true);

    LOG_NRM("Verify namespace utilization is one after single LBA write cmd.");
    nuse = idCmdNamSpc->GetValue(IDNAMESPC_NUSE);
    nsfeat = idCmdNamSpc->GetValue(IDNAMESPC_NSFEAT);
    if (nuse != 0x1  && ((nsfeat & 0x1) == 0x1)) {
        throw FrmwkEx(HERE, "Expected namspc utilization = 0x1 but found "
            "namspc utilization = 0x%08X", nuse);
    }
}
void
UnsupportRsvdFields_r12::RunCoreTest()
{
    /** \verbatim
     * Assumptions:
     * 1) Test CreateResources_r10b has run prior.
     * \endverbatim
     */

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

    LOG_NRM("Determine if DUT has atleast one namespace support");
    ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr();
    if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0)
        throw FrmwkEx(HERE, "Required to support >= 1 namespace");

    LOG_NRM("Form identify namespace cmd and associate some buffer");
    SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify());
    idCmdNamSpc->SetCNS(CNS_Namespace);
    idCmdNamSpc->SetNSID(1);

    SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer());
    idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE,
        PRP_BUFFER_OFFSET, true);

    LOG_NRM("Allow PRP1 and PRP2");
    send_64b_bitmask idPrpNamSpc =
        (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE);
    idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc);

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, "rsvdnone.set", true);

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

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

    work = idCmdNamSpc->GetDword(10);
    //work |= 0xfffffffc;      // Set DW10_b31:2 bits
    work |= 0x0000ff00;        // Set DW10_b31:8 bits
    idCmdNamSpc->SetDword(work, 10);

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

    IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, "rsvdall.set", true);

    LOG_NRM("Set CNS field reserved coded value");
    uint32_t cdw10 = idCmdNamSpc->GetDword(10);
    //work = cdw10 | 0x3;
    //idCmdNamSpc->SetDword(work, 10);
    const uint32_t cnsNonRsvdVal[] = {
        0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x13 };
    const uint32_t cnsNonRevdValCnt = sizeof(cnsNonRsvdVal) / sizeof(uint32_t);

    /*IO::SendAndReapCmdNot(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
        idCmdNamSpc, "rsvdall.val.set", true, CESTAT_SUCCESS);
     */
    for (uint32_t cnsVal = 0; cnsVal <= 0xff; cnsVal++){
        uint32_t idx = 0;

        while ((idx < cnsNonRevdValCnt) && (cnsVal != cnsNonRsvdVal[idx])){
            ++idx;
        }

        if (idx == cnsNonRevdValCnt) {
            work = cdw10 | cnsVal;
            idCmdNamSpc->SetDword(work, 10);

            IO::SendAndReapCmdNot(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq,
                idCmdNamSpc, "rsvdall.val.set", true, CESTAT_SUCCESS);
        }
    }
}