1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -177,7 +177,7 @@ struct port {
struct desc *desc_tab; /* coherent */
u32 desc_tab_phys;
int id; /* logical port ID */
- int speed, duplex;
+ int link, speed, duplex;
u8 firmware[4];
int hwts_tx_en;
int hwts_rx_en;
@@ -542,37 +542,52 @@ static void ixp4xx_mdio_remove(void)
mdiobus_free(mdio_bus);
}
-
-static void ixp4xx_adjust_link(struct net_device *dev)
+static void ixp4xx_update_link(struct net_device *dev)
{
struct port *port = netdev_priv(dev);
- struct phy_device *phydev = port->phydev;
- if (!phydev->link) {
- if (port->speed) {
- port->speed = 0;
- printk(KERN_INFO "%s: link down\n", dev->name);
- }
+ if (!port->link) {
+ netif_carrier_off(dev);
+ printk(KERN_INFO "%s: link down\n", dev->name);
return;
}
- if (port->speed == phydev->speed && port->duplex == phydev->duplex)
- return;
-
- port->speed = phydev->speed;
- port->duplex = phydev->duplex;
-
- if (port->duplex)
+ if (port->duplex == DUPLEX_FULL)
__raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
&port->regs->tx_control[0]);
else
__raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX,
&port->regs->tx_control[0]);
+ netif_carrier_on(dev);
printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n",
dev->name, port->speed, port->duplex ? "full" : "half");
}
+static void ixp4xx_adjust_link(struct net_device *dev)
+{
+ struct port *port = netdev_priv(dev);
+ struct phy_device *phydev = port->phydev;
+ int status_change = 0;
+
+ if (phydev->link) {
+ if (port->duplex != phydev->duplex
+ || port->speed != phydev->speed) {
+ status_change = 1;
+ }
+ }
+
+ if (phydev->link != port->link)
+ status_change = 1;
+
+ port->link = phydev->link;
+ port->speed = phydev->speed;
+ port->duplex = phydev->duplex;
+
+ if (status_change)
+ ixp4xx_update_link(dev);
+}
+
static int ixp4xx_phy_connect(struct net_device *dev)
{
struct port *port = netdev_priv(dev);
@@ -608,7 +623,6 @@ static void ixp4xx_phy_start(struct net_
{
struct port *port = netdev_priv(dev);
- port->speed = 0; /* force "link up" message */
phy_start(port->phydev);
}
@@ -1500,6 +1514,10 @@ static int eth_init_one(struct platform_
if ((err = register_netdev(dev)))
goto err_phy_dis;
+ port->link = 0;
+ port->speed = 0;
+ port->duplex = -1;
+
printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
npe_name(port->npe));
|