Skip to content

Commit

Permalink
drivers/net/phy: add connection between ethtool and phylib for PLCA
Browse files Browse the repository at this point in the history
This patch adds the required connection between netlink ethtool and
phylib to resolve PLCA get/set config and get status messages.

Signed-off-by: Piergiorgio Beruto <piergiorgio.beruto@gmail.com>
  • Loading branch information
pberuto authored and intel-lab-lkp committed Dec 10, 2022
1 parent 37f53c9 commit 333e7a2
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 0 deletions.
175 changes: 175 additions & 0 deletions drivers/net/phy/phy.c
Expand Up @@ -543,6 +543,181 @@ int phy_ethtool_get_stats(struct phy_device *phydev,
}
EXPORT_SYMBOL(phy_ethtool_get_stats);

/**
* phy_ethtool_get_plca_cfg - Get PLCA RS configuration
*
* @phydev: the phy_device struct
* @plca_cfg: where to store the retrieved configuration
*/
int phy_ethtool_get_plca_cfg(struct phy_device *phydev,
struct phy_plca_cfg *plca_cfg)
{
int ret;

if (!phydev->drv) {
ret = -EIO;
goto out;
}

if (!phydev->drv->get_plca_cfg) {
ret = -EOPNOTSUPP;
goto out;
}

memset(plca_cfg, 0xFF, sizeof(*plca_cfg));

mutex_lock(&phydev->lock);
ret = phydev->drv->get_plca_cfg(phydev, plca_cfg);

if (ret)
goto out_drv;

out_drv:
mutex_unlock(&phydev->lock);
out:
return ret;
}

/**
* phy_ethtool_set_plca_cfg - Set PLCA RS configuration
*
* @phydev: the phy_device struct
* @extack: extack for reporting useful error messages
* @plca_cfg: new PLCA configuration to apply
*/
int phy_ethtool_set_plca_cfg(struct phy_device *phydev,
const struct phy_plca_cfg *plca_cfg,
struct netlink_ext_ack *extack)
{
int ret;
struct phy_plca_cfg *curr_plca_cfg = 0;

if (!phydev->drv) {
ret = -EIO;
goto out;
}

if (!phydev->drv->set_plca_cfg ||
!phydev->drv->get_plca_cfg) {
ret = -EOPNOTSUPP;
goto out;
}

curr_plca_cfg = kmalloc(sizeof(*curr_plca_cfg), GFP_KERNEL);
memset(curr_plca_cfg, 0xFF, sizeof(*curr_plca_cfg));

mutex_lock(&phydev->lock);

ret = phydev->drv->get_plca_cfg(phydev, curr_plca_cfg);
if (ret)
goto out_drv;

if (curr_plca_cfg->enabled < 0 && plca_cfg->enabled >= 0) {
NL_SET_ERR_MSG(extack,
"PHY does not support changing the PLCA 'enable' attribute");
ret = -EINVAL;
goto out_drv;
}

if (curr_plca_cfg->node_id < 0 && plca_cfg->node_id >= 0) {
NL_SET_ERR_MSG(extack,
"PHY does not support changing the PLCA 'local node ID' attribute");
ret = -EINVAL;
goto out_drv;
}

if (curr_plca_cfg->node_cnt < 0 && plca_cfg->node_cnt >= 0) {
NL_SET_ERR_MSG(extack,
"PHY does not support changing the PLCA 'node count' attribute");
ret = -EINVAL;
goto out_drv;
}

if (curr_plca_cfg->to_tmr < 0 && plca_cfg->to_tmr >= 0) {
NL_SET_ERR_MSG(extack,
"PHY does not support changing the PLCA 'TO timer' attribute");
ret = -EINVAL;
goto out_drv;
}

if (curr_plca_cfg->burst_cnt < 0 && plca_cfg->burst_cnt >= 0) {
NL_SET_ERR_MSG(extack,
"PHY does not support changing the PLCA 'burst count' attribute");
ret = -EINVAL;
goto out_drv;
}

if (curr_plca_cfg->burst_tmr < 0 && plca_cfg->burst_tmr >= 0) {
NL_SET_ERR_MSG(extack,
"PHY does not support changing the PLCA 'burst timer' attribute");
ret = -EINVAL;
goto out_drv;
}

// if enabling PLCA, perform additional sanity checks
if (plca_cfg->enabled > 0) {
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT,
phydev->advertising)) {
ret = -EOPNOTSUPP;
NL_SET_ERR_MSG(extack,
"Point to Multi-Point mode is not enabled");
}

// allow setting node_id concurrently with enabled
if (plca_cfg->node_id >= 0)
curr_plca_cfg->node_id = plca_cfg->node_id;

if (curr_plca_cfg->node_id >= 255) {
NL_SET_ERR_MSG(extack, "PLCA node ID is not set");
ret = -EINVAL;
goto out_drv;
}
}

ret = phydev->drv->set_plca_cfg(phydev, plca_cfg);
if (ret)
goto out_drv;

out_drv:
kfree(curr_plca_cfg);
mutex_unlock(&phydev->lock);
out:
return ret;
}

/**
* phy_ethtool_get_plca_status - Get PLCA RS status information
*
* @phydev: the phy_device struct
* @plca_st: where to store the retrieved status information
*/
int phy_ethtool_get_plca_status(struct phy_device *phydev,
struct phy_plca_status *plca_st)
{
int ret;

if (!phydev->drv) {
ret = -EIO;
goto out;
}

if (!phydev->drv->get_plca_status) {
ret = -EOPNOTSUPP;
goto out;
}

mutex_lock(&phydev->lock);
ret = phydev->drv->get_plca_status(phydev, plca_st);

if (ret)
goto out_drv;

out_drv:
mutex_unlock(&phydev->lock);
out:
return ret;
}

/**
* phy_start_cable_test - Start a cable test
*
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/phy/phy_device.c
Expand Up @@ -3276,6 +3276,9 @@ static const struct ethtool_phy_ops phy_ethtool_phy_ops = {
.get_sset_count = phy_ethtool_get_sset_count,
.get_strings = phy_ethtool_get_strings,
.get_stats = phy_ethtool_get_stats,
.get_plca_cfg = phy_ethtool_get_plca_cfg,
.set_plca_cfg = phy_ethtool_set_plca_cfg,
.get_plca_status = phy_ethtool_get_plca_status,
.start_cable_test = phy_start_cable_test,
.start_cable_test_tdr = phy_start_cable_test_tdr,
};
Expand Down
7 changes: 7 additions & 0 deletions include/linux/phy.h
Expand Up @@ -1845,6 +1845,13 @@ int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data);
int phy_ethtool_get_sset_count(struct phy_device *phydev);
int phy_ethtool_get_stats(struct phy_device *phydev,
struct ethtool_stats *stats, u64 *data);
int phy_ethtool_get_plca_cfg(struct phy_device *phydev,
struct phy_plca_cfg *plca_cfg);
int phy_ethtool_set_plca_cfg(struct phy_device *phydev,
const struct phy_plca_cfg *plca_cfg,
struct netlink_ext_ack *extack);
int phy_ethtool_get_plca_status(struct phy_device *phydev,
struct phy_plca_status *plca_st);

static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
{
Expand Down

0 comments on commit 333e7a2

Please sign in to comment.