From: "Rafał Bilski" <rafalbilski@interia.pl>
To: Dave Jones <davej@codemonkey.org.uk>
Cc: cpufreq@lists.linux.org.uk
Subject: [PATCH] Longhaul
Date: Mon, 29 May 2006 15:25:16 +0200 [thread overview]
Message-ID: <447AF63C.2@interia.pl> (raw)
(HZ_100 | HZ_250) - for BCR2 MSR CPU's.
How it works:
1. Stop processes.
2. Call suspend(PMSG_FREEZE) for all devices.
3. Change frequency
4. Call resume() for all devices.
5. Start processes.
Adventages:
- works (sadly avg rate drops to 8MB/s),
- using infrastructure already in kernel,
- no need to poke PIC registers - all interrupts are disabled anyway
(APIC compatible?),
- seems to be PREEMPT compatible (no more "sheduling while atomic").
Disadventages:
- suspend(FREEZE) == suspend(SUSPEND) for most devices currently.
But this will be fixed anyway.
- it takes a moment.
diff -uprN -X linux-2.6.16.18-vanilla/Documentation/dontdiff linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/Kconfig linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/Kconfig
--- linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/Kconfig 2006-05-28 15:04:34.000000000 +0200
+++ linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/Kconfig 2006-05-29 14:26:51.000000000 +0200
@@ -201,9 +201,11 @@ config X86_LONGRUN
If in doubt, say N.
config X86_LONGHAUL
- tristate "VIA Cyrix III Longhaul"
+ bool "VIA Cyrix III Longhaul (EXPERIMENTAL)"
+ default n
select CPU_FREQ_TABLE
- depends on BROKEN
+ depends on EXPERIMENTAL
+ depends on !SMP && (HZ_100 || HZ_250)
help
This adds the CPUFreq driver for VIA Samuel/CyrixIII,
VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
diff -uprN -X linux-2.6.16.18-vanilla/Documentation/dontdiff linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/longhaul.c linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/longhaul.c 2006-03-20 06:53:29.000000000 +0100
+++ linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/longhaul.c 2006-05-29 14:23:30.000000000 +0200
@@ -30,6 +30,8 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/sched.h>
#include <asm/msr.h>
#include <asm/timex.h>
@@ -115,36 +117,17 @@ static int longhaul_get_cpu_mult(void)
}
-static void do_powersaver(union msr_longhaul *longhaul,
- unsigned int clock_ratio_index)
+/**
+ * Just to be 100% sure
+ */
+
+static u16 cmd_state[64];
+
+static void clear_bus_master(void)
{
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:
- version = 3;
- break;
- case CPU_NEHEMIAH:
- version = 0xf;
- break;
- default:
- return;
- }
-
- rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
- longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
- longhaul->bits.EnableSoftBusRatio = 1;
- longhaul->bits.RevisionKey = 0;
-
- preempt_disable();
- local_irq_save(flags);
+ int i;
/*
* get current pci bus master state for all devices
@@ -157,22 +140,20 @@ static void do_powersaver(union msr_long
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);
+ if (pci_cmd & PCI_COMMAND_MASTER) {
+ 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);
- halt();
-
- local_irq_disable();
- outb(tmp_mask,0x21); /* restore mask */
+static void restore_bus_master(void)
+{
+ struct pci_dev *dev;
+ u16 pci_cmd;
+ int i;
/* restore pci bus master state for all devices */
dev = NULL;
@@ -181,11 +162,62 @@ static void do_powersaver(union msr_long
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);
+ if (pci_cmd & PCI_COMMAND_MASTER)
+ pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
}
} while (dev != NULL);
- local_irq_restore(flags);
- preempt_enable();
+}
+
+
+static void do_longhaul1(int reserved, unsigned int clock_ratio_index)
+{
+ union msr_bcr2 bcr2;
+
+ local_irq_disable();
+ rdmsrl(MSR_VIA_BCR2, bcr2.val);
+ /* Enable software clock multiplier */
+ bcr2.bits.ESOFTBF = 1;
+ bcr2.bits.CLOCKMUL = clock_ratio_index;
+ safe_halt(); /* Sync */
+ wrmsrl(MSR_VIA_BCR2, bcr2.val); /* Change */
+ halt();
+
+ /* Disable software clock multiplier */
+ local_irq_disable();
+ rdmsrl(MSR_VIA_BCR2, bcr2.val);
+ bcr2.bits.ESOFTBF = 0;
+ wrmsrl(MSR_VIA_BCR2, bcr2.val);
+}
+
+
+static void do_powersaver(union msr_longhaul *longhaul,
+ unsigned int clock_ratio_index)
+{
+ int version;
+
+ switch (cpu_model) {
+ case CPU_EZRA_T:
+ version = 3;
+ break;
+ case CPU_NEHEMIAH:
+ version = 0xf;
+ break;
+ default:
+ return;
+ }
+
+ local_irq_disable();
+ rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+ longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
+ longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
+ longhaul->bits.EnableSoftBusRatio = 1;
+ longhaul->bits.RevisionKey = 0;
+
+ safe_halt(); /* Sync */
+ wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); /* Change */
+ halt();
+
+ local_irq_disable();
/* disable bus ratio bit */
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
@@ -206,8 +238,8 @@ static void longhaul_setstate(unsigned i
int speed, mult;
struct cpufreq_freqs freqs;
union msr_longhaul longhaul;
- union msr_bcr2 bcr2;
static unsigned int old_ratio=-1;
+ unsigned long flags;
if (old_ratio == clock_ratio_index)
return;
@@ -230,6 +262,15 @@ static void longhaul_setstate(unsigned i
dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
fsb, mult/10, mult%10, print_speed(speed/1000));
+ if ( freeze_processes() )
+ goto thaw;
+ if ( device_suspend(PMSG_FREEZE) ) {
+ printk(KERN_INFO PFX "Some devices failed to freeze\n");
+ goto resume;
+ }
+ clear_bus_master();
+ local_irq_save(flags);
+
switch (longhaul_version) {
/*
@@ -241,20 +282,7 @@ static void longhaul_setstate(unsigned i
*/
case TYPE_LONGHAUL_V1:
case TYPE_LONGHAUL_V2:
- rdmsrl (MSR_VIA_BCR2, bcr2.val);
- /* Enable software clock multiplier */
- bcr2.bits.ESOFTBF = 1;
- bcr2.bits.CLOCKMUL = clock_ratio_index;
- local_irq_disable();
- wrmsrl (MSR_VIA_BCR2, bcr2.val);
- safe_halt();
-
- /* Disable software clock multiplier */
- rdmsrl (MSR_VIA_BCR2, bcr2.val);
- bcr2.bits.ESOFTBF = 0;
- local_irq_disable();
- wrmsrl (MSR_VIA_BCR2, bcr2.val);
- local_irq_enable();
+ do_longhaul1(0, clock_ratio_index);
break;
/*
@@ -273,6 +301,12 @@ static void longhaul_setstate(unsigned i
break;
}
+ local_irq_restore(flags);
+ restore_bus_master();
+resume:
+ device_resume();
+thaw:
+ thaw_processes();
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
----------------------------------------------------------------------
Tysiace zdjec swietnych samochodow! >>> http://link.interia.pl/f1944
next reply other threads:[~2006-05-29 13:25 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-05-29 13:25 Rafał Bilski [this message]
-- strict thread matches above, loose matches on Subject: below --
2005-04-20 18:18 [PATCH] longhaul ken_staton
2005-04-20 18:47 ` Dave Jones
2005-04-20 16:49 ken_staton
2005-04-20 18:03 ` Dave Jones
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=447AF63C.2@interia.pl \
--to=rafalbilski@interia.pl \
--cc=cpufreq@lists.linux.org.uk \
--cc=davej@codemonkey.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox