[CPUFREQ] longhaul - disable PCI mastering around transition.
The spec states that we have to do this, which is *horrid*. Based on code from: Ken Staton <ken_staton@agilent.com> Signed-off-by: Dave Jones <davej@redhat.com>
This commit is contained in:
parent
e131832ca7
commit
3be6a48f3c
1 changed files with 45 additions and 4 deletions
|
@ -29,6 +29,7 @@
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/timex.h>
|
#include <asm/timex.h>
|
||||||
|
@ -120,6 +121,11 @@ static void do_powersaver(union msr_longhaul *longhaul,
|
||||||
unsigned int clock_ratio_index)
|
unsigned int clock_ratio_index)
|
||||||
{
|
{
|
||||||
int version;
|
int version;
|
||||||
|
unsigned long flags;
|
||||||
|
struct pci_dev *dev;
|
||||||
|
int i;
|
||||||
|
u16 pci_cmd;
|
||||||
|
u16 cmd_state[64];
|
||||||
|
|
||||||
switch (cpu_model) {
|
switch (cpu_model) {
|
||||||
case CPU_EZRA_T:
|
case CPU_EZRA_T:
|
||||||
|
@ -137,17 +143,52 @@ static void do_powersaver(union msr_longhaul *longhaul,
|
||||||
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
|
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
|
||||||
longhaul->bits.EnableSoftBusRatio = 1;
|
longhaul->bits.EnableSoftBusRatio = 1;
|
||||||
longhaul->bits.RevisionKey = 0;
|
longhaul->bits.RevisionKey = 0;
|
||||||
local_irq_disable();
|
|
||||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
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);
|
||||||
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
|
__hlt();
|
||||||
|
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||||
__hlt();
|
__hlt();
|
||||||
|
|
||||||
|
local_irq_disable();
|
||||||
|
|
||||||
|
/* 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);
|
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||||
longhaul->bits.EnableSoftBusRatio = 0;
|
longhaul->bits.EnableSoftBusRatio = 0;
|
||||||
longhaul->bits.RevisionKey = version;
|
longhaul->bits.RevisionKey = version;
|
||||||
local_irq_disable();
|
|
||||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||||
local_irq_enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue