From d729a21fd938f461b21fe5f975f7d21cf5fbab04 Mon Sep 17 00:00:00 2001 From: Tirupathi Reddy Date: Fri, 19 Aug 2016 12:16:03 +0530 Subject: [PATCH] regulator: cpr3: fix panic callback failure in interrupt context The kernel panic could happen in CPU interrupt context. CPR3 panic callback function does ioremap which cannot be executed in an interrupt context. Fix the issue by doing a ioremap during driver initialization. CRs-Fixed: 1056786 Change-Id: I191127fafb26bcf10ea25f972fe5af122debf292 Signed-off-by: Tirupathi Reddy --- drivers/regulator/cpr3-regulator.c | 5 +---- drivers/regulator/cpr3-regulator.h | 2 ++ drivers/regulator/cpr3-util.c | 6 ++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c index 9e400a9eee5c..6e8db03fe16e 100644 --- a/drivers/regulator/cpr3-regulator.c +++ b/drivers/regulator/cpr3-regulator.c @@ -5935,14 +5935,11 @@ static int cpr3_panic_callback(struct notifier_block *nfb, struct cpr3_controller, panic_notifier); struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info; struct cpr3_reg_info *reg; - void __iomem *virt_addr; int i = 0; for (i = 0; i < regs_info->reg_count; i++) { reg = &(regs_info->regs[i]); - virt_addr = ioremap(reg->addr, 0x4); - reg->value = readl_relaxed(virt_addr); - iounmap(virt_addr); + reg->value = readl_relaxed(reg->virt_addr); pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr, reg->value); } diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h index 3ddc1dc3c982..0907518722df 100644 --- a/drivers/regulator/cpr3-regulator.h +++ b/drivers/regulator/cpr3-regulator.h @@ -498,6 +498,7 @@ struct cpr3_aging_sensor_info { * @name: Register name * @addr: Register physical address * @value: Register content + * @virt_addr: Register virtual address * * This data structure is used to dump some critical register contents * when the device crashes due to a kernel panic. @@ -506,6 +507,7 @@ struct cpr3_reg_info { const char *name; u32 addr; u32 value; + void __iomem *virt_addr; }; /** diff --git a/drivers/regulator/cpr3-util.c b/drivers/regulator/cpr3-util.c index 34b51ec8cab8..9d55e9af2e7c 100644 --- a/drivers/regulator/cpr3-util.c +++ b/drivers/regulator/cpr3-util.c @@ -1078,6 +1078,12 @@ static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl) rc); return rc; } + regs[i].virt_addr = devm_ioremap(ctrl->dev, regs[i].addr, 0x4); + if (!regs[i].virt_addr) { + pr_err("Unable to map panic register addr 0x%08x\n", + regs[i].addr); + return -EINVAL; + } regs[i].value = 0xFFFFFFFF; }