DM9000: Allow the use of the NSR register to get link status.
authorBen Dooks <ben-linux@fluff.org>
Tue, 24 Jun 2008 21:16:04 +0000 (22:16 +0100)
committerJeff Garzik <jgarzik@redhat.com>
Wed, 25 Jun 2008 02:58:07 +0000 (22:58 -0400)
The DM9000's internal PHY reports a copy of the link status
in the NSR register of the chip. Reading the status when
polling for link status is faster as it eliminates the need
to sleep, but does not print as much information.

Add an platform flag to force this behaviour, and a Kconfig
option to allow it to be forced to the faster method always.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/net/Kconfig
drivers/net/dm9000.c
include/linux/dm9000.h

index 287d0873c60d1201d6aa1ada48298369e5e46a02..4d69474b6125dd217eb415bb73fd95d68bc3d54e 100644 (file)
@@ -938,6 +938,15 @@ config DM9000
          To compile this driver as a module, choose M here.  The module
          will be called dm9000.
 
+config DM9000_FORCE_SIMPLE_PHY_POLL
+       bool "Force simple NSR based PHY polling"
+       depends on DM9000
+       ---help---
+         This configuration forces the DM9000 to use the NSR's LinkStatus
+         bit to determine if the link is up or down instead of the more
+         costly MII PHY reads. Note, this will not work if the chip is
+         operating with an external PHY.
+
 config ENC28J60
        tristate "ENC28J60 support"
        depends on EXPERIMENTAL && SPI && NET_ETHERNET
index 7c38f6129b55a343b3a50c94a171177dede2bf07..5ad2ec537684a5eda8ca1bcad93db619d4fa322c 100644 (file)
@@ -552,15 +552,48 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
        .set_eeprom             = dm9000_set_eeprom,
 };
 
+static void dm9000_show_carrier(board_info_t *db,
+                               unsigned carrier, unsigned nsr)
+{
+       struct net_device *ndev = db->ndev;
+       unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
+
+       if (carrier)
+               dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",
+                        ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
+                        (ncr & NCR_FDX) ? "full" : "half");
+       else
+               dev_info(db->dev, "%s: link down\n", ndev->name);
+}
+
 static void
 dm9000_poll_work(struct work_struct *w)
 {
        struct delayed_work *dw = container_of(w, struct delayed_work, work);
        board_info_t *db = container_of(dw, board_info_t, phy_poll);
+       struct net_device *ndev = db->ndev;
+
+       if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
+           !(db->flags & DM9000_PLATF_EXT_PHY)) {
+               unsigned nsr = dm9000_read_locked(db, DM9000_NSR);
+               unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;
+               unsigned new_carrier;
 
-       mii_check_media(&db->mii, netif_msg_link(db), 0);
+               new_carrier = (nsr & NSR_LINKST) ? 1 : 0;
+
+               if (old_carrier != new_carrier) {
+                       if (netif_msg_link(db))
+                               dm9000_show_carrier(db, new_carrier, nsr);
+
+                       if (!new_carrier)
+                               netif_carrier_off(ndev);
+                       else
+                               netif_carrier_on(ndev);
+               }
+       } else
+               mii_check_media(&db->mii, netif_msg_link(db), 0);
        
-       if (netif_running(db->ndev))
+       if (netif_running(ndev))
                dm9000_schedule_poll(db);
 }
 
@@ -1267,6 +1300,10 @@ dm9000_probe(struct platform_device *pdev)
                db->flags = pdata->flags;
        }
 
+#ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL
+       db->flags |= DM9000_PLATF_SIMPLE_PHY;
+#endif
+
        dm9000_reset(db);
 
        /* try multiple times, DM9000 sometimes gets the read wrong */
index a3750462f9e34eca3c673e0da9713ecfa44d647e..fc82446b64255d7fe7c16ba9edb67c2d049b9bf4 100644 (file)
@@ -21,6 +21,7 @@
 #define DM9000_PLATF_32BITONLY (0x0004)
 #define DM9000_PLATF_EXT_PHY   (0x0008)
 #define DM9000_PLATF_NO_EEPROM (0x0010)
+#define DM9000_PLATF_SIMPLE_PHY (0x0020)  /* Use NSR to find LinkStatus */
 
 /* platfrom data for platfrom device structure's platfrom_data field */