From cee7413d84044a0c1919a7c70a2d761ae24390de Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 15 Jun 2017 17:46:37 +0200 Subject: pinctrl: samsung: Fix NULL pointer exception on external interrupts on S3C24xx After commit 8b1bd11c1f8f ("pinctrl: samsung: Add the support the multiple IORESOURCE_MEM for one pin-bank"), the S3C24xx (and probably S3C64xx as well) fails: Unable to handle kernel NULL pointer dereference at virtual address 000000a8 ... (s3c24xx_demux_eint4_7) from [] (__handle_domain_irq+0x6c/0xcc) (__handle_domain_irq) from [] (s3c24xx_handle_irq+0x6c/0x12c) (s3c24xx_handle_irq) from [] (__irq_svc+0x5c/0x78) Mentioned commit moved the pointer to controller's base IO memory address from each controller's driver data (samsung_pinctrl_drv_data) to per-bank structure (samsung_pin_bank). The external interrupt demux handlers (s3c24xx_demux_eint()) tried to get this base address from opaque pointer stored under irq_chip data: struct irq_data *irqd = irq_desc_get_irq_data(desc); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); ... pend = readl(bank->eint_base + EINTPEND_REG); which is wrong because this is hardware irq and it bank was never set for this irq_chip. For S3C24xx and S3C64xx, this partially reverts mentioned commit by bringing back the virt_base stored under each controller's driver data (samsung_pinctrl_drv_data). This virt_base address will be now duplicated: - samsung_pinctrl_drv_data->virt_base: used on S3C24xx and S3C64xx, - samsung_pin_bank->pctl_base: used on Exynos. Fixes: 8b1bd11c1f8f ("pinctrl: samsung: Add the support the multiple IORESOURCE_MEM for one pin-bank") Cc: Cc: Sergio Prado Reported-by: Sergio Prado Signed-off-by: Krzysztof Kozlowski Tested-by: Lihua Yao --- drivers/pinctrl/samsung/pinctrl-samsung.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/pinctrl/samsung/pinctrl-samsung.c') diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index f542642eed8d..61bbd54e35ba 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -1013,6 +1013,12 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, bank->eint_base = virt_base[0]; bank->pctl_base = virt_base[bdata->pctl_res_idx]; } + /* + * Legacy platforms should provide only one resource with IO memory. + * Store it as virt_base because legacy driver needs to access it + * through samsung_pinctrl_drv_data. + */ + d->virt_base = virt_base[0]; for_each_child_of_node(node, np) { if (!of_find_property(np, "gpio-controller", NULL)) -- cgit