Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
asix_common.c
Go to the documentation of this file.
1 /*
2  * ASIX AX8817X based USB 2.0 Ethernet Devices
3  * Copyright (C) 2003-2006 David Hollis <[email protected]>
4  * Copyright (C) 2005 Phil Chang <[email protected]>
5  * Copyright (C) 2006 James Painter <[email protected]>
6  * Copyright (c) 2002-2003 TiVo Inc.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 
23 #include "asix.h"
24 
26  u16 size, void *data)
27 {
28  void *buf;
29  int err = -ENOMEM;
30 
31  netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
32  cmd, value, index, size);
33 
34  buf = kmalloc(size, GFP_KERNEL);
35  if (!buf)
36  goto out;
37 
38  err = usb_control_msg(
39  dev->udev,
40  usb_rcvctrlpipe(dev->udev, 0),
41  cmd,
43  value,
44  index,
45  buf,
46  size,
47  USB_CTRL_GET_TIMEOUT);
48  if (err == size)
49  memcpy(data, buf, size);
50  else if (err >= 0)
51  err = -EINVAL;
52  kfree(buf);
53 
54 out:
55  return err;
56 }
57 
59  u16 size, void *data)
60 {
61  void *buf = NULL;
62  int err = -ENOMEM;
63 
64  netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
65  cmd, value, index, size);
66 
67  if (data) {
68  buf = kmemdup(data, size, GFP_KERNEL);
69  if (!buf)
70  goto out;
71  }
72 
73  err = usb_control_msg(
74  dev->udev,
75  usb_sndctrlpipe(dev->udev, 0),
76  cmd,
78  value,
79  index,
80  buf,
81  size,
82  USB_CTRL_SET_TIMEOUT);
83  kfree(buf);
84 
85 out:
86  return err;
87 }
88 
89 static void asix_async_cmd_callback(struct urb *urb)
90 {
91  struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
92  int status = urb->status;
93 
94  if (status < 0)
95  printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
96  status);
97 
98  kfree(req);
99  usb_free_urb(urb);
100 }
101 
103  u16 size, void *data)
104 {
105  struct usb_ctrlrequest *req;
106  int status;
107  struct urb *urb;
108 
109  netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
110  cmd, value, index, size);
111 
112  urb = usb_alloc_urb(0, GFP_ATOMIC);
113  if (!urb) {
114  netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n");
115  return;
116  }
117 
118  req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
119  if (!req) {
120  netdev_err(dev->net, "Failed to allocate memory for control request\n");
121  usb_free_urb(urb);
122  return;
123  }
124 
126  req->bRequest = cmd;
127  req->wValue = cpu_to_le16(value);
128  req->wIndex = cpu_to_le16(index);
129  req->wLength = cpu_to_le16(size);
130 
131  usb_fill_control_urb(urb, dev->udev,
132  usb_sndctrlpipe(dev->udev, 0),
133  (void *)req, data, size,
134  asix_async_cmd_callback, req);
135 
136  status = usb_submit_urb(urb, GFP_ATOMIC);
137  if (status < 0) {
138  netdev_err(dev->net, "Error submitting the control message: status=%d\n",
139  status);
140  kfree(req);
141  usb_free_urb(urb);
142  }
143 }
144 
145 int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
146 {
147  int offset = 0;
148 
149  while (offset + sizeof(u32) < skb->len) {
150  struct sk_buff *ax_skb;
151  u16 size;
152  u32 header = get_unaligned_le32(skb->data + offset);
153 
154  offset += sizeof(u32);
155 
156  /* get the packet length */
157  size = (u16) (header & 0x7ff);
158  if (size != ((~header >> 16) & 0x07ff)) {
159  netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n");
160  return 0;
161  }
162 
163  if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) ||
164  (size + offset > skb->len)) {
165  netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
166  size);
167  return 0;
168  }
169  ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
170  if (!ax_skb)
171  return 0;
172 
173  skb_put(ax_skb, size);
174  memcpy(ax_skb->data, skb->data + offset, size);
175  usbnet_skb_return(dev, ax_skb);
176 
177  offset += (size + 1) & 0xfffe;
178  }
179 
180  if (skb->len != offset) {
181  netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n",
182  skb->len);
183  return 0;
184  }
185  return 1;
186 }
187 
188 struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
189  gfp_t flags)
190 {
191  int padlen;
192  int headroom = skb_headroom(skb);
193  int tailroom = skb_tailroom(skb);
194  u32 packet_len;
195  u32 padbytes = 0xffff0000;
196 
197  padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
198 
199  /* We need to push 4 bytes in front of frame (packet_len)
200  * and maybe add 4 bytes after the end (if padlen is 4)
201  *
202  * Avoid skb_copy_expand() expensive call, using following rules :
203  * - We are allowed to push 4 bytes in headroom if skb_header_cloned()
204  * is false (and if we have 4 bytes of headroom)
205  * - We are allowed to put 4 bytes at tail if skb_cloned()
206  * is false (and if we have 4 bytes of tailroom)
207  *
208  * TCP packets for example are cloned, but skb_header_release()
209  * was called in tcp stack, allowing us to use headroom for our needs.
210  */
211  if (!skb_header_cloned(skb) &&
212  !(padlen && skb_cloned(skb)) &&
213  headroom + tailroom >= 4 + padlen) {
214  /* following should not happen, but better be safe */
215  if (headroom < 4 ||
216  tailroom < padlen) {
217  skb->data = memmove(skb->head + 4, skb->data, skb->len);
218  skb_set_tail_pointer(skb, skb->len);
219  }
220  } else {
221  struct sk_buff *skb2;
222 
223  skb2 = skb_copy_expand(skb, 4, padlen, flags);
224  dev_kfree_skb_any(skb);
225  skb = skb2;
226  if (!skb)
227  return NULL;
228  }
229 
230  packet_len = ((skb->len ^ 0x0000ffff) << 16) + skb->len;
231  skb_push(skb, 4);
232  cpu_to_le32s(&packet_len);
233  skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
234 
235  if (padlen) {
236  cpu_to_le32s(&padbytes);
237  memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
238  skb_put(skb, sizeof(padbytes));
239  }
240  return skb;
241 }
242 
244 {
245  int ret;
246  ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
247  if (ret < 0)
248  netdev_err(dev->net, "Failed to enable software MII access\n");
249  return ret;
250 }
251 
253 {
254  int ret;
255  ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
256  if (ret < 0)
257  netdev_err(dev->net, "Failed to enable hardware MII access\n");
258  return ret;
259 }
260 
261 int asix_read_phy_addr(struct usbnet *dev, int internal)
262 {
263  int offset = (internal ? 1 : 0);
264  u8 buf[2];
265  int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
266 
267  netdev_dbg(dev->net, "asix_get_phy_addr()\n");
268 
269  if (ret < 0) {
270  netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret);
271  goto out;
272  }
273  netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n",
274  *((__le16 *)buf));
275  ret = buf[offset];
276 
277 out:
278  return ret;
279 }
280 
282 {
283  /* return the address of the internal phy */
284  return asix_read_phy_addr(dev, 1);
285 }
286 
287 
289 {
290  int ret;
291 
292  ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
293  if (ret < 0)
294  netdev_err(dev->net, "Failed to send software reset: %02x\n", ret);
295 
296  return ret;
297 }
298 
300 {
301  __le16 v;
302  int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v);
303 
304  if (ret < 0) {
305  netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret);
306  goto out;
307  }
308  ret = le16_to_cpu(v);
309 out:
310  return ret;
311 }
312 
314 {
315  int ret;
316 
317  netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode);
318  ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
319  if (ret < 0)
320  netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n",
321  mode, ret);
322 
323  return ret;
324 }
325 
327 {
328  __le16 v;
329  int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v);
330 
331  if (ret < 0) {
332  netdev_err(dev->net, "Error reading Medium Status register: %02x\n",
333  ret);
334  return ret; /* TODO: callers not checking for error ret */
335  }
336 
337  return le16_to_cpu(v);
338 
339 }
340 
342 {
343  int ret;
344 
345  netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode);
346  ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
347  if (ret < 0)
348  netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n",
349  mode, ret);
350 
351  return ret;
352 }
353 
354 int asix_write_gpio(struct usbnet *dev, u16 value, int sleep)
355 {
356  int ret;
357 
358  netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value);
359  ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
360  if (ret < 0)
361  netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n",
362  value, ret);
363 
364  if (sleep)
365  msleep(sleep);
366 
367  return ret;
368 }
369 
370 /*
371  * AX88772 & AX88178 have a 16-bit RX_CTL value
372  */
374 {
375  struct usbnet *dev = netdev_priv(net);
376  struct asix_data *data = (struct asix_data *)&dev->data;
378 
379  if (net->flags & IFF_PROMISC) {
381  } else if (net->flags & IFF_ALLMULTI ||
382  netdev_mc_count(net) > AX_MAX_MCAST) {
384  } else if (netdev_mc_empty(net)) {
385  /* just broadcast and directed */
386  } else {
387  /* We use the 20 byte dev->data
388  * for our 8 byte filter buffer
389  * to avoid allocating memory that
390  * is tricky to free later */
391  struct netdev_hw_addr *ha;
392  u32 crc_bits;
393 
395 
396  /* Build the multicast hash filter. */
397  netdev_for_each_mc_addr(ha, net) {
398  crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
399  data->multi_filter[crc_bits >> 3] |=
400  1 << (crc_bits & 7);
401  }
402 
405 
406  rx_ctl |= AX_RX_CTL_AM;
407  }
408 
410 }
411 
412 int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
413 {
414  struct usbnet *dev = netdev_priv(netdev);
415  __le16 res;
416 
417  mutex_lock(&dev->phy_mutex);
418  asix_set_sw_mii(dev);
419  asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
420  (__u16)loc, 2, &res);
421  asix_set_hw_mii(dev);
422  mutex_unlock(&dev->phy_mutex);
423 
424  netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
425  phy_id, loc, le16_to_cpu(res));
426 
427  return le16_to_cpu(res);
428 }
429 
430 void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
431 {
432  struct usbnet *dev = netdev_priv(netdev);
433  __le16 res = cpu_to_le16(val);
434 
435  netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
436  phy_id, loc, val);
437  mutex_lock(&dev->phy_mutex);
438  asix_set_sw_mii(dev);
439  asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
440  asix_set_hw_mii(dev);
441  mutex_unlock(&dev->phy_mutex);
442 }
443 
444 void asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
445 {
446  struct usbnet *dev = netdev_priv(net);
447  u8 opt;
448 
449  if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
450  wolinfo->supported = 0;
451  wolinfo->wolopts = 0;
452  return;
453  }
454  wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
455  wolinfo->wolopts = 0;
456  if (opt & AX_MONITOR_LINK)
457  wolinfo->wolopts |= WAKE_PHY;
458  if (opt & AX_MONITOR_MAGIC)
459  wolinfo->wolopts |= WAKE_MAGIC;
460 }
461 
462 int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
463 {
464  struct usbnet *dev = netdev_priv(net);
465  u8 opt = 0;
466 
467  if (wolinfo->wolopts & WAKE_PHY)
468  opt |= AX_MONITOR_LINK;
469  if (wolinfo->wolopts & WAKE_MAGIC)
470  opt |= AX_MONITOR_MAGIC;
471 
473  opt, 0, 0, NULL) < 0)
474  return -EINVAL;
475 
476  return 0;
477 }
478 
480 {
481  return AX_EEPROM_LEN;
482 }
483 
485  u8 *data)
486 {
487  struct usbnet *dev = netdev_priv(net);
488  u16 *eeprom_buff;
489  int first_word, last_word;
490  int i;
491 
492  if (eeprom->len == 0)
493  return -EINVAL;
494 
495  eeprom->magic = AX_EEPROM_MAGIC;
496 
497  first_word = eeprom->offset >> 1;
498  last_word = (eeprom->offset + eeprom->len - 1) >> 1;
499 
500  eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
501  GFP_KERNEL);
502  if (!eeprom_buff)
503  return -ENOMEM;
504 
505  /* ax8817x returns 2 bytes from eeprom on read */
506  for (i = first_word; i <= last_word; i++) {
507  if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, i, 0, 2,
508  &(eeprom_buff[i - first_word])) < 0) {
509  kfree(eeprom_buff);
510  return -EIO;
511  }
512  }
513 
514  memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
515  kfree(eeprom_buff);
516  return 0;
517 }
518 
520  u8 *data)
521 {
522  struct usbnet *dev = netdev_priv(net);
523  u16 *eeprom_buff;
524  int first_word, last_word;
525  int i;
526  int ret;
527 
528  netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n",
529  eeprom->len, eeprom->offset, eeprom->magic);
530 
531  if (eeprom->len == 0)
532  return -EINVAL;
533 
534  if (eeprom->magic != AX_EEPROM_MAGIC)
535  return -EINVAL;
536 
537  first_word = eeprom->offset >> 1;
538  last_word = (eeprom->offset + eeprom->len - 1) >> 1;
539 
540  eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
541  GFP_KERNEL);
542  if (!eeprom_buff)
543  return -ENOMEM;
544 
545  /* align data to 16 bit boundaries, read the missing data from
546  the EEPROM */
547  if (eeprom->offset & 1) {
548  ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, first_word, 0, 2,
549  &(eeprom_buff[0]));
550  if (ret < 0) {
551  netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word);
552  goto free;
553  }
554  }
555 
556  if ((eeprom->offset + eeprom->len) & 1) {
557  ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, last_word, 0, 2,
558  &(eeprom_buff[last_word - first_word]));
559  if (ret < 0) {
560  netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word);
561  goto free;
562  }
563  }
564 
565  memcpy((u8 *)eeprom_buff + (eeprom->offset & 1), data, eeprom->len);
566 
567  /* write data to EEPROM */
568  ret = asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0x0000, 0, 0, NULL);
569  if (ret < 0) {
570  netdev_err(net, "Failed to enable EEPROM write\n");
571  goto free;
572  }
573  msleep(20);
574 
575  for (i = first_word; i <= last_word; i++) {
576  netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n",
577  i, eeprom_buff[i - first_word]);
578  ret = asix_write_cmd(dev, AX_CMD_WRITE_EEPROM, i,
579  eeprom_buff[i - first_word], 0, NULL);
580  if (ret < 0) {
581  netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n",
582  i);
583  goto free;
584  }
585  msleep(20);
586  }
587 
588  ret = asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0x0000, 0, 0, NULL);
589  if (ret < 0) {
590  netdev_err(net, "Failed to disable EEPROM write\n");
591  goto free;
592  }
593 
594  ret = 0;
595 free:
596  kfree(eeprom_buff);
597  return ret;
598 }
599 
601 {
602  /* Inherit standard device info */
603  usbnet_get_drvinfo(net, info);
604  strncpy (info->driver, DRIVER_NAME, sizeof info->driver);
605  strncpy (info->version, DRIVER_VERSION, sizeof info->version);
606  info->eedump_len = AX_EEPROM_LEN;
607 }
608 
610 {
611  struct usbnet *dev = netdev_priv(net);
612  struct asix_data *data = (struct asix_data *)&dev->data;
613  struct sockaddr *addr = p;
614 
615  if (netif_running(net))
616  return -EBUSY;
617  if (!is_valid_ether_addr(addr->sa_data))
618  return -EADDRNOTAVAIL;
619 
620  memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
621 
622  /* We use the 20 byte dev->data
623  * for our 6 byte mac buffer
624  * to avoid allocating memory that
625  * is tricky to free later */
626  memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
628  data->mac_addr);
629 
630  return 0;
631 }