In the commit setting up the qcom/msm pin controller to be hierarchical some callbacks were careful to check that d->parent_data on irq_data was valid before calling the parent function, however irq_chip_eoi_parent() was called unconditionally which doesn't work with elder Qualcomm platforms such as APQ8060. When the drivers/mfd/qcom-pm8xxx.c driver calls chained_irq_exit() that call will in turn call chip->irq_eoi() which is set to irq_chip_eoi_parent() by default on a hierachical IRQ chip, and the parent is pinctrl-msm.c so that will in turn unconditionally call irq_chip_eoi_parent() again, but its parent is invalid so we get the following crash: Unnable to handle kernel NULL pointer dereference at virtual address 00000010 pgd = (ptrval) [00000010] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT SMP ARM (...) PC is at irq_chip_eoi_parent+0x4/0x10 LR is at pm8xxx_irq_handler+0x1b4/0x2d8 Implement a local stub just avoiding to call down to irq_chip_eoi_parent() if d->parent_data is not set. Cc: Bjorn Andersson <bjorn.andersson@xxxxxxxxxx> Cc: Lina Iyer <ilina@xxxxxxxxxxxxxx> Cc: Marc Zyngier <maz@xxxxxxxxxx> Cc: Stephen Boyd <swboyd@xxxxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx Fixes: e35a6ae0eb3a ("pinctrl/msm: Setup GPIO chip in hierarchy") Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx> --- drivers/pinctrl/qcom/pinctrl-msm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 9a8daa256a32..511f596cf2c3 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -828,6 +828,12 @@ static void msm_gpio_irq_unmask(struct irq_data *d) msm_gpio_irq_clear_unmask(d, false); } +static void msm_gpio_irq_eoi(struct irq_data *d) +{ + if (d->parent_data) + irq_chip_eoi_parent(d); +} + static void msm_gpio_irq_ack(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); @@ -1104,7 +1110,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) pctrl->irq_chip.irq_mask = msm_gpio_irq_mask; pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask; pctrl->irq_chip.irq_ack = msm_gpio_irq_ack; - pctrl->irq_chip.irq_eoi = irq_chip_eoi_parent; + pctrl->irq_chip.irq_eoi = msm_gpio_irq_eoi; pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type; pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake; pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres; -- 2.24.1