2000-12-05 09:14:31

by Adam J. Richter

[permalink] [raw]
Subject: Patch: x86 PCI IRQ's were not being routed in some cases (against 2.4.0-test11pre4)

I don't know if this is the fault of my notebook's BIOS
or Linux. However, Linux should work around bad BIOS'es where
feasible. So, here goes.

I have a Kapok 1100M notebook computer, which has a Pentium II,
apparently with a 440BX chipset. The BIOS fills in the PCI interrupt
routing tables (the thing that begins with "$PIR" in memory) with
information indicating that the USB controller is routed to IRQ 10,
and that that is the only IRQ that it can be routed to.

Linux apparently looks at this data and takes that to mean
that the wiring has already been done. However, this is not the case.
As far as I can tell, the BIOS is just suggesting that Linux configure
the 440BX chipset to that routing. (This BIOS does not have a
"Plug & Play OS" option.)

This has not always been a problem. If I recall correctly, kernels
up to somewhere in early 2.3.x worked.

To fix this problem, I have deleted a conditional in
pcibios_enable_irq, so that it will route the IRQ, even if it
thinks the work has already been done. Now, USB and my PCMCIA
flash cards work in that notebook computer again.

I do not have that solid of an understanding of PCI
initialization in Linux. I am still rather confused about what
routines are supposed to set up an interrupt if one is needed
and has not yet been routed for the device and which ones are supposed
to punt in case. For example, there is another problem that I
am trying to fix, where the motherboard BIOS on that other computer
sets the IRQ associated with the USB controller to zero, no matter
how I program the BIOS, and pcibios_lookup_irq takes this as reason
enough to refuse to allocate and route a new IRQ.

Anyhow, I have attached the patch for the lack of PCI IRQ
initialization below. The only change was to delete the first
"if" statement. The rest of the diff lines are just the resulting
intentation and bracketing change.

--
Adam J. Richter __ ______________ 4880 Stevens Creek Blvd, Suite 104
[email protected] \ / San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l United States of America
fax +1 408 261-6631 "Free Software For The Rest Of Us."


Attachments:
(No filename) (2.13 kB)
irq.diff (1.10 kB)
Download all attachments

2000-12-05 21:18:03

by Martin Mares

[permalink] [raw]
Subject: Re: Patch: x86 PCI IRQ's were not being routed in some cases (against 2.4.0-test11pre4)

Hello!

> To fix this problem, I have deleted a conditional in
> pcibios_enable_irq, so that it will route the IRQ, even if it
> thinks the work has already been done. Now, USB and my PCMCIA
> flash cards work in that notebook computer again.

Unfortunately, your fix is wrong -- it makes Linux ignore all the IRQ
settings the user has set up in the BIOS and I also guess there are
machines where the IRQ information in the INTERRUPT_LINE register
is correct, but the BIOS tables/functions are inaccurate.

First of all, please send me the 'lspci -vvx' output for the USB
device and also try booting the kernel with a "pci=autoirq" option
which should have exactly the same effect as your patch.

> I do not have that solid of an understanding of PCI
> initialization in Linux. I am still rather confused about what
> routines are supposed to set up an interrupt if one is needed
> and has not yet been routed for the device and which ones are supposed
> to punt in case.

The IRQ assignment logic is somewhat complicated to handle all
the corner cases:

o When we are scanning the PCI bus and we encounter a device
with wrong IRQ, we ignore the IRQ information.

o During the scan, if we find a device with unset IRQ, but having
an interrupt pin advertised in its configuration header, we
try to look at the interrupt router to see what IRQ did BIOS
route the pin to.

o When pci_enable_device() is called and the IRQ is still unset
(and interrupt pin exists), we try to route the IRQ ourselves.

> For example, there is another problem that I
> am trying to fix, where the motherboard BIOS on that other computer
> sets the IRQ associated with the USB controller to zero, no matter
> how I program the BIOS, and pcibios_lookup_irq takes this as reason
> enough to refuse to allocate and route a new IRQ.

It definitely shouldn't behave so -- IRQ set to zero is always
interpreted as "no IRQ assigned".

Have a nice fortnight
--
Martin `MJ' Mares <[email protected]> <[email protected]> http://atrey.karlin.mff.cuni.cz/~mj/
Purchasing Windows is an Unrecoverable Application Error.