Commit 081d094e authored by Ben Hutchings's avatar Ben Hutchings
Browse files

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: default avatarBen Hutchings <bhutchings@solarflare.com>
parent 64235187
Loading
Loading
Loading
Loading
+17 −7
Original line number Original line Diff line number Diff line
@@ -751,18 +751,17 @@ static int ethtool_get_link(struct net_device *dev, char __user *useraddr)
	return 0;
	return 0;
}
}


static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
static int ethtool_get_any_eeprom(struct net_device *dev, void __user *useraddr,
				  int (*getter)(struct net_device *,
						struct ethtool_eeprom *, u8 *),
				  u32 total_len)
{
{
	struct ethtool_eeprom eeprom;
	struct ethtool_eeprom eeprom;
	const struct ethtool_ops *ops = dev->ethtool_ops;
	void __user *userbuf = useraddr + sizeof(eeprom);
	void __user *userbuf = useraddr + sizeof(eeprom);
	u32 bytes_remaining;
	u32 bytes_remaining;
	u8 *data;
	u8 *data;
	int ret = 0;
	int ret = 0;


	if (!ops->get_eeprom || !ops->get_eeprom_len)
		return -EOPNOTSUPP;

	if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
	if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
		return -EFAULT;
		return -EFAULT;


@@ -771,7 +770,7 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
		return -EINVAL;
		return -EINVAL;


	/* Check for exceeding total eeprom len */
	/* Check for exceeding total eeprom len */
	if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
	if (eeprom.offset + eeprom.len > total_len)
		return -EINVAL;
		return -EINVAL;


	data = kmalloc(PAGE_SIZE, GFP_USER);
	data = kmalloc(PAGE_SIZE, GFP_USER);
@@ -782,7 +781,7 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
	while (bytes_remaining > 0) {
	while (bytes_remaining > 0) {
		eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
		eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);


		ret = ops->get_eeprom(dev, &eeprom, data);
		ret = getter(dev, &eeprom, data);
		if (ret)
		if (ret)
			break;
			break;
		if (copy_to_user(userbuf, data, eeprom.len)) {
		if (copy_to_user(userbuf, data, eeprom.len)) {
@@ -803,6 +802,17 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
	return ret;
	return ret;
}
}


static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
{
	const struct ethtool_ops *ops = dev->ethtool_ops;

	if (!ops->get_eeprom || !ops->get_eeprom_len)
		return -EOPNOTSUPP;

	return ethtool_get_any_eeprom(dev, useraddr, ops->get_eeprom,
				      ops->get_eeprom_len(dev));
}

static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
{
{
	struct ethtool_eeprom eeprom;
	struct ethtool_eeprom eeprom;