NET: fix phy init for AX88772 USB ethernet
authorGrant Grundler <grundler@chromium.org>
Tue, 4 Oct 2011 09:55:16 +0000 (09:55 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Oct 2011 20:25:31 +0000 (16:25 -0400)
Fix phy initialization for AX88772 (USB 2.0 100BT). Failure was
occasionally DHCP wouldn't work after reboot or suspend/resume cycle.

Remove MONITOR_MODE. In this mode, Received packets are not buffered when
the remote wakeup is enabled.

Signed-off-by: "Freddy Xin" <freddy@asix.com.tw>
Signed-off-by: Grant Grundler <grundler@chromium.org>
Acked-by: Olof Johansson <olofj@chromium.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/usb/asix.c

index b843eedd409dd7ef17bd01f04cafcc5422eb5bee..9e0b3776b80a6500b671c2b0a3cc199ce3cef0f3 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
 
-#define DRIVER_VERSION "14-Jun-2006"
+#define DRIVER_VERSION "26-Sep-2011"
 static const char driver_name [] = "asix";
 
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
@@ -676,12 +676,6 @@ asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
        }
        wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
        wolinfo->wolopts = 0;
-       if (opt & AX_MONITOR_MODE) {
-               if (opt & AX_MONITOR_LINK)
-                       wolinfo->wolopts |= WAKE_PHY;
-               if (opt & AX_MONITOR_MAGIC)
-                       wolinfo->wolopts |= WAKE_MAGIC;
-       }
 }
 
 static int
@@ -694,8 +688,6 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
                opt |= AX_MONITOR_LINK;
        if (wolinfo->wolopts & WAKE_MAGIC)
                opt |= AX_MONITOR_MAGIC;
-       if (opt != 0)
-               opt |= AX_MONITOR_MODE;
 
        if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
                              opt, 0, 0, NULL) < 0)
@@ -966,36 +958,17 @@ static int ax88772_link_reset(struct usbnet *dev)
        return 0;
 }
 
-static const struct net_device_ops ax88772_netdev_ops = {
-       .ndo_open               = usbnet_open,
-       .ndo_stop               = usbnet_stop,
-       .ndo_start_xmit         = usbnet_start_xmit,
-       .ndo_tx_timeout         = usbnet_tx_timeout,
-       .ndo_change_mtu         = usbnet_change_mtu,
-       .ndo_set_mac_address    = asix_set_mac_address,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_do_ioctl           = asix_ioctl,
-       .ndo_set_rx_mode        = asix_set_multicast,
-};
-
-static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+static int ax88772_reset(struct usbnet *dev)
 {
        int ret, embd_phy;
        u16 rx_ctl;
-       struct asix_data *data = (struct asix_data *)&dev->data;
-       u8 buf[ETH_ALEN];
-       u32 phyid;
-
-       data->eeprom_len = AX88772_EEPROM_LEN;
-
-       usbnet_get_endpoints(dev,intf);
 
        if ((ret = asix_write_gpio(dev,
                        AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
                goto out;
 
-       /* 0x10 is the phy id of the embedded 10/100 ethernet phy */
        embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
+
        if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
                                embd_phy, 0, 0, NULL)) < 0) {
                dbg("Select PHY #1 failed: %d", ret);
@@ -1010,6 +983,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                goto out;
 
        msleep(150);
+
        if (embd_phy) {
                if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0)
                        goto out;
@@ -1028,25 +1002,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        rx_ctl = asix_read_rx_ctl(dev);
        dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
 
-       /* Get the MAC address */
-       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
-                               0, 0, ETH_ALEN, buf)) < 0) {
-               dbg("Failed to read MAC address: %d", ret);
-               goto out;
-       }
-       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
-
-       /* Initialize MII structure */
-       dev->mii.dev = dev->net;
-       dev->mii.mdio_read = asix_mdio_read;
-       dev->mii.mdio_write = asix_mdio_write;
-       dev->mii.phy_id_mask = 0x1f;
-       dev->mii.reg_num_mask = 0x1f;
-       dev->mii.phy_id = asix_get_phy_addr(dev);
-
-       phyid = asix_get_phyid(dev);
-       dbg("PHYID=0x%08x", phyid);
-
        if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
                goto out;
 
@@ -1057,9 +1012,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 
        msleep(150);
 
-       dev->net->netdev_ops = &ax88772_netdev_ops;
-       dev->net->ethtool_ops = &ax88772_ethtool_ops;
-
        asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
        asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
                        ADVERTISE_ALL | ADVERTISE_CSMA);
@@ -1085,6 +1037,61 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        rx_ctl = asix_read_medium_status(dev);
        dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
 
+       return 0;
+
+out:
+       return ret;
+
+}
+
+static const struct net_device_ops ax88772_netdev_ops = {
+       .ndo_open               = usbnet_open,
+       .ndo_stop               = usbnet_stop,
+       .ndo_start_xmit         = usbnet_start_xmit,
+       .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_set_mac_address    = asix_set_mac_address,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_do_ioctl           = asix_ioctl,
+       .ndo_set_rx_mode        = asix_set_multicast,
+};
+
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       int ret;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       u8 buf[ETH_ALEN];
+       u32 phyid;
+
+       data->eeprom_len = AX88772_EEPROM_LEN;
+
+       usbnet_get_endpoints(dev,intf);
+
+       /* Get the MAC address */
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+                               0, 0, ETH_ALEN, buf)) < 0) {
+               dbg("Failed to read MAC address: %d", ret);
+               goto out;
+       }
+       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+       /* Initialize MII structure */
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = asix_mdio_read;
+       dev->mii.mdio_write = asix_mdio_write;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0x1f;
+       dev->mii.phy_id = asix_get_phy_addr(dev);
+
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
+
+       dev->net->netdev_ops = &ax88772_netdev_ops;
+       dev->net->ethtool_ops = &ax88772_ethtool_ops;
+
+       if ((ret = ax88772_reset(dev)) < 0)
+               goto out;
+
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
                /* hard_mtu  is still the default - the device does not support
@@ -1092,7 +1099,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                dev->rx_urb_size = 2048;
        }
        return 0;
-
 out:
        return ret;
 }
@@ -1426,7 +1432,7 @@ static const struct driver_info ax88772_info = {
        .bind = ax88772_bind,
        .status = asix_status,
        .link_reset = ax88772_link_reset,
-       .reset = ax88772_link_reset,
+       .reset = ax88772_reset,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
        .rx_fixup = asix_rx_fixup,
        .tx_fixup = asix_tx_fixup,
@@ -1588,6 +1594,7 @@ static void __exit asix_exit(void)
 module_exit(asix_exit);
 
 MODULE_AUTHOR("David Hollis");
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices");
 MODULE_LICENSE("GPL");