2005-05-23 12:59:05

by Karsten Keil

[permalink] [raw]
Subject: [PATCH] bug in VIA PCI IRQ routing

Hi,

during certification of some systems with VIA 82C586_0 chipset
we found that the PCI IRQ routing of PIRQD line goes wrong and the system
will get stuck because of unacknowledged IRQs.
It seems that the special case for PIRQD (pirq 4) is not needed for all
VIA versions. With this patch, the IRQ routing on these systems works
again (It did work with older 2.4 kernel versions prior the PIRQD change)

diff -urN linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c linux-2.6.12-rc4-git7/arch/i386/pci/irq.c
--- linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c 2005-05-23 13:35:48.562759583 +0200
+++ linux-2.6.12-rc4-git7/arch/i386/pci/irq.c 2005-05-23 13:41:47.349473060 +0200
@@ -26,6 +26,7 @@

static int broken_hp_bios_irq9;
static int acer_tm360_irqrouting;
+static int via_pirq_patch_value = 5;

static struct irq_routing_table *pirq_table;

@@ -217,12 +218,12 @@
*/
static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
{
- return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
+ return read_config_nybble(router, 0x55, pirq == 4 ? via_pirq_patch_value : pirq);
}

static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{
- write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
+ write_config_nybble(router, 0x55, pirq == 4 ? via_pirq_patch_value : pirq, irq);
return 1;
}

@@ -512,6 +513,7 @@
switch(device)
{
case PCI_DEVICE_ID_VIA_82C586_0:
+ via_pirq_patch_value = 4;
case PCI_DEVICE_ID_VIA_82C596:
case PCI_DEVICE_ID_VIA_82C686:
case PCI_DEVICE_ID_VIA_8231:

--
Karsten Keil
SuSE Labs
ISDN development


2005-05-23 17:40:52

by Aleksey Gorelov

[permalink] [raw]
Subject: RE: [PATCH] bug in VIA PCI IRQ routing

>-----Original Message-----
>From: Karsten Keil [mailto:[email protected]]
>Sent: Monday, May 23, 2005 5:59 AM
>To: [email protected]
>Cc: Andrew Morton; Aleksey Gorelov
>Subject: [PATCH] bug in VIA PCI IRQ routing
>
>Hi,
>
>during certification of some systems with VIA 82C586_0 chipset
>we found that the PCI IRQ routing of PIRQD line goes wrong and
>the system
>will get stuck because of unacknowledged IRQs.
>It seems that the special case for PIRQD (pirq 4) is not needed for all
>VIA versions. With this patch, the IRQ routing on these systems works
>again (It did work with older 2.4 kernel versions prior the
>PIRQD change)

Does anybody have 82C586 datasheet to verify 0x57 register ?
For all I can say, both 82C686 & 8231 DO need special handling for
PIRQD,
since PIRQD routing is setup via bits 7-4 in 0x57 (see datasheets from
VIA
website). It seems like 82C586 might be different...

Aleks.

>
>diff -urN linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c
>linux-2.6.12-rc4-git7/arch/i386/pci/irq.c
>--- linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c
>2005-05-23 13:35:48.562759583 +0200
>+++ linux-2.6.12-rc4-git7/arch/i386/pci/irq.c 2005-05-23
>13:41:47.349473060 +0200
>@@ -26,6 +26,7 @@
>
> static int broken_hp_bios_irq9;
> static int acer_tm360_irqrouting;
>+static int via_pirq_patch_value = 5;
>
> static struct irq_routing_table *pirq_table;
>
>@@ -217,12 +218,12 @@
> */
> static int pirq_via_get(struct pci_dev *router, struct
>pci_dev *dev, int pirq)
> {
>- return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
>+ return read_config_nybble(router, 0x55, pirq == 4 ?
>via_pirq_patch_value : pirq);
> }
>
> static int pirq_via_set(struct pci_dev *router, struct
>pci_dev *dev, int pirq, int irq)
> {
>- write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
>+ write_config_nybble(router, 0x55, pirq == 4 ?
>via_pirq_patch_value : pirq, irq);
> return 1;
> }
>
>@@ -512,6 +513,7 @@
> switch(device)
> {
> case PCI_DEVICE_ID_VIA_82C586_0:
>+ via_pirq_patch_value = 4;
> case PCI_DEVICE_ID_VIA_82C596:
> case PCI_DEVICE_ID_VIA_82C686:
> case PCI_DEVICE_ID_VIA_8231:
>
>--
>Karsten Keil
>SuSE Labs
>ISDN development
>

2005-05-23 18:24:02

by Ondrej Zary

[permalink] [raw]
Subject: Re: [PATCH] bug in VIA PCI IRQ routing

Aleksey Gorelov wrote:
>>-----Original Message-----
>>From: Karsten Keil [mailto:[email protected]]
>>Sent: Monday, May 23, 2005 5:59 AM
>>To: [email protected]
>>Cc: Andrew Morton; Aleksey Gorelov
>>Subject: [PATCH] bug in VIA PCI IRQ routing
>>
>>Hi,
>>
>>during certification of some systems with VIA 82C586_0 chipset
>>we found that the PCI IRQ routing of PIRQD line goes wrong and
>>the system
>>will get stuck because of unacknowledged IRQs.
>>It seems that the special case for PIRQD (pirq 4) is not needed for all
>>VIA versions. With this patch, the IRQ routing on these systems works
>>again (It did work with older 2.4 kernel versions prior the
>>PIRQD change)
>
>
> Does anybody have 82C586 datasheet to verify 0x57 register ?
> For all I can say, both 82C686 & 8231 DO need special handling for
> PIRQD,
> since PIRQD routing is setup via bits 7-4 in 0x57 (see datasheets from
> VIA
> website). It seems like 82C586 might be different...
>
> Aleks.
>

This is from 82C586B datasheet (the 82C586A datasheet shows the same
register layout):

Note: The definitions of the fields of the following three
registers were incorrectly documented in some earlier
revisions of this document. The silicon has not changed
and the following definition should be used for all silicon
revisions:

Offset 55 - PNP IRQ Routing 1 ....................................... RW
These bits control routing for external IRQ inputs MIRQ0-1.
7-4 PIRQD# Routing (see PnP IRQ routing table)
3-0 MIRQ0 Routing (see PnP IRQ routing table)

Offset 56 - PNP IRQ Routing 2 ....................................... RW
7-4 PIRQA# Routing (see PnP IRQ routing table)
3-0 PIRQB# Routing (see PnP IRQ routing table)

Offset 57 - PNP IRQ Routing 3 ....................................... RW
7-4 PIRQC# Routing (see PnP IRQ routing table)
3-0 MIRQ1 Routing (see PnP IRQ routing table)

Note: these bits must be set to 0 if Rx48[4]=1 and
Rx59[1]=1 (input IRQ8# on MIRQ1 pin 106)

PnP IRQ Routing Table
0000 Disabled................................................. default
0001 IRQ1
0010 Reserved
0011 IRQ3
0100 IRQ4
0101 IRQ5
0110 IRQ6
0111 IRQ7
1000 Reserved
1001 IRQ9
1010 IRQ10
1011 IRQ11
1100 IRQ12
1101 Reserved
1110 IRQ14
1111 IRQ15


>
>>diff -urN linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c
>>linux-2.6.12-rc4-git7/arch/i386/pci/irq.c
>>--- linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c
>>2005-05-23 13:35:48.562759583 +0200
>>+++ linux-2.6.12-rc4-git7/arch/i386/pci/irq.c 2005-05-23
>>13:41:47.349473060 +0200
>>@@ -26,6 +26,7 @@
>>
>>static int broken_hp_bios_irq9;
>>static int acer_tm360_irqrouting;
>>+static int via_pirq_patch_value = 5;
>>
>>static struct irq_routing_table *pirq_table;
>>
>>@@ -217,12 +218,12 @@
>> */
>>static int pirq_via_get(struct pci_dev *router, struct
>>pci_dev *dev, int pirq)
>>{
>>- return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
>>+ return read_config_nybble(router, 0x55, pirq == 4 ?
>>via_pirq_patch_value : pirq);
>>}
>>
>>static int pirq_via_set(struct pci_dev *router, struct
>>pci_dev *dev, int pirq, int irq)
>>{
>>- write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
>>+ write_config_nybble(router, 0x55, pirq == 4 ?
>>via_pirq_patch_value : pirq, irq);
>> return 1;
>>}
>>
>>@@ -512,6 +513,7 @@
>> switch(device)
>> {
>> case PCI_DEVICE_ID_VIA_82C586_0:
>>+ via_pirq_patch_value = 4;
>> case PCI_DEVICE_ID_VIA_82C596:
>> case PCI_DEVICE_ID_VIA_82C686:
>> case PCI_DEVICE_ID_VIA_8231:
>>
>>--
>>Karsten Keil
>>SuSE Labs
>>ISDN development
>>
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>


--
Ondrej Zary

2005-05-23 19:53:50

by Aleksey Gorelov

[permalink] [raw]
Subject: RE: [PATCH] bug in VIA PCI IRQ routing



>-----Original Message-----
>From: Ondrej Zary [mailto:[email protected]]
>Sent: Monday, May 23, 2005 11:25 AM
>To: Aleksey Gorelov
>Cc: Karsten Keil; [email protected]; Andrew Morton;
>[email protected]
>Subject: Re: [PATCH] bug in VIA PCI IRQ routing
>
>Aleksey Gorelov wrote:
>>>-----Original Message-----
>>>From: Karsten Keil [mailto:[email protected]]
>>>Sent: Monday, May 23, 2005 5:59 AM
>>>To: [email protected]
>>>Cc: Andrew Morton; Aleksey Gorelov
>>>Subject: [PATCH] bug in VIA PCI IRQ routing
>>>
>>>Hi,
>>>
>>>during certification of some systems with VIA 82C586_0 chipset
>>>we found that the PCI IRQ routing of PIRQD line goes wrong and
>>>the system
>>>will get stuck because of unacknowledged IRQs.
>>>It seems that the special case for PIRQD (pirq 4) is not
>needed for all
>>>VIA versions. With this patch, the IRQ routing on these systems works
>>>again (It did work with older 2.4 kernel versions prior the
>>>PIRQD change)
>>
>>
>> Does anybody have 82C586 datasheet to verify 0x57 register ?
>> For all I can say, both 82C686 & 8231 DO need special handling for
>> PIRQD,
>> since PIRQD routing is setup via bits 7-4 in 0x57 (see
>datasheets from
>> VIA
>> website). It seems like 82C586 might be different...
>>
>> Aleks.
>>
>
>This is from 82C586B datasheet (the 82C586A datasheet shows the same
>register layout):
>
>Note: The definitions of the fields of the following three
>registers were incorrectly documented in some earlier
>revisions of this document. The silicon has not changed
>and the following definition should be used for all silicon
>revisions:
>
>Offset 55 - PNP IRQ Routing 1
>....................................... RW
>These bits control routing for external IRQ inputs MIRQ0-1.
>7-4 PIRQD# Routing (see PnP IRQ routing table)
>3-0 MIRQ0 Routing (see PnP IRQ routing table)
>
>Offset 56 - PNP IRQ Routing 2
>....................................... RW
>7-4 PIRQA# Routing (see PnP IRQ routing table)
>3-0 PIRQB# Routing (see PnP IRQ routing table)
>
>Offset 57 - PNP IRQ Routing 3
>....................................... RW
>7-4 PIRQC# Routing (see PnP IRQ routing table)
>3-0 MIRQ1 Routing (see PnP IRQ routing table)
>
>Note: these bits must be set to 0 if Rx48[4]=1 and
>Rx59[1]=1 (input IRQ8# on MIRQ1 pin 106)
>
>PnP IRQ Routing Table
>0000 Disabled................................................. default
>0001 IRQ1
>0010 Reserved
>0011 IRQ3
>0100 IRQ4
>0101 IRQ5
>0110 IRQ6
>0111 IRQ7
>1000 Reserved
>1001 IRQ9
>1010 IRQ10
>1011 IRQ11
>1100 IRQ12
>1101 Reserved
>1110 IRQ14
>1111 IRQ15

Hmm, this is way different.

Karsten,

could you please verify if attached patch works for you ?
Another unknown C596 south bridge. I wonder if it the same as 586, or
closer to 686 ?

Aleks.

>
>
>>
>>>diff -urN linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c
>>>linux-2.6.12-rc4-git7/arch/i386/pci/irq.c
>>>--- linux-2.6.12-rc4-git7.org/arch/i386/pci/irq.c
>>>2005-05-23 13:35:48.562759583 +0200
>>>+++ linux-2.6.12-rc4-git7/arch/i386/pci/irq.c 2005-05-23
>>>13:41:47.349473060 +0200
>>>@@ -26,6 +26,7 @@
>>>
>>>static int broken_hp_bios_irq9;
>>>static int acer_tm360_irqrouting;
>>>+static int via_pirq_patch_value = 5;
>>>
>>>static struct irq_routing_table *pirq_table;
>>>
>>>@@ -217,12 +218,12 @@
>>> */
>>>static int pirq_via_get(struct pci_dev *router, struct
>>>pci_dev *dev, int pirq)
>>>{
>>>- return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
>>>+ return read_config_nybble(router, 0x55, pirq == 4 ?
>>>via_pirq_patch_value : pirq);
>>>}
>>>
>>>static int pirq_via_set(struct pci_dev *router, struct
>>>pci_dev *dev, int pirq, int irq)
>>>{
>>>- write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
>>>+ write_config_nybble(router, 0x55, pirq == 4 ?
>>>via_pirq_patch_value : pirq, irq);
>>> return 1;
>>>}
>>>
>>>@@ -512,6 +513,7 @@
>>> switch(device)
>>> {
>>> case PCI_DEVICE_ID_VIA_82C586_0:
>>>+ via_pirq_patch_value = 4;
>>> case PCI_DEVICE_ID_VIA_82C596:
>>> case PCI_DEVICE_ID_VIA_82C686:
>>> case PCI_DEVICE_ID_VIA_8231:
>>>
>>>--
>>>Karsten Keil
>>>SuSE Labs
>>>ISDN development
>>>
>>
>>
>> -
>> To unsubscribe from this list: send the line "unsubscribe
>linux-kernel" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at http://www.tux.org/lkml/
>>
>
>
>--
>Ondrej Zary
>


Attachments:
via.patch (1.13 kB)
via.patch

2005-05-23 21:22:09

by Karsten Keil

[permalink] [raw]
Subject: Re: [PATCH] bug in VIA PCI IRQ routing

Hi,

thanks to Ondrej for the datasheet snippet.

On Mon, May 23, 2005 at 12:53:41PM -0700, Aleksey Gorelov wrote:
...
>
> Hmm, this is way different.
>
> Karsten,
>
> could you please verify if attached patch works for you ?

Will do so, since the systems are not under my control, it may take some
time.
Thanks for the patch.

> Another unknown C596 south bridge. I wonder if it the same as 586, or
> closer to 686 ?

It is a 82C586B south bridge (printed on the chip).

--
Karsten Keil
SuSE Labs
ISDN development

2005-05-24 07:29:50

by Karsten Keil

[permalink] [raw]
Subject: Re: [PATCH] bug in VIA PCI IRQ routing

Hi,

On Mon, May 23, 2005 at 12:53:41PM -0700, Aleksey Gorelov wrote:
>
> Karsten,
>
> could you please verify if attached patch works for you ?

Works and seems to be OK, according to the specs. So this
patch should go into the kernel, also into 2.4 I think.
These chipset is still used on small special purpose systems.

--- linux-2.6.11.10/arch/i386/pci/irq.c 2005-05-16 10:50:30.000000000 -0700
+++ new/arch/i386/pci/irq.c 2005-05-23 12:47:19.000000000 -0700
@@ -227,6 +227,24 @@
}

/*
+ * The VIA pirq rules are nibble-based, like ALI,
+ * but without the ugly irq number munging.
+ * However, for 82C586, nibble map is different .
+ */
+static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+ return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
+}
+
+static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+ write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+ return 1;
+}
+
+/*
* ITE 8330G pirq rules are nibble-based
* FIXME: pirqmap may be { 1, 0, 3, 2 },
* 2+3 are both mapped to irq 9 on my system
@@ -509,6 +527,10 @@
switch(device)
{
case PCI_DEVICE_ID_VIA_82C586_0:
+ r->name = "VIA";
+ r->get = pirq_via586_get;
+ r->set = pirq_via586_set;
+ return 1;
case PCI_DEVICE_ID_VIA_82C596:
case PCI_DEVICE_ID_VIA_82C686:
case PCI_DEVICE_ID_VIA_8231:

--
Karsten Keil
SuSE Labs
ISDN development

2005-05-24 16:26:51

by Aleksey Gorelov

[permalink] [raw]
Subject: RE: [PATCH] bug in VIA PCI IRQ routing

Hi Marcelo,

Attached comes appropriate patch for 2.4

Signed-off-by: Aleksey Gorelov <[email protected]>

Previously posted patch for 2.6 had been verified by Karsten Keil
<[email protected]>.

According to the VIA 82C586B datasheet (still available from
http://gkernel.sourceforge.net/specs/via/586b.pdf.bz2) this chip needs
a special PIRQ mapping. Again, according to appropriate datasheets,
82C596, 82C686 & 8231 should continue utilize old scheme.

>-----Original Message-----
>From: Karsten Keil [mailto:[email protected]]
>Sent: Tuesday, May 24, 2005 12:29 AM
>To: Aleksey Gorelov
>Cc: Ondrej Zary; [email protected]; Andrew Morton;
>[email protected]
>Subject: Re: [PATCH] bug in VIA PCI IRQ routing
>
>Hi,
>
>On Mon, May 23, 2005 at 12:53:41PM -0700, Aleksey Gorelov wrote:
>>
>> Karsten,
>>
>> could you please verify if attached patch works for you ?
>
>Works and seems to be OK, according to the specs. So this
>patch should go into the kernel, also into 2.4 I think.
>These chipset is still used on small special purpose systems.
>
>--- linux-2.6.11.10/arch/i386/pci/irq.c 2005-05-16
>10:50:30.000000000 -0700
>+++ new/arch/i386/pci/irq.c 2005-05-23 12:47:19.000000000 -0700
>@@ -227,6 +227,24 @@
> }
>
> /*
>+ * The VIA pirq rules are nibble-based, like ALI,
>+ * but without the ugly irq number munging.
>+ * However, for 82C586, nibble map is different .
>+ */
>+static int pirq_via586_get(struct pci_dev *router, struct
>pci_dev *dev, int pirq)
>+{
>+ static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
>+ return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
>+}
>+
>+static int pirq_via586_set(struct pci_dev *router, struct
>pci_dev *dev, int pirq, int irq)
>+{
>+ static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
>+ write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
>+ return 1;
>+}
>+
>+/*
> * ITE 8330G pirq rules are nibble-based
> * FIXME: pirqmap may be { 1, 0, 3, 2 },
> * 2+3 are both mapped to irq 9 on my system
>@@ -509,6 +527,10 @@
> switch(device)
> {
> case PCI_DEVICE_ID_VIA_82C586_0:
>+ r->name = "VIA";
>+ r->get = pirq_via586_get;
>+ r->set = pirq_via586_set;
>+ return 1;
> case PCI_DEVICE_ID_VIA_82C596:
> case PCI_DEVICE_ID_VIA_82C686:
> case PCI_DEVICE_ID_VIA_8231:
>
>--
>Karsten Keil
>SuSE Labs
>ISDN development
>


Attachments:
via24.patch (1.14 kB)
via24.patch