diff options
author | Grant Grundler <grundler@chromium.org> | 2011-10-04 05:55:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-04 16:25:31 -0400 |
commit | 4ad1438f025ed8d1e4e95a796ca7f0ad5a22c378 (patch) | |
tree | 532dd31a2132dcd346e2011a84fdc75912bfb98a /drivers/net/usb/asix.c | |
parent | 349d2895cc8b7db1f5be677cd685209a3805d2ed (diff) |
NET: fix phy init for AX88772 USB ethernet
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>
Diffstat (limited to 'drivers/net/usb/asix.c')
-rw-r--r-- | drivers/net/usb/asix.c | 115 |
1 files changed, 61 insertions, 54 deletions
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index b843eedd409d..9e0b3776b80a 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <linux/usb/usbnet.h> | 36 | #include <linux/usb/usbnet.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | 38 | ||
39 | #define DRIVER_VERSION "14-Jun-2006" | 39 | #define DRIVER_VERSION "26-Sep-2011" |
40 | static const char driver_name [] = "asix"; | 40 | static const char driver_name [] = "asix"; |
41 | 41 | ||
42 | /* ASIX AX8817X based USB 2.0 Ethernet Devices */ | 42 | /* ASIX AX8817X based USB 2.0 Ethernet Devices */ |
@@ -676,12 +676,6 @@ asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | |||
676 | } | 676 | } |
677 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | 677 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; |
678 | wolinfo->wolopts = 0; | 678 | wolinfo->wolopts = 0; |
679 | if (opt & AX_MONITOR_MODE) { | ||
680 | if (opt & AX_MONITOR_LINK) | ||
681 | wolinfo->wolopts |= WAKE_PHY; | ||
682 | if (opt & AX_MONITOR_MAGIC) | ||
683 | wolinfo->wolopts |= WAKE_MAGIC; | ||
684 | } | ||
685 | } | 679 | } |
686 | 680 | ||
687 | static int | 681 | static int |
@@ -694,8 +688,6 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | |||
694 | opt |= AX_MONITOR_LINK; | 688 | opt |= AX_MONITOR_LINK; |
695 | if (wolinfo->wolopts & WAKE_MAGIC) | 689 | if (wolinfo->wolopts & WAKE_MAGIC) |
696 | opt |= AX_MONITOR_MAGIC; | 690 | opt |= AX_MONITOR_MAGIC; |
697 | if (opt != 0) | ||
698 | opt |= AX_MONITOR_MODE; | ||
699 | 691 | ||
700 | if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, | 692 | if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, |
701 | opt, 0, 0, NULL) < 0) | 693 | opt, 0, 0, NULL) < 0) |
@@ -966,36 +958,17 @@ static int ax88772_link_reset(struct usbnet *dev) | |||
966 | return 0; | 958 | return 0; |
967 | } | 959 | } |
968 | 960 | ||
969 | static const struct net_device_ops ax88772_netdev_ops = { | 961 | static int ax88772_reset(struct usbnet *dev) |
970 | .ndo_open = usbnet_open, | ||
971 | .ndo_stop = usbnet_stop, | ||
972 | .ndo_start_xmit = usbnet_start_xmit, | ||
973 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
974 | .ndo_change_mtu = usbnet_change_mtu, | ||
975 | .ndo_set_mac_address = asix_set_mac_address, | ||
976 | .ndo_validate_addr = eth_validate_addr, | ||
977 | .ndo_do_ioctl = asix_ioctl, | ||
978 | .ndo_set_rx_mode = asix_set_multicast, | ||
979 | }; | ||
980 | |||
981 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | ||
982 | { | 962 | { |
983 | int ret, embd_phy; | 963 | int ret, embd_phy; |
984 | u16 rx_ctl; | 964 | u16 rx_ctl; |
985 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
986 | u8 buf[ETH_ALEN]; | ||
987 | u32 phyid; | ||
988 | |||
989 | data->eeprom_len = AX88772_EEPROM_LEN; | ||
990 | |||
991 | usbnet_get_endpoints(dev,intf); | ||
992 | 965 | ||
993 | if ((ret = asix_write_gpio(dev, | 966 | if ((ret = asix_write_gpio(dev, |
994 | AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) | 967 | AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) |
995 | goto out; | 968 | goto out; |
996 | 969 | ||
997 | /* 0x10 is the phy id of the embedded 10/100 ethernet phy */ | ||
998 | embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); | 970 | embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); |
971 | |||
999 | if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, | 972 | if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, |
1000 | embd_phy, 0, 0, NULL)) < 0) { | 973 | embd_phy, 0, 0, NULL)) < 0) { |
1001 | dbg("Select PHY #1 failed: %d", ret); | 974 | dbg("Select PHY #1 failed: %d", ret); |
@@ -1010,6 +983,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1010 | goto out; | 983 | goto out; |
1011 | 984 | ||
1012 | msleep(150); | 985 | msleep(150); |
986 | |||
1013 | if (embd_phy) { | 987 | if (embd_phy) { |
1014 | if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0) | 988 | if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0) |
1015 | goto out; | 989 | goto out; |
@@ -1028,25 +1002,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1028 | rx_ctl = asix_read_rx_ctl(dev); | 1002 | rx_ctl = asix_read_rx_ctl(dev); |
1029 | dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl); | 1003 | dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl); |
1030 | 1004 | ||
1031 | /* Get the MAC address */ | ||
1032 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, | ||
1033 | 0, 0, ETH_ALEN, buf)) < 0) { | ||
1034 | dbg("Failed to read MAC address: %d", ret); | ||
1035 | goto out; | ||
1036 | } | ||
1037 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); | ||
1038 | |||
1039 | /* Initialize MII structure */ | ||
1040 | dev->mii.dev = dev->net; | ||
1041 | dev->mii.mdio_read = asix_mdio_read; | ||
1042 | dev->mii.mdio_write = asix_mdio_write; | ||
1043 | dev->mii.phy_id_mask = 0x1f; | ||
1044 | dev->mii.reg_num_mask = 0x1f; | ||
1045 | dev->mii.phy_id = asix_get_phy_addr(dev); | ||
1046 | |||
1047 | phyid = asix_get_phyid(dev); | ||
1048 | dbg("PHYID=0x%08x", phyid); | ||
1049 | |||
1050 | if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) | 1005 | if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) |
1051 | goto out; | 1006 | goto out; |
1052 | 1007 | ||
@@ -1057,9 +1012,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1057 | 1012 | ||
1058 | msleep(150); | 1013 | msleep(150); |
1059 | 1014 | ||
1060 | dev->net->netdev_ops = &ax88772_netdev_ops; | ||
1061 | dev->net->ethtool_ops = &ax88772_ethtool_ops; | ||
1062 | |||
1063 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | 1015 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); |
1064 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | 1016 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, |
1065 | ADVERTISE_ALL | ADVERTISE_CSMA); | 1017 | ADVERTISE_ALL | ADVERTISE_CSMA); |
@@ -1085,6 +1037,61 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
1085 | rx_ctl = asix_read_medium_status(dev); | 1037 | rx_ctl = asix_read_medium_status(dev); |
1086 | dbg("Medium Status is 0x%04x after all initializations", rx_ctl); | 1038 | dbg("Medium Status is 0x%04x after all initializations", rx_ctl); |
1087 | 1039 | ||
1040 | return 0; | ||
1041 | |||
1042 | out: | ||
1043 | return ret; | ||
1044 | |||
1045 | } | ||
1046 | |||
1047 | static const struct net_device_ops ax88772_netdev_ops = { | ||
1048 | .ndo_open = usbnet_open, | ||
1049 | .ndo_stop = usbnet_stop, | ||
1050 | .ndo_start_xmit = usbnet_start_xmit, | ||
1051 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
1052 | .ndo_change_mtu = usbnet_change_mtu, | ||
1053 | .ndo_set_mac_address = asix_set_mac_address, | ||
1054 | .ndo_validate_addr = eth_validate_addr, | ||
1055 | .ndo_do_ioctl = asix_ioctl, | ||
1056 | .ndo_set_rx_mode = asix_set_multicast, | ||
1057 | }; | ||
1058 | |||
1059 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | ||
1060 | { | ||
1061 | int ret; | ||
1062 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1063 | u8 buf[ETH_ALEN]; | ||
1064 | u32 phyid; | ||
1065 | |||
1066 | data->eeprom_len = AX88772_EEPROM_LEN; | ||
1067 | |||
1068 | usbnet_get_endpoints(dev,intf); | ||
1069 | |||
1070 | /* Get the MAC address */ | ||
1071 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, | ||
1072 | 0, 0, ETH_ALEN, buf)) < 0) { | ||
1073 | dbg("Failed to read MAC address: %d", ret); | ||
1074 | goto out; | ||
1075 | } | ||
1076 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); | ||
1077 | |||
1078 | /* Initialize MII structure */ | ||
1079 | dev->mii.dev = dev->net; | ||
1080 | dev->mii.mdio_read = asix_mdio_read; | ||
1081 | dev->mii.mdio_write = asix_mdio_write; | ||
1082 | dev->mii.phy_id_mask = 0x1f; | ||
1083 | dev->mii.reg_num_mask = 0x1f; | ||
1084 | dev->mii.phy_id = asix_get_phy_addr(dev); | ||
1085 | |||
1086 | phyid = asix_get_phyid(dev); | ||
1087 | dbg("PHYID=0x%08x", phyid); | ||
1088 | |||
1089 | dev->net->netdev_ops = &ax88772_netdev_ops; | ||
1090 | dev->net->ethtool_ops = &ax88772_ethtool_ops; | ||
1091 | |||
1092 | if ((ret = ax88772_reset(dev)) < 0) | ||
1093 | goto out; | ||
1094 | |||
1088 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ | 1095 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ |
1089 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { | 1096 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { |
1090 | /* hard_mtu is still the default - the device does not support | 1097 | /* 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) | |||
1092 | dev->rx_urb_size = 2048; | 1099 | dev->rx_urb_size = 2048; |
1093 | } | 1100 | } |
1094 | return 0; | 1101 | return 0; |
1095 | |||
1096 | out: | 1102 | out: |
1097 | return ret; | 1103 | return ret; |
1098 | } | 1104 | } |
@@ -1426,7 +1432,7 @@ static const struct driver_info ax88772_info = { | |||
1426 | .bind = ax88772_bind, | 1432 | .bind = ax88772_bind, |
1427 | .status = asix_status, | 1433 | .status = asix_status, |
1428 | .link_reset = ax88772_link_reset, | 1434 | .link_reset = ax88772_link_reset, |
1429 | .reset = ax88772_link_reset, | 1435 | .reset = ax88772_reset, |
1430 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, | 1436 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, |
1431 | .rx_fixup = asix_rx_fixup, | 1437 | .rx_fixup = asix_rx_fixup, |
1432 | .tx_fixup = asix_tx_fixup, | 1438 | .tx_fixup = asix_tx_fixup, |
@@ -1588,6 +1594,7 @@ static void __exit asix_exit(void) | |||
1588 | module_exit(asix_exit); | 1594 | module_exit(asix_exit); |
1589 | 1595 | ||
1590 | MODULE_AUTHOR("David Hollis"); | 1596 | MODULE_AUTHOR("David Hollis"); |
1597 | MODULE_VERSION(DRIVER_VERSION); | ||
1591 | MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices"); | 1598 | MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices"); |
1592 | MODULE_LICENSE("GPL"); | 1599 | MODULE_LICENSE("GPL"); |
1593 | 1600 | ||