OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | --- a/drivers/net/ethernet/atheros/ar231x/ar231x.c |
2 | +++ b/drivers/net/ethernet/atheros/ar231x/ar231x.c |
||
3 | @@ -135,6 +135,7 @@ static int ar231x_mdiobus_write(struct m |
||
4 | static int ar231x_mdiobus_reset(struct mii_bus *bus); |
||
5 | static int ar231x_mdiobus_probe(struct net_device *dev); |
||
6 | static void ar231x_adjust_link(struct net_device *dev); |
||
7 | +static bool no_phy; |
||
8 | |||
9 | #ifndef ERR |
||
10 | #define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args) |
||
11 | @@ -167,6 +168,32 @@ static const struct net_device_ops ar231 |
||
12 | #endif |
||
13 | }; |
||
14 | |||
15 | +static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id) |
||
16 | +{ |
||
17 | + int phy_reg; |
||
18 | + |
||
19 | + /** |
||
20 | + * Grab the bits from PHYIR1, and put them |
||
21 | + * in the upper half. |
||
22 | + */ |
||
23 | + phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); |
||
24 | + |
||
25 | + if (phy_reg < 0) |
||
26 | + return -EIO; |
||
27 | + |
||
28 | + *phy_id = (phy_reg & 0xffff) << 16; |
||
29 | + |
||
30 | + /* Grab the bits from PHYIR2, and put them in the lower half */ |
||
31 | + phy_reg = mdiobus_read(bus, addr, MII_PHYSID2); |
||
32 | + |
||
33 | + if (phy_reg < 0) |
||
34 | + return -EIO; |
||
35 | + |
||
36 | + *phy_id |= (phy_reg & 0xffff); |
||
37 | + |
||
38 | + return 0; |
||
39 | +} |
||
40 | + |
||
41 | static int ar231x_probe(struct platform_device *pdev) |
||
42 | { |
||
43 | struct net_device *dev; |
||
44 | @@ -273,6 +300,24 @@ static int ar231x_probe(struct platform_ |
||
45 | |||
46 | mdiobus_register(sp->mii_bus); |
||
47 | |||
48 | + /** |
||
49 | + * Workaround for Micrel switch, which is only available on |
||
50 | + * one PHY and cannot be configured through MDIO. |
||
51 | + */ |
||
52 | + if (!no_phy) { |
||
53 | + u32 phy_id = 0; |
||
54 | + |
||
55 | + get_phy_id(sp->mii_bus, 1, &phy_id); |
||
56 | + if (phy_id == 0x00221450) |
||
57 | + no_phy = true; |
||
58 | + } |
||
59 | + if (no_phy) { |
||
60 | + sp->link = 1; |
||
61 | + netif_carrier_on(dev); |
||
62 | + return 0; |
||
63 | + } |
||
64 | + no_phy = true; |
||
65 | + |
||
66 | if (ar231x_mdiobus_probe(dev) != 0) { |
||
67 | printk(KERN_ERR "%s: mdiobus_probe failed\n", dev->name); |
||
68 | rx_tasklet_cleanup(dev); |
||
69 | @@ -326,8 +371,10 @@ static int ar231x_remove(struct platform |
||
70 | rx_tasklet_cleanup(dev); |
||
71 | ar231x_init_cleanup(dev); |
||
72 | unregister_netdev(dev); |
||
73 | - mdiobus_unregister(sp->mii_bus); |
||
74 | - mdiobus_free(sp->mii_bus); |
||
75 | + if (sp->mii_bus) { |
||
76 | + mdiobus_unregister(sp->mii_bus); |
||
77 | + mdiobus_free(sp->mii_bus); |
||
78 | + } |
||
79 | kfree(dev); |
||
80 | return 0; |
||
81 | } |
||
82 | @@ -870,7 +917,8 @@ static int ar231x_open(struct net_device |
||
83 | |||
84 | sp->eth_regs->mac_control |= MAC_CONTROL_RE; |
||
85 | |||
86 | - phy_start(sp->phy_dev); |
||
87 | + if (sp->phy_dev) |
||
88 | + phy_start(sp->phy_dev); |
||
89 | |||
90 | return 0; |
||
91 | } |
||
92 | @@ -951,7 +999,8 @@ static int ar231x_close(struct net_devic |
||
93 | |||
94 | #endif |
||
95 | |||
96 | - phy_stop(sp->phy_dev); |
||
97 | + if (sp->phy_dev) |
||
98 | + phy_stop(sp->phy_dev); |
||
99 | |||
100 | return 0; |
||
101 | } |
||
102 | @@ -995,6 +1044,9 @@ static int ar231x_ioctl(struct net_devic |
||
103 | { |
||
104 | struct ar231x_private *sp = netdev_priv(dev); |
||
105 | |||
106 | + if (!sp->phy_dev) |
||
107 | + return -ENODEV; |
||
108 | + |
||
109 | switch (cmd) { |
||
110 | case SIOCGMIIPHY: |
||
111 | case SIOCGMIIREG: |