Tulip 21040 hangs with ifconfig promisc
Subsystems (2)
Hi,
This is:
Linux version ~2.6.4 (Red Hat Linux 3.3.2-1)) SMP kernel, UNI CPU. (as of Mar 12 in bkcvs/linux-2.5/).
Acorp VIA77 mobo - AMD-K6 3D 500 MHz + VIA MVP3 chipset. SMC EtherPower^2 (dual DECchip 21040 + 21050 PCI-PCI bridge) All running out of ramdisk.
Doing "ifconfig eth0 promisc" kills the ethernet. Interrupts are gone, nothing in dmesg. -promisc nor ifconfig down/up doesn't fix it, only driver rmmod/insmod does.
de2104x PCI Ethernet driver v0.6 (Sep 1, 2003)
eth0: 21040 at 0xca81e000, 00:00:c0:d8:66:e0, IRQ 11 eth1: 21040 at 0xca820000, 00:00:c0:16:1b:c0, IRQ 12 eth0: enabling interface eth0: set link 10baseT-HD eth0: mode 0xfffc0040, sia 0xffffffc4,0xffff8f01,0xffffffff,0xffff0000 eth0: set mode 0xfffc0000, set sia 0x8f01,0xffff,0x0 eth0: link up, media 10baseT-HD
device eth0 entered promiscuous mode
Any idea?
Signature · 1 line
Krzysztof Halasa, B*FH
PATCH 1/1 2.6.x Re: Tulip 21040 hangs with ifconfig promisc
Hi,
Bug (2.6.x Linux, DE21040 tulip):
Quoted 3 lines
Doing "ifconfig eth0 promisc" kills the ethernet. Interrupts are gone, nothing in dmesg. -promisc nor ifconfig down/up doesn't fix it, only driver rmmod/insmod does.
The attached patch fixes the problem: de->macmode variable, meant to shadow MacMode (CSR6) register, was used inconsistently, causing some updates to this register to be dropped.
2.4 kernel doesn't shadow this register at all, so I removed shadowing from 2.6 as well.
Signature · 1 line
Krzysztof Halasa, B*FH
drivers/net/tulip/de2104x.c +13 -12
@@ -303,7 +303,6 @@struct net_device_stats net_stats;struct pci_dev *pdev; -u32 macmode;u16 setup_frame[DE_SETUP_FRAME_WORDS ];
@@ -732,7 +731,7 @@struct de_desc *txd;struct de_desc *dummy_txd =NULL ; - macmode = de->macmode & ~(AcceptAllMulticast | AcceptAllPhys); + macmode =dr32 (MacMode) & ~(AcceptAllMulticast | AcceptAllPhys);if (dev->flags &IFF_PROMISC ) {/* Set promiscuous. */ macmode |= AcceptAllMulticast | AcceptAllPhys;
@@ -805,10 +804,8 @@dw32 (TxPoll, NormalTxPoll); out: -if (macmode != de->macmode) { -dw32 (MacMode, macmode); - de->macmode = macmode; - } +if (macmode !=dr32 (MacMode)) +dw32 (MacMode, macmode); }static void de_set_rx_mode (struct net_device *dev)
@@ -923,6 +920,7 @@static void de_set_media (struct de_private *de) {unsigned media = de->media_type; +u32 macmode =dr32 (MacMode);if (de_is_running (de))BUG ();
@@ -940,9 +938,9 @@mdelay (10 );if (media ==DE_MEDIA_TP_FD ) - de->macmode |= FullDuplex; + macmode |= FullDuplex;else - de->macmode &= ~FullDuplex; + macmode &= ~FullDuplex;if (netif_msg_link (de)) { printk(KERN_INFO "%s: set link %s\n"
@@ -951,9 +949,11 @@ de->dev->name, media_name[media], de->dev->name,dr32 (MacMode),dr32 (SIAStatus),dr32 (CSR13 ),dr32 (CSR14 ),dr32 (CSR15 ), - de->dev->name, de->macmode, de->media[media].csr13, + de->dev->name, macmode, de->media[media].csr13, de->media[media].csr14, de->media[media].csr15); } +if (macmode !=dr32 (MacMode)) +dw32 (MacMode, macmode); } static void de_next_media (struct de_private *de, u32 *media,
@@ -1235,11 +1235,12 @@static int de_init_hw (struct de_private *de) {struct net_device *dev = de->dev; +u32 macmode;int rc;de_adapter_wake (de); - de->macmode =dr32 (MacMode) & ~MacModeClear; + macmode =dr32 (MacMode) & ~MacModeClear; rc =de_reset_mac (de);if (rc)
@@ -1250,7 +1251,7 @@dw32 (RxRingAddr, de->ring_dma);dw32 (TxRingAddr, de->ring_dma + (sizeof (struct de_desc ) *DE_RX_RING_SIZE )); -dw32 (MacMode, RxTx | de->macmode); +dw32 (MacMode, RxTx | macmode);dr32 (RxMissed);/* self-clearing */
@@ -1501,7 +1502,7 @@break ; } -if (de->macmode & FullDuplex) +if (dr32 (MacMode) & FullDuplex) ecmd->duplex =DUPLEX_FULL ;else ecmd->duplex =DUPLEX_HALF ;
PATCH 1/1 old-tulip 2104x update
Here's a patch versus 2.6 upstream, and also the complete driver if that's easier.
Anybody wanna give it a test?
And Rask, don't you have some other patches?
Jeff
drivers/net/tulip/de2104x.c +22 -21
@@ -28,8 +28,8 @@*/ #define DRV_NAME "de2104x" -#define DRV_VERSION "0.6" -#define DRV_RELDATE "Sep 1, 2003" +#define DRV_VERSION "0.7" +#define DRV_RELDATE "Mar 17, 2004"#include <linux/config.h> #include <linux/module.h>
@@ -303,7 +303,6 @@struct net_device_stats net_stats;struct pci_dev *pdev; -u32 macmode;u16 setup_frame[DE_SETUP_FRAME_WORDS ];
@@ -732,7 +731,7 @@struct de_desc *txd;struct de_desc *dummy_txd =NULL ; - macmode = de->macmode & ~(AcceptAllMulticast | AcceptAllPhys); + macmode =dr32 (MacMode) & ~(AcceptAllMulticast | AcceptAllPhys);if (dev->flags &IFF_PROMISC ) {/* Set promiscuous. */ macmode |= AcceptAllMulticast | AcceptAllPhys;
@@ -805,10 +804,8 @@dw32 (TxPoll, NormalTxPoll); out: -if (macmode != de->macmode) { -dw32 (MacMode, macmode); - de->macmode = macmode; - } +if (macmode !=dr32 (MacMode)) +dw32 (MacMode, macmode); }static void de_set_rx_mode (struct net_device *dev)
@@ -923,6 +920,7 @@static void de_set_media (struct de_private *de) {unsigned media = de->media_type; +u32 macmode =dr32 (MacMode);if (de_is_running (de))BUG ();
@@ -940,9 +938,9 @@mdelay (10 );if (media ==DE_MEDIA_TP_FD ) - de->macmode |= FullDuplex; + macmode |= FullDuplex;else - de->macmode &= ~FullDuplex; + macmode &= ~FullDuplex;if (netif_msg_link (de)) { printk(KERN_INFO "%s: set link %s\n"
@@ -951,9 +949,11 @@ de->dev->name, media_name[media], de->dev->name,dr32 (MacMode),dr32 (SIAStatus),dr32 (CSR13 ),dr32 (CSR14 ),dr32 (CSR15 ), - de->dev->name, de->macmode, de->media[media].csr13, + de->dev->name, macmode, de->media[media].csr13, de->media[media].csr14, de->media[media].csr15); } +if (macmode !=dr32 (MacMode)) +dw32 (MacMode, macmode); } static void de_next_media (struct de_private *de, u32 *media,
@@ -1173,18 +1173,18 @@u32 status, tmp;/* -* Reset MAC. Copied from de4x5.c. +* Reset MAC. de4x5.c and tulip.c examined for "advice" +* in this area. */ - tmp =dr32 (BusMode); -if (tmp ==0xffffffff ) -return -ENODEV ; -mdelay (1 ); +if (dr32 (BusMode) ==0xffffffff ) +return -EBUSY ; -dw32 (BusMode, tmp | CmdReset); +/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ +dw32 (BusMode, CmdReset);mdelay (1 ); -dw32 (BusMode, tmp); +dw32 (BusMode, de_bus_mode);mdelay (1 );for (tmp =0 ; tmp <5 ; tmp++) {
@@ -1235,11 +1235,12 @@static int de_init_hw (struct de_private *de) {struct net_device *dev = de->dev; +u32 macmode;int rc;de_adapter_wake (de); - de->macmode =dr32 (MacMode) & ~MacModeClear; + macmode =dr32 (MacMode) & ~MacModeClear; rc =de_reset_mac (de);if (rc)
@@ -1250,7 +1251,7 @@dw32 (RxRingAddr, de->ring_dma);dw32 (TxRingAddr, de->ring_dma + (sizeof (struct de_desc ) *DE_RX_RING_SIZE )); -dw32 (MacMode, RxTx | de->macmode); +dw32 (MacMode, RxTx | macmode);dr32 (RxMissed);/* self-clearing */
@@ -1501,7 +1502,7 @@break ; } -if (de->macmode & FullDuplex) +if (dr32 (MacMode) & FullDuplex) ecmd->duplex =DUPLEX_FULL ;else ecmd->duplex =DUPLEX_HALF ;