aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/net/usbnet.c
diff options
context:
space:
mode:
authorDavid Hollis <dhollis@davehollis.com>2005-04-22 18:07:02 -0400
committerGreg KH <gregkh@suse.de>2005-04-22 18:07:02 -0400
commit7ea13c9c0e40d24c5f45a3a6bee8a2a39bfb1df4 (patch)
treeb8a64ad2f988b45cc9183d07cbfe33432c03be20 /drivers/usb/net/usbnet.c
parentfb3b4ebc0be618dbcc2326482a83c920d51af7de (diff)
[PATCH] usbnet: Convert ASIX code to use new status infrastructure
Modify the ASIX USB Ethernet code to make use of the new status infrastructure in usbnet. Additionally, add a link_reset() handler to the struct usbnet structure to provide a generic means for a driver to perform link reset tasks such as a determining link speed and setting device flags accordingly. Signed-off-by: David Hollis <dhollis@davehollis.com> Acked-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/net/usbnet.c')
-rw-r--r--drivers/usb/net/usbnet.c261
1 files changed, 135 insertions, 126 deletions
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index bbaef047d532..0eefc14449aa 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -210,6 +210,7 @@ struct usbnet {
210# define EVENT_RX_HALT 1 210# define EVENT_RX_HALT 1
211# define EVENT_RX_MEMORY 2 211# define EVENT_RX_MEMORY 2
212# define EVENT_STS_SPLIT 3 212# define EVENT_STS_SPLIT 3
213# define EVENT_LINK_RESET 4
213}; 214};
214 215
215// device-specific info used by the driver 216// device-specific info used by the driver
@@ -243,6 +244,9 @@ struct driver_info {
243 /* for status polling */ 244 /* for status polling */
244 void (*status)(struct usbnet *, struct urb *); 245 void (*status)(struct usbnet *, struct urb *);
245 246
247 /* link reset handling, called from defer_kevent */
248 int (*link_reset)(struct usbnet *);
249
246 /* fixup rx packet (strip framing) */ 250 /* fixup rx packet (strip framing) */
247 int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb); 251 int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
248 252
@@ -304,6 +308,7 @@ static void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
304static u32 usbnet_get_link (struct net_device *); 308static u32 usbnet_get_link (struct net_device *);
305static u32 usbnet_get_msglevel (struct net_device *); 309static u32 usbnet_get_msglevel (struct net_device *);
306static void usbnet_set_msglevel (struct net_device *, u32); 310static void usbnet_set_msglevel (struct net_device *, u32);
311static void defer_kevent (struct usbnet *, int);
307 312
308/* mostly for PDA style devices, which are always connected if present */ 313/* mostly for PDA style devices, which are always connected if present */
309static int always_connected (struct usbnet *dev) 314static int always_connected (struct usbnet *dev)
@@ -501,6 +506,7 @@ static const struct driver_info an2720_info = {
501#define AX_CMD_WRITE_MULTI_FILTER 0x16 506#define AX_CMD_WRITE_MULTI_FILTER 0x16
502#define AX_CMD_READ_NODE_ID 0x17 507#define AX_CMD_READ_NODE_ID 0x17
503#define AX_CMD_READ_PHY_ID 0x19 508#define AX_CMD_READ_PHY_ID 0x19
509#define AX_CMD_READ_MEDIUM_STATUS 0x1a
504#define AX_CMD_WRITE_MEDIUM_MODE 0x1b 510#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
505#define AX_CMD_READ_MONITOR_MODE 0x1c 511#define AX_CMD_READ_MONITOR_MODE 0x1c
506#define AX_CMD_WRITE_MONITOR_MODE 0x1d 512#define AX_CMD_WRITE_MONITOR_MODE 0x1d
@@ -515,11 +521,14 @@ static const struct driver_info an2720_info = {
515#define AX_MONITOR_MAGIC 0x04 521#define AX_MONITOR_MAGIC 0x04
516#define AX_MONITOR_HSFS 0x10 522#define AX_MONITOR_HSFS 0x10
517 523
524/* AX88172 Medium Status Register values */
525#define AX_MEDIUM_FULL_DUPLEX 0x02
526#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
527#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
528
518#define AX_MCAST_FILTER_SIZE 8 529#define AX_MCAST_FILTER_SIZE 8
519#define AX_MAX_MCAST 64 530#define AX_MAX_MCAST 64
520 531
521#define AX_INTERRUPT_BUFSIZE 8
522
523#define AX_EEPROM_LEN 0x40 532#define AX_EEPROM_LEN 0x40
524 533
525#define AX_SWRESET_CLEAR 0x00 534#define AX_SWRESET_CLEAR 0x00
@@ -535,15 +544,33 @@ static const struct driver_info an2720_info = {
535#define AX88772_IPG1_DEFAULT 0x0c 544#define AX88772_IPG1_DEFAULT 0x0c
536#define AX88772_IPG2_DEFAULT 0x12 545#define AX88772_IPG2_DEFAULT 0x12
537 546
547#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
548#define AX88772_MEDIUM_RESERVED 0x0004
549#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
550#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
551#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
552#define AX88772_MEDIUM_RX_ENABLE 0x0100
553#define AX88772_MEDIUM_100MB 0x0200
554#define AX88772_MEDIUM_DEFAULT \
555 (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
556 AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
557 AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
558
538#define AX_EEPROM_MAGIC 0xdeadbeef 559#define AX_EEPROM_MAGIC 0xdeadbeef
539 560
540/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ 561/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
541struct ax8817x_data { 562struct ax8817x_data {
542 u8 multi_filter[AX_MCAST_FILTER_SIZE]; 563 u8 multi_filter[AX_MCAST_FILTER_SIZE];
543 struct urb *int_urb;
544 u8 *int_buf;
545}; 564};
546 565
566struct ax88172_int_data {
567 u16 res1;
568 u8 link;
569 u16 res2;
570 u8 status;
571 u16 res3;
572} __attribute__ ((packed));
573
547static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, 574static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
548 u16 size, void *data) 575 u16 size, void *data)
549{ 576{
@@ -586,25 +613,23 @@ static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
586 usb_free_urb(urb); 613 usb_free_urb(urb);
587} 614}
588 615
589static void ax8817x_interrupt_complete(struct urb *urb, struct pt_regs *regs) 616static void ax8817x_status(struct usbnet *dev, struct urb *urb)
590{ 617{
591 struct usbnet *dev = (struct usbnet *)urb->context; 618 struct ax88172_int_data *event;
592 struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
593 int link; 619 int link;
594 620
595 if (urb->status < 0) { 621 if (urb->actual_length < 8)
596 devdbg(dev,"ax8817x_interrupt_complete() failed with %d", 622 return;
597 urb->status); 623
598 } else { 624 event = urb->transfer_buffer;
599 link = data->int_buf[2] & 0x01; 625 link = event->link & 0x01;
600 if (netif_carrier_ok(dev->net) != link) { 626 if (netif_carrier_ok(dev->net) != link) {
601 if (link) 627 if (link) {
602 netif_carrier_on(dev->net); 628 netif_carrier_on(dev->net);
603 else 629 defer_kevent (dev, EVENT_LINK_RESET );
604 netif_carrier_off(dev->net); 630 } else
605 devdbg(dev, "ax8817x - Link Status is: %d", link); 631 netif_carrier_off(dev->net);
606 } 632 devdbg(dev, "ax8817x - Link Status is: %d", link);
607 usb_submit_urb(data->int_urb, GFP_ATOMIC);
608 } 633 }
609} 634}
610 635
@@ -711,6 +736,20 @@ static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, i
711 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf); 736 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
712} 737}
713 738
739static int ax88172_link_reset(struct usbnet *dev)
740{
741 u16 lpa;
742 u8 mode;
743
744 mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
745 lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
746 if (lpa & LPA_DUPLEX)
747 mode |= AX_MEDIUM_FULL_DUPLEX;
748 ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
749
750 return 0;
751}
752
714static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) 753static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
715{ 754{
716 struct usbnet *dev = netdev_priv(net); 755 struct usbnet *dev = netdev_priv(net);
@@ -824,35 +863,13 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
824 void *buf; 863 void *buf;
825 int i; 864 int i;
826 unsigned long gpio_bits = dev->driver_info->data; 865 unsigned long gpio_bits = dev->driver_info->data;
827 struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
828 866
829 get_endpoints(dev,intf); 867 get_endpoints(dev,intf);
830 868
831 if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == NULL) {
832 dbg ("%s: cannot allocate interrupt URB",
833 dev->net->name);
834 ret = -ENOMEM;
835 goto out1;
836 }
837
838 if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
839 dbg ("%s: cannot allocate memory for interrupt buffer",
840 dev->net->name);
841 ret = -ENOMEM;
842 goto out1;
843 }
844 memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
845
846 usb_fill_int_urb (data->int_urb, dev->udev,
847 usb_rcvintpipe (dev->udev, 1),
848 data->int_buf, AX_INTERRUPT_BUFSIZE,
849 ax8817x_interrupt_complete, dev,
850 dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
851
852 buf = kmalloc(ETH_ALEN, GFP_KERNEL); 869 buf = kmalloc(ETH_ALEN, GFP_KERNEL);
853 if(!buf) { 870 if(!buf) {
854 ret = -ENOMEM; 871 ret = -ENOMEM;
855 goto out2; 872 goto out1;
856 } 873 }
857 874
858 /* Toggle the GPIOs in a manufacturer/model specific way */ 875 /* Toggle the GPIOs in a manufacturer/model specific way */
@@ -860,32 +877,32 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
860 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, 877 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
861 (gpio_bits >> (i * 8)) & 0xff, 0, 0, 878 (gpio_bits >> (i * 8)) & 0xff, 0, 0,
862 buf)) < 0) 879 buf)) < 0)
863 goto out3; 880 goto out2;
864 msleep(5); 881 msleep(5);
865 } 882 }
866 883
867 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf)) < 0) { 884 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf)) < 0) {
868 dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret); 885 dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
869 goto out3; 886 goto out2;
870 } 887 }
871 888
872 /* Get the MAC address */ 889 /* Get the MAC address */
873 memset(buf, 0, ETH_ALEN); 890 memset(buf, 0, ETH_ALEN);
874 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf)) < 0) { 891 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf)) < 0) {
875 dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); 892 dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
876 goto out3; 893 goto out2;
877 } 894 }
878 memcpy(dev->net->dev_addr, buf, ETH_ALEN); 895 memcpy(dev->net->dev_addr, buf, ETH_ALEN);
879 896
880 /* Get the PHY id */ 897 /* Get the PHY id */
881 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) { 898 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
882 dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret); 899 dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
883 goto out3; 900 goto out2;
884 } else if (ret < 2) { 901 } else if (ret < 2) {
885 /* this should always return 2 bytes */ 902 /* this should always return 2 bytes */
886 dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret); 903 dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
887 ret = -EIO; 904 ret = -EIO;
888 goto out3; 905 goto out2;
889 } 906 }
890 907
891 /* Initialize MII structure */ 908 /* Initialize MII structure */
@@ -899,36 +916,18 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
899 dev->net->set_multicast_list = ax8817x_set_multicast; 916 dev->net->set_multicast_list = ax8817x_set_multicast;
900 dev->net->ethtool_ops = &ax8817x_ethtool_ops; 917 dev->net->ethtool_ops = &ax8817x_ethtool_ops;
901 918
902 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, 919 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
903 cpu_to_le16(BMCR_RESET));
904 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, 920 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
905 cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA | 0x0400)); 921 ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
906 mii_nway_restart(&dev->mii); 922 mii_nway_restart(&dev->mii);
907 923
908 if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
909 dbg("Failed to submit interrupt URB: %02x", ret);
910 goto out2;
911 }
912
913 return 0; 924 return 0;
914out3:
915 kfree(buf);
916out2: 925out2:
917 kfree(data->int_buf); 926 kfree(buf);
918out1: 927out1:
919 usb_free_urb(data->int_urb);
920 return ret; 928 return ret;
921} 929}
922 930
923static void ax8817x_unbind(struct usbnet *dev, struct usb_interface *intf)
924{
925 struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
926
927 usb_kill_urb(data->int_urb);
928 usb_free_urb(data->int_urb);
929 kfree(data->int_buf);
930}
931
932static struct ethtool_ops ax88772_ethtool_ops = { 931static struct ethtool_ops ax88772_ethtool_ops = {
933 .get_drvinfo = ax8817x_get_drvinfo, 932 .get_drvinfo = ax8817x_get_drvinfo,
934 .get_link = ethtool_op_get_link, 933 .get_link = ethtool_op_get_link,
@@ -946,64 +945,44 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
946{ 945{
947 int ret; 946 int ret;
948 void *buf; 947 void *buf;
949 struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
950 948
951 get_endpoints(dev,intf); 949 get_endpoints(dev,intf);
952 950
953 if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
954 dbg ("Cannot allocate interrupt URB");
955 ret = -ENOMEM;
956 goto out1;
957 }
958
959 if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
960 dbg ("Cannot allocate memory for interrupt buffer");
961 ret = -ENOMEM;
962 goto out1;
963 }
964 memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
965
966 usb_fill_int_urb (data->int_urb, dev->udev,
967 usb_rcvintpipe (dev->udev, 1),
968 data->int_buf, AX_INTERRUPT_BUFSIZE,
969 ax8817x_interrupt_complete, dev,
970 dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
971
972 buf = kmalloc(6, GFP_KERNEL); 951 buf = kmalloc(6, GFP_KERNEL);
973 if(!buf) { 952 if(!buf) {
974 dbg ("Cannot allocate memory for buffer"); 953 dbg ("Cannot allocate memory for buffer");
975 ret = -ENOMEM; 954 ret = -ENOMEM;
976 goto out2; 955 goto out1;
977 } 956 }
978 957
979 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, 958 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
980 0x00B0, 0, 0, buf)) < 0) 959 0x00B0, 0, 0, buf)) < 0)
981 goto out3; 960 goto out2;
982 961
983 msleep(5); 962 msleep(5);
984 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) { 963 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) {
985 dbg("Select PHY #1 failed: %d", ret); 964 dbg("Select PHY #1 failed: %d", ret);
986 goto out3; 965 goto out2;
987 } 966 }
988 967
989 if ((ret = 968 if ((ret =
990 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, 0, 0, buf)) < 0) { 969 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, 0, 0, buf)) < 0) {
991 dbg("Failed to power down internal PHY: %d", ret); 970 dbg("Failed to power down internal PHY: %d", ret);
992 goto out3; 971 goto out2;
993 } 972 }
994 973
995 msleep(150); 974 msleep(150);
996 if ((ret = 975 if ((ret =
997 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, 0, 0, buf)) < 0) { 976 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, 0, 0, buf)) < 0) {
998 dbg("Failed to perform software reset: %d", ret); 977 dbg("Failed to perform software reset: %d", ret);
999 goto out3; 978 goto out2;
1000 } 979 }
1001 980
1002 msleep(150); 981 msleep(150);
1003 if ((ret = 982 if ((ret =
1004 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) { 983 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
1005 dbg("Failed to set Internal/External PHY reset control: %d", ret); 984 dbg("Failed to set Internal/External PHY reset control: %d", ret);
1006 goto out3; 985 goto out2;
1007 } 986 }
1008 987
1009 msleep(150); 988 msleep(150);
@@ -1011,27 +990,27 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
1011 ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0, 990 ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0,
1012 buf)) < 0) { 991 buf)) < 0) {
1013 dbg("Failed to reset RX_CTL: %d", ret); 992 dbg("Failed to reset RX_CTL: %d", ret);
1014 goto out3; 993 goto out2;
1015 } 994 }
1016 995
1017 /* Get the MAC address */ 996 /* Get the MAC address */
1018 memset(buf, 0, ETH_ALEN); 997 memset(buf, 0, ETH_ALEN);
1019 if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) { 998 if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) {
1020 dbg("Failed to read MAC address: %d", ret); 999 dbg("Failed to read MAC address: %d", ret);
1021 goto out3; 1000 goto out2;
1022 } 1001 }
1023 memcpy(dev->net->dev_addr, buf, ETH_ALEN); 1002 memcpy(dev->net->dev_addr, buf, ETH_ALEN);
1024 1003
1025 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, buf)) < 0) { 1004 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, buf)) < 0) {
1026 dbg("Enabling software MII failed: %d", ret); 1005 dbg("Enabling software MII failed: %d", ret);
1027 goto out3; 1006 goto out2;
1028 } 1007 }
1029 1008
1030 if (((ret = 1009 if (((ret =
1031 ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0) 1010 ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0)
1032 || (*((u16 *)buf) != 0x003b)) { 1011 || (*((u16 *)buf) != 0x003b)) {
1033 dbg("Read PHY register 2 must be 0x3b00: %d", ret); 1012 dbg("Read PHY register 2 must be 0x3b00: %d", ret);
1034 goto out3; 1013 goto out2;
1035 } 1014 }
1036 1015
1037 /* Initialize MII structure */ 1016 /* Initialize MII structure */
@@ -1044,26 +1023,26 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
1044 /* Get the PHY id */ 1023 /* Get the PHY id */
1045 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) { 1024 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
1046 dbg("Error reading PHY ID: %02x", ret); 1025 dbg("Error reading PHY ID: %02x", ret);
1047 goto out3; 1026 goto out2;
1048 } else if (ret < 2) { 1027 } else if (ret < 2) {
1049 /* this should always return 2 bytes */ 1028 /* this should always return 2 bytes */
1050 dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", 1029 dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
1051 ret); 1030 ret);
1052 ret = -EIO; 1031 ret = -EIO;
1053 goto out3; 1032 goto out2;
1054 } 1033 }
1055 dev->mii.phy_id = *((u8 *)buf + 1); 1034 dev->mii.phy_id = *((u8 *)buf + 1);
1056 1035
1057 if ((ret = 1036 if ((ret =
1058 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) { 1037 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) {
1059 dbg("Set external PHY reset pin level: %d", ret); 1038 dbg("Set external PHY reset pin level: %d", ret);
1060 goto out3; 1039 goto out2;
1061 } 1040 }
1062 msleep(150); 1041 msleep(150);
1063 if ((ret = 1042 if ((ret =
1064 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) { 1043 ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
1065 dbg("Set Internal/External PHY reset control: %d", ret); 1044 dbg("Set Internal/External PHY reset control: %d", ret);
1066 goto out3; 1045 goto out2;
1067 } 1046 }
1068 msleep(150); 1047 msleep(150);
1069 1048
@@ -1071,25 +1050,24 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
1071 dev->net->set_multicast_list = ax8817x_set_multicast; 1050 dev->net->set_multicast_list = ax8817x_set_multicast;
1072 dev->net->ethtool_ops = &ax88772_ethtool_ops; 1051 dev->net->ethtool_ops = &ax88772_ethtool_ops;
1073 1052
1074 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, 1053 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
1075 cpu_to_le16(BMCR_RESET));
1076 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, 1054 ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
1077 cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA)); 1055 ADVERTISE_ALL | ADVERTISE_CSMA);
1078 mii_nway_restart(&dev->mii); 1056 mii_nway_restart(&dev->mii);
1079 1057
1080 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0x0336, 0, 0, buf)) < 0) { 1058 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
1081 dbg("Write medium mode register: %d", ret); 1059 dbg("Write medium mode register: %d", ret);
1082 goto out3; 1060 goto out2;
1083 } 1061 }
1084 1062
1085 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) { 1063 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
1086 dbg("Write IPG,IPG1,IPG2 failed: %d", ret); 1064 dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
1087 goto out3; 1065 goto out2;
1088 } 1066 }
1089 if ((ret = 1067 if ((ret =
1090 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) { 1068 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
1091 dbg("Failed to set hardware MII: %02x", ret); 1069 dbg("Failed to set hardware MII: %02x", ret);
1092 goto out3; 1070 goto out2;
1093 } 1071 }
1094 1072
1095 /* Set RX_CTL to default values with 2k buffer, and enable cactus */ 1073 /* Set RX_CTL to default values with 2k buffer, and enable cactus */
@@ -1097,25 +1075,16 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
1097 ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0, 1075 ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
1098 buf)) < 0) { 1076 buf)) < 0) {
1099 dbg("Reset RX_CTL failed: %d", ret); 1077 dbg("Reset RX_CTL failed: %d", ret);
1100 goto out3; 1078 goto out2;
1101 }
1102
1103 if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
1104 dbg("Failed to submit interrupt URB: %02x", ret);
1105 goto out3;
1106 } 1079 }
1107 1080
1108 kfree(buf); 1081 kfree(buf);
1109 1082
1110 return 0; 1083 return 0;
1111 1084
1112out3:
1113 kfree(buf);
1114out2: 1085out2:
1115 kfree(data->int_buf); 1086 kfree(buf);
1116out1: 1087out1:
1117 usb_free_urb(data->int_urb);
1118
1119 return ret; 1088 return ret;
1120} 1089}
1121 1090
@@ -1213,10 +1182,29 @@ static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
1213 return skb; 1182 return skb;
1214} 1183}
1215 1184
1185static int ax88772_link_reset(struct usbnet *dev)
1186{
1187 u16 lpa;
1188 u16 mode;
1189
1190 mode = AX88772_MEDIUM_DEFAULT;
1191 lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
1192
1193 if ((lpa & LPA_DUPLEX) == 0)
1194 mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
1195 if ((lpa & LPA_100) == 0)
1196 mode &= ~AX88772_MEDIUM_100MB;
1197 ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
1198
1199 return 0;
1200}
1201
1216static const struct driver_info ax8817x_info = { 1202static const struct driver_info ax8817x_info = {
1217 .description = "ASIX AX8817x USB 2.0 Ethernet", 1203 .description = "ASIX AX8817x USB 2.0 Ethernet",
1218 .bind = ax8817x_bind, 1204 .bind = ax8817x_bind,
1219 .unbind = ax8817x_unbind, 1205 .status = ax8817x_status,
1206 .link_reset = ax88172_link_reset,
1207 .reset = ax88172_link_reset,
1220 .flags = FLAG_ETHER, 1208 .flags = FLAG_ETHER,
1221 .data = 0x00130103, 1209 .data = 0x00130103,
1222}; 1210};
@@ -1224,7 +1212,9 @@ static const struct driver_info ax8817x_info = {
1224static const struct driver_info dlink_dub_e100_info = { 1212static const struct driver_info dlink_dub_e100_info = {
1225 .description = "DLink DUB-E100 USB Ethernet", 1213 .description = "DLink DUB-E100 USB Ethernet",
1226 .bind = ax8817x_bind, 1214 .bind = ax8817x_bind,
1227 .unbind = ax8817x_unbind, 1215 .status = ax8817x_status,
1216 .link_reset = ax88172_link_reset,
1217 .reset = ax88172_link_reset,
1228 .flags = FLAG_ETHER, 1218 .flags = FLAG_ETHER,
1229 .data = 0x009f9d9f, 1219 .data = 0x009f9d9f,
1230}; 1220};
@@ -1232,7 +1222,9 @@ static const struct driver_info dlink_dub_e100_info = {
1232static const struct driver_info netgear_fa120_info = { 1222static const struct driver_info netgear_fa120_info = {
1233 .description = "Netgear FA-120 USB Ethernet", 1223 .description = "Netgear FA-120 USB Ethernet",
1234 .bind = ax8817x_bind, 1224 .bind = ax8817x_bind,
1235 .unbind = ax8817x_unbind, 1225 .status = ax8817x_status,
1226 .link_reset = ax88172_link_reset,
1227 .reset = ax88172_link_reset,
1236 .flags = FLAG_ETHER, 1228 .flags = FLAG_ETHER,
1237 .data = 0x00130103, 1229 .data = 0x00130103,
1238}; 1230};
@@ -1240,7 +1232,9 @@ static const struct driver_info netgear_fa120_info = {
1240static const struct driver_info hawking_uf200_info = { 1232static const struct driver_info hawking_uf200_info = {
1241 .description = "Hawking UF200 USB Ethernet", 1233 .description = "Hawking UF200 USB Ethernet",
1242 .bind = ax8817x_bind, 1234 .bind = ax8817x_bind,
1243 .unbind = ax8817x_unbind, 1235 .status = ax8817x_status,
1236 .link_reset = ax88172_link_reset,
1237 .reset = ax88172_link_reset,
1244 .flags = FLAG_ETHER, 1238 .flags = FLAG_ETHER,
1245 .data = 0x001f1d1f, 1239 .data = 0x001f1d1f,
1246}; 1240};
@@ -1248,7 +1242,9 @@ static const struct driver_info hawking_uf200_info = {
1248static const struct driver_info ax88772_info = { 1242static const struct driver_info ax88772_info = {
1249 .description = "ASIX AX88772 USB 2.0 Ethernet", 1243 .description = "ASIX AX88772 USB 2.0 Ethernet",
1250 .bind = ax88772_bind, 1244 .bind = ax88772_bind,
1251 .unbind = ax8817x_unbind, 1245 .status = ax8817x_status,
1246 .link_reset = ax88772_link_reset,
1247 .reset = ax88772_link_reset,
1252 .flags = FLAG_ETHER | FLAG_FRAMING_AX, 1248 .flags = FLAG_ETHER | FLAG_FRAMING_AX,
1253 .rx_fixup = ax88772_rx_fixup, 1249 .rx_fixup = ax88772_rx_fixup,
1254 .tx_fixup = ax88772_tx_fixup, 1250 .tx_fixup = ax88772_tx_fixup,
@@ -3307,6 +3303,19 @@ kevent (void *data)
3307 } 3303 }
3308 } 3304 }
3309 3305
3306 if (test_bit (EVENT_LINK_RESET, &dev->flags)) {
3307 struct driver_info *info = dev->driver_info;
3308 int retval = 0;
3309
3310 clear_bit (EVENT_LINK_RESET, &dev->flags);
3311 if(info->link_reset && (retval = info->link_reset(dev)) < 0) {
3312 devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s",
3313 retval,
3314 dev->udev->bus->bus_name, dev->udev->devpath,
3315 info->description);
3316 }
3317 }
3318
3310 if (dev->flags) 3319 if (dev->flags)
3311 devdbg (dev, "kevent done, flags = 0x%lx", 3320 devdbg (dev, "kevent done, flags = 0x%lx",
3312 dev->flags); 3321 dev->flags);