patch 'ethdev: fix SFF-8472 calibration overflow' has been queued to stable release 24.11.9
luca.boccassi at gmail.com
luca.boccassi at gmail.com
Tue Oct 27 12:50:31 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/d22e3be411745241d8cda82c7f624f95507d72ee
Thanks.
Luca Boccassi
---
>From d22e3be411745241d8cda82c7f624f95507d72ee Mon Sep 17 00:00:00 2001
From: Roman Khromenok <roma55592 at yandex.ru>
Date: Fri, 2 Oct 2026 14:52:35 +0200
Subject: [PATCH] ethdev: fix SFF-8472 calibration overflow
[ upstream commit 3217d3e4a9f58b8c898bed4060da905ffb80e83b ]
With external calibration, SFF-8472 computes temperature, voltage,
TX bias and TX power as slope * x + offset, where the slope goes up
to 255.996 and the offset is a signed 16-bit integer.
The decoder multiplied the 16-bit fields in place by the slope and
then added the offset. A result out of the field range is undefined
behavior for the float to integer conversion, and an integer sum
below zero wraps around: a bias reading of 100 with an offset of
-1000 was reported as 129.272 mA.
Compute the formula in double precision and saturate the result
to the range of the field, as already done for the RX power.
Add a test checking that externally calibrated SFF-8472 values
out of the range of their 16-bit fields saturate at both ends,
for formula 1 (temperature, voltage, TX bias and TX power)
and for the Rx power polynomial.
Fixes: 0caf7f376b08 ("ethdev: support SFF-8472 module telemetry")
Signed-off-by: Roman Khromenok <roma55592 at yandex.ru>
---
lib/ethdev/sff_8472.c | 51 ++++++++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 17 deletions(-)
diff --git a/lib/ethdev/sff_8472.c b/lib/ethdev/sff_8472.c
index 5ffe32aca8e..aa702cd74f1 100644
--- a/lib/ethdev/sff_8472.c
+++ b/lib/ethdev/sff_8472.c
@@ -180,6 +180,25 @@ static float befloattoh(const uint32_t *source)
return converter.dst;
}
+/* Calibrated values are stored in 16-bit fields, saturate the out of range ones */
+static uint16_t sff_8472_cal_to_u16(double value)
+{
+ if (!(value > 0))
+ return 0;
+ if (value >= UINT16_MAX)
+ return UINT16_MAX;
+ return value;
+}
+
+static int16_t sff_8472_cal_to_s16(double value)
+{
+ if (value <= INT16_MIN)
+ return INT16_MIN;
+ if (value >= INT16_MAX)
+ return INT16_MAX;
+ return value;
+}
+
static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
{
unsigned long i;
@@ -189,17 +208,21 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
/* Calibration should occur for all values (threshold and current) */
for (i = 0; i < RTE_DIM(sd->bias_cur); ++i) {
/*
- * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power)
+ * Apply calibration formula 1 (Temp., Voltage, Bias, Tx Power):
+ * slope * x + offset
*/
- sd->bias_cur[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP);
- sd->tx_power[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP);
- sd->sfp_voltage[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP);
- sd->sfp_temp[i] *= A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP);
-
- sd->bias_cur[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF);
- sd->tx_power[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF);
- sd->sfp_voltage[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF);
- sd->sfp_temp[i] += A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF);
+ sd->bias_cur[i] = sff_8472_cal_to_u16(sd->bias_cur[i] *
+ A2_OFFSET_TO_SLP(SFF_A2_CAL_TXI_SLP) +
+ A2_OFFSET_TO_OFF(SFF_A2_CAL_TXI_OFF));
+ sd->tx_power[i] = sff_8472_cal_to_u16(sd->tx_power[i] *
+ A2_OFFSET_TO_SLP(SFF_A2_CAL_TXPWR_SLP) +
+ A2_OFFSET_TO_OFF(SFF_A2_CAL_TXPWR_OFF));
+ sd->sfp_voltage[i] = sff_8472_cal_to_u16(sd->sfp_voltage[i] *
+ A2_OFFSET_TO_SLP(SFF_A2_CAL_V_SLP) +
+ A2_OFFSET_TO_OFF(SFF_A2_CAL_V_OFF));
+ sd->sfp_temp[i] = sff_8472_cal_to_s16(sd->sfp_temp[i] *
+ A2_OFFSET_TO_SLP(SFF_A2_CAL_T_SLP) +
+ A2_OFFSET_TO_OFF(SFF_A2_CAL_T_OFF));
/*
* Apply calibration formula 2 (Rx Power only):
@@ -213,13 +236,7 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
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;
+ sd->rx_power[i] = sff_8472_cal_to_u16(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.973944059 +0000
+++ 0137-ethdev-fix-SFF-8472-calibration-overflow.patch 2026-10-27 11:43:53.662064030 +0000
@@ -1 +1 @@
-From 3217d3e4a9f58b8c898bed4060da905ffb80e83b Mon Sep 17 00:00:00 2001
+From d22e3be411745241d8cda82c7f624f95507d72ee Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit 3217d3e4a9f58b8c898bed4060da905ffb80e83b ]
+
@@ -25 +26,0 @@
-Cc: stable at dpdk.org
@@ -29,97 +30,3 @@
- app/test/test_ethdev_module_eeprom.c | 75 ++++++++++++++++++++++++++++
- lib/ethdev/sff_8472.c | 51 ++++++++++++-------
- 2 files changed, 109 insertions(+), 17 deletions(-)
-
-diff --git a/app/test/test_ethdev_module_eeprom.c b/app/test/test_ethdev_module_eeprom.c
-index b07a18aa06..13e5614a17 100644
---- a/app/test/test_ethdev_module_eeprom.c
-+++ b/app/test/test_ethdev_module_eeprom.c
-@@ -305,6 +305,79 @@ test_module_eeprom_sfp_8472_rx_power_polynomial(void)
- return TEST_SUCCESS;
- }
-
-+/* SFF-8472 module externally calibrated with unit slopes and zero offsets */
-+static void
-+fill_sfp_ext_cal(uint8_t *data)
-+{
-+ 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_be_float(a2, 68, 0x3f800000); /* RX_PWR(1) = 1.0 */
-+}
-+
-+static int
-+test_module_eeprom_sfp_8472_cal_saturate_max(void)
-+{
-+ uint8_t data[RTE_ETH_MODULE_SFF_8472_LEN];
-+ uint8_t *a2 = data + RTE_ETH_MODULE_SFF_8079_LEN;
-+
-+ fill_sfp_ext_cal(data);
-+ /* results above the 16-bit range must saturate */
-+ put_u16(a2, 100, 65535); /* raw TX bias */
-+ put_u16(a2, 76, 0xffff); /* TX bias slope = 255.996 */
-+ put_u16(a2, 102, 60000); /* raw TX power */
-+ put_u16(a2, 82, 10000); /* TX power offset */
-+ put_u16(a2, 96, 0x7f00); /* raw temperature: 127 C */
-+ put_u16(a2, 84, 0x0200); /* temperature slope = 2.0 */
-+ put_u16(a2, 98, 60000); /* raw voltage */
-+ put_u16(a2, 90, 10000); /* voltage offset */
-+ put_u16(a2, 104, 65535); /* raw RX power */
-+ put_be_float(a2, 56, 0x3f800000); /* RX_PWR(4) = 1.0 */
-+
-+ TEST_ASSERT_SUCCESS(parse(RTE_ETH_MODULE_SFF_8472, data, sizeof(data)),
-+ "Failed to parse externally calibrated SFF-8472 data");
-+ CHECK_FIELD("Laser bias current", "131.070 mA");
-+ CHECK_FIELD("Laser output power", "6.5535 mW / 8.16 dBm");
-+ CHECK_FIELD("Module temperature", "128.00 degrees C / 262.39 degrees F");
-+ CHECK_FIELD("Module voltage", "6.5535 V");
-+ CHECK_FIELD("Receiver signal average optical power", "6.5535 mW / 8.16 dBm");
-+ return TEST_SUCCESS;
-+}
-+
-+static int
-+test_module_eeprom_sfp_8472_cal_saturate_min(void)
-+{
-+ uint8_t data[RTE_ETH_MODULE_SFF_8472_LEN];
-+ uint8_t *a2 = data + RTE_ETH_MODULE_SFF_8079_LEN;
-+
-+ fill_sfp_ext_cal(data);
-+ /* results below the 16-bit range must saturate */
-+ put_u16(a2, 100, 100); /* raw TX bias */
-+ put_u16(a2, 78, -1000); /* TX bias offset */
-+ put_u16(a2, 102, 100); /* raw TX power */
-+ put_u16(a2, 82, -1000); /* TX power offset */
-+ put_u16(a2, 96, 0x8100); /* raw temperature: -127 C */
-+ put_u16(a2, 84, 0x0200); /* temperature slope = 2.0 */
-+ put_u16(a2, 98, 100); /* raw voltage */
-+ put_u16(a2, 90, -1000); /* voltage offset */
-+ put_be_float(a2, 68, 0xbf800000); /* RX_PWR(1) = -1.0 */
-+
-+ TEST_ASSERT_SUCCESS(parse(RTE_ETH_MODULE_SFF_8472, data, sizeof(data)),
-+ "Failed to parse externally calibrated SFF-8472 data");
-+ CHECK_FIELD("Laser bias current", "0.000 mA");
-+ CHECK_FIELD("Laser output power", "0.0000 mW / -inf dBm");
-+ CHECK_FIELD("Module temperature", "-128.00 degrees C / -198.40 degrees F");
-+ CHECK_FIELD("Module voltage", "0.0000 V");
-+ CHECK_FIELD("Receiver signal average optical power", "0.0000 mW / -inf dBm");
-+ return TEST_SUCCESS;
-+}
-+
- static int
- test_module_eeprom_invalid(void)
- {
-@@ -355,6 +428,8 @@ static struct unit_test_suite module_eeprom_testsuite = {
- 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_sfp_8472_cal_saturate_max),
-+ TEST_CASE(test_module_eeprom_sfp_8472_cal_saturate_min),
- 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 | 51 ++++++++++++++++++++++++++++---------------
+ 1 file changed, 34 insertions(+), 17 deletions(-)
+
@@ -127 +34 @@
-index 3c73a829a8..8cd41161e3 100644
+index 5ffe32aca8e..aa702cd74f1 100644
@@ -130 +37 @@
-@@ -186,6 +186,25 @@ static float befloattoh(const uint8_t *source)
+@@ -180,6 +180,25 @@ static float befloattoh(const uint32_t *source)
@@ -156 +63 @@
-@@ -195,17 +214,21 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
+@@ -189,17 +208,21 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
@@ -188 +95 @@
-@@ -219,13 +242,7 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
+@@ -213,13 +236,7 @@ static void sff_8472_calibration(const uint8_t *data, struct sff_diags *sd)
More information about the stable
mailing list