Thread (61 messages) 61 messages, 8 authors, 2021-07-16

Re: Realtek 8139 problem on 486.

From: Arnd Bergmann <arnd@kernel.org>
Date: 2021-06-22 13:25:25

On Tue, Jun 22, 2021 at 2:32 PM Nikolai Zhubr [off-list ref] wrote:
21.06.2021 14:22, Arnd Bergmann:
[...]
quoted
I looked some more through the git history and found at least one time
that the per-chipset ELCR fixup came up for discussion[1], and this
appears to have resulted in generalizing an ALI specific fixup into
common code into common code[2], so we should already be doing
exactly this in many cases. If Nikolai can boot the system with debugging
enabled for arch/x86/pci/irq.c, we should be able to see exactly
which code path is his in his case, and why it doesn't go through
setting that register at the moment.
Here is my dmesg with debugging (hopefully) added to irq.c:

https://pastebin.com/tnC2rRDM
Ok, so it's getting roughly through the right code path:

        dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
                'A' + pin - 1, pirq, mask, pirq_table->exclusive_irqs);
...
        dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin - 1, newirq);

        /* Check if it is hardcoded */
        if ((pirq & 0xf0) == 0xf0) {
                irq = pirq & 0xf;
                msg = "hardcoded";
        } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
        ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask))) {
                msg = "found";
                elcr_set_level_irq(irq);
        } else if (newirq && r->set &&
                (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
                if (r->set(pirq_router_dev, dev, pirq, newirq)) {
                        elcr_set_level_irq(newirq);
                        msg = "assigned";
                        irq = newirq;
                }
        }

        if (!irq) {
                if (newirq && mask == (1 << newirq)) {
                        msg = "guessed";
                        irq = newirq;
                } else {
                        dev_dbg(&dev->dev, "can't route interrupt\n");
                        return 0;
                }
        }
        dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' +
pin - 1, irq);

with the corresponding output from that one being

[    0.761546] 8139too 0000:00:0d.0: runtime IRQ mapping not provided by arch
[    0.761546] 8139too: 8139too Fast Ethernet driver 0.9.28
[    0.761546] 8139too 0000:00:0d.0: PCI INT A -> PIRQ 02, mask 1eb8, excl 0001
[    0.765817] 8139too 0000:00:0d.0: PCI INT A -> newirq 9
[    0.765817] 8139too 0000:00:0d.0: can't route interrupt
[    0.777546] 8139too 0000:00:0d.0 eth0: RealTek RTL8139 at
0xc4804000, 00:11:6b:32:85:74, IRQ 9

From what I can tell, this means that there is no chipset specific
get/set function,
the irq is not hardcoded but the 'mask' value in the irq_info table (0x1eb8)
lists a number of options.

In this case, the function gives up with the  "can't route interrupt\n"
output and does not call elcr_set_level_irq(newirq). Adding the call
to elcr_set_level_irq() in that code path as well probably makes it
set the irq to level mode:
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -984,6 +984,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev,
int assign)
                        irq = newirq;
                } else {
                        dev_dbg(&dev->dev, "can't route interrupt\n");
+                       elcr_set_level_irq(newirq);
                        return 0;
                }
        }

No idea if doing this is a good idea though, in particular I have no clue
about whether this is a common scenario or not.

        Arnd
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help