* 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*
*********************************************************************/
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/pci.h>
/* 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},
};
* 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))
- {
+ if (!(pmbase & 0x01)) {
printk(KERN_ERR "cpufreq: could not find speedstep register\n");
return;
}
*/
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);
+ pci_write_config_word(speedstep_chipset_dev, 0x00A0, value);
}
return 0;
/**
* 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,
+ PCI_DEVICE_ID_INTEL_82801DB_12,
PCI_ANY_ID,
PCI_ANY_ID,
NULL);
return 4; /* 4-M */
speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801CA_12,
+ PCI_DEVICE_ID_INTEL_82801CA_12,
PCI_ANY_ID,
PCI_ANY_ID,
NULL);
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,
PCI_DEVICE_ID_INTEL_82815_MC,
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");
return 0;
}
+static unsigned int speedstep_get(unsigned int cpu)
+{
+ unsigned int speed;
+ cpumask_t cpus_allowed,affected_cpu_map;
+
+ /* 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[cpu];
+#else
+ affected_cpu_map = cpumask_of_cpu(cpu);
+#endif
+ set_cpus_allowed(current, affected_cpu_map);
+ speed=speedstep_get_processor_frequency(speedstep_processor);
+ set_cpus_allowed(current, cpus_allowed);
+ return speed;
+}
/**
* speedstep_target - set a new CPUFreq 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;
int i;
if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
return -EINVAL;
+ freqs.old = speedstep_get(policy->cpu);
+ freqs.new = speedstep_freqs[newstate].frequency;
+ freqs.cpu = policy->cpu;
+
/* 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 */
static int speedstep_cpu_init(struct cpufreq_policy *policy)
{
- int result = 0;
- unsigned int speed;
- cpumask_t cpus_allowed,affected_cpu_map;
+ int result = 0;
+ unsigned int speed;
+ cpumask_t cpus_allowed,affected_cpu_map;
/* capability check */
&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->cpu);
if (!speed)
return -EIO;
- dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n",
+ dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n",
(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
(speed / 1000));
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,
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,
};