Merge tag 'pm+acpi-3.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Sep 2013 22:17:14 +0000 (15:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Sep 2013 22:17:14 +0000 (15:17 -0700)
Pull ACPI and power management fixes from Rafael Wysocki:

 1) Four fixes for cpufreq regressions introduced by the changes that
    removed Device Tree parsing for CPU device nodes from cpufreq
    drivers from Sudeep KarkadaNagesha.

 2) Two fixes for recent cpufreq regressions introduced by changes
    related to the preservation of sysfs attributes over system
    suspend/resume cycles from Viresh Kumar.

 3) Fix for ACPI-based wakeup signaling in the PCI subsystem that
    fails to stop PME polling for devices put into the D3cold power
    state from Rafael J Wysocki.

 4) Fix for bad interactions between cpufreq and udev on systems
    supporting intel_pstate where acpi-cpufreq is available as well
    from Yinghai Lu.

* tag 'pm+acpi-3.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq: return EEXIST instead of EBUSY for second registering
  PCI / ACPI / PM: Clear pme_poll for devices in D3cold on wakeup
  ARM: shmobile: change dev_id to cpu0 while registering cpu clock
  ARM: i.MX: change dev_id to cpu0 while registering cpu clock
  cpufreq: imx6q-cpufreq: assign cpu_dev correctly to cpu0 device
  cpufreq: cpufreq-cpu0: assign cpu_dev correctly to cpu0 device
  cpufreq: unlock correct rwsem while updating policy->cpu
  cpufreq: Clear policy->cpus bits in __cpufreq_remove_dev_finish()

arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-shmobile/clock-r8a73a4.c
arch/arm/mach-shmobile/clock-sh73a0.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/imx6q-cpufreq.c
drivers/pci/pci-acpi.c

index c3cfa41..c6b40f3 100644 (file)
@@ -285,7 +285,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL);
        clk_register_clkdev(clk[rtc_ipg_gate], NULL, "imx21-rtc");
        clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL);
-       clk_register_clkdev(clk[cpu_div], NULL, "cpufreq-cpu0.0");
+       clk_register_clkdev(clk[cpu_div], NULL, "cpu0");
        clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL);
 
        mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
index d9094b9..7c0dc45 100644 (file)
@@ -328,7 +328,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
        clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "imx-ssi.2");
        clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
-       clk_register_clkdev(clk[cpu_podf], NULL, "cpufreq-cpu0.0");
+       clk_register_clkdev(clk[cpu_podf], NULL, "cpu0");
        clk_register_clkdev(clk[iim_gate], "iim", NULL);
        clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0");
        clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1");
index 85a1b51..90372a2 100644 (file)
@@ -233,10 +233,15 @@ put_node:
        of_node_put(np);
 }
 
-static void __init imx6q_opp_init(struct device *cpu_dev)
+static void __init imx6q_opp_init(void)
 {
        struct device_node *np;
+       struct device *cpu_dev = get_cpu_device(0);
 
+       if (!cpu_dev) {
+               pr_warn("failed to get cpu0 device\n");
+               return;
+       }
        np = of_node_get(cpu_dev->of_node);
        if (!np) {
                pr_warn("failed to find cpu0 node\n");
@@ -268,7 +273,7 @@ static void __init imx6q_init_late(void)
                imx6q_cpuidle_init();
 
        if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
-               imx6q_opp_init(&imx6q_cpufreq_pdev.dev);
+               imx6q_opp_init();
                platform_device_register(&imx6q_cpufreq_pdev);
        }
 }
index 8ea5ef6..5bd2e85 100644 (file)
@@ -555,7 +555,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("pll2h",                  &pll2h_clk),
 
        /* CPU clock */
-       CLKDEV_DEV_ID("cpufreq-cpu0",           &z_clk),
+       CLKDEV_DEV_ID("cpu0",                   &z_clk),
 
        /* DIV6 */
        CLKDEV_CON_ID("zb",                     &div6_clks[DIV6_ZB]),
index 1942eae..c92c023 100644 (file)
@@ -616,7 +616,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("smp_twd", &twd_clk), /* smp_twd */
 
        /* DIV4 clocks */
-       CLKDEV_DEV_ID("cpufreq-cpu0", &div4_clks[DIV4_Z]),
+       CLKDEV_DEV_ID("cpu0", &div4_clks[DIV4_Z]),
 
        /* DIV6 clocks */
        CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
index cbfffa9..78c49d8 100644 (file)
@@ -12,6 +12,7 @@
 #define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
 
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -177,7 +178,11 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
        struct device_node *np;
        int ret;
 
-       cpu_dev = &pdev->dev;
+       cpu_dev = get_cpu_device(0);
+       if (!cpu_dev) {
+               pr_err("failed to get cpu0 device\n");
+               return -ENODEV;
+       }
 
        np = of_node_get(cpu_dev->of_node);
        if (!np) {
index 43c24aa..89b3c52 100644 (file)
@@ -952,9 +952,20 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
        if (cpu == policy->cpu)
                return;
 
+       /*
+        * Take direct locks as lock_policy_rwsem_write wouldn't work here.
+        * Also lock for last cpu is enough here as contention will happen only
+        * after policy->cpu is changed and after it is changed, other threads
+        * will try to acquire lock for new cpu. And policy is already updated
+        * by then.
+        */
+       down_write(&per_cpu(cpu_policy_rwsem, policy->cpu));
+
        policy->last_cpu = policy->cpu;
        policy->cpu = cpu;
 
+       up_write(&per_cpu(cpu_policy_rwsem, policy->last_cpu));
+
 #ifdef CONFIG_CPU_FREQ_TABLE
        cpufreq_frequency_table_update_policy_cpu(policy);
 #endif
@@ -1125,7 +1136,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        int ret;
 
        /* first sibling now owns the new sysfs dir */
-       cpu_dev = get_cpu_device(cpumask_first(policy->cpus));
+       cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
 
        /* Don't touch sysfs files during light-weight tear-down */
        if (frozen)
@@ -1189,12 +1200,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                        policy->governor->name, CPUFREQ_NAME_LEN);
 #endif
 
-       WARN_ON(lock_policy_rwsem_write(cpu));
+       lock_policy_rwsem_read(cpu);
        cpus = cpumask_weight(policy->cpus);
-
-       if (cpus > 1)
-               cpumask_clear_cpu(cpu, policy->cpus);
-       unlock_policy_rwsem_write(cpu);
+       unlock_policy_rwsem_read(cpu);
 
        if (cpu != policy->cpu) {
                if (!frozen)
@@ -1203,9 +1211,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
 
                new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
                if (new_cpu >= 0) {
-                       WARN_ON(lock_policy_rwsem_write(cpu));
                        update_policy_cpu(policy, new_cpu);
-                       unlock_policy_rwsem_write(cpu);
 
                        if (!frozen) {
                                pr_debug("%s: policy Kobject moved to cpu: %d "
@@ -1237,9 +1243,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                return -EINVAL;
        }
 
-       lock_policy_rwsem_read(cpu);
+       WARN_ON(lock_policy_rwsem_write(cpu));
        cpus = cpumask_weight(policy->cpus);
-       unlock_policy_rwsem_read(cpu);
+
+       if (cpus > 1)
+               cpumask_clear_cpu(cpu, policy->cpus);
+       unlock_policy_rwsem_write(cpu);
 
        /* If cpu is last user of policy, free policy */
        if (cpus == 1) {
@@ -2095,7 +2104,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
        write_lock_irqsave(&cpufreq_driver_lock, flags);
        if (cpufreq_driver) {
                write_unlock_irqrestore(&cpufreq_driver_lock, flags);
-               return -EBUSY;
+               return -EEXIST;
        }
        cpufreq_driver = driver_data;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
index 3e39654..c3fd2a1 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -202,7 +203,11 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
        unsigned long min_volt, max_volt;
        int num, ret;
 
-       cpu_dev = &pdev->dev;
+       cpu_dev = get_cpu_device(0);
+       if (!cpu_dev) {
+               pr_err("failed to get cpu0 device\n");
+               return -ENODEV;
+       }
 
        np = of_node_get(cpu_dev->of_node);
        if (!np) {
index 7c29ee4..b0299e6 100644 (file)
@@ -47,6 +47,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
        if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev)
                return;
 
+       if (pci_dev->pme_poll)
+               pci_dev->pme_poll = false;
+
        if (pci_dev->current_state == PCI_D3cold) {
                pci_wakeup_event(pci_dev);
                pm_runtime_resume(&pci_dev->dev);
@@ -57,9 +60,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
        if (pci_dev->pme_support)
                pci_check_pme_status(pci_dev);
 
-       if (pci_dev->pme_poll)
-               pci_dev->pme_poll = false;
-
        pci_wakeup_event(pci_dev);
        pm_runtime_resume(&pci_dev->dev);