NVMed: Enable Primary controller when SC is empty
NVMe device can have no secondary controller. Currently, if
the secondary list is empty. The primary controller is not
enable.
Patch Tracking Bug: b/284486810
Upstream info / review: https://gerrit.openbmc.org/c/openbmc/dbus-sensors/+/63777
Upstream-Status: Submitted
Justification: Depends on other patches
Signed-off-by: Muhammad Usama <muhammadusama@google.com>
%% original patch: 0047-NVMed-Enable-Primary-controller-when-SC-is-empty.patch
Change-Id: I039973a01f1d24a061d7f4d40422e0b598fd1b09
diff --git a/src/NVMeSubsys.cpp b/src/NVMeSubsys.cpp
index 54f0da8..9bd8a2a 100644
--- a/src/NVMeSubsys.cpp
+++ b/src/NVMeSubsys.cpp
@@ -79,6 +79,69 @@
objServer.remove_interface(assocIntf);
}
+void NVMeSubsystem::processSecondaryControllerList(nvme_secondary_ctrl_list* secCntlrList)
+{
+ auto findPrimary = controllers.begin();
+ int secCntlrCount = 0;
+ if (secCntlrList != nullptr)
+ {
+ // all sc_entry pointing to a single pcid, so we only check
+ // the first entry.
+ findPrimary = controllers.find(secCntlrList->sc_entry[0].pcid);
+ if (findPrimary == controllers.end())
+ {
+ std::cerr << "fail to match primary controller from "
+ "identify sencondary cntrl list" << std::endl;
+ status = Status::Stop;
+ markFunctional(false);
+ markAvailable(false);
+ return;
+ }
+ secCntlrCount = secCntlrList->num;
+ }
+
+ // Enable primary controller since they are required to work
+ auto& primaryController = findPrimary->second.first;
+ primaryController =
+ NVMeControllerEnabled::create(std::move(*primaryController.get()));
+
+ std::vector<std::shared_ptr<NVMeController>> secCntrls;
+ for (int i = 0; i < secCntlrCount; i++)
+ {
+ auto findSecondary = controllers.find(secCntlrList->sc_entry[i].scid);
+ if (findSecondary == controllers.end())
+ {
+ std::cerr << "fail to match secondary controller from "
+ "identify sencondary cntrl list"
+ << std::endl;
+ break;
+ }
+
+ auto& secondaryController = findSecondary->second.first;
+
+ // Check Secondary Controller State
+ if (secCntlrList->sc_entry[i].scs != 0)
+ {
+ secondaryController = NVMeControllerEnabled::create(
+ std::move(*secondaryController.get()));
+ }
+ secCntrls.push_back(secondaryController);
+ }
+ primaryController->setSecAssoc(secCntrls);
+
+ // start controller
+ for (auto& [_, pair] : controllers)
+ {
+ pair.first->start(pair.second);
+ }
+ // start plugin
+ if (plugin)
+ {
+ plugin->start();
+ }
+ status = Status::Start;
+}
+
void NVMeSubsystem::markFunctional(bool toggle)
{
if (ctemp)
@@ -194,7 +257,20 @@
The controller is SR-IOV, meaning all controllers (within a
subsystem) are pointing to a single primary controller. So we
only need to do identify on an arbatary controller.
+ If the controller list contains a single controller. Skip
+ identifying the secondary controller list. It will be the primary
+ controller.
*/
+ if (ctrlList.size() == 1)
+ {
+ // Remove all associations
+ for (const auto& [_, pair] : self->controllers)
+ {
+ pair.first->setSecAssoc();
+ }
+ self->processSecondaryControllerList(nullptr);
+ return;
+ }
auto ctrl = ctrlList.back();
nvme->adminIdentify(
ctrl, nvme_identify_cns::NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST,
@@ -210,8 +286,8 @@
self->markAvailable(false);
return;
}
- nvme_secondary_ctrl_list& listHdr =
- *reinterpret_cast<nvme_secondary_ctrl_list*>(data.data());
+ nvme_secondary_ctrl_list* listHdr =
+ reinterpret_cast<nvme_secondary_ctrl_list*>(data.data());
// Remove all associations
for (const auto& [_, pair] : self->controllers)
@@ -219,7 +295,7 @@
pair.first->setSecAssoc();
}
- if (listHdr.num == 0)
+ if (listHdr->num == 0)
{
std::cerr << "empty identify secondary controller list"
<< std::endl;
@@ -228,66 +304,8 @@
self->markAvailable(false);
return;
}
-
- // all sc_entry pointing to a single pcid, so we only check
- // the first entry.
- auto findPrimary =
- self->controllers.find(listHdr.sc_entry[0].pcid);
- if (findPrimary == self->controllers.end())
- {
- std::cerr << "fail to match primary controller from "
- "identify sencondary cntrl list"
- << std::endl;
- self->status = Status::Stop;
- self->markFunctional(false);
- self->markAvailable(false);
- return;
- }
-
- // Enable primary controller since they are required to work
- auto& primaryController = findPrimary->second.first;
- primaryController = NVMeControllerEnabled::create(
- std::move(*primaryController.get()));
-
- std::vector<std::shared_ptr<NVMeController>> secCntrls;
- for (int i = 0; i < listHdr.num; i++)
- {
- auto findSecondary =
- self->controllers.find(listHdr.sc_entry[i].scid);
- if (findSecondary == self->controllers.end())
- {
- std::cerr << "fail to match secondary controller from "
- "identify sencondary cntrl list"
- << std::endl;
- break;
- }
-
- auto& secondaryController = findSecondary->second.first;
-
- // Check Secondary Controller State
- if (listHdr.sc_entry[i].scs != 0)
- {
- secondaryController = NVMeControllerEnabled::create(
- std::move(*secondaryController.get()));
- }
- secCntrls.push_back(secondaryController);
- }
- primaryController->setSecAssoc(secCntrls);
-
- // start controller
- for (auto& [_, pair] : self->controllers)
- {
- pair.first->start(pair.second);
- }
-
- // start plugin
- if (self->plugin)
- {
- self->plugin->start();
- }
-
- self->status = Status::Start;
- });
+ self->processSecondaryControllerList(listHdr);
+ });
});
}
}
diff --git a/src/NVMeSubsys.hpp b/src/NVMeSubsys.hpp
index dd9dbfa..a86710f 100644
--- a/src/NVMeSubsys.hpp
+++ b/src/NVMeSubsys.hpp
@@ -81,4 +81,7 @@
// a counter to skip health poll when NVMe subsystem becomes Unavailable
unsigned UnavailableCount = 0;
static constexpr unsigned UnavailableMaxCount = 60;
+
+ // process Secondary controller and start controllers and the associated Plugin
+ void processSecondaryControllerList(nvme_secondary_ctrl_list* secCntlrList);
};