* [PATCH] amd76x_pm on 2.6.0-test9 more cleanup and clock skew test
@ 2003-11-10 0:33 Tony Lindgren
2003-11-10 6:01 ` Peter Gantner
0 siblings, 1 reply; 3+ messages in thread
From: Tony Lindgren @ 2003-11-10 0:33 UTC (permalink / raw)
To: linux-kernel; +Cc: pasi.savolainen, Charles Lepple, f.maibaum, peter.gantner
[-- Attachment #1: Type: text/plain, Size: 1431 bytes --]
Hi all,
I've done some more cleanup on the amd76x_pm module. Looks like Pasi and
I both did pretty much the same changes last time independently, but Pasi
chopped off even more unnecessary code. So I've continued the cleanup based
on Pasi's code.
I've done some cleanup to remove my old comments and to get rid of all
the ifdefs. This makes the code more readable and makes it easier to
develop. I've also changed the functions around a bit to group them
better, and changed variable naming to be more standard. I've only edited
the amd76x_pm.c file, and did not do any functional changes. Just cleanup.
On the clock skew problem, it's still there, and to figure out how bad the
problem is, I've done a little shell script based on the earlier thread on
adjtimex on this mailing list. You can get the skewtest.sh from:
http://www.muru.com/linux/amd-smp-idle/skewtest.sh
On my S2460 system with a pair of Athlon 1400's I get the following results:
suggested tick
Without amd76x_pm module: 10002
With amd76x_pm module: between 9952 - 9977
I guess some people see much worse skew on some systems? Can you please
run the skewtest.sh and post some results, thanks.
Following is the current patch, you can also get it from:
http://www.muru.com/linux/amd-smp-idle/
I may not have access to my Athlon box for next few weeks, but hopefully
Pasi keeps maintaining the module as needed.
Tony
[-- Attachment #2: linux-2.6-amd76x_pm-20031109.patch --]
[-- Type: text/plain, Size: 22539 bytes --]
diff -Nru linux-2.6.0-test9/drivers/acpi/Kconfig kt9/drivers/acpi/Kconfig
diff -Nru linux-2.6.0-test9/drivers/acpi/Kconfig kt9/drivers/acpi/Kconfig
--- linux-2.6.0-test9/drivers/acpi/Kconfig 2003-10-11 12:36:19.000000000 +0300
+++ kt9/drivers/acpi/Kconfig 2003-10-26 13:06:00.000000000 +0200
@@ -269,5 +269,21 @@
particular, many Toshiba laptops require this for correct operation
of the AC module.
-endmenu
+config AMD76X_PM
+ tristate "AMD76x Native Power Management support"
+ default n
+ depends on X86 && PCI
+ ---help---
+ This driver enables Power Management on AMD760MP & AMD760MPX chipsets.
+ This is about same as ACPI C2, except that ACPI folks don't do SMP ATM.
+ In /sys/devices/pci0/0000:00:00.0/ is a statistics C2_cnt
+ (RO) and lazy_idle (RW) file.
+
+ To compile this driver as a module ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read <file:Documentation/modules.txt>. The module will be called
+ amd76x_pm.
+ If unsure, say N.
+
+endmenu
diff -Nru linux-2.6.0-test9/drivers/acpi/Makefile kt9/drivers/acpi/Makefile
diff -Nru linux-2.6.0-test9/drivers/acpi/Makefile kt9/drivers/acpi/Makefile
--- linux-2.6.0-test9/drivers/acpi/Makefile 2003-10-11 12:36:19.000000000 +0300
+++ kt9/drivers/acpi/Makefile 2003-10-26 13:06:00.000000000 +0200
@@ -48,3 +48,8 @@
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_BUS) += scan.o
+
+#
+# not really ACPI thing, until they handle SMP.
+#
+obj-$(CONFIG_AMD76X_PM) += amd76x_pm.o
--- /dev/null 1969-12-31 16:00:00.000000000 -0800
+++ linux/include/linux/amd76x_pm.h 2003-11-04 12:43:25.000000000 -0800
@@ -0,0 +1,59 @@
+/*
+ * Begin 765/766
+ */
+/* C2/C3/POS options in C3A50, page 63 in AMD-766 doc */
+#define ZZ_CACHE_EN 1
+#define DCSTOP_EN (1 << 1)
+#define STPCLK_EN (1 << 2)
+#define CPUSTP_EN (1 << 3)
+#define PCISTP_EN (1 << 4)
+#define CPUSLP_EN (1 << 5)
+#define SUSPND_EN (1 << 6)
+#define CPURST_EN (1 << 7)
+
+#define C2_REGS 0
+#define C3_REGS 8
+#define POS_REGS 16
+/*
+ * End 765/766
+ */
+
+
+/*
+ * Begin 768
+ */
+/* C2/C3 options in DevB:3x4F, page 100 in AMD-768 doc */
+#define C2EN 1
+#define C3EN (1 << 1)
+#define ZZ_C3EN (1 << 2)
+#define CSLP_C3EN (1 << 3)
+#define CSTP_C3EN (1 << 4)
+
+/* POS options in DevB:3x50, page 101 in AMD-768 doc */
+#define POSEN 1
+#define CSTP (1 << 2)
+#define PSTP (1 << 3)
+#define ASTP (1 << 4)
+#define DCSTP (1 << 5)
+#define CSLP (1 << 6)
+#define SUSP (1 << 8)
+#define MSRSM (1 << 14)
+#define PITRSM (1 << 15)
+
+/* NTH options DevB:3x40, pg 93 of 768 doc */
+#define NTPER(x) (x << 3)
+#define THMINEN(x) (x << 4)
+
+/*
+ * End 768
+ */
+
+/* NTH activate. PM10, pg 110 of 768 doc, pg 70 of 766 doc */
+#define NTH_RATIO(x) (x << 1)
+#define NTH_EN (1 << 4)
+
+/* Sleep state. PM04, pg 109 of 768 doc, pg 69 of 766 doc */
+#define SLP_EN (1 << 13)
+#define SLP_TYP(x) (x << 10)
+
+#define LAZY_IDLE_DELAY 800 /* 0: Best savings, 3000: More responsive */
--- /dev/null 1969-12-31 16:00:00.000000000 -0800
+++ linux/drivers/acpi/amd76x_pm.c 2003-11-09 14:30:53.000000000 -0800
@@ -0,0 +1,672 @@
+/*
+ * ACPI style PM for SMP AMD-760MP(X) based systems.
+ * For use until the ACPI project catches up. :-)
+ *
+ * Copyright (C) 2002 Tony Lindgren <tony@atomide.com>
+ * Copyright (C) 2002 Johnathan Hicks <thetech@folkwolf.net>
+ * Copyright (C) 2003 Pasi Savolainen
+ *
+ * HISTORY
+ *
+ * 20020702 - amd-smp-idle: Tony Lindgren <tony@atomide.com>
+ * Influenced by Vcool, and LVCool. Rewrote everything from scratch to
+ * use the PCI features in Linux, and to support SMP systems. Provides
+ * C2 idling on SMP AMD-760MP systems.
+ *
+ * 20020722: JH
+ * I adapted Tony's code for the AMD-765/766 southbridge and adapted it
+ * according to the AMD-768 data sheet to provide the same capability for
+ * SMP AMD-760MPX systems. Posted to acpi-devel list.
+ *
+ * 20020722: Alan Cox
+ * Replaces non-functional amd76x_pm code in -ac tree.
+ *
+ * 20020730: JH
+ * Added ability to do normal throttling (the non-thermal kind), C3 idling
+ * and Power On Suspend (S1 sleep). It would be very easy to tie swsusp
+ * into activate_amd76x_slp(). C3 idling doesn't happen yet; see my note
+ * in amd76x_smp_idle(). I've noticed that when NTH and idling are both
+ * enabled, my hardware locks and requires a hard reset, so I have
+ * #ifndefed around the idle loop setting to prevent this. POS locks it up
+ * too, both ought to be fixable. I've also noticed that idling and NTH
+ * make some interference that is picked up by the onboard sound chip on
+ * my ASUS A7M266-D motherboard.
+ *
+ * 20030601: Pasi Savolainen
+ * Simple port to 2.5
+ * Added sysfs interface for making nice graphs with mrtg.
+ * Look for /sys/devices/pci0/00:00.0/c2_cnt & lazy_idle (latter writable)
+ *
+ * 20031026: Pasi Savolainen
+ * Removed unnecessary PCI code that caused problems with other modules
+ *
+ * 20031109: Tony Lindgren
+ * Got rid of the ifdefs, reorganized the code to make it more readable
+ * for further changes. Cleaned my old comments away, added comments on
+ * known problems. No functional changes done.
+ *
+ * TODO
+ *
+ * - Thermal throttling (TTH).
+ * - /sys interface for normal throttling level.
+ * - /sys interface for POS.
+ *
+ * NOTES
+ *
+ * Using this module saves about 70 - 90W of energy in the idle mode compared
+ * to the default idle mode. Waking up from the idle mode is fast to keep the
+ * system response time good. Currently no CPU load calculation is done, the
+ * system exits the idle mode if the idle function runs twice on the same
+ * processor in a row. This only works on SMP systems, but maybe the idle mode
+ * enabling can be integrated to ACPI to provide C2 mode at some point.
+ *
+ * At least the following systems are known to work: TYAN S2460, ASUS A7M266-D.
+ *
+ * KNOWN PROBLEMS
+ *
+ * - System goes into sleep mode on S2460 when the driver is compiled in and
+ * loaded before other ACPI initializations. The system wakes up from an
+ * ACPI interrupt at this point, such as pressing the power button once.
+ * Current workaround is to load amd76x_pm as module.
+ *
+ * - System clock skew on certain systems. This seems to be fixed on
+ * 2.6.0-test9 for most part, but still appears on some systems. This may
+ * be caused by out of sync TSCs. This problem may also be related to
+ * spurious interrupts on line 9 (ACPI). Dropping HZ to 100 is the current
+ * workaround for this problem.
+ *
+ * This software is licensed under GNU General Public License Version 2
+ * as specified in file COPYING in the Linux kernel source tree main
+ * directory.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+
+#include <linux/amd76x_pm.h>
+
+#define VERSION "20031109"
+
+/* Experimental code for future ACPI throttling */
+//#define AMD76X_C3
+//#define AMD76X_NTH
+//#define AMD76X_POS
+
+/* Have the compiler optimize away these functions if not used */
+#ifdef AMD76X_C3
+#define use_amd76x_c3() 1
+#else
+#define use_amd76x_c3() 0
+#endif
+
+#ifdef AMD76X_NTH
+#define use_amd76x_nth() 1
+#else
+#define use_amd76x_nth() 0
+#endif
+
+#ifdef AMD76X_POS
+#define use_amd76x_pos() 1
+#else
+#define use_amd76x_pos() 0
+#endif
+
+extern void default_idle(void);
+static void amd76x_smp_idle(void);
+static int amd76x_pm_main(void);
+
+unsigned long lazy_idle = 0;
+MODULE_PARM(lazy_idle, "l");
+
+static struct pci_dev *pdev_nb;
+static struct pci_dev *pdev_sb;
+
+struct PM_cfg {
+ unsigned int status_reg;
+ unsigned int c2_reg;
+ unsigned int c3_reg;
+ unsigned int nth_reg;
+ unsigned int slp_reg;
+ unsigned int resume_reg;
+ void (*orig_idle) (void);
+ void (*curr_idle) (void);
+ unsigned long c2_cnt, c3_cnt, idle_cnt;
+ int last_pr;
+};
+
+static struct PM_cfg amd76x_pm_cfg;
+
+struct cpu_idle_state {
+ int idle;
+ int count;
+};
+static struct cpu_idle_state prs[2];
+
+static struct pci_device_id __devinitdata amd_nb_tbl[] = {
+ {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,}
+};
+
+static struct pci_device_id __devinitdata amd_sb_tbl[] = {
+ {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, PCI_ANY_ID, PCI_ANY_ID,},
+ {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,}
+};
+
+/*
+ * Get the base PMIO address and set the pm registers in amd76x_pm_cfg.
+ */
+static void
+amd76x_get_pm(void)
+{
+ unsigned int regdword;
+
+ /* Get the address for pm status, P_LVL2, etc */
+ pci_read_config_dword(pdev_sb, 0x58, ®dword);
+ regdword &= 0xff80;
+ amd76x_pm_cfg.status_reg = (regdword + 0x00);
+ amd76x_pm_cfg.slp_reg = (regdword + 0x04);
+ amd76x_pm_cfg.nth_reg = (regdword + 0x10);
+ amd76x_pm_cfg.c2_reg = (regdword + 0x14);
+ amd76x_pm_cfg.c3_reg = (regdword + 0x15);
+ amd76x_pm_cfg.resume_reg = (regdword + 0x16); /* N/A for 768 */
+}
+
+/*
+ * En/Disable PMIO and configure W4SG & STPGNT.
+ */
+static int
+config_pmio_amd76x(int is_766, int enable)
+{
+ unsigned char regbyte;
+
+ /* Clear W4SG, and set PMIOEN, if using a 765/766 set STPGNT as well.
+ * AMD-766: C3A41; page 59 in AMD-766 doc
+ * AMD-768: DevB:3x41C; page 94 in AMD-768 doc */
+ pci_read_config_byte(pdev_sb, 0x41, ®byte);
+ if (enable) {
+ regbyte |= ((is_766 << 1) | (1 << 7));
+ }
+ pci_write_config_byte(pdev_sb, 0x41, regbyte);
+ return 0;
+}
+
+/*
+ * C2 idle support for AMD-766.
+ */
+static void
+config_amd766_c2(int enable)
+{
+ unsigned int regdword;
+
+ /* Set C2 options in C3A50, page 63 in AMD-766 doc */
+ pci_read_config_dword(pdev_sb, 0x50, ®dword);
+ if (enable) {
+ regdword &= ~((DCSTOP_EN | CPUSTP_EN | PCISTP_EN | SUSPND_EN |
+ CPURST_EN) << C2_REGS);
+ regdword |= (STPCLK_EN /* ~ 20 Watt savings max */
+ | CPUSLP_EN) /* Additional ~ 70 Watts max! */
+ << C2_REGS;
+ }
+ else
+ regdword &= ~((STPCLK_EN | CPUSLP_EN) << C2_REGS);
+ pci_write_config_dword(pdev_sb, 0x50, regdword);
+}
+
+/*
+ * C2 idling support for AMD-768.
+ */
+static void
+config_amd768_c2(int enable)
+{
+ unsigned char regbyte;
+
+ /* Set C2 options in DevB:3x4F, page 100 in AMD-768 doc */
+ pci_read_config_byte(pdev_sb, 0x4F, ®byte);
+ if (enable)
+ regbyte |= C2EN;
+ else
+ regbyte ^= C2EN;
+ pci_write_config_byte(pdev_sb, 0x4F, regbyte);
+}
+
+/*
+ * Untested C3 idle support for AMD-766.
+ */
+static void
+config_amd766_c3(int enable)
+{
+ unsigned int regdword;
+
+ /* Set C3 options in C3A50, page 63 in AMD-766 doc */
+ pci_read_config_dword(pdev_sb, 0x50, ®dword);
+ if (enable) {
+ regdword &= ~((DCSTOP_EN | PCISTP_EN | SUSPND_EN | CPURST_EN)
+ << C3_REGS);
+ regdword |= (STPCLK_EN /* ~ 20 Watt savings max */
+ | CPUSLP_EN /* Additional ~ 70 Watts max! */
+ | CPUSTP_EN) /* yet more savings! */
+ << C3_REGS;
+ }
+ else
+ regdword &= ~((STPCLK_EN | CPUSLP_EN | CPUSTP_EN) << C3_REGS);
+ pci_write_config_dword(pdev_sb, 0x50, regdword);
+}
+
+/*
+ * C3 idle support for AMD-768. The idle loop would need some extra
+ * handling for C3, but it would make more sense for ACPI to handle CX level
+ * transitions like it is supposed to. Unfortunately ACPI doesn't do CX
+ * levels on SMP systems yet.
+ */
+static void
+config_amd768_c3(int enable)
+{
+ unsigned char regbyte;
+
+ /* Set C3 options in DevB:3x4F, page 100 in AMD-768 doc */
+ pci_read_config_byte(pdev_sb, 0x4F, ®byte);
+ if (enable)
+ regbyte |= (C3EN /* | ZZ_C3EN | CSLP_C3EN | CSTP_C3EN */);
+ else
+ regbyte ^= C3EN;
+ pci_write_config_byte(pdev_sb, 0x4F, regbyte);
+}
+
+static void
+config_amd766_pos(int enable)
+{
+ unsigned int regdword;
+
+ /* Set C3 options in C3A50, page 63 in AMD-766 doc */
+ pci_read_config_dword(pdev_sb, 0x50, ®dword);
+ if (enable) {
+ regdword &= ~((ZZ_CACHE_EN | CPURST_EN) << POS_REGS);
+ regdword |= ((DCSTOP_EN | STPCLK_EN | CPUSTP_EN | PCISTP_EN |
+ CPUSLP_EN | SUSPND_EN) << POS_REGS);
+ }
+ else
+ regdword ^= (0xff << POS_REGS);
+ pci_write_config_dword(pdev_sb, 0x50, regdword);
+}
+
+/*
+ * Untested Power On Suspend support for AMD-768. This should also be handled
+ * by ACPI.
+ */
+static void
+config_amd768_pos(int enable)
+{
+ unsigned int regdword;
+
+ /* Set POS options in DevB:3x50, page 101 in AMD-768 doc */
+ pci_read_config_dword(pdev_sb, 0x50, ®dword);
+ if (enable)
+ regdword |= (POSEN | CSTP | PSTP | ASTP | DCSTP | CSLP | SUSP);
+ else
+ regdword ^= POSEN;
+ pci_write_config_dword(pdev_sb, 0x50, regdword);
+}
+
+/*
+ * Normal Throttling support for AMD-768. There are several settings
+ * that can be set depending on how long you want some of the delays to be.
+ * I'm not sure if this is even neccessary at all as the 766 doesn't need this.
+ */
+static void
+config_amd768_nth(int enable, int ntper, int thminen)
+{
+ unsigned char regbyte;
+
+ /* DevB:3x40, pg 93 of 768 doc */
+ pci_read_config_byte(pdev_sb, 0x40, ®byte);
+ /* Is it neccessary to use THMINEN at ANY time? */
+ regbyte |= (NTPER(ntper) | THMINEN(thminen));
+ pci_write_config_byte(pdev_sb, 0x40, regbyte);
+}
+
+/*
+ * Activate normal throttling via its ACPI register (P_CNT).
+ */
+static void
+activate_amd76x_nth(int enable, int ratio)
+{
+ unsigned int regdword;
+
+ /* PM10, pg 110 of 768 doc, pg 70 of 766 doc */
+ regdword=inl(amd76x_pm_cfg.nth_reg);
+ if (enable)
+ regdword |= (NTH_EN | NTH_RATIO(ratio));
+ else
+ regdword ^= NTH_EN;
+ outl(regdword, amd76x_pm_cfg.nth_reg);
+}
+
+/*
+ * Activate sleep state via its ACPI register (PM1_CNT).
+ */
+static void
+activate_amd76x_slp(int type)
+{
+ unsigned short regshort;
+
+ /* PM04, pg 109 of 768 doc, pg 69 of 766 doc */
+ regshort=inw(amd76x_pm_cfg.slp_reg);
+ regshort |= (SLP_EN | SLP_TYP(type)) ;
+ outw(regshort, amd76x_pm_cfg.slp_reg);
+}
+
+/*
+ * Wrapper function to activate POS sleep state.
+ */
+static void
+activate_amd76x_pos(void)
+{
+ activate_amd76x_slp(1);
+}
+
+/*
+ * Idle loop for single processor systems
+ */
+void
+amd76x_up_idle(void)
+{
+ /* ACPI knows how to do C2 on SMP when cpu_count < 2
+ * we really shouldn't end up here anyway.
+ */
+ amd76x_pm_cfg.orig_idle();
+}
+
+/*
+ * Idle loop for SMP systems, supports currently only 2 processors.
+ *
+ * Note; for 2.5 folks - not pre-empt safe
+ */
+static void
+amd76x_smp_idle(void)
+{
+ /*
+ * Exit idle mode immediately if the CPU does not change.
+ * Usually that means that we have some load on another CPU.
+ */
+ amd76x_pm_cfg.idle_cnt++;
+ if (prs[0].idle && prs[1].idle && amd76x_pm_cfg.last_pr == smp_processor_id()) {
+ prs[0].idle = 0;
+ prs[1].idle = 0;
+ return;
+ }
+
+ prs[smp_processor_id()].count++;
+
+ /* Don't start the idle mode immediately */
+ if (prs[smp_processor_id()].count >= lazy_idle) {
+
+ /* Put the current processor into idle mode */
+ prs[smp_processor_id()].idle =
+ (prs[smp_processor_id()].idle ? 2 : 1);
+
+ /* Only idle if both processors are idle */
+ if ((prs[0].idle==1) && (prs[1].idle==1)) {
+ amd76x_pm_cfg.c2_cnt++;
+ inb(amd76x_pm_cfg.c2_reg);
+ } else if (use_amd76x_c3() && (prs[0].idle==2) && (prs[1].idle==2)) {
+ /*
+ * JH: I've not been able to get into here. Could this have
+ * something to do with the way the kernel handles the idle
+ * loop, or and error that I've made?
+ */
+ amd76x_pm_cfg.c3_cnt++;
+ inb(amd76x_pm_cfg.c3_reg);
+ }
+
+ prs[smp_processor_id()].count = 0;
+
+ }
+ amd76x_pm_cfg.last_pr = smp_processor_id();
+}
+
+/*
+ * Sysfs support, RW
+ */
+static ssize_t
+show_lazy_idle (struct device *dev, char *buf)
+{
+ return sprintf(buf,"%lu\n", lazy_idle);
+}
+
+static ssize_t
+set_lazy_idle (struct device *dev, const char *buf, size_t count)
+{
+ lazy_idle = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+static ssize_t
+show_c2_cnt (struct device *dev, char *buf)
+{
+ return sprintf(buf,"%lu\n", amd76x_pm_cfg.c2_cnt);
+}
+
+static ssize_t
+show_idle_cnt (struct device *dev, char *buf)
+{
+ return sprintf(buf,"%lu\n", amd76x_pm_cfg.idle_cnt);
+}
+
+static DEVICE_ATTR(lazy_idle, S_IRUGO | S_IWUSR,
+ show_lazy_idle, set_lazy_idle);
+static DEVICE_ATTR(c2_cnt, S_IRUGO,
+ show_c2_cnt, NULL);
+static DEVICE_ATTR(idle_cnt, S_IRUGO,
+ show_idle_cnt, NULL);
+
+/*
+ * Configures the 765 & 766 southbridges.
+ */
+static int
+config_sb_amd766(int enable)
+{
+ amd76x_get_pm();
+ config_pmio_amd76x(1, 1);
+ config_amd766_c2(enable);
+
+ if (use_amd76x_c3())
+ config_amd766_c3(enable);
+
+ if (use_amd76x_pos())
+ config_amd766_pos(enable);
+
+ return 0;
+}
+
+/*
+ * Configures the 768 southbridge to support idle calls, and gets
+ * the processor idle call register location.
+ */
+static int
+config_sb_amd768(int enable)
+{
+ amd76x_get_pm();
+ config_pmio_amd76x(0, 1);
+ config_amd768_c2(enable);
+
+ if (use_amd76x_c3())
+ config_amd768_c3(enable);
+
+ if (use_amd76x_pos())
+ config_amd768_pos(enable);
+
+ if (use_amd76x_nth())
+ config_amd768_nth(enable, 1, 2);
+
+ return 0;
+}
+
+/*
+ * Configures the AMD-762 northbridge to support PM calls
+ */
+static int
+config_nb_amd762(int enable)
+{
+ unsigned int regdword;
+
+ /* Enable STPGNT in BIU Status/Control for cpu0 */
+ pci_read_config_dword(pdev_nb, 0x60, ®dword);
+ regdword |= (1 << 17);
+ pci_write_config_dword(pdev_nb, 0x60, regdword);
+
+ /* Enable STPGNT in BIU Status/Control for cpu1 */
+ pci_read_config_dword(pdev_nb, 0x68, ®dword);
+ regdword |= (1 << 17);
+ pci_write_config_dword(pdev_nb, 0x68, regdword);
+
+ /* DRAM refresh enable */
+ pci_read_config_dword(pdev_nb, 0x58, ®dword);
+ regdword &= ~(1 << 19);
+ pci_write_config_dword(pdev_nb, 0x58, regdword);
+
+ /* Self refresh enable */
+ pci_read_config_dword(pdev_nb, 0x70, ®dword);
+ regdword |= (1 << 18);
+ pci_write_config_dword(pdev_nb, 0x70, regdword);
+
+ return 0;
+}
+
+/*
+ * Finds and initializes the bridges, and then sets the idle function
+ */
+static int
+amd76x_pm_main(void)
+{
+ amd76x_pm_cfg.orig_idle = 0;
+ if (lazy_idle == 0)
+ lazy_idle = LAZY_IDLE_DELAY;
+
+ /* Find southbridge */
+ pdev_sb = NULL;
+ while((pdev_sb = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev_sb)) != NULL) {
+ if (pci_match_device(amd_sb_tbl, pdev_sb) != NULL)
+ goto found_sb;
+ }
+ printk(KERN_ERR "amd76x_pm: Could not find southbridge\n");
+ return -ENODEV;
+
+ found_sb:
+
+ /* Find northbridge */
+ pdev_nb = NULL;
+ while((pdev_nb = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev_nb)) != NULL) {
+ if (pci_match_device(amd_nb_tbl, pdev_nb) != NULL)
+ goto found_nb;
+ }
+ printk(KERN_ERR "amd76x_pm: Could not find northbridge\n");
+ return -ENODEV;
+
+ found_nb:
+
+ /* Init southbridge */
+ switch (pdev_sb->device) {
+ case PCI_DEVICE_ID_AMD_VIPER_7413: /* AMD-765 or 766 */
+ config_sb_amd766(1);
+ break;
+ case PCI_DEVICE_ID_AMD_VIPER_7443: /* AMD-768 */
+ config_sb_amd768(1);
+ break;
+ default:
+ printk(KERN_ERR "amd76x_pm: No southbridge to initialize\n");
+ break;
+ }
+
+ /* Init northbridge and queue the new idle function */
+ if (!pdev_nb) {
+ printk("amd76x_pm: No northbridge found.\n");
+ return -ENODEV;
+ }
+ switch (pdev_nb->device) {
+ case PCI_DEVICE_ID_AMD_FE_GATE_700C: /* AMD-762 */
+ config_nb_amd762(1);
+
+ if (!use_amd76x_nth())
+ amd76x_pm_cfg.curr_idle = amd76x_smp_idle;
+
+ break;
+ default:
+ printk(KERN_ERR "amd76x_pm: No northbridge to initialize\n");
+ break;
+ }
+
+ if (!use_amd76x_nth()) {
+ if (num_online_cpus() == 1) {
+ amd76x_pm_cfg.curr_idle = amd76x_up_idle;
+ printk(KERN_ERR "amd76x_pm: UP machine detected. Use ACPI\n");
+ }
+
+ if (!amd76x_pm_cfg.curr_idle) {
+ printk(KERN_ERR "amd76x_pm: Idle function not changed\n");
+ return 1;
+ }
+
+ amd76x_pm_cfg.orig_idle = pm_idle;
+ pm_idle = amd76x_pm_cfg.curr_idle;
+ wmb();
+
+ /* sysfs */
+ device_create_file(&pdev_nb->dev, &dev_attr_lazy_idle);
+ device_create_file(&pdev_nb->dev, &dev_attr_c2_cnt);
+ device_create_file(&pdev_nb->dev, &dev_attr_idle_cnt);
+ }
+
+ /* Turn NTH on with maxium throttling for testing. */
+ if (use_amd76x_nth())
+ activate_amd76x_nth(1, 1);
+
+ /* Testing here only. */
+ if (use_amd76x_pos())
+ activate_amd76x_pos();
+
+ return 0;
+}
+
+static int __init
+amd76x_pm_init(void)
+{
+ printk(KERN_INFO "amd76x_pm: Version %s\n", VERSION);
+ return amd76x_pm_main();
+}
+
+static void __exit
+amd76x_pm_cleanup(void)
+{
+ if (!use_amd76x_nth()) {
+ pm_idle = amd76x_pm_cfg.orig_idle;
+ synchronize_kernel();
+
+ /* This isn't really needed. */
+ printk(KERN_INFO "amd76x_pm: %lu C2 calls\n", amd76x_pm_cfg.c2_cnt);
+
+ if (use_amd76x_c3())
+ printk(KERN_INFO "amd76x_pm: %lu C3 calls\n",
+ amd76x_pm_cfg.c3_cnt);
+
+ /* Remove sysfs */
+ device_remove_file(&pdev_nb->dev, &dev_attr_lazy_idle);
+ device_remove_file(&pdev_nb->dev, &dev_attr_c2_cnt);
+ device_remove_file(&pdev_nb->dev, &dev_attr_idle_cnt);
+ }
+
+ /* Turn NTH off*/
+ if (use_amd76x_nth())
+ activate_amd76x_nth(0, 0);
+}
+
+MODULE_LICENSE("GPL");
+module_init(amd76x_pm_init);
+module_exit(amd76x_pm_cleanup);
/*
* Begin 765/766
*/
/* C2/C3/POS options in C3A50, page 63 in AMD-766 doc */
#define ZZ_CACHE_EN 1
#define DCSTOP_EN (1 << 1)
#define STPCLK_EN (1 << 2)
#define CPUSTP_EN (1 << 3)
#define PCISTP_EN (1 << 4)
#define CPUSLP_EN (1 << 5)
#define SUSPND_EN (1 << 6)
#define CPURST_EN (1 << 7)
#define C2_REGS 0
#define C3_REGS 8
#define POS_REGS 16
/*
* End 765/766
*/
/*
* Begin 768
*/
/* C2/C3 options in DevB:3x4F, page 100 in AMD-768 doc */
#define C2EN 1
#define C3EN (1 << 1)
#define ZZ_C3EN (1 << 2)
#define CSLP_C3EN (1 << 3)
#define CSTP_C3EN (1 << 4)
/* POS options in DevB:3x50, page 101 in AMD-768 doc */
#define POSEN 1
#define CSTP (1 << 2)
#define PSTP (1 << 3)
#define ASTP (1 << 4)
#define DCSTP (1 << 5)
#define CSLP (1 << 6)
#define SUSP (1 << 8)
#define MSRSM (1 << 14)
#define PITRSM (1 << 15)
/* NTH options DevB:3x40, pg 93 of 768 doc */
#define NTPER(x) (x << 3)
#define THMINEN(x) (x << 4)
/*
* End 768
*/
/* NTH activate. PM10, pg 110 of 768 doc, pg 70 of 766 doc */
#define NTH_RATIO(x) (x << 1)
#define NTH_EN (1 << 4)
/* Sleep state. PM04, pg 109 of 768 doc, pg 69 of 766 doc */
#define SLP_EN (1 << 13)
#define SLP_TYP(x) (x << 10)
#define LAZY_IDLE_DELAY 800 /* 0: Best savings, 3000: More responsive */
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] amd76x_pm on 2.6.0-test9 more cleanup and clock skew test
2003-11-10 0:33 [PATCH] amd76x_pm on 2.6.0-test9 more cleanup and clock skew test Tony Lindgren
@ 2003-11-10 6:01 ` Peter Gantner
2003-11-10 18:04 ` Tony Lindgren
0 siblings, 1 reply; 3+ messages in thread
From: Peter Gantner @ 2003-11-10 6:01 UTC (permalink / raw)
To: Tony Lindgren; +Cc: linux-kernel, pasi.savolainen, Charles Lepple, f.maibaum
Quoting Tony Lindgren from Nov 9
> On the clock skew problem, it's still there, and to figure out how bad the
> problem is, I've done a little shell script based on the earlier thread on
> adjtimex on this mailing list.
Here are my results from your script.
Tested two kernels, vanilla -test9 and test-9-love2, the latter is a
patchset based off -mm2, including the nick scheduler and
other stuff like reiser4 and bootsplash. More information about this
here: http://bssteph.irtonline.org/linux/patches/2.6/2.6.0-test9/2.6.0-test9-love2/2.6.0-test9-love2_notes.txt
(amd76x_pm-031027 patch backed out, new one put in )
I did three runs each, first run idle, two runs under load, i.e. two
burnK7 processes and a make -j5 kernel compile just to make sure.
loadavg goes up to ~6.5 during those.
ntpd was not running during the tests.
System is an A7M266-d w/ two AthlonXPs 1800+ (model 6 stepping 2),
L5-modded(!) for the MP setup. (I know this is considered tainting,
if you can tell me the timing issues are related to the modding I
will shut up immediately, but so far nobody seems to have pinpointed
it to this.)
The two CPUs show different bogomips (3014, 3063).
-------------------------------------------------
test9-love2:
-------------------------------------------------
idle:
-------------------------------------------------
Running test for kernel version 2.6.0-test9-love2
This test will take about 140 seconds to run
ACPI interrupts before the first test:
9: 0 0 IO-APIC-level acpi
Running test without amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068439150 -0.014522 -0.014522 10000 0
1068439160 -0.015270 -0.000748 10000 0
1068439170 -0.016013 -0.000743 10000 0 10000 4869626
1068439180 -0.016753 -0.000740 10000 0 10000 4850095
1068439190 -0.017498 -0.000744 10000 0 10000 4876657
1068439200 -0.008564 0.008934 10000 4876657 9992 -1243667
1068439210 -0.008547 0.000017 10000 4876657 10000 4765814
1068439220 -0.008529 0.000018 10000 4876657 10000 4758783
ACPI interrupts after the first test:
9: 0 0 IO-APIC-level acpi
Running test with amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068439230 0.009470 0.009470 10000 0
1068439240 0.008725 -0.000745 10000 0
1068439250 0.008987 0.000262 10000 0 10000 -1716312
1068439260 0.009249 0.000262 10000 0 10000 -1716311
1068439270 0.008507 -0.000742 10000 0 10000 4863376
1068439280 0.017441 0.008934 10000 4863375 9992 -1256949
1068439290 0.017461 0.000020 10000 4863375 10000 4732220
1068439300 0.017482 0.000021 10000 4863375 10000 4726751
ACPI interrupts after the second test:
9: 0 0 IO-APIC-level acpi
-------------------------------------------------
load - run 1
-------------------------------------------------
Running test for kernel version 2.6.0-test9-love2
This test will take about 140 seconds to run
ACPI interrupts before the first test:
9: 0 0 IO-APIC-level acpi
Running test without amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068439375 0.035483 0.035483 10000 0
1068439385 0.034744 -0.000739 10000 0
1068439395 0.034002 -0.000742 10000 0 10000 4863376
1068439405 0.033272 -0.000730 10000 0 10000 4784470
1068439440 0.030695 -0.002577 10000 0 10003 -2773359
1068439450 0.041556 0.010861 10003 -2773359 9992 -1861789
1068439464 0.044119 0.002563 10003 -2773359 10000 92261
1068439475 0.046135 0.002016 10003 -2773359 10001 -2875039
ACPI interrupts after the first test:
9: 0 0 IO-APIC-level acpi
Running test with amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068439488 0.063667 0.063667 10000 0
1068439498 0.062917 -0.000750 10000 0
1068439509 0.062106 -0.000810 10000 0 10000 5310651
1068439519 0.061371 -0.000735 10000 0 10000 4818064
1068439533 0.060339 -0.001032 10000 0 10001 211376
1068439548 0.069771 0.009432 10001 211376 9992 -2622097
1068439560 0.070127 0.000356 10001 211376 10001 -2123667
1068439571 0.070456 0.000329 10001 211376 10001 -1942035
ACPI interrupts after the second test:
9: 0 0 IO-APIC-level acpi
-------------------------------------------------
load - run 2
-------------------------------------------------
Running test for kernel version 2.6.0-test9-love2
This test will take about 140 seconds to run
ACPI interrupts before the first test:
9: 0 0 IO-APIC-level acpi
Running test without amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068439753 0.103258 0.103258 10000 0
1068439763 0.102513 -0.000745 10000 0
1068439777 0.101485 -0.001028 10000 0 10001 185595
1068439787 0.100754 -0.000731 10000 0 10000 4790720
1068439799 0.099872 -0.000882 10000 0 10000 5779020
1068439809 0.108959 0.009087 10000 5779019 9992 -1344430
1068439819 0.109129 0.000170 10000 5779019 10000 4665051
1068439829 0.109299 0.000170 10000 5779019 10000 4665833
ACPI interrupts after the first test:
9: 0 0 IO-APIC-level acpi
Running test with amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068439843 0.127032 0.127032 10000 0
1068439854 0.126197 -0.000835 10000 0
1068439867 0.218674 0.092477 10000 0 9908 -3126099
1068439882 0.124147 -0.094527 10000 0 10095 -3102405
1068439898 0.122977 -0.001170 10000 0 10001 1113739
1068439909 0.132439 0.009462 10001 1113738 9992 -1911961
1068439924 0.133104 0.000665 10001 1113738 10001 -3246667
1068439935 0.133593 0.000489 10001 1113738 10001 -2088111
ACPI interrupts after the second test:
9: 0 0 IO-APIC-level acpi
-------------------------------------------------
vanilla
-------------------------------------------------
idle
-------------------------------------------------
Running test for kernel version 2.6.0-test9
This test will take about 140 seconds to run
ACPI interrupts before the first test:
9: 0 0 IO-APIC-level acpi
Running test without amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068441482 -0.004717 -0.004717 10000 0
1068441492 -0.005453 -0.000736 10000 0
1068441502 -0.006187 -0.000734 10000 0 10000 4810251
1068441512 -0.006916 -0.000729 10000 0 10000 4778220
1068441522 -0.007656 -0.000740 10000 0 10000 4850095
1068441532 -0.007642 0.000014 10000 4850094 10000 4758782
1068441542 -0.007617 0.000025 10000 4850094 10000 4686907
1068441552 -0.007595 0.000022 10000 4850094 10000 4706439
ACPI interrupts after the first test:
9: 0 0 IO-APIC-level acpi
Running test with amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068441562 -0.007592 -0.007592 10000 0
1068441572 -0.007321 0.000271 10000 0
1068441582 -0.008068 -0.000747 10000 0 10000 4895407
1068441592 -0.008798 -0.000730 10000 0 10000 4785251
1068441602 -0.009534 -0.000736 10000 0 10000 4823532
1068441612 -0.009595 -0.000061 10000 4823532 10000 5223627
1068441622 -0.008579 0.001016 10000 4823532 10000 -1834186
1068441632 -0.007561 0.001018 10000 4823532 10000 -1847467
ACPI interrupts after the second test:
9: 0 0 IO-APIC-level acpi
-------------------------------------------------
load - run 1
-------------------------------------------------
Running test for kernel version 2.6.0-test9
This test will take about 140 seconds to run
ACPI interrupts before the first test:
9: 0 0 IO-APIC-level acpi
Running test without amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068441806 -0.023066 -0.023066 10000 0
1068441817 -0.023886 -0.000820 10000 0
1068441827 -0.024622 -0.000736 10000 0 10000 4824313
1068441838 -0.025433 -0.000810 10000 0 10000 5310651
1068441856 -0.026762 -0.001330 10000 0 10001 2159852
1068441868 -0.026087 0.000675 10001 2159851 10001 -2265817
1068441881 -0.025307 0.000780 10001 2159851 10001 -2952136
1068441892 -0.024650 0.000657 10001 2159851 10001 -2142779
ACPI interrupts after the first test:
9: 0 0 IO-APIC-level acpi
Running test with amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068441902 -0.024727 -0.024727 10000 0
1068441913 -0.025560 -0.000832 10000 0
1068441927 -0.026594 -0.001034 10000 0 10001 224658
1068441940 -0.027553 -0.000959 10000 0 10000 6284889
1068441950 -0.028289 -0.000736 10000 0 10000 4824313
1068441960 -0.028363 -0.000074 10000 4824313 10000 5309564
1068441971 -0.028348 0.000016 10000 4824313 10000 4722464
1068441982 -0.028328 0.000020 10000 4824313 10000 4695902
ACPI interrupts after the second test:
9: 0 0 IO-APIC-level acpi
-------------------------------------------------
load - run 2
-------------------------------------------------
Running test for kernel version 2.6.0-test9
This test will take about 140 seconds to run
ACPI interrupts before the first test:
9: 0 0 IO-APIC-level acpi
Running test without amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068442024 -0.028550 -0.028550 10000 0
1068442034 -0.029312 -0.000762 10000 0
1068442044 -0.030048 -0.000736 10000 0 10000 4823532
1068442060 -0.031229 -0.001181 10000 0 10001 1185614
1068442075 -0.032338 -0.001109 10000 0 10001 711776
1068442085 -0.031986 0.000352 10001 711776 10001 -1594379
1068442095 -0.031610 0.000376 10001 711776 10001 -1751411
1068442112 -0.030975 0.000635 10001 711776 10001 -3448610
ACPI interrupts after the first test:
9: 0 0 IO-APIC-level acpi
Running test with amd76x_pm module
--- current --- -- suggested --
cmos time system-cmos 2nd diff tick freq tick freq
1068442127 -0.031614 -0.031614 10000 0
1068442141 -0.032668 -0.001054 10000 0
1068442159 -0.033992 -0.001324 10000 0 10001 2126258
1068442169 -0.034728 -0.000735 10000 0 10000 4818063
1068442181 -0.035613 -0.000886 10000 0 10000 5804020
1068442191 -0.035545 0.000068 10000 5804019 10000 5358801
1068442203 -0.035345 0.000200 10000 5804019 10000 4491633
1068442217 -0.035103 0.000242 10000 5804019 10000 4219777
ACPI interrupts after the second test:
9: 0 0 IO-APIC-level acpi
-------------------------------------------------
Hope this helps a bit, and thanks for cc-ing me
Peter G.
--
I object to intellect without discipline; I object to power without
constructive purpose.
-- Spock, "The Squire of Gothos", stardate 2124.5
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] amd76x_pm on 2.6.0-test9 more cleanup and clock skew test
2003-11-10 6:01 ` Peter Gantner
@ 2003-11-10 18:04 ` Tony Lindgren
0 siblings, 0 replies; 3+ messages in thread
From: Tony Lindgren @ 2003-11-10 18:04 UTC (permalink / raw)
To: Peter Gantner; +Cc: linux-kernel, pasi.savolainen, Charles Lepple, f.maibaum
* Peter Gantner <peter.gantner@stud.uni-graz.at> [031109 22:02]:
> Quoting Tony Lindgren from Nov 9
>
> > On the clock skew problem, it's still there, and to figure out how bad the
> > problem is, I've done a little shell script based on the earlier thread on
> > adjtimex on this mailing list.
>
> Here are my results from your script.
Thanks!
> I did three runs each, first run idle, two runs under load, i.e. two
> burnK7 processes and a make -j5 kernel compile just to make sure.
> loadavg goes up to ~6.5 during those.
> ntpd was not running during the tests.
Great, I was only expecting results from idle mode, but seeing what happens
under load is interesting to see too.
> System is an A7M266-d w/ two AthlonXPs 1800+ (model 6 stepping 2),
> L5-modded(!) for the MP setup. (I know this is considered tainting,
> if you can tell me the timing issues are related to the modding I
> will shut up immediately, but so far nobody seems to have pinpointed
> it to this.)
That should not make a difference. I think I'm getting pretty much similar
results with missed ticks. I'll try to take a look at it in early December
when I have access to my Athlon box again.
Tony
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2003-11-10 18:04 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-10 0:33 [PATCH] amd76x_pm on 2.6.0-test9 more cleanup and clock skew test Tony Lindgren
2003-11-10 6:01 ` Peter Gantner
2003-11-10 18:04 ` Tony Lindgren
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).