Skip to content

Commit

Permalink
ethtool: Extend ethtool plugin module eeprom API to phylib
Browse files Browse the repository at this point in the history
This patch extends the ethtool plugin module eeprom API to support cards
whose phy support is delegated to a separate driver.

The handlers for ETHTOOL_GMODULEINFO and ETHTOOL_GMODULEEEPROM call the
module_info and module_eeprom functions if the phy driver provides them;
otherwise the handlers call the equivalent ethtool_ops functions provided
by network drivers with built-in phy support.

Signed-off-by: Ed Swierk <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Ed Swierk authored and davem330 committed Jan 6, 2015
1 parent 53831aa commit 2f43836
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
9 changes: 9 additions & 0 deletions include/linux/phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,15 @@ struct phy_driver {
void (*write_mmd_indirect)(struct phy_device *dev, int ptrad,
int devnum, int regnum, u32 val);

/* Get the size and type of the eeprom contained within a plug-in
* module */
int (*module_info)(struct phy_device *dev,
struct ethtool_modinfo *modinfo);

/* Get the eeprom information from the plug-in module */
int (*module_eeprom)(struct phy_device *dev,
struct ethtool_eeprom *ee, u8 *data);

struct device_driver driver;
};
#define to_phy_driver(d) container_of(d, struct phy_driver, driver)
Expand Down
45 changes: 34 additions & 11 deletions net/core/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1597,20 +1597,31 @@ static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr)
return err;
}

static int __ethtool_get_module_info(struct net_device *dev,
struct ethtool_modinfo *modinfo)
{
const struct ethtool_ops *ops = dev->ethtool_ops;
struct phy_device *phydev = dev->phydev;

if (phydev && phydev->drv && phydev->drv->module_info)
return phydev->drv->module_info(phydev, modinfo);

if (ops->get_module_info)
return ops->get_module_info(dev, modinfo);

return -EOPNOTSUPP;
}

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

if (!ops->get_module_info)
return -EOPNOTSUPP;

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

ret = ops->get_module_info(dev, &modinfo);
ret = __ethtool_get_module_info(dev, &modinfo);
if (ret)
return ret;

Expand All @@ -1620,21 +1631,33 @@ static int ethtool_get_module_info(struct net_device *dev,
return 0;
}

static int __ethtool_get_module_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee, u8 *data)
{
const struct ethtool_ops *ops = dev->ethtool_ops;
struct phy_device *phydev = dev->phydev;

if (phydev && phydev->drv && phydev->drv->module_eeprom)
return phydev->drv->module_eeprom(phydev, ee, data);

if (ops->get_module_eeprom)
return ops->get_module_eeprom(dev, ee, data);

return -EOPNOTSUPP;
}

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

if (!ops->get_module_info || !ops->get_module_eeprom)
return -EOPNOTSUPP;

ret = ops->get_module_info(dev, &modinfo);
ret = __ethtool_get_module_info(dev, &modinfo);
if (ret)
return ret;

return ethtool_get_any_eeprom(dev, useraddr, ops->get_module_eeprom,
return ethtool_get_any_eeprom(dev, useraddr,
__ethtool_get_module_eeprom,
modinfo.eeprom_len);
}

Expand Down

0 comments on commit 2f43836

Please sign in to comment.