Shifting a 32-bit unsigned integer by 32 or more places is undefined
behavior in C. GPIO_MASK2 computes its shift amount as (gpio) * 2, and
for pins 16-31 in the OSRH/TSRH bank this yields shifts of 32-62.
While this happens to work on PowerPC because slw masks the shift count
to the low 5 bits, compilers performing value-range propagation may
assume the else branch is unreachable and optimize it away, or may
evaluate the shift as zero on other architectures via COMPILE_TEST.
Mask gpio to the 16-pin bank index so the shift stays within [0, 30].
The registers are banked (OSRL/TSRL for gpio 0-15, OSRH/TSRH for
gpio 16-31) with an identical 2-bit-per-pin layout from MSB to LSB,
so masking to the within-bank index preserves the intended behavior.
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <redacted>
---
drivers/gpio/gpio-ppc44x.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-ppc44x.c b/drivers/gpio/gpio-ppc44x.c
index fd543fbb959a..9fdc84e922f4 100644
--- a/drivers/gpio/gpio-ppc44x.c
+++ b/drivers/gpio/gpio-ppc44x.c
@@ -19,7 +19,7 @@
#include <linux/platform_device.h>
#define GPIO_MASK(gpio) (0x80000000 >> (gpio))
-#define GPIO_MASK2(gpio) (0xc0000000 >> ((gpio) * 2))
+#define GPIO_MASK2(gpio) (0xc0000000 >> (((gpio) % 16) * 2))
/* Physical GPIO register layout */
struct ppc44x_gpio {--
2.55.0