diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2012-04-11 20:42:12 -0400 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2012-05-09 21:22:17 -0400 |
commit | 081d094eaab894ae5a517fde56179dfe67773ff0 (patch) | |
tree | c8b1533cc8910c9259465eb4a4f1cdc953444e3f | |
parent | 64235187c2b32913fc41dfafc98e3a77ea7c0217 (diff) |
ethtool: Split ethtool_get_eeprom() to allow for additional EEPROM accessors
We want to support reading module (SFP+, XFP, ...) EEPROMs as well as
NIC EEPROMs. They will need a different command number and driver
operation, but the structure and arguments will be the same and so we
can share most of the code here.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-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; |