summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-06-24 22:16:04 +0100
committerJeff Garzik <jgarzik@redhat.com>2008-06-24 22:58:07 -0400
commitf8dd0ecbb74d4b220b105d77c0633945ebb5453e (patch)
tree967cf1edddd83c99f3b579747dd2f70c7f96aadc /drivers
parentaa1eb452e8d8a97ee65ace0054e7a733ae12cf6d (diff)
DM9000: Allow the use of the NSR register to get link status.
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/Kconfig9
-rw-r--r--drivers/net/dm9000.c41
2 files changed, 48 insertions, 2 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 287d0873c60d..4d69474b6125 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -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
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 7c38f6129b55..5ad2ec537684 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -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 */