]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/core/ethtool.c
arm: use kbuild.h instead of macros in asm-offsets.c
[linux-2.6-omap-h63xx.git] / net / core / ethtool.c
index 1163eb2256d0560b1fb3b4a71db5df5d4a40a072..0133b5ebd545287be9a2ee19d8fbf75db8e9ca59 100644 (file)
@@ -284,8 +284,10 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
 {
        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;
@@ -301,26 +303,31 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
        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;
 }
@@ -329,8 +336,10 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
 {
        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;
@@ -346,22 +355,26 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
        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;
 }