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

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
......@@ -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);
......
......@@ -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 @@ static int get_phy_tunable(struct net_device *dev, void __user *useraddr)
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment