Skip to contentSkip to conversation

cpufreq: don't stick if all ->init() calls fail

PATCH New Dominik Brodowski 1 participant 1 message Feb 20, 2004 CPU frequency scaling framework

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cpufreq: don't stick if all ->init() calls fail

Some cpufreq drivers can only tell whether they work while the per-CPU ->init() function is executed [e.g. the acpi driver]. So that cpufreq_driver isn't blocked by such stale drivers, unload them unless the driver sets a special flag.

 drivers/cpufreq/cpufreq.c |   24 +++++++++++++++++++++++-
 include/linux/cpufreq.h   |    6 ++++++
 2 files changed, 29 insertions(+), 1 deletion(-)
drivers/cpufreq/cpufreq.c +23 -1
diff -ruN linux-original/drivers/cpufreq/cpufreq.c linux/drivers/cpufreq/cpufreq.c
@@ -963,6 +963,7 @@
 int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 {
 	unsigned long flags;
+	int ret;
 
 	if (!driver_data || !driver_data->verify || !driver_data->init ||
 	    ((!driver_data->setpolicy) && (!driver_data->target)))
@@ -976,7 +977,28 @@
 	cpufreq_driver = driver_data;
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-	return sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver);
+	ret = sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver);
+
+	if ((!ret) && !(cpufreq_driver->flags & CPUFREQ_STICKY)) {
+		int i;
+		ret = -ENODEV;
+
+		/* check for at least one working CPU */
+		for (i=0; i<NR_CPUS; i++)
+			if (cpufreq_cpu_data[i])
+				ret = 0;
+
+		/* if all ->init() calls failed, unregister */
+		if (ret) {
+			sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
+
+			spin_lock_irqsave(&cpufreq_driver_lock, flags);
+			cpufreq_driver = NULL;
+			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+		}
+	}
+
+	return (ret);
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_driver);
 
include/linux/cpufreq.h +6 -0
diff -ruN linux-original/include/linux/cpufreq.h linux/include/linux/cpufreq.h
@@ -175,6 +175,7 @@
 struct cpufreq_driver {
 	struct module           *owner;
 	char			name[CPUFREQ_NAME_LEN];
+	u8			flags;
 
 	/* needed by all drivers */
 	int	(*init)		(struct cpufreq_policy *policy);
@@ -192,6 +193,11 @@
 	struct freq_attr	**attr;
 };
 
+/* flags */
+
+#define CPUFREQ_STICKY	0x01	/* the driver isn't removed even if 
+				   all ->init() calls failed */
+
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);