linux-mips
[Top] [All Lists]

Re: bitrot in drivers/net/au1000_eth.c

To: linux-mips@linux-mips.org
Subject: Re: bitrot in drivers/net/au1000_eth.c
From: Ulrich Eckhardt <eckhardt@satorlaser.com>
Date: Sun, 30 Jan 2005 12:50:53 +0100
In-reply-to: <200501281501.19162.eckhardt@satorlaser.com>
Organization: Sator Laser GmbH
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <200501281501.19162.eckhardt@satorlaser.com>
Sender: linux-mips-bounce@linux-mips.org
User-agent: KMail/1.7.1
I received a private reply from Herbert Valerio Riedel with a patch that falls 
into category

> 3. Split off the MII handling code or, better, reuse the facility already
> provided by drivers/net/mii.c. 

with the permission to forward the patch here. Here comes the code and some 
comments by him...

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>code>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

there's a nasty bug in the code, which triggers a kernel freeze when
performing MII ioctl's w/ mii-tool on a device which is down;

the following code fixes that, and uses the generic mii ioctl helper in
order to use proven code...

hope it's welcomed or useful :-)


Index: drivers/net/au1000_eth.c
===================================================================
--- drivers/net/au1000_eth.c (revision 25)
+++ drivers/net/au1000_eth.c (working copy)
@@ -91,7 +91,7 @@
 static void au1000_timer(unsigned long);
 static int au1000_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *, int, int);
-static void mdio_write(struct net_device *, int, int, u16);
+static void mdio_write(struct net_device *, int, int, int);
 static void dump_mii(struct net_device *dev, int phy_id);
 
 // externs
@@ -846,7 +846,7 @@
  return (int)*mii_data_reg;
 }
 
-static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 
value)
+static void mdio_write(struct net_device *dev, int phy_id, int reg, int 
value)
 {
  struct au1000_private *aup = (struct au1000_private *) dev->priv;
  volatile u32 *mii_control_reg;
@@ -951,6 +951,10 @@
     aup->phy_ops = mii_chip_table[i].phy_ops;
     aup->phy_ops->phy_init(dev,phy_addr);
 
+    aup->mii_if.phy_id = phy_addr;
+    aup->mii_if.phy_id_mask = 0x1f;    
+    aup->mii_if.reg_num_mask = 0x1f;
+
     // Check for dual-phy and then store required 
     // values and set indicators. We need to do 
     // this now since mdio_{read,write} need the 
@@ -1544,6 +1548,10 @@
  aup->mii->mii_control_reg = 0;
  aup->mii->mii_data_reg = 0;
 
+        aup->mii_if.dev = dev;
+        aup->mii_if.mdio_read = mdio_read;
+        aup->mii_if.mdio_write = mdio_write;
+
  if (mii_probe(dev) != 0) {
   goto err_out;
  }
@@ -1592,6 +1600,7 @@
  dev->tx_timeout = au1000_tx_timeout;
  dev->watchdog_timeo = ETH_TX_TIMEOUT;
 
+
  /* 
   * The boot code uses the ethernet controller, so reset it to start 
   * fresh.  au1000_init() expects that the device is in reset state.
@@ -2127,24 +2136,17 @@
 
 static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
- struct au1000_private *aup = (struct au1000_private *)dev->priv;
- u16 *data = (u16 *)&rq->ifr_ifru;
+ struct au1000_private *const aup = netdev_priv(dev);
+ int rc;
+ unsigned long flags;
 
- switch(cmd) { 
- case SIOCGMIIPHY:
-  data[0] = aup->phy_addr;
-  /* Fall through */
- case SIOCGMIIREG:
-  data[3] = mdio_read(dev, aup->phy_addr, data[1]);
-  return 0;
- case SIOCSMIIREG:
-  if (!capable(CAP_NET_ADMIN))
-   return -EPERM;
-  mdio_write(dev, aup->phy_addr, data[1], data[2]);
-  return 0;
- default:
-  return -EOPNOTSUPP;
- }
+ if (!netif_running(dev))
+  return -EINVAL;
+
+ spin_lock_irqsave(&aup->lock, flags);
+        rc = generic_mii_ioctl(&aup->mii_if, if_mii(rq), cmd, NULL);
+        spin_unlock_irqrestore(&aup->lock, flags);
+        return rc;
 }
 
 
Index: drivers/net/au1000_eth.h
===================================================================
--- drivers/net/au1000_eth.h (revision 25)
+++ drivers/net/au1000_eth.h (working copy)
@@ -214,6 +214,7 @@
  int mac_id;
  mii_phy_t *mii;
  struct phy_ops *phy_ops;
+ struct mii_if_info mii_if;
  
  /* These variables are just for quick access to certain regs addresses. */
  volatile mac_reg_t *mac;  /* mac registers                      */   
Index: drivers/net/Kconfig
===================================================================
--- drivers/net/Kconfig (revision 25)
+++ drivers/net/Kconfig (working copy)
@@ -467,6 +467,7 @@
  bool "MIPS AU1000 Ethernet support"
  depends on NET_ETHERNET && SOC_AU1X00
  select CRC32
+ select MII
  help
    If you have an Alchemy Semi AU1X00 based system
    say Y.  Otherwise, say N.


<Prev in Thread] Current Thread [Next in Thread>