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:
Родитель
302af7c604
Коммит
c6db31ffe2
|
@ -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;
|
||||
mutex_lock(&phydev->lock);
|
||||
ret = phydev->drv->get_tunable(phydev, &tuna, data);
|
||||
mutex_unlock(&phydev->lock);
|
||||
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);
|
||||
mutex_lock(&phydev->lock);
|
||||
ret = phydev->drv->set_tunable(phydev, &tuna, data);
|
||||
mutex_unlock(&phydev->lock);
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче