123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- --- a/drivers/net/ethernet/atheros/ar231x/ar231x.c
- +++ b/drivers/net/ethernet/atheros/ar231x/ar231x.c
- @@ -135,6 +135,7 @@ static int ar231x_mdiobus_write(struct m
- static int ar231x_mdiobus_reset(struct mii_bus *bus);
- static int ar231x_mdiobus_probe(struct net_device *dev);
- static void ar231x_adjust_link(struct net_device *dev);
- +static bool no_phy;
-
- #ifndef ERR
- #define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args)
- @@ -167,6 +168,32 @@ static const struct net_device_ops ar231
- #endif
- };
-
- +static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
- +{
- + int phy_reg;
- +
- + /**
- + * Grab the bits from PHYIR1, and put them
- + * in the upper half.
- + */
- + phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
- +
- + if (phy_reg < 0)
- + return -EIO;
- +
- + *phy_id = (phy_reg & 0xffff) << 16;
- +
- + /* Grab the bits from PHYIR2, and put them in the lower half */
- + phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
- +
- + if (phy_reg < 0)
- + return -EIO;
- +
- + *phy_id |= (phy_reg & 0xffff);
- +
- + return 0;
- +}
- +
- static int ar231x_probe(struct platform_device *pdev)
- {
- struct net_device *dev;
- @@ -273,6 +300,24 @@ static int ar231x_probe(struct platform_
-
- mdiobus_register(sp->mii_bus);
-
- + /**
- + * Workaround for Micrel switch, which is only available on
- + * one PHY and cannot be configured through MDIO.
- + */
- + if (!no_phy) {
- + u32 phy_id = 0;
- +
- + get_phy_id(sp->mii_bus, 1, &phy_id);
- + if (phy_id == 0x00221450)
- + no_phy = true;
- + }
- + if (no_phy) {
- + sp->link = 1;
- + netif_carrier_on(dev);
- + return 0;
- + }
- + no_phy = true;
- +
- if (ar231x_mdiobus_probe(dev) != 0) {
- printk(KERN_ERR "%s: mdiobus_probe failed\n", dev->name);
- rx_tasklet_cleanup(dev);
- @@ -326,8 +371,10 @@ static int ar231x_remove(struct platform
- rx_tasklet_cleanup(dev);
- ar231x_init_cleanup(dev);
- unregister_netdev(dev);
- - mdiobus_unregister(sp->mii_bus);
- - mdiobus_free(sp->mii_bus);
- + if (sp->mii_bus) {
- + mdiobus_unregister(sp->mii_bus);
- + mdiobus_free(sp->mii_bus);
- + }
- kfree(dev);
- return 0;
- }
- @@ -870,7 +917,8 @@ static int ar231x_open(struct net_device
-
- sp->eth_regs->mac_control |= MAC_CONTROL_RE;
-
- - phy_start(sp->phy_dev);
- + if (sp->phy_dev)
- + phy_start(sp->phy_dev);
-
- return 0;
- }
- @@ -951,7 +999,8 @@ static int ar231x_close(struct net_devic
-
- #endif
-
- - phy_stop(sp->phy_dev);
- + if (sp->phy_dev)
- + phy_stop(sp->phy_dev);
-
- return 0;
- }
- @@ -995,6 +1044,9 @@ static int ar231x_ioctl(struct net_devic
- {
- struct ar231x_private *sp = netdev_priv(dev);
-
- + if (!sp->phy_dev)
- + return -ENODEV;
- +
- switch (cmd) {
- case SIOCGMIIPHY:
- case SIOCGMIIREG:
|