{
struct ethtool_eeprom eeprom;
const struct ethtool_ops *ops = dev->ethtool_ops;
+ void __user *userbuf = useraddr + sizeof(eeprom);
+ u32 bytes_remaining;
u8 *data;
- int ret;
+ int ret = 0;
if (!ops->get_eeprom || !ops->get_eeprom_len)
return -EOPNOTSUPP;
if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
return -EINVAL;
- data = kmalloc(eeprom.len, GFP_USER);
+ data = kmalloc(PAGE_SIZE, GFP_USER);
if (!data)
return -ENOMEM;
- ret = -EFAULT;
- if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
- goto out;
+ bytes_remaining = eeprom.len;
+ while (bytes_remaining > 0) {
+ eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
- ret = ops->get_eeprom(dev, &eeprom, data);
- if (ret)
- goto out;
+ ret = ops->get_eeprom(dev, &eeprom, data);
+ if (ret)
+ break;
+ if (copy_to_user(userbuf, data, eeprom.len)) {
+ ret = -EFAULT;
+ break;
+ }
+ userbuf += eeprom.len;
+ eeprom.offset += eeprom.len;
+ bytes_remaining -= eeprom.len;
+ }
- ret = -EFAULT;
+ eeprom.len = userbuf - (useraddr + sizeof(eeprom));
+ eeprom.offset -= eeprom.len;
if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
- goto out;
- if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
- goto out;
- ret = 0;
+ ret = -EFAULT;
- out:
kfree(data);
return ret;
}
{
struct ethtool_eeprom eeprom;
const struct ethtool_ops *ops = dev->ethtool_ops;
+ void __user *userbuf = useraddr + sizeof(eeprom);
+ u32 bytes_remaining;
u8 *data;
- int ret;
+ int ret = 0;
if (!ops->set_eeprom || !ops->get_eeprom_len)
return -EOPNOTSUPP;
if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
return -EINVAL;
- data = kmalloc(eeprom.len, GFP_USER);
+ data = kmalloc(PAGE_SIZE, GFP_USER);
if (!data)
return -ENOMEM;
- ret = -EFAULT;
- if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
- goto out;
-
- ret = ops->set_eeprom(dev, &eeprom, data);
- if (ret)
- goto out;
+ bytes_remaining = eeprom.len;
+ while (bytes_remaining > 0) {
+ eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
- if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
- ret = -EFAULT;
+ if (copy_from_user(data, userbuf, eeprom.len)) {
+ ret = -EFAULT;
+ break;
+ }
+ ret = ops->set_eeprom(dev, &eeprom, data);
+ if (ret)
+ break;
+ userbuf += eeprom.len;
+ eeprom.offset += eeprom.len;
+ bytes_remaining -= eeprom.len;
+ }
- out:
kfree(data);
return ret;
}
break;
case ETHTOOL_GTXCSUM:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_tx_csum);
+ (dev->ethtool_ops->get_tx_csum ?
+ dev->ethtool_ops->get_tx_csum :
+ ethtool_op_get_tx_csum));
break;
case ETHTOOL_STXCSUM:
rc = ethtool_set_tx_csum(dev, useraddr);
break;
case ETHTOOL_GSG:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_sg);
+ (dev->ethtool_ops->get_sg ?
+ dev->ethtool_ops->get_sg :
+ ethtool_op_get_sg));
break;
case ETHTOOL_SSG:
rc = ethtool_set_sg(dev, useraddr);
break;
case ETHTOOL_GTSO:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_tso);
+ (dev->ethtool_ops->get_tso ?
+ dev->ethtool_ops->get_tso :
+ ethtool_op_get_tso));
break;
case ETHTOOL_STSO:
rc = ethtool_set_tso(dev, useraddr);
break;
case ETHTOOL_GUFO:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_ufo);
+ (dev->ethtool_ops->get_ufo ?
+ dev->ethtool_ops->get_ufo :
+ ethtool_op_get_ufo));
break;
case ETHTOOL_SUFO:
rc = ethtool_set_ufo(dev, useraddr);