mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-30 14:34:51 +08:00
drivers/net/phy: add connection between ethtool and phylib for PLCA
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> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
16178c8ef5
commit
a23a1e57a6
@ -543,6 +543,198 @@ 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
|
||||
*
|
||||
* Retrieve the PLCA configuration from the PHY. Return 0 on success or a
|
||||
* negative value if an error occurred.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
ret = phydev->drv->get_plca_cfg(phydev, plca_cfg);
|
||||
|
||||
mutex_unlock(&phydev->lock);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* plca_check_valid - Check PLCA configuration before enabling
|
||||
* @phydev: the phy_device struct
|
||||
* @plca_cfg: current PLCA configuration
|
||||
* @extack: extack for reporting useful error messages
|
||||
*
|
||||
* Checks whether the PLCA and PHY configuration are consistent and it is safe
|
||||
* to enable PLCA. Returns 0 on success or a negative value if the PLCA or PHY
|
||||
* configuration is not consistent.
|
||||
*/
|
||||
static int plca_check_valid(struct phy_device *phydev,
|
||||
const struct phy_plca_cfg *plca_cfg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int ret = 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");
|
||||
} else if (plca_cfg->node_id >= 255) {
|
||||
NL_SET_ERR_MSG(extack, "PLCA node ID is not set");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_ethtool_set_plca_cfg - Set PLCA RS configuration
|
||||
* @phydev: the phy_device struct
|
||||
* @plca_cfg: new PLCA configuration to apply
|
||||
* @extack: extack for reporting useful error messages
|
||||
*
|
||||
* Sets the PLCA configuration in the PHY. Return 0 on success or a
|
||||
* negative value if an error occurred.
|
||||
*/
|
||||
int phy_ethtool_set_plca_cfg(struct phy_device *phydev,
|
||||
const struct phy_plca_cfg *plca_cfg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct phy_plca_cfg *curr_plca_cfg;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
if (!curr_plca_cfg) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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 a few sanity checks
|
||||
if (plca_cfg->enabled > 0) {
|
||||
// allow setting node_id concurrently with enabled
|
||||
if (plca_cfg->node_id >= 0)
|
||||
curr_plca_cfg->node_id = plca_cfg->node_id;
|
||||
|
||||
ret = plca_check_valid(phydev, curr_plca_cfg, extack);
|
||||
if (ret)
|
||||
goto out_drv;
|
||||
}
|
||||
|
||||
ret = phydev->drv->set_plca_cfg(phydev, plca_cfg);
|
||||
|
||||
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
|
||||
*
|
||||
* Retrieve the PLCA status information from the PHY. Return 0 on success or a
|
||||
* negative value if an error occurred.
|
||||
*/
|
||||
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);
|
||||
|
||||
mutex_unlock(&phydev->lock);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_start_cable_test - Start a cable test
|
||||
*
|
||||
|
@ -3283,6 +3283,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,
|
||||
};
|
||||
|
@ -1851,6 +1851,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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user