patch 'ethdev: fix SFF-8472 external Rx power calibration' has been queued to stable release 24.11.9
luca.boccassi at gmail.com
luca.boccassi at gmail.com
Tue Oct 27 12:50:30 CET 2026
Hi,
FYI, your patch has been queued to stable release 24.11.9
Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 10/29/26. So please
shout if anyone has objections.
Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.
Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable
This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/3fd839993931215eb754ac89926496fa72173a45
Thanks.
Luca Boccassi
---
>From 3fd839993931215eb754ac89926496fa72173a45 Mon Sep 17 00:00:00 2001
From: Roman Khromenok <roma55592 at yandex.ru>
Date: Tue, 29 Sep 2026 19:22:09 +0200
Subject: [PATCH] ethdev: fix SFF-8472 external Rx power calibration
[ upstream commit a6a8a58961040b7a32df831373d793355e980b52 ]
With external calibration, SFF-8472 defines the received power
as a fourth order polynomial of the raw reading x:
RX_PWR(4) * x^4 + RX_PWR(3) * x^3 + RX_PWR(2) * x^2 +
RX_PWR(1) * x + RX_PWR(0)
The decoder computed RX_PWR(0) + x * (RX_PWR(1) + RX_PWR(2) + RX_PWR(3))
and ignored RX_PWR(4), so the reported power was wrong for modules
using the higher order coefficients.
Evaluate the polynomial in double precision and clamp the result
to the 16-bit range of the stored value, as converting an out of range
floating point value to an integer is undefined behavior.
Add a test case with all the SFF-8472 Rx power calibration
coefficients set, so that the whole fourth order polynomial
is checked, including RX_PWR(4).
Fixes: 0caf7f376b08 ("ethdev: support SFF-8472 module telemetry")
Signed-off-by: Roman Khromenok <roma55592 at yandex.ru>
---
lib/ethdev/sff_8472.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c
index 97f231854cf..5ffe32aca8e 100644
--- a/lib/ethdev/sff_8472.c
+++ b/lib/ethdev/sff_8472.c
@@ -183,7 +183,8 @@ static float befloattoh(const uint32_t *source)
static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
{
unsigned long i;
- uint16_t rx_reading;
+ double rx_reading;
+ double rx_power;
/* Calibration should occur for all values (threshold and current) */
for (i = 0; i < RTE_DIM(sd->bias_cur); ++i) {
@@ -201,16 +202,24 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF);
/*
- * Apply calibration formula 2 (Rx Power only)
+ * Apply calibration formula 2 (Rx Power only):
+ * RX_PWR(4) * x^4 + RX_PWR(3) * x^3 + RX_PWR(2) * x^2 +
+ * RX_PWR(1) * x + RX_PWR(0)
*/
rx_reading = sd->rx_power[i];
- sd->rx_power[i] = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0);
- sd->rx_power[i] += rx_reading *
- A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1);
- sd->rx_power[i] += rx_reading *
- A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2);
- sd->rx_power[i] += rx_reading *
- A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3);
+ rx_power = A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR4);
+ rx_power = rx_power * rx_reading + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR3);
+ rx_power = rx_power * rx_reading + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR2);
+ rx_power = rx_power * rx_reading + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR1);
+ rx_power = rx_power * rx_reading + A2_OFFSET_TO_RXPWRx(SFF_A2_CAL_RXPWR0);
+
+ /* the result is stored in 0.1 uW units, out of range is not representable */
+ if (!(rx_power > 0))
+ sd->rx_power[i] = 0;
+ else if (rx_power >= UINT16_MAX)
+ sd->rx_power[i] = UINT16_MAX;
+ else
+ sd->rx_power[i] = rx_power;
}
}
--
2.47.3
---
Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- - 2026-10-27 11:43:58.938622003 +0000
+++ 0136-ethdev-fix-SFF-8472-external-Rx-power-calibration.patch 2026-10-27 11:43:53.662064030 +0000
@@ -1 +1 @@
-From a6a8a58961040b7a32df831373d793355e980b52 Mon Sep 17 00:00:00 2001
+From 3fd839993931215eb754ac89926496fa72173a45 Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit a6a8a58961040b7a32df831373d793355e980b52 ]
+
@@ -25 +26,0 @@
-Cc: stable at dpdk.org
@@ -29,59 +30,3 @@
- app/test/test_ethdev_module_eeprom.c | 37 ++++++++++++++++++++++++++++
- lib/ethdev/sff_8472.c | 27 +++++++++++++-------
- 2 files changed, 55 insertions(+), 9 deletions(-)
-
-diff --git a/app/test/test_ethdev_module_eeprom.c b/app/test/test_ethdev_module_eeprom.c
-index d76bdc0060..b07a18aa06 100644
---- a/app/test/test_ethdev_module_eeprom.c
-+++ b/app/test/test_ethdev_module_eeprom.c
-@@ -269,6 +269,42 @@ test_module_eeprom_sfp_8472_ext_cal_unaligned(void)
- return TEST_SUCCESS;
- }
-
-+static void
-+put_be_float(uint8_t *data, unsigned int offset, uint32_t bits)
-+{
-+ data[offset] = bits >> 24;
-+ data[offset + 1] = (bits >> 16) & 0xff;
-+ data[offset + 2] = (bits >> 8) & 0xff;
-+ data[offset + 3] = bits & 0xff;
-+}
-+
-+static int
-+test_module_eeprom_sfp_8472_rx_power_polynomial(void)
-+{
-+ uint8_t data[RTE_ETH_MODULE_SFF_8472_LEN];
-+ uint8_t *a2 = data + RTE_ETH_MODULE_SFF_8079_LEN;
-+
-+ fill_sfp(data);
-+ /* diagnostics implemented, externally calibrated, average RX power */
-+ data[92] = 0x58;
-+ a2[76] = 1; /* TX bias slope */
-+ a2[80] = 1; /* TX power slope */
-+ a2[84] = 1; /* temperature slope */
-+ a2[88] = 1; /* voltage slope */
-+ put_u16(a2, 104, 10); /* raw RX power x = 10 */
-+ /* 0.125 x^4 + 0.25 x^3 + 0.5 x^2 + x = 1250 + 250 + 50 + 10 = 1560 */
-+ put_be_float(a2, 56, 0x3e000000); /* RX_PWR(4) = 0.125 */
-+ put_be_float(a2, 60, 0x3e800000); /* RX_PWR(3) = 0.25 */
-+ put_be_float(a2, 64, 0x3f000000); /* RX_PWR(2) = 0.5 */
-+ put_be_float(a2, 68, 0x3f800000); /* RX_PWR(1) = 1.0 */
-+ put_be_float(a2, 72, 0); /* RX_PWR(0) = 0 */
-+
-+ TEST_ASSERT_SUCCESS(parse(RTE_ETH_MODULE_SFF_8472, data, sizeof(data)),
-+ "Failed to parse externally calibrated SFF-8472 data");
-+ CHECK_FIELD("Receiver signal average optical power", "0.1560 mW / -8.07 dBm");
-+ return TEST_SUCCESS;
-+}
-+
- static int
- test_module_eeprom_invalid(void)
- {
-@@ -318,6 +354,7 @@ static struct unit_test_suite module_eeprom_testsuite = {
- TEST_CASE(test_module_eeprom_sfp_8472),
- TEST_CASE(test_module_eeprom_sfp_8472_short),
- TEST_CASE(test_module_eeprom_sfp_8472_ext_cal_unaligned),
-+ TEST_CASE(test_module_eeprom_sfp_8472_rx_power_polynomial),
- TEST_CASE(test_module_eeprom_qsfp_8636),
- TEST_CASE(test_module_eeprom_qsfp_8636_thresholds),
- TEST_CASE(test_module_eeprom_invalid),
+ lib/ethdev/sff_8472.c | 27 ++++++++++++++++++---------
+ 1 file changed, 18 insertions(+), 9 deletions(-)
+
@@ -89 +34 @@
-index cdb6ef1f7e..3c73a829a8 100644
+index 97f231854cf..5ffe32aca8e 100644
@@ -92 +37 @@
-@@ -189,7 +189,8 @@ static float befloattoh(const uint8_t *source)
+@@ -183,7 +183,8 @@ static float befloattoh(const uint32_t *source)
@@ -102 +47 @@
-@@ -207,16 +208,24 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
+@@ -201,16 +202,24 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
More information about the stable
mailing list