Message ID | 1635507743-17919-2-git-send-email-hector.yuan@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | viresh kumar |
Headers | show |
Series | [v1,1/1] cpufreq: mediatek-hw: Fix double devm_remap in hotplug case | expand |
On 29-10-21, 19:42, Hector Yuan wrote: > From: "Hector.Yuan" <hector.yuan@mediatek.com> > > When hotpluging policy cpu, cpu policy init will be called multiple times. > Unplug CPU7 -> CPU6 -> CPU5 -> CPU4, then plug CPU4 again. > In this case, devm_remap will double remap and resource allocate fail. > So replace devm_remap to ioremap and release resources in cpu policy exit. > > Signed-off-by: Hector.Yuan <hector.yuan@mediatek.com> > --- > drivers/cpufreq/mediatek-cpufreq-hw.c | 33 ++++++++++++++++++++++++++++++--- > 1 file changed, 30 insertions(+), 3 deletions(-) > > diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c > index 0cf18dd..25317d7 100644 > --- a/drivers/cpufreq/mediatek-cpufreq-hw.c > +++ b/drivers/cpufreq/mediatek-cpufreq-hw.c > @@ -36,6 +36,8 @@ enum { > struct mtk_cpufreq_data { > struct cpufreq_frequency_table *table; > void __iomem *reg_bases[REG_ARRAY_SIZE]; > + struct resource *res; > + void __iomem *base; > int nr_opp; > }; > > @@ -156,6 +158,7 @@ static int mtk_cpu_resources_init(struct platform_device *pdev, pdev specific initializations shouldn't be done from policy->init(), but instead do those only once from mtk_cpufreq_hw_driver_probe(). That way such bugs won't occur again.
On 29-10-21, 19:42, Hector Yuan wrote: > From: "Hector.Yuan" <hector.yuan@mediatek.com> > > When hotpluging policy cpu, cpu policy init will be called multiple times. > Unplug CPU7 -> CPU6 -> CPU5 -> CPU4, then plug CPU4 again. > In this case, devm_remap will double remap and resource allocate fail. > So replace devm_remap to ioremap and release resources in cpu policy exit. > > Signed-off-by: Hector.Yuan <hector.yuan@mediatek.com> > --- > drivers/cpufreq/mediatek-cpufreq-hw.c | 33 ++++++++++++++++++++++++++++++--- > 1 file changed, 30 insertions(+), 3 deletions(-) Applied. Thanks.
diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c index 0cf18dd..25317d7 100644 --- a/drivers/cpufreq/mediatek-cpufreq-hw.c +++ b/drivers/cpufreq/mediatek-cpufreq-hw.c @@ -36,6 +36,8 @@ enum { struct mtk_cpufreq_data { struct cpufreq_frequency_table *table; void __iomem *reg_bases[REG_ARRAY_SIZE]; + struct resource *res; + void __iomem *base; int nr_opp; }; @@ -156,6 +158,7 @@ static int mtk_cpu_resources_init(struct platform_device *pdev, { struct mtk_cpufreq_data *data; struct device *dev = &pdev->dev; + struct resource *res; void __iomem *base; int ret, i; int index; @@ -170,9 +173,26 @@ static int mtk_cpu_resources_init(struct platform_device *pdev, if (index < 0) return index; - base = devm_platform_ioremap_resource(pdev, index); - if (IS_ERR(base)) - return PTR_ERR(base); + res = platform_get_resource(pdev, IORESOURCE_MEM, index); + if (!res) { + dev_err(dev, "failed to get mem resource %d\n", index); + return -ENODEV; + } + + if (!request_mem_region(res->start, resource_size(res), res->name)) { + dev_err(dev, "failed to request resource %pR\n", res); + return -EBUSY; + } + + base = ioremap(res->start, resource_size(res)); + if (!base) { + dev_err(dev, "failed to map resource %pR\n", res); + ret = -ENOMEM; + goto release_region; + } + + data->base = base; + data->res = res; for (i = REG_FREQ_LUT_TABLE; i < REG_ARRAY_SIZE; i++) data->reg_bases[i] = base + offsets[i]; @@ -187,6 +207,9 @@ static int mtk_cpu_resources_init(struct platform_device *pdev, policy->driver_data = data; return 0; +release_region: + release_mem_region(res->start, resource_size(res)); + return ret; } static int mtk_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) @@ -233,9 +256,13 @@ static int mtk_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) static int mtk_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy) { struct mtk_cpufreq_data *data = policy->driver_data; + struct resource *res = data->res; + void __iomem *base = data->base; /* HW should be in paused state now */ writel_relaxed(0x0, data->reg_bases[REG_FREQ_ENABLE]); + iounmap(base); + release_mem_region(res->start, resource_size(res)); return 0; }