[PATCH] au1000_tx_timeout and promiscuous mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




hello,

the attached patch fixes a problem I had when running 2 different
Au15xx-based boards (Au1500 and Au1550) in bridging mode under high load.
au1000_tx_timeout() would reset the device for which it was called, but
promiscuous mode was not re-established.

tested under 2.6.14, 2.6.16-rc6 and 2.4.31.

on the 2.6.1x systems, the timeout appears after some 5 seconds, under
2.4.31 I thought it did not appear, but after half an hour of full load
I've seen it there, too.  now this makes me wonder why it takes only a
few seconds to have a tx timeout under 2.6 and half an hour under 2.4.
any ideas?

regards,
	elmar
1) au1000_tx_timeout(): Re-establish promiscuous mode (when bridging)
   after the re-init.

2) Do not dereference device private structure but use netdev_priv()
   instead (according to Rubini et.al. "Linux Device Drivers", 3rd
   edition, o-Reilly.

Apply to kernel trees 2.6.x and 2.4.x.

Tested on
 - myCable XXS1500, Rev.B, Au1500-based, and
 - Kurz NVB, Au1550-based, not in kernel-tree.

Signed-off-by: elmar gerdes <elmar.gerdes@xxxxxxxxxxxx>


--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -206,7 +206,7 @@
 		printk(KERN_ERR "bcm_5201_status error: NULL dev\n");
 		return -1;
 	}
-	aup = (struct au1000_private *) dev->priv;
+	aup = netdev_priv(dev);
 
 	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
 	if (mii_data & MII_STAT_LINK) {
@@ -293,7 +293,7 @@
 		printk(KERN_ERR "lsi_80227_status error: NULL dev\n");
 		return -1;
 	}
-	aup = (struct au1000_private *) dev->priv;
+	aup = netdev_priv(dev);
 
 	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
 	if (mii_data & MII_STAT_LINK) {
@@ -404,7 +404,7 @@
 		return -1;
 	}
 
-	aup = (struct au1000_private *) dev->priv;
+	aup = netdev_priv(dev);
 	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
 
 	if (mii_data & MII_STAT_LINK) {
@@ -486,7 +486,7 @@
 		printk(KERN_ERR "lxt971a_status error: NULL dev\n");
 		return -1;
 	}
-	aup = (struct au1000_private *) dev->priv;
+	aup = netdev_priv(dev);
 
 	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
 	if (mii_data & MII_STAT_LINK) {
@@ -571,7 +571,7 @@
 		printk(KERN_ERR "ks8995m_status error: NULL dev\n");
 		return -1;
 	}
-	aup = (struct au1000_private *) dev->priv;
+	aup = netdev_priv(dev);
 
 	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
 	if (mii_data & MII_STAT_LINK) {
@@ -664,7 +664,7 @@
 		return -1;
 	}
 
-	aup = (struct au1000_private *) dev->priv;
+	aup = netdev_priv(dev);
 	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
 
 	if (mii_data & MII_STAT_LINK) {
@@ -794,7 +794,7 @@
 
 static int mdio_read(struct net_device *dev, int phy_id, int reg)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	volatile u32 *mii_control_reg;
 	volatile u32 *mii_data_reg;
 	u32 timedout = 20;
@@ -854,7 +854,7 @@
 
 static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	volatile u32 *mii_control_reg;
 	volatile u32 *mii_data_reg;
 	u32 timedout = 20;
@@ -911,7 +911,7 @@
 
 static int mii_probe (struct net_device * dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	int phy_addr;
 #ifdef CONFIG_MIPS_BOSPORUS
 	int phy_found=0;
@@ -1078,7 +1078,7 @@
 
 static void enable_rx_tx(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (au1000_debug > 4)
 		printk(KERN_INFO "%s: enable_rx_tx\n", dev->name);
@@ -1089,7 +1089,7 @@
 
 static void hard_stop(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (au1000_debug > 4)
 		printk(KERN_INFO "%s: hard stop\n", dev->name);
@@ -1103,7 +1103,7 @@
 {
 	int i;
 	u32 flags;
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (au1000_debug > 4) 
 		printk(KERN_INFO "%s: reset mac, aup %x\n", 
@@ -1240,7 +1240,7 @@
 
 static int au1000_setup_aneg(struct net_device *dev, u32 advertise)
 {
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	u16 ctl, adv;
 
 	/* Setup standard advertise */
@@ -1266,7 +1266,7 @@
 
 static int au1000_setup_forced(struct net_device *dev, int speed, int fd)
 {
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	u16 ctl;
 
 	ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
@@ -1297,7 +1297,7 @@
 static void
 au1000_start_link(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	u32 advertise;
 	int autoneg;
 	int forced_speed;
@@ -1333,7 +1333,7 @@
 
 static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	u16 link, speed;
 
 	cmd->supported = GENMII_DEFAULT_FEATURES;
@@ -1358,7 +1358,7 @@
 
 static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	 struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	 struct au1000_private *aup = netdev_priv(dev);
 	  unsigned long features = GENMII_DEFAULT_FEATURES;
 
 	 if (!capable(CAP_NET_ADMIN))
@@ -1402,7 +1402,7 @@
 
 static int au1000_nway_reset(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (!aup->want_autoneg)
 		return -EINVAL;
@@ -1415,7 +1415,7 @@
 static void
 au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	strcpy(info->driver, DRV_NAME);
 	strcpy(info->version, DRV_VERSION);
@@ -1470,7 +1470,7 @@
 	printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", 
 			dev->name, ioaddr, irq);
 
-	aup = dev->priv;
+	aup = netdev_priv(dev);
 
 	/* Allocate the data buffers */
 	/* Snooping works fine with eth on all au1xxx */
@@ -1637,7 +1637,7 @@
  */
 static int au1000_init(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	u32 flags;
 	int i;
 	u32 control;
@@ -1689,7 +1689,7 @@
 static void au1000_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	unsigned char if_port;
 	u16 link, speed;
 
@@ -1742,7 +1742,7 @@
 static int au1000_open(struct net_device *dev)
 {
 	int retval;
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (au1000_debug > 4)
 		printk("%s: open: dev=%p\n", dev->name, dev);
@@ -1776,7 +1776,7 @@
 static int au1000_close(struct net_device *dev)
 {
 	u32 flags;
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (au1000_debug > 4)
 		printk("%s: close: dev=%p\n", dev->name, dev);
@@ -1804,7 +1804,7 @@
 	for (i = 0; i < num_ifs; i++) {
 		dev = iflist[i].dev;
 		if (dev) {
-			aup = (struct au1000_private *) dev->priv;
+			aup = netdev_priv(dev);
 			unregister_netdev(dev);
 			kfree(aup->mii);
 			for (j = 0; j < NUM_RX_DMA; j++) {
@@ -1829,7 +1829,7 @@
 static inline void 
 update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	struct net_device_stats *ps = &aup->stats;
 
 	ps->tx_packets++;
@@ -1861,7 +1861,7 @@
  */
 static void au1000_tx_ack(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	volatile tx_dma_t *ptxd;
 
 	ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -1888,7 +1888,7 @@
  */
 static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	volatile tx_dma_t *ptxd;
 	u32 buff_stat;
 	db_dest_t *pDB;
@@ -1939,7 +1939,7 @@
 
 static inline void update_rx_stats(struct net_device *dev, u32 status)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	struct net_device_stats *ps = &aup->stats;
 
 	ps->rx_packets++;
@@ -1967,7 +1967,7 @@
  */
 static int au1000_rx(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	struct sk_buff *skb;
 	volatile rx_dma_t *prxd;
 	u32 buff_stat, status;
@@ -2070,6 +2070,8 @@
 	printk(KERN_ERR "%s: au1000_tx_timeout: dev=%p\n", dev->name, dev);
 	reset_mac(dev);
 	au1000_init(dev);
+	/* Set promiscuous mode */
+	set_rx_mode(dev);
 	dev->trans_start = jiffies;
 	netif_wake_queue(dev);
 }
@@ -2093,7 +2095,7 @@
 
 static void set_rx_mode(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (au1000_debug > 4) 
 		printk("%s: set_rx_mode: flags=%x\n", dev->name, dev->flags);
@@ -2127,7 +2129,7 @@
 
 static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	u16 *data = (u16 *)&rq->ifr_ifru;
 
 	switch(cmd) { 
@@ -2154,7 +2156,7 @@
 
 static int au1000_set_config(struct net_device *dev, struct ifmap *map)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 	u16 control;
 
 	if (au1000_debug > 4)  {
@@ -2248,7 +2250,7 @@
 
 static struct net_device_stats *au1000_get_stats(struct net_device *dev)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct au1000_private *aup = netdev_priv(dev);
 
 	if (au1000_debug > 4)
 		printk("%s: au1000_get_stats: dev=%p\n", dev->name, dev);

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux