Skip to contentSkip to conversation

amd76x_pm on 2.6.0-test9 cleanup

PATCH In review Tony Lindgren 5 participants 17 messages Nov 4, 2003 – Nov 14, 2003 ACPI

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 amd76x_pm on 2.6.0-test9 cleanup

Hi all,

After a year of not having access to my dual athlon box I finally ran apt-get dist-upgrade on it :)

I also did some cleanup on the amd76x_pm to make the amd76x_pm to load as module, and to remove some unnecessary PCI code.

I used Pasi Savolainen's version amd76x_pm-2.6.0-test4.patch as the base for the driver.

I'm planning todo some more cleanup on the driver. Pasi do you have some changes in mind also so we can coordinate?

The patch is also available at:

http://www.muru.com/linux/amd-smp-idle/

Regards,

Tony

drivers/acpi/amd76x_pm.c +706 -0
diff -urN -X /home/tmlind/dontdiff linux-2.6.0-test9-vanilla/drivers/acpi/amd76x_pm.c linux-2.6.0-test9/drivers/acpi/amd76x_pm.c
@@ -0,0 +1,706 @@
+/*
+ * ACPI style PM for SMP AMD-760MP(X) based systems.
+ * For use until the ACPI project catches up. :-)
+ *
+ * Copyright (C) 2002 Johnathan Hicks <[email protected]>
+ *
+ * History:
+ * 
+ *   20020702 - amd-smp-idle: Tony Lindgren <[email protected]>
+ *	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)
+ *
+ *   20031027: Tony Lindgren
+ *      Fixed the loading as module and removed some unnecessary PCI code
+ *
+ * TODO: Thermal throttling (TTH).
+ * 	 /proc interface for normal throttling level.
+ * 	 /proc interface for POS.
+ *
+ *
+ *    <Notes from 20020722-ac revision>
+ *
+ * Processor idle mode module for AMD SMP 760MP(X) based systems
+ *
+ * Copyright (C) 2002 Tony Lindgren <[email protected]>
+ *                    Johnathan Hicks (768 support)
+ *
+ * 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.
+ *
+ * NOTE: Currently there's a bug somewhere where the reading the
+ *       P_LVL2 for the first time causes the system to sleep instead of 
+ *       idling. This means that you need to hit the power button once to
+ *       wake the system after loading the module for the first time after
+ *       reboot. After that the system idles as supposed.
+ *
+ *
+ * Influenced by Vcool, and LVCool. Rewrote everything from scratch to
+ * use the PCI features in Linux, and to support SMP systems.
+ * 
+ * Currently only tested on a TYAN S2460 (760MP) system (Tony) and an
+ * ASUS A7M266-D (760MPX) system (Johnathan). Adding support for other Athlon
+ * SMP or single processor systems should be easy if desired.
+ *
+ * This software is licensed under GNU General Public License Version 2 
+ * as specified in file COPYING in the Linux kernel source tree main 
+ * directory.
+ * 
+ *   </Notes from 20020722-ac revision>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/in.h>
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+
+#include <linux/amd76x_pm.h>
+
+#define VERSION	"20031027"
+
+// #define AMD76X_C3  1
+// #define AMD76X_NTH 1
+// #define AMD76X_POS 1
+
+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, 0, 0},
+	{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, 0, 0, 0},
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{0,}
+};
+
+static struct pci_driver amd_nb_driver = {
+	.name     = "amd76x_pm-nb",
+	.id_table = amd_nb_tbl,
+#ifdef CONFIG_PM
+	.suspend  = NULL,
+	.resume   = NULL,
+#endif
+};
+
+/*
+ * Configures the AMD-762 northbridge to support PM calls
+ */
+static int
+config_amd762(int enable)
+{
+	unsigned int regdword;
+
+	/* Enable STPGNT in BIU Status/Control for cpu0 */
+	pci_read_config_dword(pdev_nb, 0x60, &regdword);
+	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, &regdword);
+	regdword |= (1 << 17);
+	pci_write_config_dword(pdev_nb, 0x68, regdword);
+
+	/* DRAM refresh enable */
+	pci_read_config_dword(pdev_nb, 0x58, &regdword);
+	regdword &= ~(1 << 19);
+	pci_write_config_dword(pdev_nb, 0x58, regdword);
+
+	/* Self refresh enable */
+	pci_read_config_dword(pdev_nb, 0x70, &regdword);
+	regdword |= (1 << 18);
+	pci_write_config_dword(pdev_nb, 0x70, regdword);
+
+	return 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, &regdword);
+	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, &regbyte);
+	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, &regdword);
+	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);
+}
+
+
+#ifdef AMD76X_C3
+/*
+ * Untested C3 idle support for AMD-766.
+ */
+static void
+config_amd766_C3(int enable)
+{
+	unsigned int regdword;pci_module_init
+
+	/* Set C3 options in C3A50, page 63 in AMD-766 doc */
+	pci_read_config_dword(pdev_sb, 0x50, &regdword);
+	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);
+}
+#endif
+
+
+#ifdef AMD76X_POS
+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, &regdword);
+	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);
+}
+#endif
+
+
+/*
+ * Configures the 765 & 766 southbridges.
+ */
+static int
+config_amd766(int enable)
+{
+	amd76x_get_PM();
+	config_PMIO_amd76x(1, 1);
+
+	config_amd766_C2(enable);
+#ifdef AMD76X_C3
+	config_amd766_C3(enable);
+#endif
+#ifdef AMD76X_POS
+	config_amd766_POS(enable);
+#endif
+
+	return 0;
+}
+
+
+/*
+ * 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, &regbyte);
+	if(enable)
+		regbyte |= C2EN;
+	else
+		regbyte ^= C2EN;
+	pci_write_config_byte(pdev_sb, 0x4F, regbyte);
+}
+
+
+#ifdef AMD76X_C3
+/*
+ * 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, &regbyte);
+	if(enable)
+		regbyte |= (C3EN /* | ZZ_C3EN | CSLP_C3EN | CSTP_C3EN */);
+	else
+		regbyte ^= C3EN;
+	pci_write_config_byte(pdev_sb, 0x4F, regbyte);
+}
+#endif
+
+
+#ifdef AMD76X_POS
+/*
+ * 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, &regdword);
+	if(enable) 
+		regdword |= (POSEN | CSTP | PSTP | ASTP | DCSTP | CSLP | SUSP);
+	else
+		regdword ^= POSEN;
+	pci_write_config_dword(pdev_sb, 0x50, regdword);
+}
+#endif
+
+
+#ifdef AMD76X_NTH
+/*
+ * 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, &regbyte);
+	/* Is it neccessary to use THMINEN at ANY time? */
+	regbyte |= (NTPER(ntper) | THMINEN(thminen));
+	pci_write_config_byte(pdev_sb, 0x40, regbyte);
+}
+#endif
+
+
+/*
+ * Configures the 768 southbridge to support idle calls, and gets
+ * the processor idle call register location.
+ */
+static int
+config_amd768(int enable)
+{
+	amd76x_get_PM();
+
+	config_PMIO_amd76x(0, 1);
+
+	config_amd768_C2(enable);
+#ifdef AMD76X_C3
+	config_amd768_C3(enable);
+#endif
+#ifdef AMD76X_POS
+	config_amd768_POS(enable);
+#endif
+#ifdef AMD76X_NTH
+	config_amd768_NTH(enable, 1, 2);
+#endif
+
+	return 0;
+}
+
+
+#ifdef AMD76X_NTH
+/*
+ * 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);
+}
+#endif
+
+#ifdef AMD76X_SLP
+/*
+ * 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);
+}
+#endif /* AMD76X_SLP */
+
+#ifdef AMD76X_POS
+/*
+ * Wrapper function to activate POS sleep state.
+ */
+static void
+activate_amd76x_POS(void)
+{
+	activate_amd76x_SLP(1);
+}
+#endif
+
+
+/*
+ * 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);
+		}
+ #ifdef AMD76X_C3
+		/*
+		 * 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?
+		 */
+		else if ((prs[0].idle==2) && (prs[1].idle==2)) {
+			amd76x_pm_cfg.C3_cnt++;
+			inb(amd76x_pm_cfg.C3_reg);
+		}
+ #endif
+
+		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);
+
+/*
+ * Finds and initializes the bridges, and then sets the idle function
+ */
+static int
+amd76x_pm_main(void)
+{
+	int found;
+	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 */
+	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:
+	found = pci_module_init(&amd_nb_driver);
+	if (found < 0) {
+		printk(KERN_ERR "amd76x_pm: Could not initialize northbridge\n");
+		return -ENODEV;
+	}
+
+	/* Init southbridge */
+	switch (pdev_sb->device) {
+	case PCI_DEVICE_ID_AMD_VIPER_7413:	/* AMD-765 or 766 */
+		config_amd766(1);
+		break;
+	case PCI_DEVICE_ID_AMD_VIPER_7443:	/* AMD-768 */
+		config_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");
+		pci_unregister_driver(&amd_nb_driver);
+		return -ENODEV;
+	}
+	switch (pdev_nb->device) {
+	case PCI_DEVICE_ID_AMD_FE_GATE_700C:	/* AMD-762 */
+		config_amd762(1);
+#ifndef AMD76X_NTH
+		amd76x_pm_cfg.curr_idle = amd76x_smp_idle;
+#endif
+		break;
+	default:
+		printk(KERN_ERR "amd76x_pm: No northbridge to initialize\n");
+		break;
+	}
+
+#ifndef AMD76X_NTH
+	if(num_online_cpus() == 1) {
+		amd76x_pm_cfg.curr_idle = amd76x_up_idle;
+		printk(KERN_ERR "amd76x_pm: UP machine detected. ACPI is your friend.\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);
+#endif
+
+#ifdef AMD76X_NTH
+	/* Turn NTH on with maxium throttling for testing. */
+	activate_amd76x_NTH(1, 1);
+#endif
+
+#ifdef AMD76X_POS
+	/* Testing here only. */
+	activate_amd76x_POS();
+#endif
+	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)
+{
+#ifndef 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);
+
+#ifdef AMD76X_C3
+	printk(KERN_INFO "amd76x_pm: %lu C3 calls\n", amd76x_pm_cfg.C3_cnt);
+#endif
+	/* 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);
+
+#endif
+
+#ifdef AMD76X_NTH
+	/* Turn NTH off*/
+	activate_amd76x_NTH(0, 0);
+#endif
+
+	pci_unregister_driver(&amd_nb_driver);
+}
+
+
+MODULE_LICENSE("GPL");
+module_init(amd76x_pm_init);
+module_exit(amd76x_pm_cleanup);

Binary files linux-2.6.0-test9-vanilla/drivers/acpi/amd76x_pm.ko and linux-2.6.0-test9/drivers/acpi/amd76x_pm.ko differ

drivers/acpi/Kconfig +17 -1
diff -urN -X /home/tmlind/dontdiff linux-2.6.0-test9-vanilla/drivers/acpi/Kconfig linux-2.6.0-test9/drivers/acpi/Kconfig
@@ -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
drivers/acpi/Makefile +5 -0
diff -urN -X /home/tmlind/dontdiff linux-2.6.0-test9-vanilla/drivers/acpi/Makefile linux-2.6.0-test9/drivers/acpi/Makefile
@@ -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
include/linux/amd76x_pm.h +59 -0

59 lines not on this page · raw message

#1 lore raw
Quoted 5 lines · Tony Lindgren

After a year of not having access to my dual athlon box I finally ran apt-get dist-upgrade on it :)

I also did some cleanup on the amd76x_pm to make the amd76x_pm to load as module, and to remove some unnecessary PCI code.

I've received some reports that this patch causes time problems.

Have those issues been looked into further, or addressed?

thanks
-john

#2 lore raw
Quoted 10 lines · john stultz
Quoted 5 lines · Tony Lindgren

After a year of not having access to my dual athlon box I finally ran apt-get dist-upgrade on it :)

I also did some cleanup on the amd76x_pm to make the amd76x_pm to load as module, and to remove some unnecessary PCI code.

I've received some reports that this patch causes time problems.

Have those issues been looked into further, or addressed?

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

Then the 2.4 version does not load if i2c-amd756 is loaded, but this may have been already fixed by this patch, I have not verified it yet though.

I have problem where my S2460 goes into sleep for a while if compiled in, but this does not happen when loaded as module.

So it looks like there are some dependencies to other drivers that need to be sorted out, or amd76x_pm needs to be loaded after some other initializations.

Tony

#3 lore raw
Quoted 2 lines · Tony Lindgren

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

In some of the earlier testX versions of the kernel, I did not see any difference between compiling as a module, and compiling into the kernel. (It is currently a module on my system.)

I did, however, manage to keep ntpd happy by reducing HZ to 100. Even raising HZ to 200 is enough to throw off its PLL. The machine is idle for 90% of the day, though, so I don't know if the PLL is adapting to the fact that the system is idling, but the values for tick look reasonable.

Quoted 2 lines

Then the 2.4 version does not load if i2c-amd756 is loaded, but this may have been already fixed by this patch, I have not verified it yet though.

Pasi's patch against test9 seems to work fine in this regard. I am running with i2c_amd756 and amd_k7_agp now, and neither one has trouble loading anymore (after a cold boot, anyway).

Quoted 2 lines

I have problem where my S2460 goes into sleep for a while if compiled in, but this does not happen when loaded as module.

After a warm reboot on my S2460 motherboard, it seems as though the module occasionally needs to receive an interrupt from somewhere ACPI-related. Most of the time, this means that I have to press either the soft power button or the sleep button to get the system to continue booting (!).

I am using the default #defines (i.e. no C3, POS or NTH enabled).

Info on the northbridge:

$ lspci -vn -s 0:0
00:00.0 Class 0600: 1022:700c (rev 11)
...

and the southbridge:

$ lspci -vn -s 7:3
00:07.3 Class 0680: 1022:7413 (rev 01)
...

I looked through the chipset documentation again (specifically checking the errata for these revisions), and nothing jumped out at me. I won't be able to look at this in depth for another month or two, though.

Signature · 2 lines
Charles Lepple
ghz.cc!clepple
#4 lore raw
Quoted 4 lines · Charles Lepple
Quoted 2 lines · Tony Lindgren

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

Quoted 8 lines

In some of the earlier testX versions of the kernel, I did not see any difference between compiling as a module, and compiling into the kernel. (It is currently a module on my system.)

I did, however, manage to keep ntpd happy by reducing HZ to 100. Even raising HZ to 200 is enough to throw off its PLL. The machine is idle for 90% of the day, though, so I don't know if the PLL is adapting to the fact that the system is idling, but the values for tick look reasonable.

Interesting, sounds like the idling causes missed timer interrupts? Can you briefly describe what's the easiest way to reproduce the timer problem, just change HZ to 200 and look at the system time?

Quoted 6 lines
Quoted 2 lines

Then the 2.4 version does not load if i2c-amd756 is loaded, but this may have been already fixed by this patch, I have not verified it yet though.

Pasi's patch against test9 seems to work fine in this regard. I am running with i2c_amd756 and amd_k7_agp now, and neither one has trouble loading anymore (after a cold boot, anyway).

OK

Quoted 9 lines
Quoted 2 lines

I have problem where my S2460 goes into sleep for a while if compiled in, but this does not happen when loaded as module.

After a warm reboot on my S2460 motherboard, it seems as though the module occasionally needs to receive an interrupt from somewhere ACPI-related. Most of the time, this means that I have to press either the soft power button or the sleep button to get the system to continue booting (!).

I am using the default #defines (i.e. no C3, POS or NTH enabled).

I had this problem when compiled in, but not as module though. I've been using kexec for reboots recently though as the bios reboot is soo slow.

But just to verify: 2.6.0-test9 & amd76x_pm as module, and the system drops into sleep mode when the module is loaded for the first time until power is pressed? And this does not happen after cold reboots or when the amd76x_pm is reloaded?

Quoted 3 lines

I looked through the chipset documentation again (specifically checking the errata for these revisions), and nothing jumped out at me. I won't be able to look at this in depth for another month or two, though.

I'm thinking this one is a BIOS bug in S2460, as it does not happen on other boards AFAIK. Anybody have a working linuxbios config for S2460?

Tony

#5 lore raw
Quoted 9 lines · Tony Lindgren
Quoted 8 lines · Charles Lepple
Quoted 2 lines · Tony Lindgren

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

In some of the earlier testX versions of the kernel, I did not see any difference between compiling as a module, and compiling into the kernel. (It is currently a module on my system.)

Quoted 8 lines
Quoted 4 lines

I did, however, manage to keep ntpd happy by reducing HZ to 100. Even raising HZ to 200 is enough to throw off its PLL. The machine is idle for 90% of the day, though, so I don't know if the PLL is adapting to the fact that the system is idling, but the values for tick look reasonable.

Interesting, sounds like the idling causes missed timer interrupts? Can you briefly describe what's the easiest way to reproduce the timer problem, just change HZ to 200 and look at the system time?

At HZ=200, it would take a while to notice. I used adjtimexconfig, which counts the number of kernel ticks which occur in 70 seconds (according to the RTC). The RTC is pretty stable without power management, so I tend to trust it. I think I ended up with a value of tick=11000 (compensation for a 10% slow clock), and if I left the machine idle, ntpd would converge based on the new tick value.

Then again, I don't think I tried HZ>=200 on -test9. (When I got Pasi's -test9 patch, I applied it to a -test8-bk kernel with HZ=1000-- I don't remember exactly which one.) Based on his followup email, timekeeping may be better in -test9. I'll check.

Quoted 1 line

I've been using kexec for reboots recently though as the bios reboot is soo slow.

The slowness on my system is supposedly related to ECC initialization, but it's only ~30 seconds for 512MB. Still, if I upgrade the memory, that's a good tip.

Quoted 4 lines

But just to verify: 2.6.0-test9 & amd76x_pm as module, and the system drops into sleep mode when the module is loaded for the first time until power is pressed? And this does not happen after cold reboots or when the amd76x_pm is reloaded?

Correct.

Signature · 2 lines
Charles Lepple
[email protected]
#6 lore raw
In reply to Tony Lindgren
Quoted 9 lines · Tony Lindgren
Quoted 8 lines · Charles Lepple
Quoted 2 lines · Tony Lindgren

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

In some of the earlier testX versions of the kernel, I did not see any difference between compiling as a module, and compiling into the kernel. (It is currently a module on my system.)

Quoted 8 lines
Quoted 4 lines

I did, however, manage to keep ntpd happy by reducing HZ to 100. Even raising HZ to 200 is enough to throw off its PLL. The machine is idle for 90% of the day, though, so I don't know if the PLL is adapting to the fact that the system is idling, but the values for tick look reasonable.

Interesting, sounds like the idling causes missed timer interrupts? Can you briefly describe what's the easiest way to reproduce the timer problem, just change HZ to 200 and look at the system time?

Weird. On -test9-bk at HZ=1000, with amd76x_pm loaded as a module (lazy_idle=800, the default), the system clock is running fast.

With ntpd running, the clock was stepped back 2.5 seconds twice in 20 minutes.

Here's what I get from adjtimexconfig (after stopping ntpd, of course):

# adjtimexconfig
Comparing clocks (this will take 70 sec)... adjusting system time by  -126.211  sec/day
Done

Now tick is 9985. I distinctly remember it being somewhat over 10,000 the last time I ran with HZ=1000 and amd_76x_pm active. With HZ=100, adjtimexconfig sets tick=10002.

I'm not entirely sure what the "acpi" interrupt is doing-- it increments about once every two seconds when the system is idle, and various types of system activity make it happen more frequently. At least I'm not getting any "irq 9: nobody cared!" messages anymore (the button module is loaded, so I guess it is handling it). If I don't have amd76x_pm loaded, the acpi interrupt is triggered a couple of times after button is loaded, but then it doesn't happen again until I actually press a button.

Signature · 2 lines
Charles Lepple
ghz.cc! clepple
#7 lore raw
Quoted 44 lines · Charles Lepple
Quoted 19 lines · Tony Lindgren
Quoted 10 lines · Charles Lepple
Quoted 3 lines · Tony Lindgren

I've heard of timing problems if it's compiled in, but supposedly they
don't happen when loaded as module.

In some of the earlier testX versions of the kernel, I did not see any difference between compiling as a module, and compiling into the kernel. (It
is currently a module on my system.)

Quoted 7 lines

I did, however, manage to keep ntpd happy by reducing HZ to 100. Even raising
HZ to 200 is enough to throw off its PLL. The machine is idle for 90% of the
day, though, so I don't know if the PLL is adapting to the fact that the
system is idling, but the values for tick look reasonable.

Quoted 5 lines

Interesting, sounds like the idling causes missed timer interrupts? Can you
briefly describe what's the easiest way to reproduce the timer problem, just
change HZ to 200 and look at the system time?

Weird. On -test9-bk at HZ=1000, with amd76x_pm loaded as a module (lazy_idle=800, the default), the system clock is running fast.

With ntpd running, the clock was stepped back 2.5 seconds twice in 20 minutes.

Here's what I get from adjtimexconfig (after stopping ntpd, of course):

# adjtimexconfig
Comparing clocks (this will take 70 sec)... adjusting system time by  
-126.211  sec/day
Done

Now tick is 9985. I distinctly remember it being somewhat over 10,000 the last time I ran with HZ=1000 and amd_76x_pm active. With HZ=100, adjtimexconfig sets tick=10002.

Quoted 8 lines

I'm not entirely sure what the "acpi" interrupt is doing-- it increments about once every two seconds when the system is idle, and various types of system activity make it happen more frequently. At least I'm not getting any "irq 9: nobody cared!" messages anymore (the button module is loaded, so I guess it is handling it). If I don't have amd76x_pm loaded, the acpi interrupt is triggered a couple of times after button is loaded, but then it doesn't happen again until I actually press a button.

Weird. On my system the irq 9 count is still 0 0 since I started the machine this morning. I have ACPI compiled into the kernel, and then load amd76x_pm as module. But I have HZ=100, I'll try it with HZ=1000 at some point.

But it sounds like the timer problem may be related to the snooze-on-load problem on S2460, especially if the timer problem only happens on S2460.

Tony

#8 lore raw
Quoted 17 lines · Tony Lindgren
Quoted 16 lines · Charles Lepple
Quoted 14 lines · Tony Lindgren
Quoted 12 lines · Charles Lepple
Quoted 3 lines · Tony Lindgren

I've heard of timing problems if it's compiled in, but supposedly they
don't happen when loaded as module.

I did, however, manage to keep ntpd happy by reducing HZ to 100. Even raising
HZ to 200 is enough to throw off its PLL. The machine is idle for 90% of the
day, though, so I don't know if the PLL is adapting to the fact that the
system is idling, but the values for tick look reasonable.

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

Interesting, sounds like the idling causes missed timer interrupts? Can you
briefly describe what's the easiest way to reproduce the timer problem, just
change HZ to 200 and look at the system time?

AFAIK the problem was that TSC's got desynchronized and the gettimeofday didn't produce monotonic dates at that.

You could make problem go away either by setting HZ=100 or compiling without TSC support. (kerneloption notsc didn't have the effect).

Quoted 2 lines
Quoted 2 lines

Weird. On -test9-bk at HZ=1000, with amd76x_pm loaded as a module (lazy_idle=800, the default), the system clock is running fast.

I'm making mrtg graphs of /sys/devices/pci0000\:00/0000\:00\:00.0/C2_cnt , and it looks like -test9 is calling it at a rate of 1100Hz, compared to ~1000Hz on previous (HZ=1000) kernels.
Of course these numbers are not under mutex and increased by both processors.

With ntpd I'm getting following:

Nov  5 00:26:32 tienel ntpd[501]: time reset -7.151071 s
Nov  5 00:26:32 tienel ntpd[501]: synchronisation lost
Nov  5 00:41:35 tienel ntpd[501]: time reset -7.150284 s
Nov  5 00:41:35 tienel ntpd[501]: synchronisation lost

So drift is about 10min / 24h (unless I botched the math, it seems to happen after a dose of modula-3)

Signature · 1 line
Psi -- <http://www.iki.fi/pasi.savolainen>
#9 lore raw
In reply to Tony Lindgren
Quoted 8 lines · Tony Lindgren
Quoted 7 lines · john stultz
Quoted 5 lines · Tony Lindgren

After a year of not having access to my dual athlon box I finally ran apt-get dist-upgrade on it :)

I also did some cleanup on the amd76x_pm to make the amd76x_pm to load as module, and to remove some unnecessary PCI code.

Quoted 6 lines
Quoted 3 lines

I've received some reports that this patch causes time problems.

Have those issues been looked into further, or addressed?

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

Not happening since 2.6.0-test9. Don't know what really fixed it, but they're just not there anymore.

Quoted 2 lines

Then the 2.4 version does not load if i2c-amd756 is loaded, but this may have been already fixed by this patch, I have not verified it yet though.

Most probably caused by the same thing that prevented it loading under amd_k7_agp, that is indeed sorted out.

Quoted 2 lines

I have problem where my S2460 goes into sleep for a while if compiled in, but this does not happen when loaded as module.

Could you have some AMD_76X -define left over? I skimmed through MP & MPX AMD documents, but found nothing incriminating.
Could it be ACPI doing it's things with S -states? (it does check for SMP, but does report S -states as supported). And if ACPI isn't enabled, could you toggle it on, or vice-versa.

Signature · 1 line
Psi -- <http://www.iki.fi/pasi.savolainen>
#10 lore raw
Quoted 5 lines · Pasi Savolainen
Quoted 4 lines · Tony Lindgren
Quoted 3 lines · john stultz

On Mon, 2003-11-03 at 16:22, Tony Lindgren wrote:
I've received some reports that this patch causes time problems.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

Have those issues been looked into further, or addressed?

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

Not happening since 2.6.0-test9. Don't know what really fixed it, but they're just not there anymore.

Weird, John, is this true on your S2460 also?

Quoted 5 lines
Quoted 2 lines

Then the 2.4 version does not load if i2c-amd756 is loaded, but this may have been already fixed by this patch, I have not verified it yet though.

Most probably caused by the same thing that prevented it loading under amd_k7_agp, that is indeed sorted out.

OK

Quoted 8 lines
Quoted 2 lines

I have problem where my S2460 goes into sleep for a while if compiled in, but this does not happen when loaded as module.

Could you have some AMD_76X -define left over? I skimmed through MP & MPX AMD documents, but found nothing incriminating.
Could it be ACPI doing it's things with S -states? (it does check for SMP, but does report S -states as supported). And if ACPI isn't enabled, could you toggle it on, or vice-versa.

Well, I think I had this problem originally in amd-smp-idle.c before there was any ACPI support in the module. It's probably related to some ACPI register though.

Tony

#11 lore raw
Quoted 8 lines · Tony Lindgren
Quoted 7 lines · Pasi Savolainen
Quoted 6 lines · Tony Lindgren
Quoted 4 lines · john stultz

On Mon, 2003-11-03 at 16:22, Tony Lindgren wrote:
I've received some reports that this patch causes time problems.

Have those issues been looked into further, or addressed?

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

Not happening since 2.6.0-test9. Don't know what really fixed it, but they're just not there anymore.

Weird, John, is this true on your S2460 also?

I don't have any such hardware. I just saw related problem reports dealing with the time code and wanted to make sure they were addressed.

thanks
-john

#12 lore raw
Quoted 12 lines · john stultz
Quoted 11 lines · Tony Lindgren
Quoted 10 lines · Pasi Savolainen
Quoted 8 lines · Tony Lindgren
Quoted 4 lines · john stultz

On Mon, 2003-11-03 at 16:22, Tony Lindgren wrote:
I've received some reports that this patch causes time problems.

Have those issues been looked into further, or addressed?

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Not happening since 2.6.0-test9. Don't know what really fixed it, but they're just not there anymore.

Weird, John, is this true on your S2460 also?

I don't have any such hardware. I just saw related problem reports dealing with the time code and wanted to make sure they were addressed.

Sorry, meant to ask Charles. Looks like he already is going to check it.

Tony

#13 lore raw
In reply to Tony Lindgren
Quoted 8 lines · Tony Lindgren
Quoted 7 lines · Pasi Savolainen
Quoted 6 lines · Tony Lindgren
Quoted 4 lines · john stultz

On Mon, 2003-11-03 at 16:22, Tony Lindgren wrote:
I've received some reports that this patch causes time problems.

Have those issues been looked into further, or addressed?

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

Not happening since 2.6.0-test9. Don't know what really fixed it, but they're just not there anymore.

Weird, John, is this true on your S2460 also?

Well I'll be damned. It took 18 days to show up. Though I've been riding this baby heavy for about a week.
So I've gettimeofday() jumping backwards again.

# uname -a
Linux tienel 2.6.0-test9 #2 SMP Sun Oct 26 14:35:02 EET 2003 i686 GNU/Linux

It's this test I'm running (snipped from previous TSC desych -conversation):

- -
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>

int main( void )

{
        int                     i = 0;

        while( 1 )
        {
                struct timeval          start;
                struct timeval          stop;
                struct timeval          diff;
                int                     rc1;
                int                     rc2;

                if( i++ % 1000000 == 0 )
                        printf( "% 12d: Iterations so far\n", i );

                rc1 = gettimeofday( &start, 0 );
                rc2 = gettimeofday( &stop, 0 );
                timersub( &stop, &start, &diff );

                if( rc1 < 0 || rc2 < 0 )
                        printf( " %12d: rc1=%d rc2=%d.   Failure!\n",
                                i,
                                rc1,
                                rc2
                        );

                if( diff.tv_sec >= 0 && diff.tv_usec >= 0 )
                        continue;

                printf( "% 12d: Time went backwards: %d:%06d\n",
                        i,
                        diff.tv_sec,
                        diff.tv_usec
                );

        }
}

- -

Signature · 1 line
Psi -- <http://www.iki.fi/pasi.savolainen>
#14 lore raw
In reply to Pasi Savolainen
Quoted 9 lines · Pasi Savolainen
Quoted 2 lines · Tony Lindgren

I have problem where my S2460 goes into sleep for a while if compiled in, but this does not happen when loaded as module.

Could you have some AMD_76X -define left over? I skimmed through MP & MPX AMD documents, but found nothing incriminating.
Could it be ACPI doing it's things with S -states? (it does check for SMP, but does report S -states as supported). And if ACPI isn't enabled, could you toggle it on, or vice-versa.

I wonder if the initialization code puts the chipset to sleep as it is setting up the stopgrant control bits?

Here's a wild hypothesis: module loads, twiddles the registers, and the chipset enters sleep mode. In certain cases, enough interrupts are unmasked that the next interrupt wakes the chipset up, and things continue on their merry way. In other cases, it takes an ACPI interrupt (which, in my case, has not been initialized, since my BIOS evidently doesn't officially support ACPI C states) to wake things up (e.g. from a front-panel button).

FWIW, I just found this in the dmesg output:

irq 9: nobody cared!

Call Trace:
 [<c010b7ba>] __report_bad_irq+0x2a/0x90
 [<c010b8ac>] note_interrupt+0x6c/0xa0
 [<c010bbdb>] do_IRQ+0x15b/0x190
 [<c0109d88>] common_interrupt+0x18/0x20
 [<e10ac26d>] amd76x_smp_idle+0x0/0xba [amd76x_pm]
 [<e10ac302>] amd76x_smp_idle+0x95/0xba [amd76x_pm]
 [<c0106f63>] cpu_idle+0x33/0x40
 [<c0120f04>] printk+0x164/0x1d0

handlers:
[<c01ebeb3>] (acpi_irq+0x0/0x16)
Disabling IRQ #9

Interestingly enough, I guess the 'button' module has claimed IRQ 9, since I have this in /proc/interrupts:

9: 5013 94989 IO-APIC-edge acpi

Well, I'm officially confused :-)

Signature · 2 lines
Charles Lepple
[email protected]
#15 lore raw
Quoted 16 lines · Charles Lepple
Quoted 10 lines · Pasi Savolainen
Quoted 3 lines · Tony Lindgren

I have problem where my S2460 goes into sleep for a while if compiled in,
but this does not happen when loaded as module.

Could you have some AMD_76X -define left over? I skimmed through MP & MPX AMD documents, but found nothing incriminating.
Could it be ACPI doing it's things with S -states? (it does check for SMP, but does report S -states as supported). And if ACPI isn't enabled, could you toggle it on, or vice-versa.

I wonder if the initialization code puts the chipset to sleep as it is setting up the stopgrant control bits?

Quoted 7 lines

Here's a wild hypothesis: module loads, twiddles the registers, and the chipset enters sleep mode. In certain cases, enough interrupts are unmasked that the next interrupt wakes the chipset up, and things continue on their merry way. In other cases, it takes an ACPI interrupt (which, in my case, has not been initialized, since my BIOS evidently doesn't officially support ACPI C states) to wake things up (e.g. from a front-panel button).

Yeah, that makes sense.

Quoted 17 lines

FWIW, I just found this in the dmesg output:

irq 9: nobody cared!

Call Trace:
 [<c010b7ba>] __report_bad_irq+0x2a/0x90
 [<c010b8ac>] note_interrupt+0x6c/0xa0
 [<c010bbdb>] do_IRQ+0x15b/0x190
 [<c0109d88>] common_interrupt+0x18/0x20
 [<e10ac26d>] amd76x_smp_idle+0x0/0xba [amd76x_pm]
 [<e10ac302>] amd76x_smp_idle+0x95/0xba [amd76x_pm]
 [<c0106f63>] cpu_idle+0x33/0x40
 [<c0120f04>] printk+0x164/0x1d0

handlers:
[<c01ebeb3>] (acpi_irq+0x0/0x16)
Disabling IRQ #9

Quoted 6 lines

Interestingly enough, I guess the 'button' module has claimed IRQ 9, since I have this in /proc/interrupts:

9: 5013 94989 IO-APIC-edge acpi

Well, I'm officially confused :-)

Is your ACPI button a module too? Maybe load ACPI button first, then amd76x_pm?

Tony

#16 lore raw
In reply to Tony Lindgren
Quoted 2 lines · Tony Lindgren

I've heard of timing problems if it's compiled in, but supposedly they don't happen when loaded as module.

As of 2.4.22 they happen regardless of compiling the code as a module or statically

Quoted 3 lines

So it looks like there are some dependencies to other drivers that need to be sorted out, or amd76x_pm needs to be loaded after some other initializations.

In an older thread it was mentioned that the module should sync the TSCs to the bios clock, or at least between the processors when it wakes up.

regards

Felix

Signature · 1 line
LINUX - because booting is for adding hardware!