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:
parent
8bb66a7e41
commit
3da98b2c15
1 changed files with 79 additions and 32 deletions
|
@ -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");
|
||||
|
|
Loading…
Add table
Reference in a new issue