diff options
Diffstat (limited to 'drivers/net/usb/asix_devices.c')
-rw-r--r-- | drivers/net/usb/asix_devices.c | 660 |
1 files changed, 1 insertions, 659 deletions
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 6564c32d3af..8c513f7921f 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c | |||
@@ -20,137 +20,7 @@ | |||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | // #define DEBUG // error path messages, extra info | 23 | #include "asix.h" |
24 | // #define VERBOSE // more; success messages | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/kmod.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/netdevice.h> | ||
30 | #include <linux/etherdevice.h> | ||
31 | #include <linux/ethtool.h> | ||
32 | #include <linux/workqueue.h> | ||
33 | #include <linux/mii.h> | ||
34 | #include <linux/usb.h> | ||
35 | #include <linux/crc32.h> | ||
36 | #include <linux/usb/usbnet.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/if_vlan.h> | ||
39 | |||
40 | #define DRIVER_VERSION "22-Dec-2011" | ||
41 | #define DRIVER_NAME "asix" | ||
42 | |||
43 | /* ASIX AX8817X based USB 2.0 Ethernet Devices */ | ||
44 | |||
45 | #define AX_CMD_SET_SW_MII 0x06 | ||
46 | #define AX_CMD_READ_MII_REG 0x07 | ||
47 | #define AX_CMD_WRITE_MII_REG 0x08 | ||
48 | #define AX_CMD_SET_HW_MII 0x0a | ||
49 | #define AX_CMD_READ_EEPROM 0x0b | ||
50 | #define AX_CMD_WRITE_EEPROM 0x0c | ||
51 | #define AX_CMD_WRITE_ENABLE 0x0d | ||
52 | #define AX_CMD_WRITE_DISABLE 0x0e | ||
53 | #define AX_CMD_READ_RX_CTL 0x0f | ||
54 | #define AX_CMD_WRITE_RX_CTL 0x10 | ||
55 | #define AX_CMD_READ_IPG012 0x11 | ||
56 | #define AX_CMD_WRITE_IPG0 0x12 | ||
57 | #define AX_CMD_WRITE_IPG1 0x13 | ||
58 | #define AX_CMD_READ_NODE_ID 0x13 | ||
59 | #define AX_CMD_WRITE_NODE_ID 0x14 | ||
60 | #define AX_CMD_WRITE_IPG2 0x14 | ||
61 | #define AX_CMD_WRITE_MULTI_FILTER 0x16 | ||
62 | #define AX88172_CMD_READ_NODE_ID 0x17 | ||
63 | #define AX_CMD_READ_PHY_ID 0x19 | ||
64 | #define AX_CMD_READ_MEDIUM_STATUS 0x1a | ||
65 | #define AX_CMD_WRITE_MEDIUM_MODE 0x1b | ||
66 | #define AX_CMD_READ_MONITOR_MODE 0x1c | ||
67 | #define AX_CMD_WRITE_MONITOR_MODE 0x1d | ||
68 | #define AX_CMD_READ_GPIOS 0x1e | ||
69 | #define AX_CMD_WRITE_GPIOS 0x1f | ||
70 | #define AX_CMD_SW_RESET 0x20 | ||
71 | #define AX_CMD_SW_PHY_STATUS 0x21 | ||
72 | #define AX_CMD_SW_PHY_SELECT 0x22 | ||
73 | |||
74 | #define AX_MONITOR_MODE 0x01 | ||
75 | #define AX_MONITOR_LINK 0x02 | ||
76 | #define AX_MONITOR_MAGIC 0x04 | ||
77 | #define AX_MONITOR_HSFS 0x10 | ||
78 | |||
79 | /* AX88172 Medium Status Register values */ | ||
80 | #define AX88172_MEDIUM_FD 0x02 | ||
81 | #define AX88172_MEDIUM_TX 0x04 | ||
82 | #define AX88172_MEDIUM_FC 0x10 | ||
83 | #define AX88172_MEDIUM_DEFAULT \ | ||
84 | ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC ) | ||
85 | |||
86 | #define AX_MCAST_FILTER_SIZE 8 | ||
87 | #define AX_MAX_MCAST 64 | ||
88 | |||
89 | #define AX_SWRESET_CLEAR 0x00 | ||
90 | #define AX_SWRESET_RR 0x01 | ||
91 | #define AX_SWRESET_RT 0x02 | ||
92 | #define AX_SWRESET_PRTE 0x04 | ||
93 | #define AX_SWRESET_PRL 0x08 | ||
94 | #define AX_SWRESET_BZ 0x10 | ||
95 | #define AX_SWRESET_IPRL 0x20 | ||
96 | #define AX_SWRESET_IPPD 0x40 | ||
97 | |||
98 | #define AX88772_IPG0_DEFAULT 0x15 | ||
99 | #define AX88772_IPG1_DEFAULT 0x0c | ||
100 | #define AX88772_IPG2_DEFAULT 0x12 | ||
101 | |||
102 | /* AX88772 & AX88178 Medium Mode Register */ | ||
103 | #define AX_MEDIUM_PF 0x0080 | ||
104 | #define AX_MEDIUM_JFE 0x0040 | ||
105 | #define AX_MEDIUM_TFC 0x0020 | ||
106 | #define AX_MEDIUM_RFC 0x0010 | ||
107 | #define AX_MEDIUM_ENCK 0x0008 | ||
108 | #define AX_MEDIUM_AC 0x0004 | ||
109 | #define AX_MEDIUM_FD 0x0002 | ||
110 | #define AX_MEDIUM_GM 0x0001 | ||
111 | #define AX_MEDIUM_SM 0x1000 | ||
112 | #define AX_MEDIUM_SBP 0x0800 | ||
113 | #define AX_MEDIUM_PS 0x0200 | ||
114 | #define AX_MEDIUM_RE 0x0100 | ||
115 | |||
116 | #define AX88178_MEDIUM_DEFAULT \ | ||
117 | (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ | ||
118 | AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ | ||
119 | AX_MEDIUM_RE) | ||
120 | |||
121 | #define AX88772_MEDIUM_DEFAULT \ | ||
122 | (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ | ||
123 | AX_MEDIUM_TFC | AX_MEDIUM_PS | \ | ||
124 | AX_MEDIUM_AC | AX_MEDIUM_RE) | ||
125 | |||
126 | /* AX88772 & AX88178 RX_CTL values */ | ||
127 | #define AX_RX_CTL_SO 0x0080 | ||
128 | #define AX_RX_CTL_AP 0x0020 | ||
129 | #define AX_RX_CTL_AM 0x0010 | ||
130 | #define AX_RX_CTL_AB 0x0008 | ||
131 | #define AX_RX_CTL_SEP 0x0004 | ||
132 | #define AX_RX_CTL_AMALL 0x0002 | ||
133 | #define AX_RX_CTL_PRO 0x0001 | ||
134 | #define AX_RX_CTL_MFB_2048 0x0000 | ||
135 | #define AX_RX_CTL_MFB_4096 0x0100 | ||
136 | #define AX_RX_CTL_MFB_8192 0x0200 | ||
137 | #define AX_RX_CTL_MFB_16384 0x0300 | ||
138 | |||
139 | #define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB) | ||
140 | |||
141 | /* GPIO 0 .. 2 toggles */ | ||
142 | #define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ | ||
143 | #define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */ | ||
144 | #define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */ | ||
145 | #define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */ | ||
146 | #define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ | ||
147 | #define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ | ||
148 | #define AX_GPIO_RESERVED 0x40 /* Reserved */ | ||
149 | #define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ | ||
150 | |||
151 | #define AX_EEPROM_MAGIC 0xdeadbeef | ||
152 | #define AX88172_EEPROM_LEN 0x40 | ||
153 | #define AX88772_EEPROM_LEN 0xff | ||
154 | 24 | ||
155 | #define PHY_MODE_MARVELL 0x0000 | 25 | #define PHY_MODE_MARVELL 0x0000 |
156 | #define MII_MARVELL_LED_CTRL 0x0018 | 26 | #define MII_MARVELL_LED_CTRL 0x0018 |
@@ -166,15 +36,6 @@ | |||
166 | 36 | ||
167 | #define PHY_MODE_RTL8211CL 0x000C | 37 | #define PHY_MODE_RTL8211CL 0x000C |
168 | 38 | ||
169 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ | ||
170 | struct asix_data { | ||
171 | u8 multi_filter[AX_MCAST_FILTER_SIZE]; | ||
172 | u8 mac_addr[ETH_ALEN]; | ||
173 | u8 phymode; | ||
174 | u8 ledmode; | ||
175 | u8 eeprom_len; | ||
176 | }; | ||
177 | |||
178 | struct ax88172_int_data { | 39 | struct ax88172_int_data { |
179 | __le16 res1; | 40 | __le16 res1; |
180 | u8 link; | 41 | u8 link; |
@@ -183,225 +44,6 @@ struct ax88172_int_data { | |||
183 | __le16 res3; | 44 | __le16 res3; |
184 | } __packed; | 45 | } __packed; |
185 | 46 | ||
186 | static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
187 | u16 size, void *data) | ||
188 | { | ||
189 | void *buf; | ||
190 | int err = -ENOMEM; | ||
191 | |||
192 | netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", | ||
193 | cmd, value, index, size); | ||
194 | |||
195 | buf = kmalloc(size, GFP_KERNEL); | ||
196 | if (!buf) | ||
197 | goto out; | ||
198 | |||
199 | err = usb_control_msg( | ||
200 | dev->udev, | ||
201 | usb_rcvctrlpipe(dev->udev, 0), | ||
202 | cmd, | ||
203 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
204 | value, | ||
205 | index, | ||
206 | buf, | ||
207 | size, | ||
208 | USB_CTRL_GET_TIMEOUT); | ||
209 | if (err == size) | ||
210 | memcpy(data, buf, size); | ||
211 | else if (err >= 0) | ||
212 | err = -EINVAL; | ||
213 | kfree(buf); | ||
214 | |||
215 | out: | ||
216 | return err; | ||
217 | } | ||
218 | |||
219 | static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
220 | u16 size, void *data) | ||
221 | { | ||
222 | void *buf = NULL; | ||
223 | int err = -ENOMEM; | ||
224 | |||
225 | netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", | ||
226 | cmd, value, index, size); | ||
227 | |||
228 | if (data) { | ||
229 | buf = kmemdup(data, size, GFP_KERNEL); | ||
230 | if (!buf) | ||
231 | goto out; | ||
232 | } | ||
233 | |||
234 | err = usb_control_msg( | ||
235 | dev->udev, | ||
236 | usb_sndctrlpipe(dev->udev, 0), | ||
237 | cmd, | ||
238 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
239 | value, | ||
240 | index, | ||
241 | buf, | ||
242 | size, | ||
243 | USB_CTRL_SET_TIMEOUT); | ||
244 | kfree(buf); | ||
245 | |||
246 | out: | ||
247 | return err; | ||
248 | } | ||
249 | |||
250 | static void asix_async_cmd_callback(struct urb *urb) | ||
251 | { | ||
252 | struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; | ||
253 | int status = urb->status; | ||
254 | |||
255 | if (status < 0) | ||
256 | printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d", | ||
257 | status); | ||
258 | |||
259 | kfree(req); | ||
260 | usb_free_urb(urb); | ||
261 | } | ||
262 | |||
263 | static void | ||
264 | asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
265 | u16 size, void *data) | ||
266 | { | ||
267 | struct usb_ctrlrequest *req; | ||
268 | int status; | ||
269 | struct urb *urb; | ||
270 | |||
271 | netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", | ||
272 | cmd, value, index, size); | ||
273 | |||
274 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
275 | if (!urb) { | ||
276 | netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n"); | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); | ||
281 | if (!req) { | ||
282 | netdev_err(dev->net, "Failed to allocate memory for control request\n"); | ||
283 | usb_free_urb(urb); | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
288 | req->bRequest = cmd; | ||
289 | req->wValue = cpu_to_le16(value); | ||
290 | req->wIndex = cpu_to_le16(index); | ||
291 | req->wLength = cpu_to_le16(size); | ||
292 | |||
293 | usb_fill_control_urb(urb, dev->udev, | ||
294 | usb_sndctrlpipe(dev->udev, 0), | ||
295 | (void *)req, data, size, | ||
296 | asix_async_cmd_callback, req); | ||
297 | |||
298 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
299 | if (status < 0) { | ||
300 | netdev_err(dev->net, "Error submitting the control message: status=%d\n", | ||
301 | status); | ||
302 | kfree(req); | ||
303 | usb_free_urb(urb); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
308 | { | ||
309 | int offset = 0; | ||
310 | |||
311 | while (offset + sizeof(u32) < skb->len) { | ||
312 | struct sk_buff *ax_skb; | ||
313 | u16 size; | ||
314 | u32 header = get_unaligned_le32(skb->data + offset); | ||
315 | |||
316 | offset += sizeof(u32); | ||
317 | |||
318 | /* get the packet length */ | ||
319 | size = (u16) (header & 0x7ff); | ||
320 | if (size != ((~header >> 16) & 0x07ff)) { | ||
321 | netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || | ||
326 | (size + offset > skb->len)) { | ||
327 | netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", | ||
328 | size); | ||
329 | return 0; | ||
330 | } | ||
331 | ax_skb = netdev_alloc_skb_ip_align(dev->net, size); | ||
332 | if (!ax_skb) | ||
333 | return 0; | ||
334 | |||
335 | skb_put(ax_skb, size); | ||
336 | memcpy(ax_skb->data, skb->data + offset, size); | ||
337 | usbnet_skb_return(dev, ax_skb); | ||
338 | |||
339 | offset += (size + 1) & 0xfffe; | ||
340 | } | ||
341 | |||
342 | if (skb->len != offset) { | ||
343 | netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n", | ||
344 | skb->len); | ||
345 | return 0; | ||
346 | } | ||
347 | return 1; | ||
348 | } | ||
349 | |||
350 | static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | ||
351 | gfp_t flags) | ||
352 | { | ||
353 | int padlen; | ||
354 | int headroom = skb_headroom(skb); | ||
355 | int tailroom = skb_tailroom(skb); | ||
356 | u32 packet_len; | ||
357 | u32 padbytes = 0xffff0000; | ||
358 | |||
359 | padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4; | ||
360 | |||
361 | /* We need to push 4 bytes in front of frame (packet_len) | ||
362 | * and maybe add 4 bytes after the end (if padlen is 4) | ||
363 | * | ||
364 | * Avoid skb_copy_expand() expensive call, using following rules : | ||
365 | * - We are allowed to push 4 bytes in headroom if skb_header_cloned() | ||
366 | * is false (and if we have 4 bytes of headroom) | ||
367 | * - We are allowed to put 4 bytes at tail if skb_cloned() | ||
368 | * is false (and if we have 4 bytes of tailroom) | ||
369 | * | ||
370 | * TCP packets for example are cloned, but skb_header_release() | ||
371 | * was called in tcp stack, allowing us to use headroom for our needs. | ||
372 | */ | ||
373 | if (!skb_header_cloned(skb) && | ||
374 | !(padlen && skb_cloned(skb)) && | ||
375 | headroom + tailroom >= 4 + padlen) { | ||
376 | /* following should not happen, but better be safe */ | ||
377 | if (headroom < 4 || | ||
378 | tailroom < padlen) { | ||
379 | skb->data = memmove(skb->head + 4, skb->data, skb->len); | ||
380 | skb_set_tail_pointer(skb, skb->len); | ||
381 | } | ||
382 | } else { | ||
383 | struct sk_buff *skb2; | ||
384 | |||
385 | skb2 = skb_copy_expand(skb, 4, padlen, flags); | ||
386 | dev_kfree_skb_any(skb); | ||
387 | skb = skb2; | ||
388 | if (!skb) | ||
389 | return NULL; | ||
390 | } | ||
391 | |||
392 | packet_len = ((skb->len ^ 0x0000ffff) << 16) + skb->len; | ||
393 | skb_push(skb, 4); | ||
394 | cpu_to_le32s(&packet_len); | ||
395 | skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); | ||
396 | |||
397 | if (padlen) { | ||
398 | cpu_to_le32s(&padbytes); | ||
399 | memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); | ||
400 | skb_put(skb, sizeof(padbytes)); | ||
401 | } | ||
402 | return skb; | ||
403 | } | ||
404 | |||
405 | static void asix_status(struct usbnet *dev, struct urb *urb) | 47 | static void asix_status(struct usbnet *dev, struct urb *urb) |
406 | { | 48 | { |
407 | struct ax88172_int_data *event; | 49 | struct ax88172_int_data *event; |
@@ -422,200 +64,6 @@ static void asix_status(struct usbnet *dev, struct urb *urb) | |||
422 | } | 64 | } |
423 | } | 65 | } |
424 | 66 | ||
425 | static inline int asix_set_sw_mii(struct usbnet *dev) | ||
426 | { | ||
427 | int ret; | ||
428 | ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); | ||
429 | if (ret < 0) | ||
430 | netdev_err(dev->net, "Failed to enable software MII access\n"); | ||
431 | return ret; | ||
432 | } | ||
433 | |||
434 | static inline int asix_set_hw_mii(struct usbnet *dev) | ||
435 | { | ||
436 | int ret; | ||
437 | ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); | ||
438 | if (ret < 0) | ||
439 | netdev_err(dev->net, "Failed to enable hardware MII access\n"); | ||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | static inline int asix_get_phy_addr(struct usbnet *dev) | ||
444 | { | ||
445 | u8 buf[2]; | ||
446 | int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); | ||
447 | |||
448 | netdev_dbg(dev->net, "asix_get_phy_addr()\n"); | ||
449 | |||
450 | if (ret < 0) { | ||
451 | netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret); | ||
452 | goto out; | ||
453 | } | ||
454 | netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n", | ||
455 | *((__le16 *)buf)); | ||
456 | ret = buf[1]; | ||
457 | |||
458 | out: | ||
459 | return ret; | ||
460 | } | ||
461 | |||
462 | static int asix_sw_reset(struct usbnet *dev, u8 flags) | ||
463 | { | ||
464 | int ret; | ||
465 | |||
466 | ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); | ||
467 | if (ret < 0) | ||
468 | netdev_err(dev->net, "Failed to send software reset: %02x\n", ret); | ||
469 | |||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | static u16 asix_read_rx_ctl(struct usbnet *dev) | ||
474 | { | ||
475 | __le16 v; | ||
476 | int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v); | ||
477 | |||
478 | if (ret < 0) { | ||
479 | netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret); | ||
480 | goto out; | ||
481 | } | ||
482 | ret = le16_to_cpu(v); | ||
483 | out: | ||
484 | return ret; | ||
485 | } | ||
486 | |||
487 | static int asix_write_rx_ctl(struct usbnet *dev, u16 mode) | ||
488 | { | ||
489 | int ret; | ||
490 | |||
491 | netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode); | ||
492 | ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); | ||
493 | if (ret < 0) | ||
494 | netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n", | ||
495 | mode, ret); | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | static u16 asix_read_medium_status(struct usbnet *dev) | ||
501 | { | ||
502 | __le16 v; | ||
503 | int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); | ||
504 | |||
505 | if (ret < 0) { | ||
506 | netdev_err(dev->net, "Error reading Medium Status register: %02x\n", | ||
507 | ret); | ||
508 | return ret; /* TODO: callers not checking for error ret */ | ||
509 | } | ||
510 | |||
511 | return le16_to_cpu(v); | ||
512 | |||
513 | } | ||
514 | |||
515 | static int asix_write_medium_mode(struct usbnet *dev, u16 mode) | ||
516 | { | ||
517 | int ret; | ||
518 | |||
519 | netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode); | ||
520 | ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); | ||
521 | if (ret < 0) | ||
522 | netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n", | ||
523 | mode, ret); | ||
524 | |||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) | ||
529 | { | ||
530 | int ret; | ||
531 | |||
532 | netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value); | ||
533 | ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL); | ||
534 | if (ret < 0) | ||
535 | netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n", | ||
536 | value, ret); | ||
537 | |||
538 | if (sleep) | ||
539 | msleep(sleep); | ||
540 | |||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * AX88772 & AX88178 have a 16-bit RX_CTL value | ||
546 | */ | ||
547 | static void asix_set_multicast(struct net_device *net) | ||
548 | { | ||
549 | struct usbnet *dev = netdev_priv(net); | ||
550 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
551 | u16 rx_ctl = AX_DEFAULT_RX_CTL; | ||
552 | |||
553 | if (net->flags & IFF_PROMISC) { | ||
554 | rx_ctl |= AX_RX_CTL_PRO; | ||
555 | } else if (net->flags & IFF_ALLMULTI || | ||
556 | netdev_mc_count(net) > AX_MAX_MCAST) { | ||
557 | rx_ctl |= AX_RX_CTL_AMALL; | ||
558 | } else if (netdev_mc_empty(net)) { | ||
559 | /* just broadcast and directed */ | ||
560 | } else { | ||
561 | /* We use the 20 byte dev->data | ||
562 | * for our 8 byte filter buffer | ||
563 | * to avoid allocating memory that | ||
564 | * is tricky to free later */ | ||
565 | struct netdev_hw_addr *ha; | ||
566 | u32 crc_bits; | ||
567 | |||
568 | memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); | ||
569 | |||
570 | /* Build the multicast hash filter. */ | ||
571 | netdev_for_each_mc_addr(ha, net) { | ||
572 | crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; | ||
573 | data->multi_filter[crc_bits >> 3] |= | ||
574 | 1 << (crc_bits & 7); | ||
575 | } | ||
576 | |||
577 | asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, | ||
578 | AX_MCAST_FILTER_SIZE, data->multi_filter); | ||
579 | |||
580 | rx_ctl |= AX_RX_CTL_AM; | ||
581 | } | ||
582 | |||
583 | asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); | ||
584 | } | ||
585 | |||
586 | static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) | ||
587 | { | ||
588 | struct usbnet *dev = netdev_priv(netdev); | ||
589 | __le16 res; | ||
590 | |||
591 | mutex_lock(&dev->phy_mutex); | ||
592 | asix_set_sw_mii(dev); | ||
593 | asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, | ||
594 | (__u16)loc, 2, &res); | ||
595 | asix_set_hw_mii(dev); | ||
596 | mutex_unlock(&dev->phy_mutex); | ||
597 | |||
598 | netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", | ||
599 | phy_id, loc, le16_to_cpu(res)); | ||
600 | |||
601 | return le16_to_cpu(res); | ||
602 | } | ||
603 | |||
604 | static void | ||
605 | asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) | ||
606 | { | ||
607 | struct usbnet *dev = netdev_priv(netdev); | ||
608 | __le16 res = cpu_to_le16(val); | ||
609 | |||
610 | netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", | ||
611 | phy_id, loc, val); | ||
612 | mutex_lock(&dev->phy_mutex); | ||
613 | asix_set_sw_mii(dev); | ||
614 | asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); | ||
615 | asix_set_hw_mii(dev); | ||
616 | mutex_unlock(&dev->phy_mutex); | ||
617 | } | ||
618 | |||
619 | /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ | 67 | /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ |
620 | static u32 asix_get_phyid(struct usbnet *dev) | 68 | static u32 asix_get_phyid(struct usbnet *dev) |
621 | { | 69 | { |
@@ -645,88 +93,6 @@ static u32 asix_get_phyid(struct usbnet *dev) | |||
645 | return phy_id; | 93 | return phy_id; |
646 | } | 94 | } |
647 | 95 | ||
648 | static void | ||
649 | asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
650 | { | ||
651 | struct usbnet *dev = netdev_priv(net); | ||
652 | u8 opt; | ||
653 | |||
654 | if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { | ||
655 | wolinfo->supported = 0; | ||
656 | wolinfo->wolopts = 0; | ||
657 | return; | ||
658 | } | ||
659 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | ||
660 | wolinfo->wolopts = 0; | ||
661 | if (opt & AX_MONITOR_LINK) | ||
662 | wolinfo->wolopts |= WAKE_PHY; | ||
663 | if (opt & AX_MONITOR_MAGIC) | ||
664 | wolinfo->wolopts |= WAKE_MAGIC; | ||
665 | } | ||
666 | |||
667 | static int | ||
668 | asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
669 | { | ||
670 | struct usbnet *dev = netdev_priv(net); | ||
671 | u8 opt = 0; | ||
672 | |||
673 | if (wolinfo->wolopts & WAKE_PHY) | ||
674 | opt |= AX_MONITOR_LINK; | ||
675 | if (wolinfo->wolopts & WAKE_MAGIC) | ||
676 | opt |= AX_MONITOR_MAGIC; | ||
677 | |||
678 | if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, | ||
679 | opt, 0, 0, NULL) < 0) | ||
680 | return -EINVAL; | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static int asix_get_eeprom_len(struct net_device *net) | ||
686 | { | ||
687 | struct usbnet *dev = netdev_priv(net); | ||
688 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
689 | |||
690 | return data->eeprom_len; | ||
691 | } | ||
692 | |||
693 | static int asix_get_eeprom(struct net_device *net, | ||
694 | struct ethtool_eeprom *eeprom, u8 *data) | ||
695 | { | ||
696 | struct usbnet *dev = netdev_priv(net); | ||
697 | __le16 *ebuf = (__le16 *)data; | ||
698 | int i; | ||
699 | |||
700 | /* Crude hack to ensure that we don't overwrite memory | ||
701 | * if an odd length is supplied | ||
702 | */ | ||
703 | if (eeprom->len % 2) | ||
704 | return -EINVAL; | ||
705 | |||
706 | eeprom->magic = AX_EEPROM_MAGIC; | ||
707 | |||
708 | /* ax8817x returns 2 bytes from eeprom on read */ | ||
709 | for (i=0; i < eeprom->len / 2; i++) { | ||
710 | if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, | ||
711 | eeprom->offset + i, 0, 2, &ebuf[i]) < 0) | ||
712 | return -EINVAL; | ||
713 | } | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static void asix_get_drvinfo (struct net_device *net, | ||
718 | struct ethtool_drvinfo *info) | ||
719 | { | ||
720 | struct usbnet *dev = netdev_priv(net); | ||
721 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
722 | |||
723 | /* Inherit standard device info */ | ||
724 | usbnet_get_drvinfo(net, info); | ||
725 | strncpy (info->driver, DRIVER_NAME, sizeof info->driver); | ||
726 | strncpy (info->version, DRIVER_VERSION, sizeof info->version); | ||
727 | info->eedump_len = data->eeprom_len; | ||
728 | } | ||
729 | |||
730 | static u32 asix_get_link(struct net_device *net) | 96 | static u32 asix_get_link(struct net_device *net) |
731 | { | 97 | { |
732 | struct usbnet *dev = netdev_priv(net); | 98 | struct usbnet *dev = netdev_priv(net); |
@@ -741,30 +107,6 @@ static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) | |||
741 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | 107 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); |
742 | } | 108 | } |
743 | 109 | ||
744 | static int asix_set_mac_address(struct net_device *net, void *p) | ||
745 | { | ||
746 | struct usbnet *dev = netdev_priv(net); | ||
747 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
748 | struct sockaddr *addr = p; | ||
749 | |||
750 | if (netif_running(net)) | ||
751 | return -EBUSY; | ||
752 | if (!is_valid_ether_addr(addr->sa_data)) | ||
753 | return -EADDRNOTAVAIL; | ||
754 | |||
755 | memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); | ||
756 | |||
757 | /* We use the 20 byte dev->data | ||
758 | * for our 6 byte mac buffer | ||
759 | * to avoid allocating memory that | ||
760 | * is tricky to free later */ | ||
761 | memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); | ||
762 | asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, | ||
763 | data->mac_addr); | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | /* We need to override some ethtool_ops so we require our | 110 | /* We need to override some ethtool_ops so we require our |
769 | own structure so we don't interfere with other usbnet | 111 | own structure so we don't interfere with other usbnet |
770 | devices that may be connected at the same time. */ | 112 | devices that may be connected at the same time. */ |