diff options
-rw-r--r-- | drivers/net/usb/asix.h | 1 | ||||
-rw-r--r-- | drivers/net/usb/asix_common.c | 53 | ||||
-rw-r--r-- | drivers/net/usb/asix_devices.c | 1 |
3 files changed, 45 insertions, 10 deletions
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h index d1092421aaa7..9a4171b90947 100644 --- a/drivers/net/usb/asix.h +++ b/drivers/net/usb/asix.h | |||
@@ -209,6 +209,7 @@ void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, | |||
209 | int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, | 209 | int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, |
210 | struct asix_rx_fixup_info *rx); | 210 | struct asix_rx_fixup_info *rx); |
211 | int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb); | 211 | int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb); |
212 | void asix_rx_fixup_common_free(struct asix_common_private *dp); | ||
212 | 213 | ||
213 | struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | 214 | struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, |
214 | gfp_t flags); | 215 | gfp_t flags); |
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 7847436c441e..522d2900cd1d 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c | |||
@@ -75,6 +75,27 @@ void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | |||
75 | value, index, data, size); | 75 | value, index, data, size); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx) | ||
79 | { | ||
80 | /* Reset the variables that have a lifetime outside of | ||
81 | * asix_rx_fixup_internal() so that future processing starts from a | ||
82 | * known set of initial conditions. | ||
83 | */ | ||
84 | |||
85 | if (rx->ax_skb) { | ||
86 | /* Discard any incomplete Ethernet frame in the netdev buffer */ | ||
87 | kfree_skb(rx->ax_skb); | ||
88 | rx->ax_skb = NULL; | ||
89 | } | ||
90 | |||
91 | /* Assume the Data header 32-bit word is at the start of the current | ||
92 | * or next URB socket buffer so reset all the state variables. | ||
93 | */ | ||
94 | rx->remaining = 0; | ||
95 | rx->split_head = false; | ||
96 | rx->header = 0; | ||
97 | } | ||
98 | |||
78 | int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, | 99 | int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, |
79 | struct asix_rx_fixup_info *rx) | 100 | struct asix_rx_fixup_info *rx) |
80 | { | 101 | { |
@@ -99,15 +120,7 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, | |||
99 | if (size != ((~rx->header >> 16) & 0x7ff)) { | 120 | if (size != ((~rx->header >> 16) & 0x7ff)) { |
100 | netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n", | 121 | netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n", |
101 | rx->remaining); | 122 | rx->remaining); |
102 | if (rx->ax_skb) { | 123 | reset_asix_rx_fixup_info(rx); |
103 | kfree_skb(rx->ax_skb); | ||
104 | rx->ax_skb = NULL; | ||
105 | /* Discard the incomplete netdev Ethernet frame | ||
106 | * and assume the Data header is at the start of | ||
107 | * the current URB socket buffer. | ||
108 | */ | ||
109 | } | ||
110 | rx->remaining = 0; | ||
111 | } | 124 | } |
112 | } | 125 | } |
113 | 126 | ||
@@ -139,11 +152,13 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, | |||
139 | if (size != ((~rx->header >> 16) & 0x7ff)) { | 152 | if (size != ((~rx->header >> 16) & 0x7ff)) { |
140 | netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n", | 153 | netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n", |
141 | rx->header, offset); | 154 | rx->header, offset); |
155 | reset_asix_rx_fixup_info(rx); | ||
142 | return 0; | 156 | return 0; |
143 | } | 157 | } |
144 | if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { | 158 | if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { |
145 | netdev_dbg(dev->net, "asix_rx_fixup() Bad RX Length %d\n", | 159 | netdev_dbg(dev->net, "asix_rx_fixup() Bad RX Length %d\n", |
146 | size); | 160 | size); |
161 | reset_asix_rx_fixup_info(rx); | ||
147 | return 0; | 162 | return 0; |
148 | } | 163 | } |
149 | 164 | ||
@@ -168,8 +183,10 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, | |||
168 | if (rx->ax_skb) { | 183 | if (rx->ax_skb) { |
169 | skb_put_data(rx->ax_skb, skb->data + offset, | 184 | skb_put_data(rx->ax_skb, skb->data + offset, |
170 | copy_length); | 185 | copy_length); |
171 | if (!rx->remaining) | 186 | if (!rx->remaining) { |
172 | usbnet_skb_return(dev, rx->ax_skb); | 187 | usbnet_skb_return(dev, rx->ax_skb); |
188 | rx->ax_skb = NULL; | ||
189 | } | ||
173 | } | 190 | } |
174 | 191 | ||
175 | offset += (copy_length + 1) & 0xfffe; | 192 | offset += (copy_length + 1) & 0xfffe; |
@@ -178,6 +195,7 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, | |||
178 | if (skb->len != offset) { | 195 | if (skb->len != offset) { |
179 | netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n", | 196 | netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n", |
180 | skb->len, offset); | 197 | skb->len, offset); |
198 | reset_asix_rx_fixup_info(rx); | ||
181 | return 0; | 199 | return 0; |
182 | } | 200 | } |
183 | 201 | ||
@@ -192,6 +210,21 @@ int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb) | |||
192 | return asix_rx_fixup_internal(dev, skb, rx); | 210 | return asix_rx_fixup_internal(dev, skb, rx); |
193 | } | 211 | } |
194 | 212 | ||
213 | void asix_rx_fixup_common_free(struct asix_common_private *dp) | ||
214 | { | ||
215 | struct asix_rx_fixup_info *rx; | ||
216 | |||
217 | if (!dp) | ||
218 | return; | ||
219 | |||
220 | rx = &dp->rx_fixup_info; | ||
221 | |||
222 | if (rx->ax_skb) { | ||
223 | kfree_skb(rx->ax_skb); | ||
224 | rx->ax_skb = NULL; | ||
225 | } | ||
226 | } | ||
227 | |||
195 | struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | 228 | struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, |
196 | gfp_t flags) | 229 | gfp_t flags) |
197 | { | 230 | { |
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index a3aa0a27dfe5..b2ff88e69a81 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c | |||
@@ -764,6 +764,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
764 | 764 | ||
765 | static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf) | 765 | static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf) |
766 | { | 766 | { |
767 | asix_rx_fixup_common_free(dev->driver_priv); | ||
767 | kfree(dev->driver_priv); | 768 | kfree(dev->driver_priv); |
768 | } | 769 | } |
769 | 770 | ||