Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3be6a48f authored by Dave Jones's avatar Dave Jones
Browse files

[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: default avatarDave Jones <davej@redhat.com>
parent e131832c
Loading
Loading
Loading
Loading
+45 −4
Original line number Diff line number Diff line
@@ -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>
@@ -120,6 +121,11 @@ static void do_powersaver(union msr_longhaul *longhaul,
			unsigned int clock_ratio_index)
{
	int version;
	unsigned long flags;
	struct pci_dev *dev;
	int i;
	u16 pci_cmd;
	u16 cmd_state[64];

	switch (cpu_model) {
	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.EnableSoftBusRatio = 1;
	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();

	__hlt();
	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
	__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);
	longhaul->bits.EnableSoftBusRatio = 0;
	longhaul->bits.RevisionKey = version;
	local_irq_disable();
	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
	local_irq_enable();
}

/**