mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-06 22:58:29 +00:00
PM / devfreq: tegra: Properly disable interrupts
There is no guarantee that interrupt handling isn't running in parallel with tegra_actmon_disable_interrupts(), hence it is necessary to protect DEV_CTRL register accesses and clear IRQ status with ACTMON's IRQ being disabled in the Interrupt Controller in order to ensure that device interrupt is indeed being disabled. Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Acked-by: Thierry Reding <treding@nvidia.com> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
This commit is contained in:
parent
dd3f2616bb
commit
7514dd05ea
1 changed files with 15 additions and 6 deletions
|
@ -159,6 +159,8 @@ struct tegra_devfreq {
|
||||||
struct notifier_block rate_change_nb;
|
struct notifier_block rate_change_nb;
|
||||||
|
|
||||||
struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)];
|
struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)];
|
||||||
|
|
||||||
|
int irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_actmon_emc_ratio {
|
struct tegra_actmon_emc_ratio {
|
||||||
|
@ -405,6 +407,8 @@ static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra)
|
||||||
u32 val;
|
u32 val;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
disable_irq(tegra->irq);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
||||||
dev = &tegra->devices[i];
|
dev = &tegra->devices[i];
|
||||||
|
|
||||||
|
@ -415,9 +419,14 @@ static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra)
|
||||||
val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
|
val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
|
||||||
|
|
||||||
device_writel(dev, val, ACTMON_DEV_CTRL);
|
device_writel(dev, val, ACTMON_DEV_CTRL);
|
||||||
|
|
||||||
|
device_writel(dev, ACTMON_INTR_STATUS_CLEAR,
|
||||||
|
ACTMON_DEV_INTR_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
actmon_write_barrier(tegra);
|
actmon_write_barrier(tegra);
|
||||||
|
|
||||||
|
enable_irq(tegra->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_actmon_configure_device(struct tegra_devfreq *tegra,
|
static void tegra_actmon_configure_device(struct tegra_devfreq *tegra,
|
||||||
|
@ -592,7 +601,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
int irq;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
|
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
|
||||||
|
@ -661,15 +669,16 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
|
||||||
dev_pm_opp_add(&pdev->dev, rate, 0);
|
dev_pm_opp_add(&pdev->dev, rate, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
tegra->irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (tegra->irq < 0) {
|
||||||
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
|
err = tegra->irq;
|
||||||
return irq;
|
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", err);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, tegra);
|
platform_set_drvdata(pdev, tegra);
|
||||||
|
|
||||||
err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL,
|
||||||
actmon_thread_isr, IRQF_ONESHOT,
|
actmon_thread_isr, IRQF_ONESHOT,
|
||||||
"tegra-devfreq", tegra);
|
"tegra-devfreq", tegra);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue