aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/mv643xx_eth.c91
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 ***************************************************/
1688static 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
1682static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) 1746static 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);