----- Original Message ----- From: "(Eric W. Biederman)" ebiederman@lnxi.com To: "Ronald G. Minnich" rminnich@lanl.gov Cc: riskin@263.net,linuxbios@clustermatic.org Sent: 2003-02-12 20:44:11 Subject: Re: rtl8139 NIC IRQ is 0 on m758lmr+ mainboard
2.2 was o.k. with an SMP kernel, and an MP table in LinuxBIOS. The other cases it failed with. We were just happy when we could load 2.2 and we quickly switched to 2.3.x. The 2.4.x kernel code for assigning interrupts from irqs is not to bad, if you want to look at putting it into LinuxBIOS to support your 2.2.x kernel....
We're going to have to get linuxbios to set this stuff up.
I made a first stab but ran out of time, will have to try again later.
The interesting variant which is coming up is MSI. Interrupts over the pci bus, as specified in pci 2.3, pci-x 2.0 and pci-express.
The interrupt story keeps getting more complicated, not less...
Eric
Does your mainboad support APIC?
I think that if The SMP kernel is ok,the mainboard must support APIC. If the mainboad doesn't support APIC,maybe the kernel need support IRQ route table. But the 2.2.x kernel doesn't support parsing the IRQ route table supplied by LinuxBIOS. But the mainboad(sis630 chip set) used by me doesn't support it,according to ollie.( ollie@sis.com.tw)
Is the sis630 chip set wired as following?
* INTA INTB INTC INTD * ---------------------------- * slot 1: dev=0x9 wiring: PIRQ_C PIRQ_D PIRQ_A PIRQ_B * slot 2: dev=0xb wiring: PIRQ_B PIRQ_C PIRQ_D PIRQ_A * slot 3: dev=0xd wiring: PIRQ_A PIRQ_B PIRQ_C PIRQ_D
In "freebios/src/northsouthbridge/sis/630/southbridge.c"
.........
#ifdef OLD_KERNEL_HACK struct pci_dev *pcidev;
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); if (pcidev != NULL) { printk_info("Remapping IRQ on southbridge for OLD_KERNEL_HACK\n"); // remap IRQ for PCI -- this is exactly what the BIOS does now. pci_write_config_byte(pcidev, 0x42, 0xa); pci_write_config_byte(pcidev, 0x43, 0xb); pci_write_config_byte(pcidev, 0x44, 0xc); } // ethernet fixup. This should all work, and doesn't, yet. // so we hack it for now. // need a manifest constant for the enet device. pcidev = pci_find_device(PCI_VENDOR_ID_SI, 0x0900, (void *)NULL); if (pcidev != NULL) { u32 bar0 = 0xb001; // set the BAR 0 to 0xb000. Safe, high value, known good. // pci config set doesn't work for reasons we don't understand. pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_0, bar0);
// Make sure bus mastering is on. The tried-and-true probe in linuxpci.c // doesn't set this for some reason. pci_write_config_byte(pcidev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
// set the interrupt to 'b' pci_write_config_byte(pcidev, PCI_INTERRUPT_LINE, 0xb); } else { printk_err("Can't find ethernet interface\n"); } #endif /* OLD_KERNEL_HACK */ ........
So, I modified mainboard.c in "freebios/src/mainboard/pcchips/m758lmr+" as following:
/**********************************************************************/ #include <printk.h> #include <pci.h> #include <pci_ids.h> #include <cpu/p5/io.h> #include <arch/pirq_routing.h> #include <types.h>
#define IRQ1 11 #define IRQ2 12 #define IRQ3 10
#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3)) #define INTERRUPT_PIN 0x3d #define INTERRUPT_LINE 0x3c #define BUS 0
extern struct irq_routing_table intel_irq_routing_table; void mainboard_fixup(void) { }
static int pci_conf1_read_config_word(unsigned char bus, int devfn, int where, u16 * value) { outl(CONFIG_CMD(bus, devfn, where), 0xCF8); *value = inw(0xCFC + (where & 2)); return 0; }
static int pci_conf1_write_config_byte(unsigned char bus, int devfn, int where, u8 value) { outl(CONFIG_CMD(bus, devfn, where), 0xCF8); outb(value, 0xCFC + (where & 3)); return 0; }
static int pci_conf1_read_config_byte(unsigned char bus, int devfn, int where, u8 * value) { outl(CONFIG_CMD(bus, devfn, where), 0xCF8); *value = inb(0xCFC + (where & 3)); return 0; } // // calculate the irq_tables checksum // int calc_checksum(struct irq_routing_table *rt) { long i; u8 *addr,sum2=0; addr= (u8 *) rt; for (i=0;i<rt->size;i++) sum2 += addr[i]; return(sum2); } static void pci_irq_route_fixup() { u8 pin, devfn, irq, irq_written, stpc_reg; u8 irq_list[] = { IRQ1, IRQ2, IRQ3 }; // pirq(slot,pin); slot[0:2] pin[0:3] u8 pirq[3][4] = { {2,3,0,1},{1,2,3,0},{0,1,2,3}}; u16 vendor_id, mask; int i,j; printk_debug("pci_irq_route_fixup()\n");
mask = (1<<irq_list[0]) | (1<<irq_list[1]) | (1<<irq_list[2]);
// search all 3 slots for a device and program the pci INTERRUPT_LINE register // note: not needed by 2.4 but used by 2.2 // also program the stpc pirq routing registers // and set the value in the bios-style routing table used by linux. // When done, calculate and store the routing table checksum. // j=0; for (i=0;i<3;i++) { // i= slot# -1 // read the pin if the device exists devfn = PCI_DEVFN(0x9+i*2,0); pci_conf1_read_config_word(BUS,devfn,0,&vendor_id); if (vendor_id == 0xffff) continue;
pci_conf1_read_config_byte(BUS,devfn,INTERRUPT_PIN,&pin); if (!pin) continue;
printk_debug("sis630 pci_irq_route_fixup(): found INT pin for dev 0x%x -> pin %d\n",0x9+i,pin); pin--; // we start at 0: pin 0-3 -> INTA-D
// get the next irq in our list irq = irq_list[j++];
// program the pci registers pci_conf1_write_config_byte(BUS,devfn,INTERRUPT_LINE,irq); pci_conf1_read_config_byte(BUS,devfn,INTERRUPT_LINE,&irq_written); printk_debug("sis630 pci_irq_route_fixup(): wrote pci INTERRUPT_LINE for dev 0x%x -> irq %d (%d)\n", PCI_SLOT(devfn),irq,irq_written);
// set the routing table // The 0xf0 causes linux to consider the irq hard-wired and use the link value // as the actual irq, so it does not need a router for the stpc. // Otherwise a kernel patch would be needed to add the stpc router into arch/i386/kernel/pci-irq.c intel_irq_routing_table.slots[i+2].irq[pin].link = irq | 0xf0; intel_irq_routing_table.slots[i+2].irq[pin].bitmap = mask; printk_debug("irq routing_table.slots[%d].irq[%d].link,mask = 0x%x,0x%x\n",i+2,pin, intel_irq_routing_table.slots[i+2].irq[pin].link, intel_irq_routing_table.slots[i+2].irq[pin].bitmap ); }
// // Now... // set the checksum in the routing table; // intel_irq_routing_table.checksum = 0; intel_irq_routing_table.checksum = -calc_checksum( (struct irq_routing_table *) &intel_irq_routing_table); printk_debug("sis630 pci_irq_route_fixup(): checksum calculated= 0x%x\n",intel_irq_routing_table.checksum);
printk_debug("sis630 pci_irq_route_fixup complete.\n"); }
void final_mainboard_fixup(void) { void final_southbridge_fixup(void); void final_superio_fixup(void);
printk_info("PCCHIPS m758lmr+ (and similar)...");
final_southbridge_fixup(); pci_irq_route_fixup(); #ifndef USE_NEW_SUPERIO_INTERFACE final_superio_fixup(); #endif }
/************************************************/
Then,I pluged my RTL8139 NIC into slot#1(PCI1). After my box started,the IRQ of RTL8139 is 11. But when I did "ping",I got following messages:
/**************************************************/
#ifconfig eth1 192.168.0.165 up eth1: RTL8139 Interrupt line blocked, status 1. #ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. --- 192.168.0.1 ping statistics --- 21 packets transmitted, 0 packets received, 100% packet loss #neighbour table overflow neighbour table overflow neighbour table overflow
#ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. --- 192.168.0.1 ping statistics --- 20 packets transmitted, 0 packets received, 100% packet loss
#ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. neighbour table overflow neighbour table overflow neighbour table overflow
--- 192.168.0.1 ping statistics --- 21 packets transmitted, 0 packets received, 100% packet loss
#neighbour table overflow neighbour table overflow neighbour table overflow ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. --- 192.168.0.1 ping statistics --- 14 packets transmitted, 0 packets received, 100% packet loss #eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. neighbour table overflow neighbour table overflow neighbour table overflow
#ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data.
--- 192.168.0.1 ping statistics --- 15 packets transmitted, 0 packets received, 100% packet loss #eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. neighbour table overflow #ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data.
--- 192.168.0.1 ping statistics --- 17 packets transmitted, 0 packets received, 100% packet loss #NET: 2 messages suppressed. neighbour table overflow eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data.
--- 192.168.0.1 ping statistics --- 14 packets transmitted, 0 packets received, 100% packet loss
#NET: 2 messages suppressed. neighbour table overflow ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0.
--- 192.168.0.1 ping statistics --- 20 packets transmitted, 0 packets received, 100% packet loss
#ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0.
--- 192.168.0.1 ping statistics --- 21 packets transmitted, 0 packets received, 100% packet loss
#NET: 5 messages suppressed. neighbour table overflow eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0.
#ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data.
--- 192.168.0.1 ping statistics --- 21 packets transmitted, 0 packets received, 100% packet loss
#NET: 2 messages suppressed. neighbour table overflow neighbour table overflow eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0.
#ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. eth1: RTL8139 Interrupt line blocked, status 5.
--- 192.168.0.1 ping statistics --- 18 packets transmitted, 0 packets received, 100% packet loss
#ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) from 192.168.0.165 : 72(100) bytes of data. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 8 dirty entry 4. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. /*************************************************/
The critical messages are:
eth1: RTL8139 Interrupt line blocked, status 1. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 8 dirty entry 4. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0. eth1: Transmit timeout, status 0c 0005 media 18. eth1: Tx queue start entry 4 dirty entry 0.
Could you give me some advice to resolve them?
Thanks.
riskin
========================== 263电子邮件-信赖邮自专业