Skip to contentSkip to conversation

Tulip 21040 hangs with ifconfig promisc

PATCH New Krzysztof Halasa 2 participants 3 messages Mar 14, 2004 – Mar 17, 2004

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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;
#2 lore raw

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
diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
@@ -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;