From: Geert Uytterhoeven geert@linux-m68k.org
[ Upstream commit 6d5674090543b89aac0c177d67e5fb32ddc53804 ]
The function signatures of the m68k-optimized implementations of the find_{first,next}_{,zero_}bit() helpers do not match the generic variants.
Fix this by changing all non-pointer inputs and outputs to "unsigned long", and updating a few local variables.
Reported-by: kernel test robot lkp@intel.com Closes: https://lore.kernel.org/oe-kbuild-all/202509092305.ncd9mzaZ-lkp@intel.com/ Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Acked-by: "Yury Norov (NVIDIA)" yury.norov@gmail.com Link: https://patch.msgid.link/de6919554fbb4cd1427155c6bafbac8a9df822c8.1757517135... Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
Based on my thorough analysis of this commit, here is my assessment:
## Backport Recommendation: **YES**
### Extensive Analysis
#### 1. **Nature of the Bug**
This commit fixes an **API signature mismatch** between m68k-specific implementations of `find_{first,next}_{,zero_}bit()` and the generic variants defined in `include/linux/find.h`.
**Specific Issues Fixed:** - **Return type mismatch**: m68k returned `int` instead of `unsigned long` - **Parameter type mismatch**: m68k used `int`/`unsigned int` for size/offset parameters instead of `unsigned long` - **Internal variable types**: Updated `res` from `int` to `unsigned long` and `words` from `unsigned int` to `unsigned long` for consistency
**Code Changes:** ```c // Before (incorrect): static inline int find_first_zero_bit(const unsigned long *vaddr, unsigned size) { int res = 32; unsigned int words; ... }
// After (correct): static inline unsigned long find_first_zero_bit(const unsigned long *vaddr, unsigned long size) { unsigned long res = 32; unsigned long words; ... } ```
#### 2. **Root Cause and Discovery**
**Historical Context:** - The generic `find_*_bit()` API has used `unsigned long` for return values and size/offset parameters since at least **May 2021** (commit 2cc7b6a44ac21d) - In **June 2022**, commit 0e862838f2901 unified non-atomic bitops prototypes across architectures, but m68k's `find_*_bit()` functions were missed - m68k did update `__fls()` to return `unsigned long` in 2022, but `find_*_bit()` was overlooked
**Discovery:** - Reported by kernel test robot on **September 9, 2025** - Triggered by the `gpio-mpsse` driver (introduced in v6.13) when compiled for m68k with GCC 15.1.0 - Build warning: `warning: format '%ld' expects argument of type 'long int', but argument 3 has type 'int' [-Wformat=]` - The gpio-mpsse driver correctly assumed `find_first_bit()` returns `unsigned long` and used `%ld` format specifier
#### 3. **Impact Assessment**
**Build Impact:** - Causes `-Wformat` warnings with modern compilers (GCC 15.1.0+) - Breaks W=1 builds (extra warnings enabled) - Affects m68k-allmodconfig builds
**Runtime Impact:** - **On m68k (32-bit)**: Both `int` and `long` are 32 bits, so no data corruption or truncation at runtime - **Type safety**: Violates API contract and breaks type safety guarantees - **Future-proofing**: Could cause issues with future compiler optimizations or analysis tools
**Affected Code:** - Any code using these functions with format strings (like gpio-mpsse) - Any code relying on proper type signatures for static analysis
#### 4. **Fix Quality Assessment**
**Strengths:** - **Small and focused**: Only changes type signatures, no logic changes - **Self-contained**: No dependencies on other commits - **Low risk**: On m68k, `int` and `unsigned long` have identical size and alignment - **Well-tested**: The generic API with these signatures has been used successfully across all other architectures since 2021 - **Maintainer approval**: Acked by Yury Norov (NVIDIA), the maintainer of bitmap/find_bit subsystem
**Changes Made:** 1. Function return types: `int` → `unsigned long` (4 functions) 2. Size parameters: `unsigned size` → `unsigned long size` 3. Offset parameters: `int offset` → `unsigned long offset` 4. Internal variables: `int res` → `unsigned long res`, `unsigned int words` → `unsigned long words`
#### 5. **Consistency with Kernel Standards**
This fix brings m68k in line with: - The generic API defined in `include/linux/find.h` (lines 385, 179, 206, 60) - All other architecture-specific implementations - The kernel's bitmap subsystem standards established in 2021-2022
#### 6. **Backport Suitability**
**Meets Stable Kernel Criteria:** ✅ **Fixes important bug**: API signature mismatch causing build warnings ✅ **Small and contained**: ~20 lines changed, type-only modifications ✅ **No architectural changes**: Pure signature corrections ✅ **Minimal regression risk**: Same size types on target architecture ✅ **No new features**: Only fixes existing API compliance
**Priority by Kernel Version:** - **High priority for 6.13+**: Contains gpio-mpsse driver that exposes the bug - **Medium priority for 6.6-6.12**: No immediate triggering code, but bug exists - **Low priority for <6.6**: Older compilers less likely to catch the issue, but correctness still matters
**Dependencies:** None - the fix is self-contained and applies cleanly to any kernel with the current m68k bitops.h structure (present since at least 2021).
#### 7. **Potential Risks**
**Minimal risks identified:** - On m68k, `int` and `unsigned long` are both 32-bit, so binary compatibility is preserved - No ABI changes (inline functions) - No performance impact - No behavior changes
### Conclusion
This commit is an **excellent candidate for backporting** to stable kernel trees. It fixes a long-standing API compliance bug with minimal risk, improves type safety, resolves build warnings with modern compilers, and aligns m68k with kernel-wide standards. The fix is small, focused, well-reviewed, and has no dependencies, making it ideal for stable tree inclusion.
arch/m68k/include/asm/bitops.h | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h index 14c64a6f12176..50ec92651d5a5 100644 --- a/arch/m68k/include/asm/bitops.h +++ b/arch/m68k/include/asm/bitops.h @@ -350,12 +350,12 @@ static inline bool xor_unlock_is_negative_byte(unsigned long mask, #include <asm-generic/bitops/ffz.h> #else
-static inline int find_first_zero_bit(const unsigned long *vaddr, - unsigned size) +static inline unsigned long find_first_zero_bit(const unsigned long *vaddr, + unsigned long size) { const unsigned long *p = vaddr; - int res = 32; - unsigned int words; + unsigned long res = 32; + unsigned long words; unsigned long num;
if (!size) @@ -376,8 +376,9 @@ static inline int find_first_zero_bit(const unsigned long *vaddr, } #define find_first_zero_bit find_first_zero_bit
-static inline int find_next_zero_bit(const unsigned long *vaddr, int size, - int offset) +static inline unsigned long find_next_zero_bit(const unsigned long *vaddr, + unsigned long size, + unsigned long offset) { const unsigned long *p = vaddr + (offset >> 5); int bit = offset & 31UL, res; @@ -406,11 +407,12 @@ static inline int find_next_zero_bit(const unsigned long *vaddr, int size, } #define find_next_zero_bit find_next_zero_bit
-static inline int find_first_bit(const unsigned long *vaddr, unsigned size) +static inline unsigned long find_first_bit(const unsigned long *vaddr, + unsigned long size) { const unsigned long *p = vaddr; - int res = 32; - unsigned int words; + unsigned long res = 32; + unsigned long words; unsigned long num;
if (!size) @@ -431,8 +433,9 @@ static inline int find_first_bit(const unsigned long *vaddr, unsigned size) } #define find_first_bit find_first_bit
-static inline int find_next_bit(const unsigned long *vaddr, int size, - int offset) +static inline unsigned long find_next_bit(const unsigned long *vaddr, + unsigned long size, + unsigned long offset) { const unsigned long *p = vaddr + (offset >> 5); int bit = offset & 31UL, res;