Add delay between frame send retries
Introduced a delay between retries to allow the bus to stabilize
and ongoing transactions to complete. The delay increases
exponentially, calculated as 30 ms multiplied by 2 raised to the
power of the number of retries.
Change-Id: Ibbfd202118a69c270cbb4f047ef44f15ebf72bd6
Signed-off-by: Cosmo Chou <cosmo.chou@quantatw.com>
diff --git a/ipmbbridged.cpp b/ipmbbridged.cpp
index a2bcf6b..d33e28c 100644
--- a/ipmbbridged.cpp
+++ b/ipmbbridged.cpp
@@ -284,8 +284,27 @@
msgToLog.c_str());
return;
}
- currentRetryCnt++;
- ipmbSendI2cFrame(buffer, currentRetryCnt);
+ scheduleFrameResend(buffer, currentRetryCnt);
+ }
+ });
+}
+
+void IpmbChannel::scheduleFrameResend(
+ std::shared_ptr<std::vector<uint8_t>> buffer, size_t retryCount)
+{
+ // SMBus timeout: 30 ms (spec range 25-35 ms)
+ static constexpr size_t resendDelay = 30;
+
+ // Delay increases exponentially with 30 ms multiplied by 2 raised
+ // to the power of retries, e.g.
+ // 1st retry: 30 ms, 2nd: 60 ms, 3rd: 120 ms ...
+ retryTimer.expires_after(
+ std::chrono::milliseconds(resendDelay * (1 << retryCount)));
+ retryTimer.async_wait(
+ [this, buffer, retryCount](const boost::system::error_code& ec) {
+ if (!ec)
+ {
+ ipmbSendI2cFrame(buffer, retryCount + 1);
}
});
}
@@ -527,7 +546,8 @@
uint8_t ipmbBmcTargetAddress,
uint8_t ipmbRqTargetAddress, uint8_t channelIdx,
std::shared_ptr<IpmbCommandFilter> commandFilter) :
- i2cTargetDescriptor(io), ipmbBmcTargetAddress(ipmbBmcTargetAddress),
+ i2cTargetDescriptor(io), retryTimer(io),
+ ipmbBmcTargetAddress(ipmbBmcTargetAddress),
ipmbRqTargetAddress(ipmbRqTargetAddress), channelIdx(channelIdx),
commandFilter(commandFilter)
{}
diff --git a/ipmbbridged.hpp b/ipmbbridged.hpp
index b8f708a..6805efc 100644
--- a/ipmbbridged.hpp
+++ b/ipmbbridged.hpp
@@ -300,6 +300,7 @@
private:
boost::asio::posix::stream_descriptor i2cTargetDescriptor;
+ boost::asio::steady_timer retryTimer;
int ipmbi2cTargetFd;
@@ -322,6 +323,9 @@
void makeRequestInvalid(IpmbRequest& request);
void makeRequestValid(std::shared_ptr<IpmbRequest> request);
+
+ void scheduleFrameResend(std::shared_ptr<std::vector<uint8_t>> buffer,
+ size_t retryCount);
};
/**