[PATCH] media: i2c: max96717: fix bitfield overflow in pinconf setter

From: ZhangDM-520

Date: Thu Nov 05 2026 - 16:29:22 EST


max96717_conf_pin_config_set_one() inverted the single-bit enable value
with a bitwise NOT, so disabling a pin passed ~en_val to field_prep().
For a one-bit field that value is 0xfffffffe or 0xffffffff, which no
longer fits the mask:

field_prep: value too large for the field

The runtime shift masks the high bits, so a plain build is fine. Once
max96717_get_pin_config_reg() is inlined and both mask and en_val are
constant folded - which ThinLTO with an AutoFDO profile does - the
__BF_FIELD_CHECK_MASK() assertion in include/linux/bitfield.h fires and
the build dies in ld.lld:

ld.lld: error: call to __compiletime_assert_550 marked
"dontcall-error": field_prep: value too large for the field

Use logical NOT instead. All masks reaching this branch are single-bit
(GPIO_OUT_DIS, TX_EN, RX_EN, GPIO_OUT, TX_COMP_EN, RES_CFG), so the
resulting field value is identical at runtime and fits the field at
compile time.

Fixes: ea15bcd94f0f ("media: i2c: maxim-serdes: add MAX96717 driver")

Signed-off-by: ZhangDM-520 <jixianqiang1540@xxxxxxxxx>

---
drivers/media/i2c/maxim-serdes/max96717.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

The failure needs a profile-guided or IPO build that folds
max96717_get_pin_config_reg() into its caller; it was hit by a distro kernel
built with CONFIG_AUTOFDO_CLANG and ThinLTO.

Reproducer:

make O=/tmp/afdo LLVM=1 defconfig
./scripts/config --file /tmp/afdo/.config \
-e MEDIA_SUPPORT -e MEDIA_CAMERA_SUPPORT -e VIDEO_DEV -e I2C -e PINCTRL \
-e GENERIC_PINCONF -e GENERIC_PINCTRL_GROUPS -e GENERIC_PINMUX_FUNCTIONS \
-e COMMON_CLK -e LTO_CLANG -e LTO_CLANG_THIN -e AUTOFDO_CLANG \
-m VIDEO_MAXIM_SERDES -m VIDEO_MAX96717
make O=/tmp/afdo LLVM=1 olddefconfig
make O=/tmp/afdo LLVM=1 CLANG_AUTOFDO_PROFILE=/path/to/afdo.prof \
drivers/media/i2c/maxim-serdes/max96717.o

Unpatched:

ld.lld: error: call to __compiletime_assert_NNN marked "dontcall-error": field_prep: value too large for the field
make[7]: *** [scripts/Makefile.build:290: drivers/media/i2c/maxim-serdes/max96717.o] Error 1

The index in the symbol name depends on the configuration. With this patch the
object compiles and drivers/media/i2c/maxim-serdes/ links max-serdes.o. The same
build with CONFIG_AUTOFDO_CLANG=y and no CLANG_AUTOFDO_PROFILE compiles even
unpatched, which isolates the profile-guarded inlining as the trigger.

The essence, without a profile - the check itself turns the constant into a
fatal error under both compilers:

field_prep(BIT(0), ~1U) -> clang/gcc: "negative width in bit-field"
field_prep(BIT(0), !1U) -> fine

Not tested: hardware, and a GCC LTO build of this driver.

Two other FIELD_PREP() users pass ~value with fields narrower than the value's
type, drivers/net/ethernet/sunplus/spl2sw_{mac,phy}.c. They are latent for the
same reason but receive runtime values, so they did not fail here and are not
touched by this patch.

diff --git a/drivers/media/i2c/maxim-serdes/max96717.c b/drivers/media/i2c/maxim-serdes/max96717.c
index e004e71cb768..e57dd701017c 100644
--- a/drivers/media/i2c/maxim-serdes/max96717.c
+++ b/drivers/media/i2c/maxim-serdes/max96717.c
@@ -604,7 +604,7 @@ static int max96717_conf_pin_config_set_one(struct max96717_priv *priv,
case PIN_CONFIG_OUTPUT_ENABLE:
case PIN_CONFIG_INPUT_ENABLE:
case PIN_CONFIG_LEVEL:
- val = field_prep(mask, arg ? en_val : ~en_val);
+ val = field_prep(mask, arg ? en_val : !en_val);

ret = regmap_update_bits(priv->regmap, reg, mask, val);
break;
--
2.56.0.341.gebdc087dc9