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: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Igor Russkikh <irusskikh@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
302af7c604
commit
c6db31ffe2
@ -505,6 +505,10 @@ struct ethtool_ops {
|
|||||||
struct ethtool_fecparam *);
|
struct ethtool_fecparam *);
|
||||||
void (*get_ethtool_phy_stats)(struct net_device *,
|
void (*get_ethtool_phy_stats)(struct net_device *,
|
||||||
struct ethtool_stats *, u64 *);
|
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);
|
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)
|
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 phy_device *phydev = dev->phydev;
|
||||||
|
struct ethtool_tunable tuna;
|
||||||
|
bool phy_drv_tunable;
|
||||||
void *data;
|
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;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
|
if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ret = ethtool_phy_tunable_valid(&tuna);
|
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);
|
data = kmalloc(tuna.len, GFP_USER);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
mutex_lock(&phydev->lock);
|
if (phy_drv_tunable) {
|
||||||
ret = phydev->drv->get_tunable(phydev, &tuna, data);
|
mutex_lock(&phydev->lock);
|
||||||
mutex_unlock(&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)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
useraddr += sizeof(tuna);
|
useraddr += sizeof(tuna);
|
||||||
@ -2493,12 +2498,14 @@ out:
|
|||||||
|
|
||||||
static int set_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 phy_device *phydev = dev->phydev;
|
||||||
|
struct ethtool_tunable tuna;
|
||||||
|
bool phy_drv_tunable;
|
||||||
void *data;
|
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;
|
return -EOPNOTSUPP;
|
||||||
if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
|
if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -2509,9 +2516,13 @@ static int set_phy_tunable(struct net_device *dev, void __user *useraddr)
|
|||||||
data = memdup_user(useraddr, tuna.len);
|
data = memdup_user(useraddr, tuna.len);
|
||||||
if (IS_ERR(data))
|
if (IS_ERR(data))
|
||||||
return PTR_ERR(data);
|
return PTR_ERR(data);
|
||||||
mutex_lock(&phydev->lock);
|
if (phy_drv_tunable) {
|
||||||
ret = phydev->drv->set_tunable(phydev, &tuna, data);
|
mutex_lock(&phydev->lock);
|
||||||
mutex_unlock(&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);
|
kfree(data);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user