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