cpufreq-core: add a common debug infrastructure
RFC PATCH 1/1 cpufreq-core: add a common debug infrastructure
Add a unified cpufreq debug infrastructure. Patches which update the individual drivers and add some dprintks in core files [exception: ondemand governor, and proc_itnf. The latter will go away soon, so I don't see a real need for it anyway...] do exist, but as they're mostly about replacing some stuff I won't send them to the list yet.
cpufreq_debug_printk will print messages if
a) debugging for the specified part is activated (add 1 for core,
2 for drivers,
4 for governors
and pass value as
cpufreq.debug=<value>
on the kernel command line).
b) and either
b1) printk_ratelimit() allows it to be printed, b2) the user disables ratelimit'ing by passing
cpufreq.debug_ratelimit=0
on the kernel command line, _or_
b3) during driver initialization [unless a different
driver has been initialized successfully] and unloading, and whenever a new policy is set.
The last point may cause for numerous messages if an userspace-based dynamic governor is used which mis-uses the policy interface to set specific frequencies. Oh, the ACPI processor.c interface to the file "performance" uses the same trick, but that interface is marked deprecated as well, so I don't care. And debugging isn't activated normally, you know...
drivers/cpufreq/Kconfig | 14 +++++ drivers/cpufreq/cpufreq.c | 116 ++++++++++++++++++++++++++++++++++++++++++++-- include/linux/cpufreq.h | 19 +++++++ 3 files changed, 146 insertions(+), 3 deletions(-)
drivers/cpufreq/cpufreq.c +113 -3
@@ -107,6 +107,90 @@module_put (cpufreq_driver->owner); } + +/********************************************************************* +* UNIFIED DEBUG HELPERS * +*********************************************************************/ +#ifdef CONFIG_CPU_FREQ_DEBUG + +/* what part(s) of the CPUfreq subsystem are debugged? */ +static unsigned int debug; + +/* is the debug output ratelimit'ed using printk_ratelimit? User can +* set or modify this value. +*/ +static unsigned int debug_ratelimit =1 ; + +/* is the printk_ratelimit'ing enabled? It's enabled after a successful +* loading of a cpufreq driver, temporarily disabled when a new policy +* is set, and disabled upon cpufreq driver removal +*/ +static unsigned int disable_ratelimit =1 ; +static spinlock_t disable_ratelimit_lock =SPIN_LOCK_UNLOCKED ; + +static inline void cpufreq_debug_enable_ratelimit (void ) +{ +unsigned long flags; + +spin_lock_irqsave (&disable_ratelimit_lock, flags); +if (disable_ratelimit) + disable_ratelimit--; +spin_unlock_irqrestore (&disable_ratelimit_lock, flags); +} + +static inline void cpufreq_debug_disable_ratelimit (void ) +{ +unsigned long flags; + +spin_lock_irqsave (&disable_ratelimit_lock, flags); + disable_ratelimit++; +spin_unlock_irqrestore (&disable_ratelimit_lock, flags); +} + +void cpufreq_debug_printk (unsigned int type,const char *prefix,const char *fmt, ...) +{ +char s[256 ]; +va_list args; +unsigned int len; +unsigned long flags; + +WARN_ON (!prefix); +if (type & debug) { +spin_lock_irqsave (&disable_ratelimit_lock, flags); +if (!disable_ratelimit && debug_ratelimit && !printk_ratelimit ()) { +spin_unlock_irqrestore (&disable_ratelimit_lock, flags); +return ; + } +spin_unlock_irqrestore (&disable_ratelimit_lock, flags); + + len =snprintf (s,256 ,KERN_DEBUG "%s: " , prefix); + +va_start (args, fmt); + len +=vsnprintf (&s[len], (256 - len), fmt, args); +va_end (args); + +printk (s); + +WARN_ON (len <5 ); + } +} +EXPORT_SYMBOL (cpufreq_debug_printk); + + +module_param (debug, uint,0644 ); +MODULE_PARM_DESC (debug,"CPUfreq debugging: add 1 to debug core, 2 to debug drivers, and 4 to debug governors." ); + +module_param (debug_ratelimit, uint,0644 ); +MODULE_PARM_DESC (debug_ratelimit,"CPUfreq debugging: set to 0 to disable ratelimiting." ); + +#else /* !CONFIG_CPU_FREQ_DEBUG */ + +static inline void cpufreq_debug_enable_ratelimit (void ) {return ; } +static inline void cpufreq_debug_disable_ratelimit (void ) {return ; } + +#endif /* CONFIG_CPU_FREQ_DEBUG */ + +/********************************************************************* * EXTERNALLY AFFECTING FREQUENCY CHANGES * *********************************************************************/
@@ -468,6 +552,8 @@unsigned long flags;unsigned int j; +cpufreq_debug_disable_ratelimit (); +#ifdef CONFIG_SMP /* check whether a different CPU already registered this * CPU because it is in the same boat. */
@@ -475,12 +561,15 @@if (unlikely (policy)) { cpu_sys_devices[cpu] = sys_dev;sysfs_create_link (&sys_dev->kobj, &policy->kobj,"cpufreq" ); +cpufreq_debug_enable_ratelimit ();return 0 ; }#endif -if (!try_module_get (cpufreq_driver->owner)) -return -EINVAL ; +if (!try_module_get (cpufreq_driver->owner)) { + ret = -EINVAL ; + goto module_out; + } policy =kmalloc (sizeof (struct cpufreq_policy ),GFP_KERNEL );if (!policy) {
@@ -541,6 +630,8 @@module_put (cpufreq_driver->owner); cpu_sys_devices[cpu] = sys_dev; +cpufreq_debug_enable_ratelimit (); +return 0 ;
@@ -558,6 +649,8 @@ nomem_out:module_put (cpufreq_driver->owner); + module_out: +cpufreq_debug_enable_ratelimit ();return ret; }
@@ -576,12 +669,15 @@unsigned int j;#endif +cpufreq_debug_disable_ratelimit (); +spin_lock_irqsave (&cpufreq_driver_lock, flags); data = cpufreq_cpu_data[cpu];if (!data) {spin_unlock_irqrestore (&cpufreq_driver_lock, flags); cpu_sys_devices[cpu] =NULL ; +cpufreq_debug_enable_ratelimit ();return -EINVAL ; } cpufreq_cpu_data[cpu] =NULL ;
@@ -596,6 +692,7 @@sysfs_remove_link (&sys_dev->kobj,"cpufreq" ); cpu_sys_devices[cpu] =NULL ;cpufreq_cpu_put (data); +cpufreq_debug_enable_ratelimit (); return 0; }#endif
@@ -604,6 +701,7 @@if (!kobject_get (&data->kobj)) {spin_unlock_irqrestore (&cpufreq_driver_lock, flags); +cpufreq_debug_enable_ratelimit ();return -EFAULT ; }
@@ -654,6 +752,8 @@kfree (data); +cpufreq_debug_enable_ratelimit (); +return 0 ; }
@@ -1024,6 +1124,8 @@ {int ret =0 ; +cpufreq_debug_disable_ratelimit (); +memcpy (&policy->cpuinfo, &data->cpuinfo,sizeof (struct cpufreq_cpuinfo ));
@@ -1089,6 +1191,7 @@ } error_out: +cpufreq_debug_enable_ratelimit ();return ret; }
@@ -1218,6 +1321,9 @@ } } +if (!ret) +cpufreq_debug_enable_ratelimit (); +return (ret); }EXPORT_SYMBOL_GPL (cpufreq_register_driver);
@@ -1235,8 +1341,12 @@ {unsigned long flags; -if (!cpufreq_driver || (driver != cpufreq_driver)) +cpufreq_debug_disable_ratelimit (); + +if (!cpufreq_driver || (driver != cpufreq_driver)) { +cpufreq_debug_enable_ratelimit ();return -EINVAL ; + }sysdev_driver_unregister (&cpu_sysdev_class, &cpufreq_sysdev_driver);
drivers/cpufreq/Kconfig +14 -0
@@ -13,6 +13,20 @@ If in doubt, say N. +config CPU_FREQ_DEBUG + bool "Enable CPUfreq debugging" + depends on CPU_FREQ + help + Say Y here to enable CPUfreq subsystem (including drivers) + debugging. You will need to activate it via the kernel + command line by passing + cpufreq.debug=<value> + + To get <value>, add + 1 to activate CPUfreq core debugging, + 2 to activate CPUfreq drivers debugging, and + 4 to activate CPUfreq governor debugging + config CPU_FREQ_PROC_INTF tristate "/proc/cpufreq interface (deprecated)" depends on CPU_FREQ && PROC_FS
include/linux/cpufreq.h +19 -0
@@ -360,4 +360,23 @@void cpufreq_frequency_table_put_attr (unsigned int cpu); +/********************************************************************* +* UNIFIED DEBUG HELPERS * +*********************************************************************/ + +#define CPUFREQ_DEBUG_CORE 1 +#define CPUFREQ_DEBUG_DRIVER 2 +#define CPUFREQ_DEBUG_GOVERNOR 4 + +#ifdef CONFIG_CPU_FREQ_DEBUG + +extern void cpufreq_debug_printk (unsigned int type,const char *prefix, +const char *fmt, ...); + +#else + +#define cpufreq_debug_printk(msg...) do { } while(0) + +#endif /* CONFIG_CPU_FREQ_DEBUG */ +#endif /* _LINUX_CPUFREQ_H */