Commit c6db31ff authored by Igor Russkikh's avatar Igor Russkikh Committed by David S. Miller
Browse files

ethtool: allow netdev driver to define phy tunables



Define get/set phy tunable callbacks in ethtool ops.
This will allow MAC drivers with integrated PHY still to implement
these tunables.

Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 302af7c6
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -505,6 +505,10 @@ struct ethtool_ops {
				      struct ethtool_fecparam *);
	void	(*get_ethtool_phy_stats)(struct net_device *,
					 struct ethtool_stats *, u64 *);
	int	(*get_phy_tunable)(struct net_device *,
				   const struct ethtool_tunable *, void *);
	int	(*set_phy_tunable)(struct net_device *,
				   const struct ethtool_tunable *, const void *);
};

int ethtool_check_ops(const struct ethtool_ops *ops);
+24 −13
Original line number Diff line number Diff line
@@ -2459,14 +2459,15 @@ static int ethtool_phy_tunable_valid(const struct ethtool_tunable *tuna)

static int get_phy_tunable(struct net_device *dev, void __user *useraddr)
{
	int ret;
	struct ethtool_tunable tuna;
	struct phy_device *phydev = dev->phydev;
	struct ethtool_tunable tuna;
	bool phy_drv_tunable;
	void *data;
	int ret;

	if (!(phydev && phydev->drv && phydev->drv->get_tunable))
	phy_drv_tunable = phydev && phydev->drv && phydev->drv->get_tunable;
	if (!phy_drv_tunable && !dev->ethtool_ops->get_phy_tunable)
		return -EOPNOTSUPP;

	if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
		return -EFAULT;
	ret = ethtool_phy_tunable_valid(&tuna);
@@ -2475,9 +2476,13 @@ static int get_phy_tunable(struct net_device *dev, void __user *useraddr)
	data = kmalloc(tuna.len, GFP_USER);
	if (!data)
		return -ENOMEM;
	if (phy_drv_tunable) {
		mutex_lock(&phydev->lock);
		ret = phydev->drv->get_tunable(phydev, &tuna, data);
		mutex_unlock(&phydev->lock);
	} else {
		ret = dev->ethtool_ops->get_phy_tunable(dev, &tuna, data);
	}
	if (ret)
		goto out;
	useraddr += sizeof(tuna);
@@ -2493,12 +2498,14 @@ out:

static int set_phy_tunable(struct net_device *dev, void __user *useraddr)
{
	int ret;
	struct ethtool_tunable tuna;
	struct phy_device *phydev = dev->phydev;
	struct ethtool_tunable tuna;
	bool phy_drv_tunable;
	void *data;
	int ret;

	if (!(phydev && phydev->drv && phydev->drv->set_tunable))
	phy_drv_tunable = phydev && phydev->drv && phydev->drv->get_tunable;
	if (!phy_drv_tunable && !dev->ethtool_ops->set_phy_tunable)
		return -EOPNOTSUPP;
	if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
		return -EFAULT;
@@ -2509,9 +2516,13 @@ static int set_phy_tunable(struct net_device *dev, void __user *useraddr)
	data = memdup_user(useraddr, tuna.len);
	if (IS_ERR(data))
		return PTR_ERR(data);
	if (phy_drv_tunable) {
		mutex_lock(&phydev->lock);
		ret = phydev->drv->set_tunable(phydev, &tuna, data);
		mutex_unlock(&phydev->lock);
	} else {
		ret = dev->ethtool_ops->set_phy_tunable(dev, &tuna, data);
	}

	kfree(data);
	return ret;