aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/asix_common.c
diff options
context:
space:
mode:
authorChristian Riesch <christian.riesch@omicron.at>2012-07-18 20:23:06 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-19 13:48:07 -0400
commitceb02c91dd76012e902799e0132ad3ad3e659394 (patch)
tree4a200ab9b830cc15eebb88a2201d197c30ccf800 /drivers/net/usb/asix_common.c
parent84c9f8c41df9f62a34eb680009b59cc817a76d6e (diff)
asix: Rework reading from EEPROM
The current code for reading the EEPROM via ethtool in the asix driver has a few issues. It cannot handle odd length values (accesses must be aligned at 16 bit boundaries) and interprets the offset provided by ethtool as 16 bit word offset instead as byte offset. The new code for asix_get_eeprom() introduced by this patch is modeled after the code in drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c and provides read access to the entire EEPROM with arbitrary offsets and lengths. Signed-off-by: Christian Riesch <christian.riesch@omicron.at> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/asix_common.c')
-rw-r--r--drivers/net/usb/asix_common.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 336f75567091..0b5b2d328a56 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -478,46 +478,51 @@ int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
478 478
479int asix_get_eeprom_len(struct net_device *net) 479int asix_get_eeprom_len(struct net_device *net)
480{ 480{
481 struct usbnet *dev = netdev_priv(net); 481 return AX_EEPROM_LEN;
482 struct asix_data *data = (struct asix_data *)&dev->data;
483
484 return data->eeprom_len;
485} 482}
486 483
487int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, 484int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
488 u8 *data) 485 u8 *data)
489{ 486{
490 struct usbnet *dev = netdev_priv(net); 487 struct usbnet *dev = netdev_priv(net);
491 __le16 *ebuf = (__le16 *)data; 488 u16 *eeprom_buff;
489 int first_word, last_word;
492 int i; 490 int i;
493 491
494 /* Crude hack to ensure that we don't overwrite memory 492 if (eeprom->len == 0)
495 * if an odd length is supplied
496 */
497 if (eeprom->len % 2)
498 return -EINVAL; 493 return -EINVAL;
499 494
500 eeprom->magic = AX_EEPROM_MAGIC; 495 eeprom->magic = AX_EEPROM_MAGIC;
501 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
502 /* ax8817x returns 2 bytes from eeprom on read */ 505 /* ax8817x returns 2 bytes from eeprom on read */
503 for (i=0; i < eeprom->len / 2; i++) { 506 for (i = first_word; i <= last_word; i++) {
504 if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, 507 if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, i, 0, 2,
505 eeprom->offset + i, 0, 2, &ebuf[i]) < 0) 508 &(eeprom_buff[i - first_word])) < 0) {
506 return -EINVAL; 509 kfree(eeprom_buff);
510 return -EIO;
511 }
507 } 512 }
513
514 memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
515 kfree(eeprom_buff);
508 return 0; 516 return 0;
509} 517}
510 518
511void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) 519void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
512{ 520{
513 struct usbnet *dev = netdev_priv(net);
514 struct asix_data *data = (struct asix_data *)&dev->data;
515
516 /* Inherit standard device info */ 521 /* Inherit standard device info */
517 usbnet_get_drvinfo(net, info); 522 usbnet_get_drvinfo(net, info);
518 strncpy (info->driver, DRIVER_NAME, sizeof info->driver); 523 strncpy (info->driver, DRIVER_NAME, sizeof info->driver);
519 strncpy (info->version, DRIVER_VERSION, sizeof info->version); 524 strncpy (info->version, DRIVER_VERSION, sizeof info->version);
520 info->eedump_len = data->eeprom_len; 525 info->eedump_len = AX_EEPROM_LEN;
521} 526}
522 527
523int asix_set_mac_address(struct net_device *net, void *p) 528int asix_set_mac_address(struct net_device *net, void *p)