[PATCH] de2104x: request_irq() before causing interrupts

From: Rask Ingemann Lambertsen (rask@sygehus.dk)
Date: Sun Nov 02 2003 - 13:52:18 EST


Hi.

With de2104x from 2.6.0-test8, I did:

$ modprobe de2104x debug=0x207f
$ ethtool -s eth0 port bnc
$ ifconfig eth0 up 192.168.2.4 broadcast 192.168.2.15 netmask 255.255.255.240

and this happened:

kernel: de2104x PCI Ethernet driver v0.6 (Sep 1, 2003)
kernel: PCI: Found IRQ 11 for device 0000:00:0e.0
kernel: de0: SROM leaf offset 65, default media 10baseT auto
kernel: de0: media block #0: BNC
kernel: de0: media block #1: AUI
kernel: de0: media block #2: 10baseT-FD
kernel: de0: media block #3: 10baseT-HD
kernel: eth0: 21041 at 0xc297b000, 00:00:f8:00:e3:f8, IRQ 11
kernel: eth0: set link BNC
kernel: eth0: mode 0x7ffc0040, sia 0xc4,0xffff0000,0xfffff7fd,0xffff0006
kernel: eth0: set mode 0x0, set sia 0xef09,0xf7fd,0x6
kernel: eth0: enabling interface
kernel: eth0: set link BNC
kernel: eth0: mode 0x7ffc0040, sia 0x10c4,0xffffef09,0xfffff7fd,0xffff0006
kernel: eth0: set mode 0x7ffc0000, set sia 0xef09,0xf7fd,0x6
kernel: irq 11: nobody cared!
kernel: Call Trace:
kernel: [__report_bad_irq+50/160] __report_bad_irq+0x32/0xa0
kernel: [note_interrupt+76/112] note_interrupt+0x4c/0x70
kernel: [do_IRQ+131/240] do_IRQ+0x83/0xf0
kernel: [common_interrupt+24/32] common_interrupt+0x18/0x20
kernel: [do_softirq+59/160] do_softirq+0x3b/0xa0
kernel: [do_IRQ+215/240] do_IRQ+0xd7/0xf0
kernel: [common_interrupt+24/32] common_interrupt+0x18/0x20
kernel: [_end+40481229/1070687900] de_set_rx_mode+0x11/0x20 [de2104x]
kernel: [_end+40483775/1070687900] de_init_hw+0x73/0x80 [de2104x]
kernel: [_end+40484642/1070687900] de_open+0x66/0xf0 [de2104x]
kernel: [dev_open+105/224] dev_open+0x69/0xe0
kernel: [dev_change_flags+79/272] dev_change_flags+0x4f/0x110
kernel: [devinet_ioctl+820/1648] devinet_ioctl+0x334/0x670
kernel: [dev_ioctl+376/880] dev_ioctl+0x178/0x370
kernel: [inet_ioctl+167/240] inet_ioctl+0xa7/0xf0
kernel: [sock_ioctl+506/528] sock_ioctl+0x1fa/0x210
kernel: [sys_ioctl+488/512] sys_ioctl+0x1e8/0x200
kernel: [sysenter_past_esp+82/113] sysenter_past_esp+0x52/0x71
kernel:
kernel: handlers:
kernel: [_end+40623596/1070687900] (e100intr+0x0/0x210 [e100])
kernel: Disabling IRQ #11
kernel: eth0: link up, media BNC


Why? Because de_open() calls de_init_hw() which calls de_set_rx_mode() which
causes an interrupt from the DS21041. The only interrupt handler on irq 11
is the e100 which correctly says the irq wasn't for any of the two e100
devices I have. You need to have something else sharing the irq to get the
call trace and irq disabled. I can reproduce this problem easily.

This patch fixes the problem, I think. It registers the interrupt handler
because calling de_init_hw().

--- linux-2.6.0-test8/drivers/net/tulip/de2104x.c-orig Tue Oct 21 12:34:44 2003
+++ linux-2.6.0-test8/drivers/net/tulip/de2104x.c Sun Nov 2 18:36:07 2003
@@ -1380,18 +1391,18 @@
return rc;
}

- rc = de_init_hw(de);
+ rc = request_irq(dev->irq, de_interrupt, SA_SHIRQ, dev->name, dev);
if (rc) {
- printk(KERN_ERR "%s: h/w init failure, err=%d\n",
- dev->name, rc);
+ printk(KERN_ERR "%s: IRQ %d request failure, err=%d\n",
+ dev->name, dev->irq, rc);
goto err_out_free;
}

- rc = request_irq(dev->irq, de_interrupt, SA_SHIRQ, dev->name, dev);
+ rc = de_init_hw(de);
if (rc) {
- printk(KERN_ERR "%s: IRQ %d request failure, err=%d\n",
- dev->name, dev->irq, rc);
- goto err_out_hw;
+ printk(KERN_ERR "%s: h/w init failure, err=%d\n",
+ dev->name, rc);
+ goto err_out_free_irq;
}

netif_start_queue(dev);
@@ -1399,10 +1410,8 @@

return 0;

-err_out_hw:
- spin_lock_irqsave(&de->lock, flags);
- de_stop_hw(de);
- spin_unlock_irqrestore(&de->lock, flags);
+err_out_free_irq:
+ free_irq (dev->irq, dev);

err_out_free:
de_free_rings(de);


--
Regards,
Rask Ingemann Lambertsen
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html