summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-25 21:07:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-25 21:07:59 -0700
commit16c29dafcc86024048f1dbb8349d31cb22c7c55a (patch)
tree100c4fd34903adf02c9b8ae7705a3e1f30c8d712 /drivers
parentdc50eddb2f3a0dff365f093b2a93fb4ab4dd4389 (diff)
parentd47d81c0e9abdc3c88653fabff5beae82c949b09 (diff)
Merge branch 'syscore' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'syscore' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6: Introduce ARCH_NO_SYSDEV_OPS config option (v2) cpufreq: Use syscore_ops for boot CPU suspend/resume (v2) KVM: Use syscore_ops instead of sysdev class and sysdev PCI / Intel IOMMU: Use syscore_ops instead of sysdev class and sysdev timekeeping: Use syscore_ops instead of sysdev class and sysdev x86: Use syscore_ops instead of sysdev classes and sysdevs
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/Kconfig7
-rw-r--r--drivers/base/sys.c3
-rw-r--r--drivers/cpufreq/cpufreq.c66
-rw-r--r--drivers/pci/intel-iommu.c38
4 files changed, 44 insertions, 70 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d57e8d0fb823..e9e5238f3106 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -168,4 +168,11 @@ config SYS_HYPERVISOR
bool
default n
+config ARCH_NO_SYSDEV_OPS
+ bool
+ ---help---
+ To be selected by architectures that don't use sysdev class or
+ sysdev driver power management (suspend/resume) and shutdown
+ operations.
+
endmenu
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index f6fb54741602..fbe72da6c414 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -329,7 +329,7 @@ void sysdev_unregister(struct sys_device *sysdev)
}
-
+#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
/**
* sysdev_shutdown - Shut down all system devices.
*
@@ -524,6 +524,7 @@ int sysdev_resume(void)
return 0;
}
EXPORT_SYMBOL_GPL(sysdev_resume);
+#endif /* CONFIG_ARCH_NO_SYSDEV_OPS */
int __init system_bus_init(void)
{
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0f17ad8585d7..b03771d4787c 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -28,6 +28,7 @@
#include <linux/cpu.h>
#include <linux/completion.h>
#include <linux/mutex.h>
+#include <linux/syscore_ops.h>
#include <trace/events/power.h>
@@ -1340,35 +1341,31 @@ out:
}
EXPORT_SYMBOL(cpufreq_get);
+static struct sysdev_driver cpufreq_sysdev_driver = {
+ .add = cpufreq_add_dev,
+ .remove = cpufreq_remove_dev,
+};
+
/**
- * cpufreq_suspend - let the low level driver prepare for suspend
+ * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
+ *
+ * This function is only executed for the boot processor. The other CPUs
+ * have been put offline by means of CPU hotplug.
*/
-
-static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
+static int cpufreq_bp_suspend(void)
{
int ret = 0;
- int cpu = sysdev->id;
+ int cpu = smp_processor_id();
struct cpufreq_policy *cpu_policy;
dprintk("suspending cpu %u\n", cpu);
- if (!cpu_online(cpu))
- return 0;
-
- /* we may be lax here as interrupts are off. Nonetheless
- * we need to grab the correct cpu policy, as to check
- * whether we really run on this CPU.
- */
-
+ /* If there's no policy for the boot CPU, we have nothing to do. */
cpu_policy = cpufreq_cpu_get(cpu);
if (!cpu_policy)
- return -EINVAL;
-
- /* only handle each CPU group once */
- if (unlikely(cpu_policy->cpu != cpu))
- goto out;
+ return 0;
if (cpufreq_driver->suspend) {
ret = cpufreq_driver->suspend(cpu_policy);
@@ -1377,13 +1374,12 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
"step on CPU %u\n", cpu_policy->cpu);
}
-out:
cpufreq_cpu_put(cpu_policy);
return ret;
}
/**
- * cpufreq_resume - restore proper CPU frequency handling after resume
+ * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
*
* 1.) resume CPUfreq hardware support (cpufreq_driver->resume())
* 2.) schedule call cpufreq_update_policy() ASAP as interrupts are
@@ -1391,31 +1387,23 @@ out:
* what we believe it to be. This is a bit later than when it
* should be, but nonethteless it's better than calling
* cpufreq_driver->get() here which might re-enable interrupts...
+ *
+ * This function is only executed for the boot CPU. The other CPUs have not
+ * been turned on yet.
*/
-static int cpufreq_resume(struct sys_device *sysdev)
+static void cpufreq_bp_resume(void)
{
int ret = 0;
- int cpu = sysdev->id;
+ int cpu = smp_processor_id();
struct cpufreq_policy *cpu_policy;
dprintk("resuming cpu %u\n", cpu);
- if (!cpu_online(cpu))
- return 0;
-
- /* we may be lax here as interrupts are off. Nonetheless
- * we need to grab the correct cpu policy, as to check
- * whether we really run on this CPU.
- */
-
+ /* If there's no policy for the boot CPU, we have nothing to do. */
cpu_policy = cpufreq_cpu_get(cpu);
if (!cpu_policy)
- return -EINVAL;
-
- /* only handle each CPU group once */
- if (unlikely(cpu_policy->cpu != cpu))
- goto fail;
+ return;
if (cpufreq_driver->resume) {
ret = cpufreq_driver->resume(cpu_policy);
@@ -1430,14 +1418,11 @@ static int cpufreq_resume(struct sys_device *sysdev)
fail:
cpufreq_cpu_put(cpu_policy);
- return ret;
}
-static struct sysdev_driver cpufreq_sysdev_driver = {
- .add = cpufreq_add_dev,
- .remove = cpufreq_remove_dev,
- .suspend = cpufreq_suspend,
- .resume = cpufreq_resume,
+static struct syscore_ops cpufreq_syscore_ops = {
+ .suspend = cpufreq_bp_suspend,
+ .resume = cpufreq_bp_resume,
};
@@ -2002,6 +1987,7 @@ static int __init cpufreq_core_init(void)
cpufreq_global_kobject = kobject_create_and_add("cpufreq",
&cpu_sysdev_class.kset.kobj);
BUG_ON(!cpufreq_global_kobject);
+ register_syscore_ops(&cpufreq_syscore_ops);
return 0;
}
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 4789f8e8bf7a..a4115f1afe1f 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -36,7 +36,7 @@
#include <linux/iova.h>
#include <linux/iommu.h>
#include <linux/intel-iommu.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/tboot.h>
#include <linux/dmi.h>
#include <asm/cacheflush.h>
@@ -3135,7 +3135,7 @@ static void iommu_flush_all(void)
}
}
-static int iommu_suspend(struct sys_device *dev, pm_message_t state)
+static int iommu_suspend(void)
{
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu = NULL;
@@ -3175,7 +3175,7 @@ nomem:
return -ENOMEM;
}
-static int iommu_resume(struct sys_device *dev)
+static void iommu_resume(void)
{
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu = NULL;
@@ -3183,7 +3183,7 @@ static int iommu_resume(struct sys_device *dev)
if (init_iommu_hw()) {
WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
- return -EIO;
+ return;
}
for_each_active_iommu(iommu, drhd) {
@@ -3204,40 +3204,20 @@ static int iommu_resume(struct sys_device *dev)
for_each_active_iommu(iommu, drhd)
kfree(iommu->iommu_state);
-
- return 0;
}
-static struct sysdev_class iommu_sysclass = {
- .name = "iommu",
+static struct syscore_ops iommu_syscore_ops = {
.resume = iommu_resume,
.suspend = iommu_suspend,
};
-static struct sys_device device_iommu = {
- .cls = &iommu_sysclass,
-};
-
-static int __init init_iommu_sysfs(void)
+static void __init init_iommu_pm_ops(void)
{
- int error;
-
- error = sysdev_class_register(&iommu_sysclass);
- if (error)
- return error;
-
- error = sysdev_register(&device_iommu);
- if (error)
- sysdev_class_unregister(&iommu_sysclass);
-
- return error;
+ register_syscore_ops(&iommu_syscore_ops);
}
#else
-static int __init init_iommu_sysfs(void)
-{
- return 0;
-}
+static inline int init_iommu_pm_ops(void) { }
#endif /* CONFIG_PM */
/*
@@ -3320,7 +3300,7 @@ int __init intel_iommu_init(void)
#endif
dma_ops = &intel_dma_ops;
- init_iommu_sysfs();
+ init_iommu_pm_ops();
register_iommu(&intel_iommu_ops);