Commit ba6cecb3 authored by Marc Zyngier's avatar Marc Zyngier Committed by Zheng Zengkai
Browse files

gpio: tegra186: Fix chip_data type confusion

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=4185b788d3adc9e66b5b9c959b91ae17b8488fc3



--------------------------------

commit d1e972ac 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: 5b2b135a ("gpio: Add Tegra186 support")
Signed-off-by: default avatarMarc 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: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarYu Liao <liaoyu15@huawei.com>
Reviewed-by: default avatarWei Li <liwei391@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent d68bba77
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -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;