Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / i386 / kernel / cpu / cpufreq / longhaul.c
index e243f0f..8ef3854 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/pci.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
@@ -58,24 +59,10 @@ static int vrmrev;
 
 /* Module parameters */
 static int dont_scale_voltage;
-static int debug;
 
-static void dprintk(const char *fmt, ...)
-{
-       char s[256];
-       va_list args;
-
-       if (debug == 0)
-               return;
-
-       va_start(args, fmt);
-       vsprintf(s, fmt, args);
-       printk(s);
-       va_end(args);
-}
 
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
 
-#define __hlt()     __asm__ __volatile__("hlt": : :"memory")
 
 /* Clock ratios multiplied by 10 */
 static int clock_ratio[32];
@@ -84,6 +71,8 @@ static int voltage_table[32];
 static unsigned int highest_speed, lowest_speed; /* kHz */
 static int longhaul_version;
 static struct cpufreq_frequency_table *longhaul_table;
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
 static char speedbuffer[8];
 
 static char *print_speed(int speed)
@@ -98,6 +87,7 @@ static char *print_speed(int speed)
 
        return speedbuffer;
 }
+#endif
 
 
 static unsigned int calc_speed(int mult)
@@ -128,7 +118,13 @@ static int longhaul_get_cpu_mult(void)
 static void do_powersaver(union msr_longhaul *longhaul,
                        unsigned int clock_ratio_index)
 {
+       struct pci_dev *dev;
+       unsigned long flags;
+       unsigned int tmp_mask;
        int version;
+       int i;
+       u16 pci_cmd;
+       u16 cmd_state[64];
 
        switch (cpu_model) {
        case CPU_EZRA_T:
@@ -146,17 +142,56 @@ static void do_powersaver(union msr_longhaul *longhaul,
        longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
        longhaul->bits.EnableSoftBusRatio = 1;
        longhaul->bits.RevisionKey = 0;
-       local_irq_disable();
+
+       preempt_disable();
+       local_irq_save(flags);
+
+       /*
+        * get current pci bus master state for all devices
+        * and clear bus master bit
+        */
+       dev = NULL;
+       i = 0;
+       do {
+               dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+               if (dev != NULL) {
+                       pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+                       cmd_state[i++] = pci_cmd;
+                       pci_cmd &= ~PCI_COMMAND_MASTER;
+                       pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+               }
+       } while (dev != NULL);
+
+       tmp_mask=inb(0x21);     /* works on C3. save mask. */
+       outb(0xFE,0x21);        /* TMR0 only */
+       outb(0xFF,0x80);        /* delay */
+
+       safe_halt();
        wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-       local_irq_enable();
-       __hlt();
+       halt();
+
+       local_irq_disable();
+
+       outb(tmp_mask,0x21);    /* restore mask */
 
+       /* restore pci bus master state for all devices */
+       dev = NULL;
+       i = 0;
+       do {
+               dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+               if (dev != NULL) {
+                       pci_cmd = cmd_state[i++];
+                       pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
+               }
+       } while (dev != NULL);
+       local_irq_restore(flags);
+       preempt_enable();
+
+       /* disable bus ratio bit */
        rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
        longhaul->bits.EnableSoftBusRatio = 0;
        longhaul->bits.RevisionKey = version;
-       local_irq_disable();
        wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-       local_irq_enable();
 }
 
 /**
@@ -192,7 +227,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-       dprintk (KERN_INFO PFX "Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
+       dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
                        fsb, mult/10, mult%10, print_speed(speed/1000));
 
        switch (longhaul_version) {
@@ -212,9 +247,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
                bcr2.bits.CLOCKMUL = clock_ratio_index;
                local_irq_disable();
                wrmsrl (MSR_VIA_BCR2, bcr2.val);
-               local_irq_enable();
-
-               __hlt();
+               safe_halt();
 
                /* Disable software clock multiplier */
                rdmsrl (MSR_VIA_BCR2, bcr2.val);
@@ -356,7 +389,7 @@ static int __init longhaul_get_ranges(void)
                }
        }
 
-       dprintk (KERN_INFO PFX "MinMult:%d.%dx MaxMult:%d.%dx\n",
+       dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
                 minmult/10, minmult%10, maxmult/10, maxmult%10);
 
        if (fsb == -1) {
@@ -366,9 +399,9 @@ static int __init longhaul_get_ranges(void)
 
        highest_speed = calc_speed(maxmult);
        lowest_speed = calc_speed(minmult);
-       dprintk (KERN_INFO PFX "FSB:%dMHz  ", fsb);
-       dprintk ("Lowest speed:%s  ", print_speed(lowest_speed/1000));
-       dprintk ("Highest speed:%s\n", print_speed(highest_speed/1000));
+       dprintk ("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
+                print_speed(lowest_speed/1000), 
+                print_speed(highest_speed/1000));
 
        if (lowest_speed == highest_speed) {
                printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
@@ -434,11 +467,11 @@ static void __init longhaul_setup_voltagescaling(void)
        }
 
        if (vrmrev==0) {
-               dprintk (KERN_INFO PFX "VRM 8.5 : ");
+               dprintk ("VRM 8.5\n");
                memcpy (voltage_table, vrm85scales, sizeof(voltage_table));
                numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25;
        } else {
-               dprintk (KERN_INFO PFX "Mobile VRM : ");
+               dprintk ("Mobile VRM\n");
                memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table));
                numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5;
        }
@@ -587,7 +620,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                longhaul_setup_voltagescaling();
 
        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+       policy->cpuinfo.transition_latency = 200000;    /* nsec */
        policy->cur = calc_speed(longhaul_get_cpu_mult());
 
        ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
@@ -658,9 +691,6 @@ static void __exit longhaul_exit(void)
 module_param (dont_scale_voltage, int, 0644);
 MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor");
 
-module_param (debug, int, 0644);
-MODULE_PARM_DESC(debug, "Dump debugging information.");
-
 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
 MODULE_LICENSE ("GPL");