[BUG] Ricoh Cardbus -> Can't get interrupts

Jean Tourrilhes jt at bougret.hpl.hp.com
Tue Nov 25 17:54:16 GMT 2003


On Mon, Nov 24, 2003 at 09:17:21PM -0800, Linus Torvalds wrote:
> 
> 
> On Mon, 24 Nov 2003, Linus Torvalds wrote:
> >
> > That "Bus 0 IRQ 44" should actually be it: that decodes to bus 0, slot 17,
> > pin 0. Exactly what we want.
> 
> Never mind. We didn't want 17, we wanted 19. 17 was the USB thing.
> 
> Slot 18 was Ethernet, and slot 19 was your cardbus bridge.
> 
> However, you said that it still didn't work when you switched the ethernet
> and cardbus cards around, which actually makes me suspect that slot 19 got
> dynamically turned into _this_ entry by the BIOS:
> 
> > Int: type 0, pol 3, trig 3, bus 1, IRQ 00, APIC ID 2, APIC INT 12

	Wrong, this is my AGP Matrox card.
	The correct answer is that it's nowhere to be found in the
APIC table.

> ie it has noticed that slot 19 contains a PCI->CardBus bridge, and thus
> instead of calling it "bus 0, irq 4c" (which would be slot 19 on bus 0),
> it has the IRQ translation as "bus 1, irq 0" (which is "slot 0 on bus 1").
> 
> And indeed, we won't find that for the PCI->Cardbus bridge chip. But it
> kind of makes sense, because the device _behind_ the bridge (which will
> have the same irq) will indeed be "slot 0 on bus 1").

	Nope, Bus 1 is the AGP. Bus 2 is a PCI multifunction
card. Carbus cards appear on Bus 3, but I don't think any of the info
from Bus 3 is very useful.

> Just for fun, could you switch the ethernet/cardbus cards around again,
> and see if that "bus 1" line moves up one (current slot 18 aka "irq 48"),
> and the one that is now "bus 1"  ends up being "bus 0, IRQ 4C" (ie slot 19
> which now would have the ethernet card instead of a PCI bridge).

	I did that, "bus 1" remained the same and the Ethernet was
moved from irq 48 to irq 4C.

> Ingo, any ideas on how to handle this sanely?
> 
> Jean - you could just _force_ the match, by special-casing it, and seeing
> it it works. We actaully already try the _other_ way in
> 
> 	arch/i386/pci/irq.c: pcibios_fixup_irqs()
> 
> if we don't find a translation, we try to find a translation through the
> _parent_ infromation, but we never think to ask "oh, if we are a bridge,
> maybe we should ask the child".

	I tried that. But, the list of childs is empty. Well, I guess
that when next point to the list head, it's empty ;-)
	Note that I tried that without any CardBus device in the
slot. Maybe if there was a CardBus card in it, we may get one
child. But, I don't want to depend on that.

> 			Linus

	The fix is simple. We just need a "manual override". It's
basically impossible for the kernel to find the right answer without
some outside help. This was the conclusion that David Hinds reached
with the Pcmcia package (see Pcmcia Howto 5.2).
	The patch below just does that. I tried this patch with a 16
bits Pcmcia card (ISA irq) and a 32 bits Carbus card (PCI irq), and
both work fine (I just need the magic sequence "manual_pci_irq=0,19,17").
	You may no like this kind of ugly patch, but it brings feature
parity with respect to the old Pcmcia package.

	Anyway, thanks greatly for the help, you lead me in the right
direction and I now have a workable solution.

	Have fun...

	Jean

-------------------------------------------------------------

diff -u -p linux/arch/i386/pci/irq.j1.c linux/arch/i386/pci/irq.c
--- linux/arch/i386/pci/irq.j1.c	Tue Nov 25 10:36:45 2003
+++ linux/arch/i386/pci/irq.c	Tue Nov 25 17:35:44 2003
@@ -693,6 +693,43 @@ static int pcibios_lookup_irq(struct pci
 	return 1;
 }
 
+#define MAX_MIRQS 4
+int manual_irq_entries[MAX_MIRQS][3];		/* bus/slot/irq */
+int manual_irqs_enabled;	/* = 0 */
+
+static int __init manual_irq_setup(char *str)
+{
+	int i, max;
+	int ints[(MAX_MIRQS*3)+1];
+
+	get_options(str, ARRAY_SIZE(ints), ints);
+
+	for (i = 0; i < MAX_MIRQS; i++)
+		manual_irq_entries[i][0] = -1;
+
+	manual_irqs_enabled = 1;
+
+	max = MAX_MIRQS * 3;
+	if (ints[0] < max)
+		max = ints[0];
+	max = max / 3;
+
+	for (i = 0; i < max; i++) {
+		/* Fill our mapping table */
+		manual_irq_entries[i][0] = ints[(3*i) + 1];
+		manual_irq_entries[i][1] = ints[(3*i) + 2];
+		manual_irq_entries[i][2] = ints[(3*i) + 3];
+
+		printk(KERN_DEBUG "Manual PCI %d:%d -> IRQ %d\n",
+		       manual_irq_entries[i][0],
+		       manual_irq_entries[i][1],
+		       manual_irq_entries[i][2]);
+	}
+	return 1;
+}
+
+__setup("manual_pci_irq=", manual_irq_setup);
+
 static void __init pcibios_fixup_irqs(void)
 {
 	struct pci_dev *dev = NULL;
@@ -757,6 +794,30 @@ static void __init pcibios_fixup_irqs(vo
 		 */
 		if (pin && !dev->irq)
 			pcibios_lookup_irq(dev, 0);
+
+		/*
+		 * Manual fixups. Use at your own risks. Jean II
+		 * This assume that the PCI IRQ routing is done right,
+		 * and it's just the BIOS that ignore the card. If you
+		 * need to also fixup the PCI IRQ routing, you will
+		 * probably need to use the "pirq=" option.
+		 * I use this hack to get a PCI-CardBus add-on adapter
+		 * to be recognised on my destktop.
+		 * Jean II
+		 */
+		if (manual_irqs_enabled) {
+			int i;
+			for(i = 0; i < MAX_MIRQS; i++)
+				if ((dev->bus->number ==
+				     manual_irq_entries[i][0])
+				    && (PCI_SLOT(dev->devfn) ==
+					manual_irq_entries[i][1])) {
+					printk(KERN_INFO "PCI->APIC IRQ manual fixup: (B%d,I%d) -> %d\n",
+						dev->bus->number, PCI_SLOT(dev->devfn), manual_irq_entries[i][2]);
+					dev->irq = manual_irq_entries[i][2];
+					pci_write_config_byte(dev, PCI_INTERRUPT_LINE, manual_irq_entries[i][2]);
+				}
+		}
 	}
 }
 




More information about the linux-pcmcia mailing list