X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fi386%2Fkernel%2Fcpu%2Fcpufreq%2Fspeedstep-ich.c;h=5b7d18a06afaeee09b090c20d3bb6b7c7016f0f4;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=93b70f0dc53b2a6e4012c57894c4c5420d2b182a;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 93b70f0dc..5b7d18a06 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -7,7 +7,7 @@ * for chipsets ICH2-M and ICH3-M. * * Many thanks to Ducrot Bruno for finding and fixing the last - * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler + * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler * for extensive testing. * * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* @@ -19,7 +19,7 @@ *********************************************************************/ #include -#include +#include #include #include #include @@ -29,68 +29,58 @@ /* speedstep_chipset: - * It is necessary to know which chipset is used. As accesses to - * this device occur at various places in this module, we need a + * It is necessary to know which chipset is used. As accesses to + * this device occur at various places in this module, we need a * static struct pci_dev * pointing to that device. */ -static struct pci_dev *speedstep_chipset_dev; +static struct pci_dev *speedstep_chipset_dev; /* speedstep_processor */ -static unsigned int speedstep_processor = 0; +static unsigned int speedstep_processor = 0; -/* +/* * There are only two frequency states for each processor. Values * are in kHz for the time being. */ static struct cpufreq_frequency_table speedstep_freqs[] = { - {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_HIGH, 0}, {SPEEDSTEP_LOW, 0}, {0, CPUFREQ_TABLE_END}, }; -/* DEBUG - * Define it if you want verbose debug output, e.g. for bug reporting - */ -//#define SPEEDSTEP_DEBUG - -#ifdef SPEEDSTEP_DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-ich", msg) /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * - * Tries to change the SpeedStep state. + * Tries to change the SpeedStep state. */ static void speedstep_set_state (unsigned int state) { - u32 pmbase; - u8 pm2_blk; - u8 value; - unsigned long flags; + u32 pmbase; + u8 pm2_blk; + u8 value; + unsigned long flags; if (!speedstep_chipset_dev || (state > 0x1)) return; /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + if (!(pmbase & 0x01)) { + printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); return; } pmbase &= 0xFFFFFFFE; if (!pmbase) { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); return; } @@ -100,13 +90,13 @@ static void speedstep_set_state (unsigned int state) /* read state */ value = inb(pmbase + 0x50); - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); /* write new state */ value &= 0xFE; value |= state; - dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); + dprintk("writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); /* Disable bus master arbitration */ pm2_blk = inb(pmbase + 0x20); @@ -126,10 +116,10 @@ static void speedstep_set_state (unsigned int state) /* Enable IRQs */ local_irq_restore(flags); - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); if (state == (value & 0x1)) { - dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (speedstep_get_processor_frequency(speedstep_processor) / 1000)); + dprintk("change to %u MHz succeeded\n", (speedstep_get_processor_frequency(speedstep_processor) / 1000)); } else { printk (KERN_ERR "cpufreq: change failed - I/O error\n"); } @@ -146,18 +136,16 @@ static void speedstep_set_state (unsigned int state) */ static int speedstep_activate (void) { - u16 value = 0; + u16 value = 0; if (!speedstep_chipset_dev) return -EINVAL; - pci_read_config_word(speedstep_chipset_dev, - 0x00A0, &value); + pci_read_config_word(speedstep_chipset_dev, 0x00A0, &value); if (!(value & 0x08)) { value |= 0x08; - dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); - pci_write_config_word(speedstep_chipset_dev, - 0x00A0, value); + dprintk("activating SpeedStep (TM) registers\n"); + pci_write_config_word(speedstep_chipset_dev, 0x00A0, value); } return 0; @@ -167,23 +155,23 @@ static int speedstep_activate (void) /** * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic * - * Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to - * the LPC bridge / PM module which contains all power-management + * Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to + * the LPC bridge / PM module which contains all power-management * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected * chipset, or zero on failure. */ static unsigned int speedstep_detect_chipset (void) { - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801DB_12, + speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, NULL); if (speedstep_chipset_dev) return 4; /* 4-M */ - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801CA_12, + speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, NULL); @@ -191,20 +179,20 @@ static unsigned int speedstep_detect_chipset (void) return 3; /* 3-M */ - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, NULL); if (speedstep_chipset_dev) { /* speedstep.c causes lockups on Dell Inspirons 8000 and - * 8100 which use a pretty old revision of the 82815 + * 8100 which use a pretty old revision of the 82815 * host brige. Abort on these systems. */ - static struct pci_dev *hostbridge; - u8 rev = 0; + static struct pci_dev *hostbridge; + u8 rev = 0; - hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, + hostbridge = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_MC, PCI_ANY_ID, PCI_ANY_ID, @@ -212,20 +200,39 @@ static unsigned int speedstep_detect_chipset (void) if (!hostbridge) return 2; /* 2-M */ - + pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); if (rev < 5) { - dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n"); + dprintk("hostbridge does not support speedstep\n"); speedstep_chipset_dev = NULL; + pci_dev_put(hostbridge); return 0; } + pci_dev_put(hostbridge); return 2; /* 2-M */ } return 0; } +static unsigned int _speedstep_get(cpumask_t cpus) +{ + unsigned int speed; + cpumask_t cpus_allowed; + + cpus_allowed = current->cpus_allowed; + set_cpus_allowed(current, cpus); + speed = speedstep_get_processor_frequency(speedstep_processor); + set_cpus_allowed(current, cpus_allowed); + dprintk("detected %u kHz as current frequency\n", speed); + return speed; +} + +static unsigned int speedstep_get(unsigned int cpu) +{ + return _speedstep_get(cpumask_of_cpu(cpu)); +} /** * speedstep_target - set a new CPUFreq policy @@ -239,45 +246,40 @@ static int speedstep_target (struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - unsigned int newstate = 0; + unsigned int newstate = 0; struct cpufreq_freqs freqs; - cpumask_t cpus_allowed, affected_cpu_map; + cpumask_t cpus_allowed; int i; if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) return -EINVAL; + freqs.old = _speedstep_get(policy->cpus); + freqs.new = speedstep_freqs[newstate].frequency; + freqs.cpu = policy->cpu; + + dprintk("transiting from %u to %u kHz\n", freqs.old, freqs.new); + /* no transition necessary */ if (freqs.old == freqs.new) return 0; - freqs.old = speedstep_get_processor_frequency(speedstep_processor); - freqs.new = speedstep_freqs[newstate].frequency; - freqs.cpu = policy->cpu; - cpus_allowed = current->cpus_allowed; - /* only run on CPU to be set, or on its sibling */ -#ifdef CONFIG_SMP - affected_cpu_map = cpu_sibling_map[policy->cpu]; -#else - affected_cpu_map = cpumask_of_cpu(policy->cpu); -#endif - - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } /* switch to physical CPU where state is to be changed */ - set_cpus_allowed(current, affected_cpu_map); + set_cpus_allowed(current, policy->cpus); speedstep_set_state(newstate); /* allow to be run on all CPUs */ set_cpus_allowed(current, cpus_allowed); - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } @@ -301,41 +303,33 @@ static int speedstep_verify (struct cpufreq_policy *policy) static int speedstep_cpu_init(struct cpufreq_policy *policy) { - int result = 0; - unsigned int speed; - cpumask_t cpus_allowed,affected_cpu_map; - - - /* capability check */ - if (policy->cpu != 0) /* FIXME: better support for SMT in cpufreq core. Up until then, it's better to register only one CPU */ - return -ENODEV; + int result = 0; + unsigned int speed; + cpumask_t cpus_allowed; /* only run on CPU to be set, or on its sibling */ - cpus_allowed = current->cpus_allowed; #ifdef CONFIG_SMP - affected_cpu_map = cpu_sibling_map[policy->cpu]; -#else - affected_cpu_map = cpumask_of_cpu(policy->cpu); + policy->cpus = cpu_sibling_map[policy->cpu]; #endif - set_cpus_allowed(current, affected_cpu_map); + + cpus_allowed = current->cpus_allowed; + set_cpus_allowed(current, policy->cpus); /* detect low and high frequency */ result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, &speedstep_set_state); - if (result) { - set_cpus_allowed(current, cpus_allowed); + set_cpus_allowed(current, cpus_allowed); + if (result) return result; - } /* get current speed setting */ - speed = speedstep_get_processor_frequency(speedstep_processor); - set_cpus_allowed(current, cpus_allowed); + speed = _speedstep_get(policy->cpus); if (!speed) return -EIO; - dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + dprintk("currently at %s speed setting - %i MHz\n", (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", (speed / 1000)); @@ -360,11 +354,6 @@ static int speedstep_cpu_exit(struct cpufreq_policy *policy) return 0; } -static unsigned int speedstep_get(unsigned int cpu) -{ - return speedstep_get_processor_frequency(speedstep_processor); -} - static struct freq_attr* speedstep_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, @@ -372,14 +361,14 @@ static struct freq_attr* speedstep_attr[] = { static struct cpufreq_driver speedstep_driver = { - .name = "speedstep-ich", - .verify = speedstep_verify, - .target = speedstep_target, - .init = speedstep_cpu_init, - .exit = speedstep_cpu_exit, - .get = speedstep_get, - .owner = THIS_MODULE, - .attr = speedstep_attr, + .name = "speedstep-ich", + .verify = speedstep_verify, + .target = speedstep_target, + .init = speedstep_cpu_init, + .exit = speedstep_cpu_exit, + .get = speedstep_get, + .owner = THIS_MODULE, + .attr = speedstep_attr, }; @@ -394,18 +383,22 @@ static int __init speedstep_init(void) { /* detect processor */ speedstep_processor = speedstep_detect_processor(); - if (!speedstep_processor) + if (!speedstep_processor) { + dprintk("Intel(R) SpeedStep(TM) capable processor not found\n"); return -ENODEV; + } /* detect chipset */ if (!speedstep_detect_chipset()) { - printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n"); + dprintk("Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n"); return -ENODEV; } /* activate speedstep support */ - if (speedstep_activate()) + if (speedstep_activate()) { + pci_dev_put(speedstep_chipset_dev); return -EINVAL; + } return cpufreq_register_driver(&speedstep_driver); } @@ -418,6 +411,7 @@ static int __init speedstep_init(void) */ static void __exit speedstep_exit(void) { + pci_dev_put(speedstep_chipset_dev); cpufreq_unregister_driver(&speedstep_driver); }