aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/usb/asix.h15
-rw-r--r--drivers/net/usb/asix_common.c90
-rw-r--r--drivers/net/usb/asix_devices.c23
-rw-r--r--drivers/net/usb/ax88172a.c11
4 files changed, 109 insertions, 30 deletions
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index 7afe8ac078e8..346c032aa795 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -167,6 +167,17 @@ struct asix_data {
167 u8 res; 167 u8 res;
168}; 168};
169 169
170struct asix_rx_fixup_info {
171 struct sk_buff *ax_skb;
172 u32 header;
173 u16 size;
174 bool split_head;
175};
176
177struct asix_common_private {
178 struct asix_rx_fixup_info rx_fixup_info;
179};
180
170/* ASIX specific flags */ 181/* ASIX specific flags */
171#define FLAG_EEPROM_MAC (1UL << 0) /* init device MAC from eeprom */ 182#define FLAG_EEPROM_MAC (1UL << 0) /* init device MAC from eeprom */
172 183
@@ -179,7 +190,9 @@ int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
179void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, 190void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
180 u16 index, u16 size, void *data); 191 u16 index, u16 size, void *data);
181 192
182int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb); 193int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
194 struct asix_rx_fixup_info *rx);
195int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb);
183 196
184struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 197struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
185 gfp_t flags); 198 gfp_t flags);
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 19bc23f20526..f7f623a5390e 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -51,49 +51,89 @@ void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
51 value, index, data, size); 51 value, index, data, size);
52} 52}
53 53
54int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 54int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
55 struct asix_rx_fixup_info *rx)
55{ 56{
56 int offset = 0; 57 int offset = 0;
57 58
58 while (offset + sizeof(u32) < skb->len) { 59 while (offset + sizeof(u16) <= skb->len) {
59 struct sk_buff *ax_skb; 60 u16 remaining = 0;
60 u16 size; 61 unsigned char *data;
61 u32 header = get_unaligned_le32(skb->data + offset); 62
62 63 if (!rx->size) {
63 offset += sizeof(u32); 64 if ((skb->len - offset == sizeof(u16)) ||
64 65 rx->split_head) {
65 /* get the packet length */ 66 if(!rx->split_head) {
66 size = (u16) (header & 0x7ff); 67 rx->header = get_unaligned_le16(
67 if (size != ((~header >> 16) & 0x07ff)) { 68 skb->data + offset);
68 netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); 69 rx->split_head = true;
69 return 0; 70 offset += sizeof(u16);
71 break;
72 } else {
73 rx->header |= (get_unaligned_le16(
74 skb->data + offset)
75 << 16);
76 rx->split_head = false;
77 offset += sizeof(u16);
78 }
79 } else {
80 rx->header = get_unaligned_le32(skb->data +
81 offset);
82 offset += sizeof(u32);
83 }
84
85 /* get the packet length */
86 rx->size = (u16) (rx->header & 0x7ff);
87 if (rx->size != ((~rx->header >> 16) & 0x7ff)) {
88 netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
89 rx->header, offset);
90 rx->size = 0;
91 return 0;
92 }
93 rx->ax_skb = netdev_alloc_skb_ip_align(dev->net,
94 rx->size);
95 if (!rx->ax_skb)
96 return 0;
70 } 97 }
71 98
72 if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || 99 if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
73 (size + offset > skb->len)) {
74 netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", 100 netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
75 size); 101 rx->size);
102 kfree_skb(rx->ax_skb);
76 return 0; 103 return 0;
77 } 104 }
78 ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
79 if (!ax_skb)
80 return 0;
81 105
82 skb_put(ax_skb, size); 106 if (rx->size > skb->len - offset) {
83 memcpy(ax_skb->data, skb->data + offset, size); 107 remaining = rx->size - (skb->len - offset);
84 usbnet_skb_return(dev, ax_skb); 108 rx->size = skb->len - offset;
109 }
110
111 data = skb_put(rx->ax_skb, rx->size);
112 memcpy(data, skb->data + offset, rx->size);
113 if (!remaining)
114 usbnet_skb_return(dev, rx->ax_skb);
85 115
86 offset += (size + 1) & 0xfffe; 116 offset += (rx->size + 1) & 0xfffe;
117 rx->size = remaining;
87 } 118 }
88 119
89 if (skb->len != offset) { 120 if (skb->len != offset) {
90 netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n", 121 netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n",
91 skb->len); 122 skb->len, offset);
92 return 0; 123 return 0;
93 } 124 }
125
94 return 1; 126 return 1;
95} 127}
96 128
129int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb)
130{
131 struct asix_common_private *dp = dev->driver_priv;
132 struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
133
134 return asix_rx_fixup_internal(dev, skb, rx);
135}
136
97struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 137struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
98 gfp_t flags) 138 gfp_t flags)
99{ 139{
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 0ecc3bc6c3d7..37de7db56d63 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -495,9 +495,19 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
495 dev->rx_urb_size = 2048; 495 dev->rx_urb_size = 2048;
496 } 496 }
497 497
498 dev->driver_priv = kzalloc(sizeof(struct asix_common_private), GFP_KERNEL);
499 if (!dev->driver_priv)
500 return -ENOMEM;
501
498 return 0; 502 return 0;
499} 503}
500 504
505void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
506{
507 if (dev->driver_priv)
508 kfree(dev->driver_priv);
509}
510
501static const struct ethtool_ops ax88178_ethtool_ops = { 511static const struct ethtool_ops ax88178_ethtool_ops = {
502 .get_drvinfo = asix_get_drvinfo, 512 .get_drvinfo = asix_get_drvinfo,
503 .get_link = asix_get_link, 513 .get_link = asix_get_link,
@@ -829,6 +839,10 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
829 dev->rx_urb_size = 2048; 839 dev->rx_urb_size = 2048;
830 } 840 }
831 841
842 dev->driver_priv = kzalloc(sizeof(struct asix_common_private), GFP_KERNEL);
843 if (!dev->driver_priv)
844 return -ENOMEM;
845
832 return 0; 846 return 0;
833} 847}
834 848
@@ -875,23 +889,25 @@ static const struct driver_info hawking_uf200_info = {
875static const struct driver_info ax88772_info = { 889static const struct driver_info ax88772_info = {
876 .description = "ASIX AX88772 USB 2.0 Ethernet", 890 .description = "ASIX AX88772 USB 2.0 Ethernet",
877 .bind = ax88772_bind, 891 .bind = ax88772_bind,
892 .unbind = ax88772_unbind,
878 .status = asix_status, 893 .status = asix_status,
879 .link_reset = ax88772_link_reset, 894 .link_reset = ax88772_link_reset,
880 .reset = ax88772_reset, 895 .reset = ax88772_reset,
881 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET, 896 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET,
882 .rx_fixup = asix_rx_fixup, 897 .rx_fixup = asix_rx_fixup_common,
883 .tx_fixup = asix_tx_fixup, 898 .tx_fixup = asix_tx_fixup,
884}; 899};
885 900
886static const struct driver_info ax88772b_info = { 901static const struct driver_info ax88772b_info = {
887 .description = "ASIX AX88772B USB 2.0 Ethernet", 902 .description = "ASIX AX88772B USB 2.0 Ethernet",
888 .bind = ax88772_bind, 903 .bind = ax88772_bind,
904 .unbind = ax88772_unbind,
889 .status = asix_status, 905 .status = asix_status,
890 .link_reset = ax88772_link_reset, 906 .link_reset = ax88772_link_reset,
891 .reset = ax88772_reset, 907 .reset = ax88772_reset,
892 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | 908 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
893 FLAG_MULTI_PACKET, 909 FLAG_MULTI_PACKET,
894 .rx_fixup = asix_rx_fixup, 910 .rx_fixup = asix_rx_fixup_common,
895 .tx_fixup = asix_tx_fixup, 911 .tx_fixup = asix_tx_fixup,
896 .data = FLAG_EEPROM_MAC, 912 .data = FLAG_EEPROM_MAC,
897}; 913};
@@ -899,11 +915,12 @@ static const struct driver_info ax88772b_info = {
899static const struct driver_info ax88178_info = { 915static const struct driver_info ax88178_info = {
900 .description = "ASIX AX88178 USB 2.0 Ethernet", 916 .description = "ASIX AX88178 USB 2.0 Ethernet",
901 .bind = ax88178_bind, 917 .bind = ax88178_bind,
918 .unbind = ax88772_unbind,
902 .status = asix_status, 919 .status = asix_status,
903 .link_reset = ax88178_link_reset, 920 .link_reset = ax88178_link_reset,
904 .reset = ax88178_reset, 921 .reset = ax88178_reset,
905 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, 922 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
906 .rx_fixup = asix_rx_fixup, 923 .rx_fixup = asix_rx_fixup_common,
907 .tx_fixup = asix_tx_fixup, 924 .tx_fixup = asix_tx_fixup,
908}; 925};
909 926
diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
index fdbab72926bd..76ee5410d69e 100644
--- a/drivers/net/usb/ax88172a.c
+++ b/drivers/net/usb/ax88172a.c
@@ -35,6 +35,7 @@ struct ax88172a_private {
35 u16 phy_addr; 35 u16 phy_addr;
36 u16 oldmode; 36 u16 oldmode;
37 int use_embdphy; 37 int use_embdphy;
38 struct asix_rx_fixup_info rx_fixup_info;
38}; 39};
39 40
40/* MDIO read and write wrappers for phylib */ 41/* MDIO read and write wrappers for phylib */
@@ -400,6 +401,14 @@ out:
400 401
401} 402}
402 403
404static int ax88172a_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
405{
406 struct ax88172a_private *dp = dev->driver_priv;
407 struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
408
409 return asix_rx_fixup_internal(dev, skb, rx);
410}
411
403const struct driver_info ax88172a_info = { 412const struct driver_info ax88172a_info = {
404 .description = "ASIX AX88172A USB 2.0 Ethernet", 413 .description = "ASIX AX88172A USB 2.0 Ethernet",
405 .bind = ax88172a_bind, 414 .bind = ax88172a_bind,
@@ -409,6 +418,6 @@ const struct driver_info ax88172a_info = {
409 .status = ax88172a_status, 418 .status = ax88172a_status,
410 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | 419 .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
411 FLAG_MULTI_PACKET, 420 FLAG_MULTI_PACKET,
412 .rx_fixup = asix_rx_fixup, 421 .rx_fixup = ax88172a_rx_fixup,
413 .tx_fixup = asix_tx_fixup, 422 .tx_fixup = asix_tx_fixup,
414}; 423};