diff options
-rw-r--r-- | net/core/ethtool.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index beacdd93cd8f..ca7698fd24d4 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -751,18 +751,17 @@ static int ethtool_get_link(struct net_device *dev, char __user *useraddr) | |||
751 | return 0; | 751 | return 0; |
752 | } | 752 | } |
753 | 753 | ||
754 | static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | 754 | static int ethtool_get_any_eeprom(struct net_device *dev, void __user *useraddr, |
755 | int (*getter)(struct net_device *, | ||
756 | struct ethtool_eeprom *, u8 *), | ||
757 | u32 total_len) | ||
755 | { | 758 | { |
756 | struct ethtool_eeprom eeprom; | 759 | struct ethtool_eeprom eeprom; |
757 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
758 | void __user *userbuf = useraddr + sizeof(eeprom); | 760 | void __user *userbuf = useraddr + sizeof(eeprom); |
759 | u32 bytes_remaining; | 761 | u32 bytes_remaining; |
760 | u8 *data; | 762 | u8 *data; |
761 | int ret = 0; | 763 | int ret = 0; |
762 | 764 | ||
763 | if (!ops->get_eeprom || !ops->get_eeprom_len) | ||
764 | return -EOPNOTSUPP; | ||
765 | |||
766 | if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) | 765 | if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) |
767 | return -EFAULT; | 766 | return -EFAULT; |
768 | 767 | ||
@@ -771,7 +770,7 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
771 | return -EINVAL; | 770 | return -EINVAL; |
772 | 771 | ||
773 | /* Check for exceeding total eeprom len */ | 772 | /* Check for exceeding total eeprom len */ |
774 | if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) | 773 | if (eeprom.offset + eeprom.len > total_len) |
775 | return -EINVAL; | 774 | return -EINVAL; |
776 | 775 | ||
777 | data = kmalloc(PAGE_SIZE, GFP_USER); | 776 | data = kmalloc(PAGE_SIZE, GFP_USER); |
@@ -782,7 +781,7 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
782 | while (bytes_remaining > 0) { | 781 | while (bytes_remaining > 0) { |
783 | eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); | 782 | eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); |
784 | 783 | ||
785 | ret = ops->get_eeprom(dev, &eeprom, data); | 784 | ret = getter(dev, &eeprom, data); |
786 | if (ret) | 785 | if (ret) |
787 | break; | 786 | break; |
788 | if (copy_to_user(userbuf, data, eeprom.len)) { | 787 | if (copy_to_user(userbuf, data, eeprom.len)) { |
@@ -803,6 +802,17 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
803 | return ret; | 802 | return ret; |
804 | } | 803 | } |
805 | 804 | ||
805 | static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | ||
806 | { | ||
807 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
808 | |||
809 | if (!ops->get_eeprom || !ops->get_eeprom_len) | ||
810 | return -EOPNOTSUPP; | ||
811 | |||
812 | return ethtool_get_any_eeprom(dev, useraddr, ops->get_eeprom, | ||
813 | ops->get_eeprom_len(dev)); | ||
814 | } | ||
815 | |||
806 | static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | 816 | static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) |
807 | { | 817 | { |
808 | struct ethtool_eeprom eeprom; | 818 | struct ethtool_eeprom eeprom; |