]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ethtool_ops eeprom stuff
authorScott Feldman <scott.feldman@intel.com>
Tue, 14 Oct 2003 09:52:16 +0000 (05:52 -0400)
committerStephen Hemminger <shemminger@osdl.org>
Tue, 14 Oct 2003 09:52:16 +0000 (05:52 -0400)
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?

include/linux/ethtool.h
net/core/ethtool.c

index cc942f675ae963236f669b63b1ce6185c0300666..8d4d0e397ed5ad3494eb37a72541e4972f22b6af 100644 (file)
@@ -307,14 +307,14 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data);
  *
  * get_eeprom:
  *     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
- *     argument with the eeprom values from offset to offset + len.  Update
- *     len to the amount read.  Returns an error or zero.
+ *     or wraparound.  Fill in the data argument with the eeprom values
+ *     from offset to offset + len.  Update len to the amount read.
+ *     Returns an error or zero.
  *
  * set_eeprom:
  *     Should validate the magic field.  Don't need to check len for zero
- *     or wraparound but must check offset + len < size.  Update len to
- *     the amount written.  Returns an error or zero.
+ *     or wraparound.  Update len to the amount written.  Returns an error
+ *     or zero.
  */
 struct ethtool_ops {
        int     (*get_settings)(struct net_device *, struct ethtool_cmd *);
@@ -328,6 +328,7 @@ struct ethtool_ops {
        void    (*set_msglevel)(struct net_device *, u32);
        int     (*nway_reset)(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     (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
        int     (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);
index 35f27196b1541a78e03ba2eb181374d550d02a82..46e3cf090b3ca9408faa5b02da07b78070d97af9 100644 (file)
@@ -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: