From: Marc Zyngier maz@kernel.org
stable inclusion from stable-v5.10.103 commit 4185b788d3adc9e66b5b9c959b91ae17b8488fc3 bugzilla: https://gitee.com/openeuler/kernel/issues/I56NE7
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit d1e972ace42390de739cde87d96043dcbe502286 upstream.
The tegra186 GPIO driver makes the assumption that the pointer returned by irq_data_get_irq_chip_data() is a pointer to a tegra_gpio structure. Unfortunately, it is actually a pointer to the inner gpio_chip structure, as mandated by the gpiolib infrastructure. Nice try.
The saving grace is that the gpio_chip is the first member of tegra_gpio, so the bug has gone undetected since... forever.
Fix it by performing a container_of() on the pointer. This results in no additional code, and makes it possible to understand how the whole thing works.
Fixes: 5b2b135a87fc ("gpio: Add Tegra186 support") Signed-off-by: Marc Zyngier maz@kernel.org Cc: Thierry Reding treding@nvidia.com Cc: Linus Walleij linus.walleij@linaro.org Cc: Bartosz Golaszewski bgolaszewski@baylibre.com Link: https://lore.kernel.org/r/20220211093904.1112679-1-maz@kernel.org Signed-off-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yu Liao liaoyu15@huawei.com Reviewed-by: Wei Li liwei391@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/gpio/gpio-tegra186.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 9500074b1f1b..7fbe5f0681b9 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -337,9 +337,12 @@ static int tegra186_gpio_of_xlate(struct gpio_chip *chip, return offset + pin; }
+#define to_tegra_gpio(x) container_of((x), struct tegra_gpio, gpio) + static void tegra186_irq_ack(struct irq_data *data) { - struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct tegra_gpio *gpio = to_tegra_gpio(gc); void __iomem *base;
base = tegra186_gpio_get_base(gpio, data->hwirq); @@ -351,7 +354,8 @@ static void tegra186_irq_ack(struct irq_data *data)
static void tegra186_irq_mask(struct irq_data *data) { - struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct tegra_gpio *gpio = to_tegra_gpio(gc); void __iomem *base; u32 value;
@@ -366,7 +370,8 @@ static void tegra186_irq_mask(struct irq_data *data)
static void tegra186_irq_unmask(struct irq_data *data) { - struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct tegra_gpio *gpio = to_tegra_gpio(gc); void __iomem *base; u32 value;
@@ -381,7 +386,8 @@ static void tegra186_irq_unmask(struct irq_data *data)
static int tegra186_irq_set_type(struct irq_data *data, unsigned int type) { - struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct tegra_gpio *gpio = to_tegra_gpio(gc); void __iomem *base; u32 value;