Commit 06191dd6 authored by Scott Feldman's avatar Scott Feldman Committed by Stephen Hemminger

[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?
parent 019904d0
...@@ -307,14 +307,14 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data); ...@@ -307,14 +307,14 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data);
* *
* get_eeprom: * get_eeprom:
* Should fill in the magic field. Don't need to check len for zero * Should fill in the magic field. Don't need to check len for zero
* or wraparound but must check offset + len < size. Fill in the data * or wraparound. Fill in the data argument with the eeprom values
* argument with the eeprom values from offset to offset + len. Update * from offset to offset + len. Update len to the amount read.
* len to the amount read. Returns an error or zero. * Returns an error or zero.
* *
* set_eeprom: * set_eeprom:
* Should validate the magic field. Don't need to check len for zero * Should validate the magic field. Don't need to check len for zero
* or wraparound but must check offset + len < size. Update len to * or wraparound. Update len to the amount written. Returns an error
* the amount written. Returns an error or zero. * or zero.
*/ */
struct ethtool_ops { struct ethtool_ops {
int (*get_settings)(struct net_device *, struct ethtool_cmd *); int (*get_settings)(struct net_device *, struct ethtool_cmd *);
...@@ -328,6 +328,7 @@ struct ethtool_ops { ...@@ -328,6 +328,7 @@ struct ethtool_ops {
void (*set_msglevel)(struct net_device *, u32); void (*set_msglevel)(struct net_device *, u32);
int (*nway_reset)(struct net_device *); int (*nway_reset)(struct net_device *);
u32 (*get_link)(struct net_device *); u32 (*get_link)(struct net_device *);
int (*get_eeprom_len)(struct net_device *);
int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);
......
...@@ -122,7 +122,8 @@ static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) ...@@ -122,7 +122,8 @@ static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr)
info.n_stats = ops->get_stats_count(dev); info.n_stats = ops->get_stats_count(dev);
if (ops->get_regs_len) if (ops->get_regs_len)
info.regdump_len = ops->get_regs_len(dev); 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))) if (copy_to_user(useraddr, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
...@@ -245,29 +246,34 @@ static int ethtool_get_link(struct net_device *dev, void *useraddr) ...@@ -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) static int ethtool_get_eeprom(struct net_device *dev, void *useraddr)
{ {
struct ethtool_eeprom eeprom; struct ethtool_eeprom eeprom;
struct ethtool_ops *ops = dev->ethtool_ops;
u8 *data; u8 *data;
int len, ret; int ret;
if (!dev->ethtool_ops->get_eeprom) if (!ops->get_eeprom || !ops->get_eeprom_len)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
return -EFAULT; return -EFAULT;
len = eeprom.len;
/* Check for wrap and zero */ /* 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; return -EINVAL;
data = kmalloc(len, GFP_USER); data = kmalloc(eeprom.len, GFP_USER);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
if (copy_from_user(data, useraddr + sizeof(eeprom), len)) ret = -EFAULT;
return -EFAULT; if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
goto out;
ret = dev->ethtool_ops->get_eeprom(dev, &eeprom, data); ret = ops->get_eeprom(dev, &eeprom, data);
if (!ret) if (ret)
goto out; goto out;
ret = -EFAULT; ret = -EFAULT;
...@@ -285,32 +291,37 @@ static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) ...@@ -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) static int ethtool_set_eeprom(struct net_device *dev, void *useraddr)
{ {
struct ethtool_eeprom eeprom; struct ethtool_eeprom eeprom;
struct ethtool_ops *ops = dev->ethtool_ops;
u8 *data; u8 *data;
int len, ret; int ret;
if (!dev->ethtool_ops->set_eeprom) if (!ops->set_eeprom || !ops->get_eeprom_len)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
return -EFAULT; return -EFAULT;
len = eeprom.len;
/* Check for wrap and zero */ /* 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; return -EINVAL;
data = kmalloc(len, GFP_USER); data = kmalloc(eeprom.len, GFP_USER);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
if (copy_from_user(data, useraddr + sizeof(eeprom), len)) ret = -EFAULT;
return -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) if (ret)
goto out; goto out;
if (copy_to_user(useraddr + sizeof(eeprom), data, len)) if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
ret = -EFAULT; ret = -EFAULT;
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment