2004-09-24 06:39:47

by Suresh Siddha

[permalink] [raw]
Subject: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

As part of the workaround for the "Interrupt message re-ordering across
hub interface" errata (page #16 in
http://developer.intel.com/design/chipsets/specupdt/30288402.pdf),
BIOS may enable hardware IRQ balancing for Lindenhurst/Tumwater based chipset
platforms. Software based irq_balance/irq_affinity should be disabled if
hardware IRQ balancing is enabled.

This is applicable for chipsets with PCI id's

E7520, 0x3590
E7320, 0x3592
E7525, 0x359E

and with revision ID 0x09 and below.

Patch is broken into two parts.

1/2 - Set TARGET_CPUS on x86_64 to cpu_online_map. This brings the code inline
with x86 mach-default
2/2 - Add pci quirks to disable irq_balance/affinity based on the above
information and make sure destination cpus in IO-APIC redirection table
entries are set to cpu_online_map

Signed-off-by: Suresh Siddha <[email protected]>


2004-09-24 15:13:33

by Zwane Mwaikambo

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

On Thu, 23 Sep 2004, Suresh Siddha wrote:

> As part of the workaround for the "Interrupt message re-ordering across
> hub interface" errata (page #16 in
> http://developer.intel.com/design/chipsets/specupdt/30288402.pdf),
> BIOS may enable hardware IRQ balancing for Lindenhurst/Tumwater based chipset
> platforms. Software based irq_balance/irq_affinity should be disabled if
> hardware IRQ balancing is enabled.

Can we avoid those tests? Like not starting the irq balancer code at all
with those chipsets?

Thanks,
Zwane

2004-09-24 20:25:40

by Jeff Garzik

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

Zwane Mwaikambo wrote:
> On Thu, 23 Sep 2004, Suresh Siddha wrote:
>
>
>>As part of the workaround for the "Interrupt message re-ordering across
>>hub interface" errata (page #16 in
>>http://developer.intel.com/design/chipsets/specupdt/30288402.pdf),
>>BIOS may enable hardware IRQ balancing for Lindenhurst/Tumwater based chipset
>>platforms. Software based irq_balance/irq_affinity should be disabled if
>>hardware IRQ balancing is enabled.
>
>
> Can we avoid those tests? Like not starting the irq balancer code at all
> with those chipsets?


That's my preference.

Or, compile with !CONFIG_KIRQD -- the recommended setting for modern
distros, since irqbalanced(1) is shipped.

Jeff


2004-09-24 22:21:36

by Suresh Siddha

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

On Fri, Sep 24, 2004 at 04:24:47PM -0400, Jeff Garzik wrote:
> Zwane Mwaikambo wrote:
> > On Thu, 23 Sep 2004, Suresh Siddha wrote:
> >
> >
> >>As part of the workaround for the "Interrupt message re-ordering across
> >>hub interface" errata (page #16 in
> >>http://developer.intel.com/design/chipsets/specupdt/30288402.pdf),
> >>BIOS may enable hardware IRQ balancing for Lindenhurst/Tumwater based chipset
> >>platforms. Software based irq_balance/irq_affinity should be disabled if
> >>hardware IRQ balancing is enabled.
> >
> >
> > Can we avoid those tests? Like not starting the irq balancer code at all
> > with those chipsets?
>
>
> That's my preference.
>

Ok. How about this patch?

Add pci quirks to disable irqbalance/affinity for E7520/E7320/E7525
with revision ID 0x09 and below.

Signed-off-by: Suresh Siddha <[email protected]>

diff -Nru linux-2.6.9-rc2/arch/i386/kernel/io_apic.c linux-irq/arch/i386/kernel/io_apic.c
--- linux-2.6.9-rc2/arch/i386/kernel/io_apic.c 2004-09-12 22:32:00.000000000 -0700
+++ linux-irq/arch/i386/kernel/io_apic.c 2004-09-04 12:12:42.499670496 -0700
@@ -31,6 +31,7 @@
#include <linux/mc146818rtc.h>
#include <linux/compiler.h>
#include <linux/acpi.h>
+#include <linux/pci.h>

#include <linux/sysdev.h>
#include <asm/io.h>
@@ -260,7 +261,7 @@
cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];

#define IRQBALANCE_CHECK_ARCH -999
-static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
+int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
static int physical_balance = 0;

struct irq_cpu_info {
@@ -582,6 +583,30 @@
return 0;
}

+/* HW irqbalance may be enabled for E7520/E7320/E7525 with revision ID
+ * 0x09 and below. Disable sw irqbalance in that case
+ */
+static void check_hw_irqbalance(void)
+{
+ struct pci_dev *dev = NULL;
+ extern void quirk_intel_irqbalance(struct pci_dev *dev);
+
+ dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH,
+ dev);
+ if (!dev)
+ dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_E7320_MCH, dev);
+ if (!dev)
+ dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_E7525_MCH, dev);
+ if (!dev)
+ return;
+
+ quirk_intel_irqbalance(dev);
+
+ return;
+}
+
static int __init balanced_irq_init(void)
{
int i;
@@ -590,6 +615,8 @@

cpus_shift_right(tmp, cpu_online_map, 2);
c = &boot_cpu_data;
+
+ check_hw_irqbalance();
/* When not overwritten by the command line ask subarchitecture. */
if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH)
irqbalance_disabled = NO_BALANCE_IRQ;
@@ -636,7 +663,7 @@
return 0;
}

-static int __init irqbalance_disable(char *str)
+int __init irqbalance_disable(char *str)
{
irqbalance_disabled = 1;
return 0;
diff -Nru linux-2.6.9-rc2/arch/i386/kernel/irq.c linux-irq/arch/i386/kernel/irq.c
--- linux-2.6.9-rc2/arch/i386/kernel/irq.c 2004-09-12 22:31:30.000000000 -0700
+++ linux-irq/arch/i386/kernel/irq.c 2004-09-04 11:48:21.000000000 -0700
@@ -272,7 +272,7 @@

static int noirqdebug;

-static int __init noirqdebug_setup(char *str)
+int __init noirqdebug_setup(char *str)
{
noirqdebug = 1;
printk("IRQ lockup detection disabled\n");
@@ -997,13 +997,15 @@
return len;
}

+int no_irq_affinity;
+
static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int irq = (long)data, full_count = count, err;
cpumask_t new_value, tmp;

- if (!irq_desc[irq].handler->set_affinity)
+ if (!irq_desc[irq].handler->set_affinity || no_irq_affinity)
return -EIO;

err = cpumask_parse(buffer, count, new_value);
diff -Nru linux-2.6.9-rc2/arch/x86_64/kernel/irq.c linux-irq/arch/x86_64/kernel/irq.c
--- linux-2.6.9-rc2/arch/x86_64/kernel/irq.c 2004-09-12 22:32:26.000000000 -0700
+++ linux-irq/arch/x86_64/kernel/irq.c 2004-09-04 11:48:23.000000000 -0700
@@ -835,6 +835,8 @@
return len;
}

+int no_irq_affinity;
+
static int irq_affinity_write_proc (struct file *file,
const char __user *buffer,
unsigned long count, void *data)
@@ -842,7 +844,7 @@
int irq = (long) data, full_count = count, err;
cpumask_t tmp, new_value;

- if (!irq_desc[irq].handler->set_affinity)
+ if (!irq_desc[irq].handler->set_affinity || no_irq_affinity)
return -EIO;

err = cpumask_parse(buffer, count, new_value);
diff -Nru linux-2.6.9-rc2/drivers/pci/quirks.c linux-irq/drivers/pci/quirks.c
--- linux-2.6.9-rc2/drivers/pci/quirks.c 2004-09-12 22:31:27.000000000 -0700
+++ linux-irq/drivers/pci/quirks.c 2004-09-04 12:33:54.373316312 -0700
@@ -814,6 +814,64 @@
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );

+#ifdef CONFIG_X86_IO_APIC
+#include <asm/hw_irq.h>
+#ifdef CONFIG_IRQBALANCE
+extern int irqbalance_disable(char *str);
+#endif
+extern int no_irq_affinity;
+extern int noirqdebug_setup(char *str);
+
+
+void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+{
+ u8 config, rev;
+ u32 word;
+ extern struct pci_raw_ops *raw_pci_ops;
+#ifdef CONFIG_IRQBALANCE
+ extern int irqbalance_disabled;
+
+ /* we might have come through check_hw_irqbalance()
+ * and enabled the workaround
+ */
+ if (irqbalance_disabled == 1 && no_irq_affinity)
+ return;
+#endif
+
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+ if (rev > 0x9)
+ return;
+
+ printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+
+ /* enable access to config space*/
+ pci_read_config_byte(dev, 0xf4, &config);
+ config |= 0x2;
+ pci_write_config_byte(dev, 0xf4, config);
+
+ /* read xTPR register */
+ raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+
+ if (!(word & (1 << 13))) {
+ printk(KERN_INFO "Disabling irq balancing and affinity\n");
+#ifdef __i386__
+#ifdef CONFIG_IRQBALANCE
+ irqbalance_disable("");
+#endif
+ noirqdebug_setup("");
+#endif
+ no_irq_affinity = 1;
+ }
+
+ config &= ~0x2;
+ /* disable access to config space*/
+ pci_write_config_byte(dev, 0xf4, config);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
+#endif
+
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
*/
diff -Nru linux-2.6.9-rc2/include/linux/pci_ids.h linux-irq/include/linux/pci_ids.h
--- linux-2.6.9-rc2/include/linux/pci_ids.h 2004-09-12 22:33:54.000000000 -0700
+++ linux-irq/include/linux/pci_ids.h 2004-09-04 11:48:26.000000000 -0700
@@ -2204,6 +2204,8 @@
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
#define PCI_DEVICE_ID_INTEL_SMCH 0x3590
+#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592
+#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_80310 0x530d
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010

2004-09-25 09:16:50

by Zwane Mwaikambo

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

Hello Suresh,

On Fri, 24 Sep 2004, Suresh Siddha wrote:

> Ok. How about this patch?
>
> Add pci quirks to disable irqbalance/affinity for E7520/E7320/E7525
> with revision ID 0x09 and below.

> diff -Nru linux-2.6.9-rc2/drivers/pci/quirks.c linux-irq/drivers/pci/quirks.c
> --- linux-2.6.9-rc2/drivers/pci/quirks.c 2004-09-12 22:31:27.000000000 -0700
> +++ linux-irq/drivers/pci/quirks.c 2004-09-04 12:33:54.373316312 -0700
> @@ -814,6 +814,64 @@
> DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
> DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
>
> +#ifdef CONFIG_X86_IO_APIC
> +#include <asm/hw_irq.h>
> +#ifdef CONFIG_IRQBALANCE
> +extern int irqbalance_disable(char *str);
> +#endif
> +extern int no_irq_affinity;
> +extern int noirqdebug_setup(char *str);

Ok this is sort of ugly, but it's not your fault, i understand that the
PCI quirks code is too late after IOAPIC setup, x86_64 has some early PCI
bridge detection code which helps in doing IOAPIC quirks.

> +void __devinit quirk_intel_irqbalance(struct pci_dev *dev)

This may as well be moved elsewhere since it's not actually going to be
used in PCI quirks. I think you should just do the chipset detection in
io_apic.c and then do the disable from there, it's racy and strange
(although it may seem natural) to do it in quirks.c

Thanks,
Zwane

2004-09-27 18:06:33

by Suresh Siddha

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

Zwane,

As far as irq_affinity is concerned, workaround fits nicely in quirks.c
infrastructure.

x86 irqbalance is the one which is causing the pain. Workaround will be more
cleaner if we can move balanced_irq_init() to late_initcall.

If there is no objection, I can post a new patch with that change.

thanks,
suresh

On Sat, Sep 25, 2004 at 12:15:27PM +0300, Zwane Mwaikambo wrote:
> On Fri, 24 Sep 2004, Suresh Siddha wrote:
> > +#ifdef CONFIG_X86_IO_APIC
> > +#include <asm/hw_irq.h>
> > +#ifdef CONFIG_IRQBALANCE
> > +extern int irqbalance_disable(char *str);
> > +#endif
> > +extern int no_irq_affinity;
> > +extern int noirqdebug_setup(char *str);
>
> Ok this is sort of ugly, but it's not your fault, i understand that the
> PCI quirks code is too late after IOAPIC setup, x86_64 has some early PCI
> bridge detection code which helps in doing IOAPIC quirks.
>
> > +void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
>
> This may as well be moved elsewhere since it's not actually going to be
> used in PCI quirks. I think you should just do the chipset detection in
> io_apic.c and then do the disable from there, it's racy and strange
> (although it may seem natural) to do it in quirks.c

2004-09-28 21:14:21

by Suresh Siddha

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

On Mon, Sep 27, 2004 at 11:03:51AM -0700, Suresh Siddha wrote:
> As far as irq_affinity is concerned, workaround fits nicely in quirks.c
> infrastructure.
>
> x86 irqbalance is the one which is causing the pain. Workaround will be more
> cleaner if we can move balanced_irq_init() to late_initcall.
>
> If there is no objection, I can post a new patch with that change.

Here is a new patch. Andrew please apply.

thanks,
suresh

--

As part of the workaround for the "Interrupt message re-ordering across
hub interface" errata (page #16 in
http://developer.intel.com/design/chipsets/specupdt/30288402.pdf),
BIOS may enable hardware IRQ balancing for E7520/E7320/E7525(revision ID
0x9 and below) based platforms.

Add pci quirks to disable SW irqbalance/affinity on those platforms.
Move balanced_irq_init() to late_initcall so that kirqd will be started
after pci quirks.

Signed-off-by: Suresh Siddha <[email protected]>

diff -Nru linux-2.6.9-rc2/arch/i386/kernel/io_apic.c linux-irq/arch/i386/kernel/io_apic.c
--- linux-2.6.9-rc2/arch/i386/kernel/io_apic.c 2004-09-12 22:32:00.000000000 -0700
+++ linux-irq/arch/i386/kernel/io_apic.c 2004-09-08 09:51:56.000000000 -0700
@@ -636,7 +636,7 @@
return 0;
}

-static int __init irqbalance_disable(char *str)
+int __init irqbalance_disable(char *str)
{
irqbalance_disabled = 1;
return 0;
@@ -653,7 +653,7 @@
}
}

-__initcall(balanced_irq_init);
+late_initcall(balanced_irq_init);

#else /* !CONFIG_IRQBALANCE */
static inline void move_irq(int irq) { }
diff -Nru linux-2.6.9-rc2/arch/i386/kernel/irq.c linux-irq/arch/i386/kernel/irq.c
--- linux-2.6.9-rc2/arch/i386/kernel/irq.c 2004-09-12 22:31:30.000000000 -0700
+++ linux-irq/arch/i386/kernel/irq.c 2004-09-08 09:28:35.000000000 -0700
@@ -272,7 +272,7 @@

static int noirqdebug;

-static int __init noirqdebug_setup(char *str)
+int __init noirqdebug_setup(char *str)
{
noirqdebug = 1;
printk("IRQ lockup detection disabled\n");
@@ -997,13 +997,15 @@
return len;
}

+int no_irq_affinity;
+
static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int irq = (long)data, full_count = count, err;
cpumask_t new_value, tmp;

- if (!irq_desc[irq].handler->set_affinity)
+ if (!irq_desc[irq].handler->set_affinity || no_irq_affinity)
return -EIO;

err = cpumask_parse(buffer, count, new_value);
diff -Nru linux-2.6.9-rc2/arch/x86_64/kernel/irq.c linux-irq/arch/x86_64/kernel/irq.c
--- linux-2.6.9-rc2/arch/x86_64/kernel/irq.c 2004-09-12 22:32:26.000000000 -0700
+++ linux-irq/arch/x86_64/kernel/irq.c 2004-09-08 09:28:35.000000000 -0700
@@ -835,6 +835,8 @@
return len;
}

+int no_irq_affinity;
+
static int irq_affinity_write_proc (struct file *file,
const char __user *buffer,
unsigned long count, void *data)
@@ -842,7 +844,7 @@
int irq = (long) data, full_count = count, err;
cpumask_t tmp, new_value;

- if (!irq_desc[irq].handler->set_affinity)
+ if (!irq_desc[irq].handler->set_affinity || no_irq_affinity)
return -EIO;

err = cpumask_parse(buffer, count, new_value);
diff -Nru linux-2.6.9-rc2/drivers/pci/quirks.c linux-irq/drivers/pci/quirks.c
--- linux-2.6.9-rc2/drivers/pci/quirks.c 2004-09-12 22:31:27.000000000 -0700
+++ linux-irq/drivers/pci/quirks.c 2004-09-08 18:20:59.794026624 -0700
@@ -814,6 +814,55 @@
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );

+#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
+#include <asm/hw_irq.h>
+#ifdef CONFIG_IRQBALANCE
+extern int irqbalance_disable(char *str);
+#endif
+extern int no_irq_affinity;
+extern int noirqdebug_setup(char *str);
+
+
+void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+{
+ u8 config, rev;
+ u32 word;
+ extern struct pci_raw_ops *raw_pci_ops;
+
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+ if (rev > 0x9)
+ return;
+
+ printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+
+ /* enable access to config space*/
+ pci_read_config_byte(dev, 0xf4, &config);
+ config |= 0x2;
+ pci_write_config_byte(dev, 0xf4, config);
+
+ /* read xTPR register */
+ raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+
+ if (!(word & (1 << 13))) {
+ printk(KERN_INFO "Disabling irq balancing and affinity\n");
+#ifdef __i386__
+#ifdef CONFIG_IRQBALANCE
+ irqbalance_disable("");
+#endif
+ noirqdebug_setup("");
+#endif
+ no_irq_affinity = 1;
+ }
+
+ config &= ~0x2;
+ /* disable access to config space*/
+ pci_write_config_byte(dev, 0xf4, config);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
+#endif
+
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
*/
diff -Nru linux-2.6.9-rc2/include/linux/pci_ids.h linux-irq/include/linux/pci_ids.h
--- linux-2.6.9-rc2/include/linux/pci_ids.h 2004-09-12 22:33:54.000000000 -0700
+++ linux-irq/include/linux/pci_ids.h 2004-09-08 09:28:35.000000000 -0700
@@ -2204,6 +2204,8 @@
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
#define PCI_DEVICE_ID_INTEL_SMCH 0x3590
+#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592
+#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_80310 0x530d
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010

2004-09-29 13:39:44

by Zwane Mwaikambo

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

On Mon, 27 Sep 2004, Suresh Siddha wrote:

> As far as irq_affinity is concerned, workaround fits nicely in quirks.c
> infrastructure.
>
> x86 irqbalance is the one which is causing the pain. Workaround will be more
> cleaner if we can move balanced_irq_init() to late_initcall.
>
> If there is no objection, I can post a new patch with that change.

I don't see anything wrong with that, go ahead.

Thanks,
Zwane

2004-09-29 15:20:26

by Zwane Mwaikambo

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

On Tue, 28 Sep 2004, Suresh Siddha wrote:

> On Mon, Sep 27, 2004 at 11:03:51AM -0700, Suresh Siddha wrote:
> > As far as irq_affinity is concerned, workaround fits nicely in quirks.c
> > infrastructure.
> >
> > x86 irqbalance is the one which is causing the pain. Workaround will be more
> > cleaner if we can move balanced_irq_init() to late_initcall.
> >
> > If there is no objection, I can post a new patch with that change.
>
> Here is a new patch. Andrew please apply.

Thanks Suresh, looks good.

Zwane

2004-09-30 22:48:00

by Andrew Morton

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

Suresh Siddha <[email protected]> wrote:
>
> --- linux-2.6.9-rc2/drivers/pci/quirks.c 2004-09-12 22:31:27.000000000 -0700
> +++ linux-irq/drivers/pci/quirks.c 2004-09-08 18:20:59.794026624 -0700
> @@ -814,6 +814,55 @@
> DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
> DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
>
> +#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
> +#include <asm/hw_irq.h>
> +#ifdef CONFIG_IRQBALANCE
> +extern int irqbalance_disable(char *str);
> +#endif
> +extern int no_irq_affinity;
> +extern int noirqdebug_setup(char *str);

Please don't put extern declarations in .c files. Try to find a suitable
header file which is included by both the definition and the users of these
variables/functions.

If there is no appropriate header file, feel free to create a new one.

2004-10-01 01:16:45

by Suresh Siddha

[permalink] [raw]
Subject: Re: [Patch 0/2] Disable SW irqbalance/irqaffinity for E7520/E7320/E7525

On Thu, Sep 30, 2004 at 03:51:34PM -0700, Andrew Morton wrote:
> Please don't put extern declarations in .c files.

Ok Andrew. Here is the new patch.

thanks,
suresh
--

As part of the workaround for the "Interrupt message re-ordering across
hub interface" errata (page #16 in
http://developer.intel.com/design/chipsets/specupdt/30288402.pdf),
BIOS may enable hardware IRQ balancing for E7520/E7320/E7525(revision ID
0x9 and below) based platforms.

Add pci quirks to disable SW irqbalance/affinity on those platforms.
Move balanced_irq_init() to late_initcall so that kirqd will be started
after pci quirks.

Signed-off-by: Suresh Siddha <[email protected]>


diff -Nru linux-2.6.9-rc3/arch/i386/kernel/io_apic.c linux-irq/arch/i386/kernel/io_apic.c
--- linux-2.6.9-rc3/arch/i386/kernel/io_apic.c 2004-09-29 20:04:25.000000000 -0700
+++ linux-irq/arch/i386/kernel/io_apic.c 2004-09-10 21:44:01.951220200 -0700
@@ -636,7 +636,7 @@
return 0;
}

-static int __init irqbalance_disable(char *str)
+int __init irqbalance_disable(char *str)
{
irqbalance_disabled = 1;
return 0;
@@ -653,7 +653,7 @@
}
}

-__initcall(balanced_irq_init);
+late_initcall(balanced_irq_init);

#else /* !CONFIG_IRQBALANCE */
static inline void move_irq(int irq) { }
diff -Nru linux-2.6.9-rc3/arch/i386/kernel/irq.c linux-irq/arch/i386/kernel/irq.c
--- linux-2.6.9-rc3/arch/i386/kernel/irq.c 2004-09-29 20:03:51.000000000 -0700
+++ linux-irq/arch/i386/kernel/irq.c 2004-09-10 21:44:01.951220200 -0700
@@ -272,7 +272,7 @@

static int noirqdebug;

-static int __init noirqdebug_setup(char *str)
+int __init noirqdebug_setup(char *str)
{
noirqdebug = 1;
printk("IRQ lockup detection disabled\n");
@@ -997,13 +997,15 @@
return len;
}

+int no_irq_affinity;
+
static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int irq = (long)data, full_count = count, err;
cpumask_t new_value, tmp;

- if (!irq_desc[irq].handler->set_affinity)
+ if (!irq_desc[irq].handler->set_affinity || no_irq_affinity)
return -EIO;

err = cpumask_parse(buffer, count, new_value);
diff -Nru linux-2.6.9-rc3/arch/x86_64/kernel/irq.c linux-irq/arch/x86_64/kernel/irq.c
--- linux-2.6.9-rc3/arch/x86_64/kernel/irq.c 2004-09-29 20:04:32.000000000 -0700
+++ linux-irq/arch/x86_64/kernel/irq.c 2004-09-10 21:44:01.952220048 -0700
@@ -835,6 +835,8 @@
return len;
}

+int no_irq_affinity;
+
static int irq_affinity_write_proc (struct file *file,
const char __user *buffer,
unsigned long count, void *data)
@@ -842,7 +844,7 @@
int irq = (long) data, full_count = count, err;
cpumask_t tmp, new_value;

- if (!irq_desc[irq].handler->set_affinity)
+ if (!irq_desc[irq].handler->set_affinity || no_irq_affinity)
return -EIO;

err = cpumask_parse(buffer, count, new_value);
diff -Nru linux-2.6.9-rc3/drivers/pci/quirks.c linux-irq/drivers/pci/quirks.c
--- linux-2.6.9-rc3/drivers/pci/quirks.c 2004-09-29 20:03:48.000000000 -0700
+++ linux-irq/drivers/pci/quirks.c 2004-09-10 22:07:13.033743512 -0700
@@ -814,6 +814,49 @@
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );

+#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
+#include <asm/irq.h>
+
+void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+{
+ u8 config, rev;
+ u32 word;
+ extern struct pci_raw_ops *raw_pci_ops;
+
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+ if (rev > 0x9)
+ return;
+
+ printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+
+ /* enable access to config space*/
+ pci_read_config_byte(dev, 0xf4, &config);
+ config |= 0x2;
+ pci_write_config_byte(dev, 0xf4, config);
+
+ /* read xTPR register */
+ raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+
+ if (!(word & (1 << 13))) {
+ printk(KERN_INFO "Disabling irq balancing and affinity\n");
+#ifdef __i386__
+#ifdef CONFIG_IRQBALANCE
+ irqbalance_disable("");
+#endif
+ noirqdebug_setup("");
+#endif
+ no_irq_affinity = 1;
+ }
+
+ config &= ~0x2;
+ /* disable access to config space*/
+ pci_write_config_byte(dev, 0xf4, config);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
+#endif
+
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
*/
diff -Nru linux-2.6.9-rc3/include/asm-i386/irq.h linux-irq/include/asm-i386/irq.h
--- linux-2.6.9-rc3/include/asm-i386/irq.h 2004-09-29 20:05:19.000000000 -0700
+++ linux-irq/include/asm-i386/irq.h 2004-09-10 22:03:40.351076192 -0700
@@ -55,4 +55,10 @@
asmlinkage int handle_IRQ_event(unsigned int, struct pt_regs *,
struct irqaction *);

+#ifdef CONFIG_IRQBALANCE
+extern int irqbalance_disable(char *str);
+#endif
+extern int no_irq_affinity;
+extern int noirqdebug_setup(char *str);
+
#endif /* _ASM_IRQ_H */
diff -Nru linux-2.6.9-rc3/include/asm-x86_64/irq.h linux-irq/include/asm-x86_64/irq.h
--- linux-2.6.9-rc3/include/asm-x86_64/irq.h 2004-09-29 20:03:42.000000000 -0700
+++ linux-irq/include/asm-x86_64/irq.h 2004-09-10 21:59:46.831576552 -0700
@@ -57,4 +57,6 @@
struct pt_regs;
int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);

+extern int no_irq_affinity;
+
#endif /* _ASM_IRQ_H */
diff -Nru linux-2.6.9-rc3/include/linux/pci_ids.h linux-irq/include/linux/pci_ids.h
--- linux-2.6.9-rc3/include/linux/pci_ids.h 2004-09-29 20:06:05.000000000 -0700
+++ linux-irq/include/linux/pci_ids.h 2004-09-10 21:44:01.954219744 -0700
@@ -2205,6 +2205,8 @@
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
#define PCI_DEVICE_ID_INTEL_SMCH 0x3590
+#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592
+#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_80310 0x530d
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010