summaryrefslogtreecommitdiff
path: root/net/core/ethtool.c
diff options
context:
space:
mode:
authorScott Feldman <scott.feldman@intel.com>2003-10-14 05:52:16 -0400
committerStephen Hemminger <shemminger@osdl.org>2003-10-14 05:52:16 -0400
commit06191dd615af60ddb97a894f76ca88d68f7a79ed (patch)
tree7bcaa2358ab8921c40ba76d10a5c996a522fb933 /net/core/ethtool.c
parent019904d0dee2a4bf329f1778551dda0b3686a83a (diff)
[PATCH] ethtool_ops eeprom stuff
Finally got around to adding ethtool_ops to e100-3.0.x. I found a bug with get_eeprom() and it seems to work best if we add get_eeprom_len() to the ops list. Also moved check for offest + len < size into ethtool.c. I was able to test [GS]EEPROM, PHYS_ID, GSTATS, GSTRINGS, and TEST, and everything looks good. Should I send same for 2.4?
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r--net/core/ethtool.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 35f27196b154..46e3cf090b3c 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -122,7 +122,8 @@ static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr)
info.n_stats = ops->get_stats_count(dev);
if (ops->get_regs_len)
info.regdump_len = ops->get_regs_len(dev);
- /* XXX: eeprom? */
+ if (ops->get_eeprom_len)
+ info.eedump_len = ops->get_eeprom_len(dev);
if (copy_to_user(useraddr, &info, sizeof(info)))
return -EFAULT;
@@ -245,29 +246,34 @@ static int ethtool_get_link(struct net_device *dev, void *useraddr)
static int ethtool_get_eeprom(struct net_device *dev, void *useraddr)
{
struct ethtool_eeprom eeprom;
+ struct ethtool_ops *ops = dev->ethtool_ops;
u8 *data;
- int len, ret;
+ int ret;
- if (!dev->ethtool_ops->get_eeprom)
+ if (!ops->get_eeprom || !ops->get_eeprom_len)
return -EOPNOTSUPP;
if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
return -EFAULT;
- len = eeprom.len;
/* Check for wrap and zero */
- if (eeprom.offset + len <= eeprom.offset)
+ if (eeprom.offset + eeprom.len <= eeprom.offset)
+ return -EINVAL;
+
+ /* Check for exceeding total eeprom len */
+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
return -EINVAL;
- data = kmalloc(len, GFP_USER);
+ data = kmalloc(eeprom.len, GFP_USER);
if (!data)
return -ENOMEM;
- if (copy_from_user(data, useraddr + sizeof(eeprom), len))
- return -EFAULT;
+ ret = -EFAULT;
+ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
+ goto out;
- ret = dev->ethtool_ops->get_eeprom(dev, &eeprom, data);
- if (!ret)
+ ret = ops->get_eeprom(dev, &eeprom, data);
+ if (ret)
goto out;
ret = -EFAULT;
@@ -285,32 +291,37 @@ static int ethtool_get_eeprom(struct net_device *dev, void *useraddr)
static int ethtool_set_eeprom(struct net_device *dev, void *useraddr)
{
struct ethtool_eeprom eeprom;
+ struct ethtool_ops *ops = dev->ethtool_ops;
u8 *data;
- int len, ret;
+ int ret;
- if (!dev->ethtool_ops->set_eeprom)
+ if (!ops->set_eeprom || !ops->get_eeprom_len)
return -EOPNOTSUPP;
if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
return -EFAULT;
- len = eeprom.len;
/* Check for wrap and zero */
- if (eeprom.offset + len <= eeprom.offset)
+ if (eeprom.offset + eeprom.len <= eeprom.offset)
+ return -EINVAL;
+
+ /* Check for exceeding total eeprom len */
+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
return -EINVAL;
- data = kmalloc(len, GFP_USER);
+ data = kmalloc(eeprom.len, GFP_USER);
if (!data)
return -ENOMEM;
- if (copy_from_user(data, useraddr + sizeof(eeprom), len))
- return -EFAULT;
+ ret = -EFAULT;
+ if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
+ goto out;
- ret = dev->ethtool_ops->set_eeprom(dev, &eeprom, data);
+ ret = ops->set_eeprom(dev, &eeprom, data);
if (ret)
goto out;
- if (copy_to_user(useraddr + sizeof(eeprom), data, len))
+ if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
ret = -EFAULT;
out: