diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2008-07-24 00:22:59 -0400 |
---|---|---|
committer | Lennert Buytenhek <buytenh@marvell.com> | 2008-07-24 00:22:59 -0400 |
commit | 2f7eb47a7b9f703d4f7dfdab358df6ff1f2a2204 (patch) | |
tree | 67c8e54be34d5eafa8b6aa29d0a5b482c9297532 /drivers/net/mv643xx_eth.c | |
parent | 81600eea98789da09a32de69ca9d3be8b9503c54 (diff) |
mv643xx_eth: print message on link status change
When there is a link status change (link or phy status interrupt),
print a message notifying the user of the new link status.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 91 |
1 files changed, 69 insertions, 22 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 29d4fe37cd50..01dd3c505d25 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -91,6 +91,12 @@ static char mv643xx_eth_driver_version[] = "1.1"; | |||
91 | #define PORT_STATUS(p) (0x0444 + ((p) << 10)) | 91 | #define PORT_STATUS(p) (0x0444 + ((p) << 10)) |
92 | #define TX_FIFO_EMPTY 0x00000400 | 92 | #define TX_FIFO_EMPTY 0x00000400 |
93 | #define TX_IN_PROGRESS 0x00000080 | 93 | #define TX_IN_PROGRESS 0x00000080 |
94 | #define PORT_SPEED_MASK 0x00000030 | ||
95 | #define PORT_SPEED_1000 0x00000010 | ||
96 | #define PORT_SPEED_100 0x00000020 | ||
97 | #define PORT_SPEED_10 0x00000000 | ||
98 | #define FLOW_CONTROL_ENABLED 0x00000008 | ||
99 | #define FULL_DUPLEX 0x00000004 | ||
94 | #define LINK_UP 0x00000002 | 100 | #define LINK_UP 0x00000002 |
95 | #define TXQ_COMMAND(p) (0x0448 + ((p) << 10)) | 101 | #define TXQ_COMMAND(p) (0x0448 + ((p) << 10)) |
96 | #define TXQ_FIX_PRIO_CONF(p) (0x044c + ((p) << 10)) | 102 | #define TXQ_FIX_PRIO_CONF(p) (0x044c + ((p) << 10)) |
@@ -1679,6 +1685,64 @@ static void txq_deinit(struct tx_queue *txq) | |||
1679 | 1685 | ||
1680 | 1686 | ||
1681 | /* netdev ops and related ***************************************************/ | 1687 | /* netdev ops and related ***************************************************/ |
1688 | static void handle_link_event(struct mv643xx_eth_private *mp) | ||
1689 | { | ||
1690 | struct net_device *dev = mp->dev; | ||
1691 | u32 port_status; | ||
1692 | int speed; | ||
1693 | int duplex; | ||
1694 | int fc; | ||
1695 | |||
1696 | port_status = rdl(mp, PORT_STATUS(mp->port_num)); | ||
1697 | if (!(port_status & LINK_UP)) { | ||
1698 | if (netif_carrier_ok(dev)) { | ||
1699 | int i; | ||
1700 | |||
1701 | printk(KERN_INFO "%s: link down\n", dev->name); | ||
1702 | |||
1703 | netif_carrier_off(dev); | ||
1704 | netif_stop_queue(dev); | ||
1705 | |||
1706 | for (i = 0; i < 8; i++) { | ||
1707 | struct tx_queue *txq = mp->txq + i; | ||
1708 | |||
1709 | if (mp->txq_mask & (1 << i)) { | ||
1710 | txq_reclaim(txq, 1); | ||
1711 | txq_reset_hw_ptr(txq); | ||
1712 | } | ||
1713 | } | ||
1714 | } | ||
1715 | return; | ||
1716 | } | ||
1717 | |||
1718 | switch (port_status & PORT_SPEED_MASK) { | ||
1719 | case PORT_SPEED_10: | ||
1720 | speed = 10; | ||
1721 | break; | ||
1722 | case PORT_SPEED_100: | ||
1723 | speed = 100; | ||
1724 | break; | ||
1725 | case PORT_SPEED_1000: | ||
1726 | speed = 1000; | ||
1727 | break; | ||
1728 | default: | ||
1729 | speed = -1; | ||
1730 | break; | ||
1731 | } | ||
1732 | duplex = (port_status & FULL_DUPLEX) ? 1 : 0; | ||
1733 | fc = (port_status & FLOW_CONTROL_ENABLED) ? 1 : 0; | ||
1734 | |||
1735 | printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " | ||
1736 | "flow control %sabled\n", dev->name, | ||
1737 | speed, duplex ? "full" : "half", | ||
1738 | fc ? "en" : "dis"); | ||
1739 | |||
1740 | if (!netif_carrier_ok(dev)) { | ||
1741 | netif_carrier_on(dev); | ||
1742 | netif_wake_queue(dev); | ||
1743 | } | ||
1744 | } | ||
1745 | |||
1682 | static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) | 1746 | static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) |
1683 | { | 1747 | { |
1684 | struct net_device *dev = (struct net_device *)dev_id; | 1748 | struct net_device *dev = (struct net_device *)dev_id; |
@@ -1698,28 +1762,8 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) | |||
1698 | wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext); | 1762 | wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext); |
1699 | } | 1763 | } |
1700 | 1764 | ||
1701 | if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK)) { | 1765 | if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK)) |
1702 | if (rdl(mp, PORT_STATUS(mp->port_num)) & LINK_UP) { | 1766 | handle_link_event(mp); |
1703 | if (!netif_carrier_ok(dev)) { | ||
1704 | netif_carrier_on(dev); | ||
1705 | netif_wake_queue(dev); | ||
1706 | } | ||
1707 | } else if (netif_carrier_ok(dev)) { | ||
1708 | int i; | ||
1709 | |||
1710 | netif_stop_queue(dev); | ||
1711 | netif_carrier_off(dev); | ||
1712 | |||
1713 | for (i = 0; i < 8; i++) { | ||
1714 | struct tx_queue *txq = mp->txq + i; | ||
1715 | |||
1716 | if (mp->txq_mask & (1 << i)) { | ||
1717 | txq_reclaim(txq, 1); | ||
1718 | txq_reset_hw_ptr(txq); | ||
1719 | } | ||
1720 | } | ||
1721 | } | ||
1722 | } | ||
1723 | 1767 | ||
1724 | /* | 1768 | /* |
1725 | * RxBuffer or RxError set for any of the 8 queues? | 1769 | * RxBuffer or RxError set for any of the 8 queues? |
@@ -1970,6 +2014,9 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
1970 | napi_enable(&mp->napi); | 2014 | napi_enable(&mp->napi); |
1971 | #endif | 2015 | #endif |
1972 | 2016 | ||
2017 | netif_carrier_off(dev); | ||
2018 | netif_stop_queue(dev); | ||
2019 | |||
1973 | port_start(mp); | 2020 | port_start(mp); |
1974 | 2021 | ||
1975 | set_rx_coal(mp, 0); | 2022 | set_rx_coal(mp, 0); |