+
+/*********************************************************************
+ * 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 *
+ *********************************************************************/
+
+/**
+ * adjust_jiffies - adjust the system "loops_per_jiffy"
+ *
+ * This function alters the system "loops_per_jiffy" for the clock
+ * speed change. Note that loops_per_jiffy cannot be updated on SMP
+ * systems as each CPU might be scaled differently. So, use the arch
+ * per-CPU loops_per_jiffy value wherever possible.
+ */
+#ifndef CONFIG_SMP
+static unsigned long l_p_j_ref;
+static unsigned int l_p_j_ref_freq;
+
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
+{
+ if (ci->flags & CPUFREQ_CONST_LOOPS)
+ return;
+
+ if (!l_p_j_ref_freq) {
+ l_p_j_ref = loops_per_jiffy;
+ l_p_j_ref_freq = ci->old;
+ dprintk("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
+ }
+ if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
+ (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
+ (val == CPUFREQ_RESUMECHANGE)) {
+ loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
+ dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new);
+ }
+}
+#else
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
+#endif
+
+
+/**
+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
+ *
+ * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
+ * twice on all CPU frequency changes that have external effects.
+ */
+void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+{
+ BUG_ON(irqs_disabled());
+
+ freqs->flags = cpufreq_driver->flags;
+ dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new);
+
+ down_read(&cpufreq_notifier_rwsem);
+ switch (state) {
+ case CPUFREQ_PRECHANGE:
+ /* detect if the driver reported a value as "old frequency" which
+ * is not equal to what the cpufreq core thinks is "old frequency".
+ */
+ if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
+ if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
+ (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) &&
+ (likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
+ (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
+ {
+ printk(KERN_WARNING "Warning: CPU frequency is %u, "
+ "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
+ freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
+ }
+ }
+ notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
+ adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
+ break;
+ case CPUFREQ_POSTCHANGE:
+ adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
+ notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
+ if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
+ (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)))
+ cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
+ break;
+ }
+ up_read(&cpufreq_notifier_rwsem);
+}
+EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
+
+
+