common: i2c: Add non-coroutine sendReceive()
This commit introduces a non-coroutine version of `sendReceive()` in the
common I2C module. The new implementation avoids potential stack buffer
issues by ensuring synchronous execution.
Change-Id: I1d308f24fafa6e0d68ffcc67073e0a2e67a6b419
Signed-off-by: Daniel Hsu <Daniel-Hsu@quantatw.com>
diff --git a/common/i2c/i2c.cpp b/common/i2c/i2c.cpp
index fb8bee0..653f823 100644
--- a/common/i2c/i2c.cpp
+++ b/common/i2c/i2c.cpp
@@ -76,6 +76,51 @@
co_return result;
}
+bool I2C::sendReceive(const std::vector<uint8_t>& writeData,
+ std::vector<uint8_t>& readData) const
+{
+ bool result = true;
+
+ if (fd <= 0)
+ {
+ return false;
+ }
+ else
+ {
+ struct i2c_msg msg[2];
+ struct i2c_rdwr_ioctl_data readWriteData;
+ int msgIndex = 0;
+
+ if (!writeData.empty())
+ {
+ msg[msgIndex].addr = deviceNode;
+ msg[msgIndex].flags = 0;
+ msg[msgIndex].len = writeData.size();
+ msg[msgIndex].buf = const_cast<uint8_t*>(writeData.data());
+ msgIndex++;
+ }
+
+ if (!readData.empty())
+ {
+ msg[msgIndex].addr = deviceNode;
+ msg[msgIndex].flags = I2C_M_RD;
+ msg[msgIndex].len = readData.size();
+ msg[msgIndex].buf = readData.data();
+ msgIndex++;
+ }
+
+ readWriteData.msgs = msg;
+ readWriteData.nmsgs = msgIndex;
+
+ if (ioctl(fd, I2C_RDWR, &readWriteData) < 0)
+ {
+ result = false;
+ }
+ }
+
+ return result;
+}
+
int I2C::close() const
{
return ::close(fd);
diff --git a/common/include/i2c/i2c.hpp b/common/include/i2c/i2c.hpp
index e86d574..d230ef7 100644
--- a/common/include/i2c/i2c.hpp
+++ b/common/include/i2c/i2c.hpp
@@ -42,6 +42,8 @@
sdbusplus::async::task<bool> sendReceive(
uint8_t* writeData, uint8_t writeSize, uint8_t* readData,
uint8_t readSize) const;
+ bool sendReceive(const std::vector<uint8_t>& writeData,
+ std::vector<uint8_t>& readData) const;
bool isOpen() const
{
diff --git a/cpld/cpld_software_manager.cpp b/cpld/cpld_software_manager.cpp
index faf14a5..6303135 100644
--- a/cpld/cpld_software_manager.cpp
+++ b/cpld/cpld_software_manager.cpp
@@ -16,17 +16,14 @@
std::string configIface =
"xyz.openbmc_project.Configuration." + config.configType;
- std::optional<uint64_t> busNo = co_await dbusGetRequiredProperty<uint64_t>(
+ auto busNo = co_await dbusGetRequiredProperty<uint64_t>(
ctx, service, path, configIface, "Bus");
- std::optional<uint64_t> address =
- co_await dbusGetRequiredProperty<uint64_t>(ctx, service, path,
- configIface, "Address");
- std::optional<std::string> chipType =
- co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
- configIface, "Type");
- std::optional<std::string> chipName =
- co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
- configIface, "Name");
+ auto address = co_await dbusGetRequiredProperty<uint64_t>(
+ ctx, service, path, configIface, "Address");
+ auto chipType = co_await dbusGetRequiredProperty<std::string>(
+ ctx, service, path, configIface, "Type");
+ auto chipName = co_await dbusGetRequiredProperty<std::string>(
+ ctx, service, path, configIface, "Name");
if (!busNo.has_value() || !address.has_value() || !chipType.has_value() ||
!chipName.has_value())
diff --git a/cpld/lattice/lattice.cpp b/cpld/lattice/lattice.cpp
index ce70fa3..48e2479 100644
--- a/cpld/lattice/lattice.cpp
+++ b/cpld/lattice/lattice.cpp
@@ -8,8 +8,6 @@
#include <thread>
#include <vector>
-using sdbusplus::async::details::context_friend;
-
constexpr uint8_t busyWaitmaxRetry = 30;
constexpr uint8_t busyFlagBit = 0x80;
constexpr std::chrono::milliseconds waitBusyTime(200);
@@ -73,6 +71,14 @@
return static_cast<int>(pos2 - pos1 - 1);
}
+std::string uint32ToHexStr(uint32_t value)
+{
+ std::ostringstream oss;
+ oss << std::setfill('0') << std::setw(8) << std::hex << std::uppercase
+ << value;
+ return oss.str();
+}
+
bool CpldLatticeManager::jedFileParser()
{
bool cfStart = false;
@@ -332,13 +338,12 @@
sdbusplus::async::task<bool> CpldLatticeManager::readDeviceId()
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandReadDeviceId, 0x0, 0x0, 0x0};
+ std::vector<uint8_t> request = {commandReadDeviceId, 0x0, 0x0, 0x0};
constexpr size_t resSize = 4;
std::vector<uint8_t> readData(resSize, 0);
- bool success = co_await stdexec::starts_on(
- sched, i2cInterface.sendReceive(command.data(), command.size(),
- readData.data(), resSize));
+ bool success = co_await i2cInterface.sendReceive(
+ request.data(), request.size(), readData.data(), resSize);
+
if (!success)
{
lg2::error(
@@ -377,14 +382,12 @@
sdbusplus::async::task<bool> CpldLatticeManager::enableProgramMode()
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandEnableConfigMode, 0x08, 0x0, 0x0};
- bool success = co_await stdexec::starts_on(
- sched,
- i2cInterface.sendReceive(command.data(), command.size(), nullptr, 0));
+ std::vector<uint8_t> request = {commandEnableConfigMode, 0x08, 0x0, 0x0};
+ std::vector<uint8_t> response;
- if (!success)
+ if (!i2cInterface.sendReceive(request, response))
{
+ lg2::error("Failed to send enable program mode request.");
co_return false;
}
@@ -399,8 +402,8 @@
sdbusplus::async::task<bool> CpldLatticeManager::eraseFlash()
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command;
+ std::vector<uint8_t> request;
+ std::vector<uint8_t> response;
if (isLCMXO3D)
{
@@ -426,11 +429,11 @@
*/
if (target.empty() || target == "CFG0")
{
- command = {commandEraseFlash, 0x00, 0x01, 0x00};
+ request = {commandEraseFlash, 0x00, 0x01, 0x00};
}
else if (target == "CFG1")
{
- command = {commandEraseFlash, 0x00, 0x02, 0x00};
+ request = {commandEraseFlash, 0x00, 0x02, 0x00};
}
else
{
@@ -440,14 +443,12 @@
}
else
{
- command = {commandEraseFlash, 0xC, 0x0, 0x0};
+ request = {commandEraseFlash, 0xC, 0x0, 0x0};
}
- bool success = co_await stdexec::starts_on(
- sched,
- i2cInterface.sendReceive(command.data(), command.size(), nullptr, 0));
- if (!success)
+ if (!i2cInterface.sendReceive(request, response))
{
+ lg2::error("Failed to send erase flash request.");
co_return false;
}
@@ -462,8 +463,8 @@
sdbusplus::async::task<bool> CpldLatticeManager::resetConfigFlash()
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command;
+ std::vector<uint8_t> request;
+ std::vector<uint8_t> response;
if (isLCMXO3D)
{
/*
@@ -491,11 +492,11 @@
*/
if (target.empty() || target == "CFG0")
{
- command = {commandResetConfigFlash, 0x00, 0x01, 0x00};
+ request = {commandResetConfigFlash, 0x00, 0x01, 0x00};
}
else if (target == "CFG1")
{
- command = {commandResetConfigFlash, 0x00, 0x02, 0x00};
+ request = {commandResetConfigFlash, 0x00, 0x02, 0x00};
}
else
{
@@ -506,12 +507,10 @@
}
else
{
- command = {commandResetConfigFlash, 0x0, 0x0, 0x0};
+ request = {commandResetConfigFlash, 0x0, 0x0, 0x0};
}
- co_return co_await stdexec::starts_on(
- sched,
- i2cInterface.sendReceive(command.data(), command.size(), nullptr, 0));
+ co_return i2cInterface.sendReceive(request, response);
}
sdbusplus::async::task<bool> CpldLatticeManager::writeProgramPage()
@@ -521,8 +520,8 @@
used to program the NVCM0/CFG or
NVCM1/UFM.
*/
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandProgramPage, 0x0, 0x0, 0x01};
+ std::vector<uint8_t> request = {commandProgramPage, 0x0, 0x0, 0x01};
+ std::vector<uint8_t> response;
size_t iterSize = 16;
for (size_t i = 0; i < fwInfo.cfgData.size(); i += iterSize)
@@ -535,17 +534,16 @@
uint8_t len = ((i + iterSize) < fwInfo.cfgData.size())
? iterSize
: (fwInfo.cfgData.size() - i);
- std::vector<uint8_t> data = command;
+ std::vector<uint8_t> data = request;
data.insert(
data.end(), fwInfo.cfgData.begin() + static_cast<std::ptrdiff_t>(i),
fwInfo.cfgData.begin() + static_cast<std::ptrdiff_t>(i + len));
- bool success = co_await stdexec::starts_on(
- sched,
- i2cInterface.sendReceive(data.data(), data.size(), nullptr, 0));
- if (!success)
+ if (!i2cInterface.sendReceive(data, response))
{
+ lg2::error("Failed to send program page request. {CURRENT}",
+ "CURRENT", uint32ToHexStr(i));
co_return false;
}
@@ -570,21 +568,18 @@
sdbusplus::async::task<bool> CpldLatticeManager::programUserCode()
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandProgramUserCode, 0x0, 0x0, 0x0};
+ std::vector<uint8_t> request = {commandProgramUserCode, 0x0, 0x0, 0x0};
+ std::vector<uint8_t> response;
for (int i = 3; i >= 0; i--)
{
- command.push_back((fwInfo.version >> (i * 8)) & 0xFF);
+ request.push_back((fwInfo.version >> (i * 8)) & 0xFF);
}
- bool success = co_await stdexec::starts_on(
- sched,
- i2cInterface.sendReceive(command.data(), command.size(), nullptr, 0));
- if (!success)
+ if (!i2cInterface.sendReceive(request, response))
{
+ lg2::error("Failed to send program user code request.");
co_return false;
}
-
if (!(co_await waitBusyAndVerify()))
{
lg2::error("Wait busy and verify fail");
@@ -596,16 +591,15 @@
sdbusplus::async::task<bool> CpldLatticeManager::programDone()
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandProgramDone, 0x0, 0x0, 0x0};
- bool success = co_await stdexec::starts_on(
- sched,
- i2cInterface.sendReceive(command.data(), command.size(), nullptr, 0));
+ std::vector<uint8_t> request = {commandProgramDone, 0x0, 0x0, 0x0};
+ std::vector<uint8_t> response;
- if (!success)
+ if (!i2cInterface.sendReceive(request, response))
{
+ lg2::error("Failed to send program done request.");
co_return false;
}
+
if (!(co_await waitBusyAndVerify()))
{
lg2::error("Wait busy and verify fail");
@@ -617,14 +611,9 @@
sdbusplus::async::task<bool> CpldLatticeManager::disableConfigInterface()
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandDisableConfigInterface, 0x0, 0x0};
-
- bool success = co_await stdexec::starts_on(
- sched,
- i2cInterface.sendReceive(command.data(), command.size(), nullptr, 0));
-
- co_return success;
+ std::vector<uint8_t> request = {commandDisableConfigInterface, 0x0, 0x0};
+ std::vector<uint8_t> response;
+ co_return i2cInterface.sendReceive(request, response);
}
sdbusplus::async::task<bool> CpldLatticeManager::waitBusyAndVerify()
@@ -635,7 +624,8 @@
{
uint8_t busyFlag = 0xff;
- if (!(co_await readBusyFlag(busyFlag)))
+ auto readBusyFlagResult = co_await readBusyFlag(busyFlag);
+ if (!readBusyFlagResult)
{
lg2::error("Fail to read busy flag.");
co_return false;
@@ -659,16 +649,16 @@
} // while loop busy check
// Check out status reg
- uint8_t statusReg = 0xff;
+ auto statusReg = std::make_unique<uint8_t>(0xff);
- if (!(co_await readStatusReg(statusReg)))
+ if (!(co_await readStatusReg(*statusReg)))
{
lg2::error("Fail to read status register.");
co_return false;
}
- if (((statusReg >> busyOrReadyBit) & 1) == isReady &&
- ((statusReg >> failOrOKBit) & 1) == isOK)
+ if (((*statusReg >> busyOrReadyBit) & 1) == isReady &&
+ ((*statusReg >> failOrOKBit) & 1) == isOK)
{
lg2::debug("Status Reg : OK");
co_return true;
@@ -680,35 +670,28 @@
sdbusplus::async::task<bool> CpldLatticeManager::readBusyFlag(uint8_t& busyFlag)
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandReadBusyFlag, 0x0, 0x0, 0x0};
constexpr size_t resSize = 1;
- std::vector<uint8_t> readData(resSize, 0);
- bool success = co_await stdexec::starts_on(
- sched, i2cInterface.sendReceive(command.data(), command.size(),
- readData.data(), resSize));
+ std::vector<uint8_t> request = {commandReadBusyFlag, 0x0, 0x0, 0x0};
+ std::vector<uint8_t> response(resSize, 0);
- if (!success || (readData.size() != resSize))
+ auto success = i2cInterface.sendReceive(request, response);
+ if (!success && response.size() != resSize)
{
co_return false;
}
- busyFlag = readData.at(0);
+ busyFlag = response.at(0);
co_return true;
}
sdbusplus::async::task<bool> CpldLatticeManager::readStatusReg(
uint8_t& statusReg)
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandReadStatusReg, 0x0, 0x0, 0x0};
- constexpr size_t resSize = 4;
- std::vector<uint8_t> readData(resSize, 0);
- bool success = co_await stdexec::starts_on(
- sched, i2cInterface.sendReceive(command.data(), command.size(),
- readData.data(), resSize));
+ std::vector<uint8_t> request = {commandReadStatusReg, 0x0, 0x0, 0x0};
+ std::vector<uint8_t> response(4, 0);
- if (!success || (readData.size() != resSize))
+ if (!i2cInterface.sendReceive(request, response))
{
+ lg2::error("Failed to send read status register request.");
co_return false;
}
/*
@@ -717,30 +700,27 @@
0x3C 00 00 00 N/A YY YY YY YY Bit 1 0
12 Busy Ready
13 Fail OK
- */
- statusReg = readData.at(2);
+ */
+ statusReg = response.at(2);
co_return true;
}
sdbusplus::async::task<bool> CpldLatticeManager::readUserCode(
uint32_t& userCode)
{
- auto sched = context_friend::get_scheduler(ctx);
- std::vector<uint8_t> command = {commandReadFwVersion, 0x0, 0x0, 0x0};
constexpr size_t resSize = 4;
- std::vector<uint8_t> readData(resSize, 0);
- bool success = co_await stdexec::starts_on(
- sched, i2cInterface.sendReceive(command.data(), command.size(),
- readData.data(), resSize));
+ std::vector<uint8_t> request = {commandReadFwVersion, 0x0, 0x0, 0x0};
+ std::vector<uint8_t> response(resSize, 0);
- if (!success)
+ if (!i2cInterface.sendReceive(request, response))
{
+ lg2::error("Failed to send read user code request.");
co_return false;
}
for (size_t i = 0; i < resSize; i++)
{
- userCode |= readData.at(i) << ((3 - i) * 8);
+ userCode |= response.at(i) << ((3 - i) * 8);
}
co_return true;
}
@@ -856,28 +836,20 @@
co_return false;
}
-std::string uint32ToHexStr(uint32_t value)
-{
- std::ostringstream oss;
- oss << std::setfill('0') << std::setw(8) << std::hex << std::uppercase
- << value;
- return oss.str();
-}
-
sdbusplus::async::task<bool> CpldLatticeManager::getVersion(
std::string& version)
{
- uint32_t userCode = 0;
+ auto userCode = std::make_unique<uint32_t>(0);
if (target.empty())
{
- if (!(co_await readUserCode(userCode)))
+ if (!(co_await readUserCode(*userCode)))
{
lg2::error("Read usercode failed.");
co_return false;
}
- lg2::debug("CPLD version: {VERSION}", "VERSION", userCode);
+ lg2::debug("CPLD version: {VERSION}", "VERSION", *userCode);
}
else if (target == "CFG0" || target == "CFG1")
{
@@ -896,7 +868,7 @@
co_return false;
}
- if (!(co_await readUserCode(userCode)))
+ if (!(co_await readUserCode(*userCode)))
{
lg2::error("Read usercode failed.");
co_return false;
@@ -915,7 +887,7 @@
}
lg2::debug("CPLD {TARGET} version: {VERSION}", "TARGET", target,
- "VERSION", userCode);
+ "VERSION", *userCode);
}
else
{
@@ -923,11 +895,11 @@
co_return false;
}
- if (userCode == 0)
+ if (*userCode == 0)
{
lg2::error("User code is zero, cannot get version.");
co_return false;
}
- version = uint32ToHexStr(userCode);
+ version = uint32ToHexStr(*userCode);
co_return true;
}