clk: msm: clock-osm: remove ioremaps from panic callback

Calling ioremap() in clk_osm_panic_callback() can result in
BUG() when the kernel is panic-ing. It is not safe to use
ioremap() in atomic context. Map the debug registers at probe
time instead.

CRs-Fixed: 1086427
Change-Id: Ie14be6ee9ffbcb09009d5d05235e20f6ac215fa0
Signed-off-by: Osvaldo Banuelos <osvaldob@codeaurora.org>
This commit is contained in:
Osvaldo Banuelos 2016-12-12 17:31:21 -08:00 committed by Taniya Das
parent 8bb66a7e41
commit 3da98b2c15

View file

@ -231,6 +231,8 @@ enum clk_osm_trace_packet_id {
#define MSM8998V2_PWRCL_BOOT_RATE 1555200000
#define MSM8998V2_PERFCL_BOOT_RATE 1728000000
#define DEBUG_REG_NUM 3
/* ACD registers */
#define ACD_HW_VERSION 0x0
#define ACDCR 0x4
@ -340,6 +342,12 @@ struct osm_entry {
long frequency;
};
const char *clk_panic_reg_names[] = {"WDOG_DOMAIN_PSTATE_STATUS",
"WDOG_PROGRAM_COUNTER",
"APM_STATUS"};
const int clk_panic_reg_offsets[] = {WDOG_DOMAIN_PSTATE_STATUS,
WDOG_PROGRAM_COUNTER};
static struct dentry *osm_debugfs_base;
struct clk_osm {
@ -350,6 +358,7 @@ struct clk_osm {
struct platform_device *vdd_dev;
void *vbases[NUM_BASES];
unsigned long pbases[NUM_BASES];
void __iomem *debug_regs[DEBUG_REG_NUM];
spinlock_t lock;
u32 cpu_reg_mask;
@ -1371,6 +1380,64 @@ static int clk_osm_resources_init(struct platform_device *pdev)
perfcl_clk.acd_init = false;
}
pwrcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev,
pwrcl_clk.pbases[OSM_BASE] +
clk_panic_reg_offsets[0],
0x4);
if (!pwrcl_clk.debug_regs[0]) {
dev_err(&pdev->dev, "Failed to map %s debug register\n",
clk_panic_reg_names[0]);
return -ENOMEM;
}
pwrcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev,
pwrcl_clk.pbases[OSM_BASE] +
clk_panic_reg_offsets[1],
0x4);
if (!pwrcl_clk.debug_regs[1]) {
dev_err(&pdev->dev, "Failed to map %s debug register\n",
clk_panic_reg_names[1]);
return -ENOMEM;
}
pwrcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev,
pwrcl_clk.apm_ctrl_status,
0x4);
if (!pwrcl_clk.debug_regs[2]) {
dev_err(&pdev->dev, "Failed to map %s debug register\n",
clk_panic_reg_names[2]);
return -ENOMEM;
}
perfcl_clk.debug_regs[0] = devm_ioremap(&pdev->dev,
perfcl_clk.pbases[OSM_BASE] +
clk_panic_reg_offsets[0],
0x4);
if (!perfcl_clk.debug_regs[0]) {
dev_err(&pdev->dev, "Failed to map %s debug register\n",
clk_panic_reg_names[0]);
return -ENOMEM;
}
perfcl_clk.debug_regs[1] = devm_ioremap(&pdev->dev,
perfcl_clk.pbases[OSM_BASE] +
clk_panic_reg_offsets[1],
0x4);
if (!perfcl_clk.debug_regs[1]) {
dev_err(&pdev->dev, "Failed to map %s debug register\n",
clk_panic_reg_names[1]);
return -ENOMEM;
}
perfcl_clk.debug_regs[2] = devm_ioremap(&pdev->dev,
perfcl_clk.apm_ctrl_status,
0x4);
if (!perfcl_clk.debug_regs[2]) {
dev_err(&pdev->dev, "Failed to map %s debug register\n",
clk_panic_reg_names[2]);
return -ENOMEM;
}
vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl");
if (IS_ERR(vdd_pwrcl)) {
rc = PTR_ERR(vdd_pwrcl);
@ -2976,36 +3043,16 @@ static int clk_osm_panic_callback(struct notifier_block *nfb,
unsigned long event,
void *data)
{
void __iomem *virt_addr;
u32 value, reg;
int i;
u32 value;
struct clk_osm *c = container_of(nfb,
struct clk_osm,
panic_notifier);
reg = c->pbases[OSM_BASE] + WDOG_DOMAIN_PSTATE_STATUS;
virt_addr = ioremap(reg, 0x4);
if (virt_addr != NULL) {
value = readl_relaxed(virt_addr);
pr_err("DOM%d_PSTATE_STATUS[0x%08x]=0x%08x\n", c->cluster_num,
reg, value);
iounmap(virt_addr);
}
reg = c->pbases[OSM_BASE] + WDOG_PROGRAM_COUNTER;
virt_addr = ioremap(reg, 0x4);
if (virt_addr != NULL) {
value = readl_relaxed(virt_addr);
pr_err("DOM%d_PROGRAM_COUNTER[0x%08x]=0x%08x\n", c->cluster_num,
reg, value);
iounmap(virt_addr);
}
virt_addr = ioremap(c->apm_ctrl_status, 0x4);
if (virt_addr != NULL) {
value = readl_relaxed(virt_addr);
pr_err("APM_CTLER_STATUS_%d[0x%08x]=0x%08x\n", c->cluster_num,
c->apm_ctrl_status, value);
iounmap(virt_addr);
for (i = 0; i < DEBUG_REG_NUM; i++) {
value = readl_relaxed(c->debug_regs[i]);
pr_err("%s_%d=0x%08x\n", clk_panic_reg_names[i],
c->cluster_num, value);
}
return NOTIFY_OK;
@ -3108,6 +3155,12 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
msm8998_v2 = true;
}
rc = clk_osm_parse_dt_configs(pdev);
if (rc) {
dev_err(&pdev->dev, "Unable to parse device tree configurations\n");
return rc;
}
rc = clk_osm_resources_init(pdev);
if (rc) {
if (rc != -EPROBE_DEFER)
@ -3116,12 +3169,6 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
return rc;
}
rc = clk_osm_parse_dt_configs(pdev);
if (rc) {
dev_err(&pdev->dev, "Unable to parse device tree configurations\n");
return rc;
}
if ((pwrcl_clk.secure_init || perfcl_clk.secure_init) &&
msm8998_v2) {
pr_err("unsupported configuration for msm8998 v2\n");