Commit c356be05 authored by David S. Miller's avatar David S. Miller

Merge branch 'xpcs-phylink_pcs_ops'

Vladimir Oltean says:

====================
Convert xpcs to phylink_pcs_ops

Background: the sja1105 DSA driver currently drives a Designware XPCS
for SGMII and 2500base-X, and it would be nice to reuse some code with
the xpcs module. This would also help consolidate the phylink_pcs_ops,
since the only other dedicated PCS driver, currently, is the lynx_pcs.

Therefore, this series makes the xpcs expose the same kind of API that
the lynx_pcs module does. The main changes are getting rid of struct
mdio_xpcs_ops, being compatible with struct phylink_pcs_ops and being
less reliant on the phy_interface_t passed to xpcs_probe (now renamed to
xpcs_create).

This patch series is partially tested (some code paths have been covered
on the NXP SJA1105 and some others with the help of Vee Khee Wong on
Intel Tiger Lake / stmmac) but further testing on 10G setups would be
appreciated, if possible.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b596ce68 11059740
...@@ -503,8 +503,7 @@ struct mac_device_info { ...@@ -503,8 +503,7 @@ struct mac_device_info {
const struct stmmac_hwtimestamp *ptp; const struct stmmac_hwtimestamp *ptp;
const struct stmmac_tc_ops *tc; const struct stmmac_tc_ops *tc;
const struct stmmac_mmc_ops *mmc; const struct stmmac_mmc_ops *mmc;
const struct mdio_xpcs_ops *xpcs; struct mdio_xpcs_args *xpcs;
struct mdio_xpcs_args xpcs_args;
struct mii_regs mii; /* MII register Addresses */ struct mii_regs mii; /* MII register Addresses */
struct mac_link link; struct mac_link link;
void __iomem *pcsr; /* vpointer to device CSRs */ void __iomem *pcsr; /* vpointer to device CSRs */
......
...@@ -613,20 +613,6 @@ struct stmmac_mmc_ops { ...@@ -613,20 +613,6 @@ struct stmmac_mmc_ops {
#define stmmac_mmc_read(__priv, __args...) \ #define stmmac_mmc_read(__priv, __args...) \
stmmac_do_void_callback(__priv, mmc, read, __args) stmmac_do_void_callback(__priv, mmc, read, __args)
/* XPCS callbacks */
#define stmmac_xpcs_validate(__priv, __args...) \
stmmac_do_callback(__priv, xpcs, validate, __args)
#define stmmac_xpcs_config(__priv, __args...) \
stmmac_do_callback(__priv, xpcs, config, __args)
#define stmmac_xpcs_get_state(__priv, __args...) \
stmmac_do_callback(__priv, xpcs, get_state, __args)
#define stmmac_xpcs_link_up(__priv, __args...) \
stmmac_do_callback(__priv, xpcs, link_up, __args)
#define stmmac_xpcs_probe(__priv, __args...) \
stmmac_do_callback(__priv, xpcs, probe, __args)
#define stmmac_xpcs_config_eee(__priv, __args...) \
stmmac_do_callback(__priv, xpcs, config_eee, __args)
struct stmmac_regs_off { struct stmmac_regs_off {
u32 ptp_off; u32 ptp_off;
u32 mmc_off; u32 mmc_off;
......
...@@ -720,11 +720,13 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev, ...@@ -720,11 +720,13 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
netdev_warn(priv->dev, netdev_warn(priv->dev,
"Setting EEE tx-lpi is not supported\n"); "Setting EEE tx-lpi is not supported\n");
ret = stmmac_xpcs_config_eee(priv, &priv->hw->xpcs_args, if (priv->hw->xpcs) {
ret = xpcs_config_eee(priv->hw->xpcs,
priv->plat->mult_fact_100ns, priv->plat->mult_fact_100ns,
edata->eee_enabled); edata->eee_enabled);
if (ret) if (ret)
return ret; return ret;
}
if (!edata->eee_enabled) if (!edata->eee_enabled)
stmmac_disable_eee_mode(priv); stmmac_disable_eee_mode(priv);
......
...@@ -996,29 +996,14 @@ static void stmmac_validate(struct phylink_config *config, ...@@ -996,29 +996,14 @@ static void stmmac_validate(struct phylink_config *config,
linkmode_andnot(state->advertising, state->advertising, mask); linkmode_andnot(state->advertising, state->advertising, mask);
/* If PCS is supported, check which modes it supports. */ /* If PCS is supported, check which modes it supports. */
stmmac_xpcs_validate(priv, &priv->hw->xpcs_args, supported, state); if (priv->hw->xpcs)
} xpcs_validate(priv->hw->xpcs, supported, state);
static void stmmac_mac_pcs_get_state(struct phylink_config *config,
struct phylink_link_state *state)
{
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
state->link = 0;
stmmac_xpcs_get_state(priv, &priv->hw->xpcs_args, state);
} }
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode, static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state) const struct phylink_link_state *state)
{ {
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); /* Nothing to do, xpcs_config() handles everything */
stmmac_xpcs_config(priv, &priv->hw->xpcs_args, state);
}
static void stmmac_mac_an_restart(struct phylink_config *config)
{
/* Not Supported */
} }
static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up) static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
...@@ -1060,8 +1045,6 @@ static void stmmac_mac_link_up(struct phylink_config *config, ...@@ -1060,8 +1045,6 @@ static void stmmac_mac_link_up(struct phylink_config *config,
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
u32 ctrl; u32 ctrl;
stmmac_xpcs_link_up(priv, &priv->hw->xpcs_args, speed, interface);
ctrl = readl(priv->ioaddr + MAC_CTRL_REG); ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
ctrl &= ~priv->hw->link.speed_mask; ctrl &= ~priv->hw->link.speed_mask;
...@@ -1154,9 +1137,7 @@ static void stmmac_mac_link_up(struct phylink_config *config, ...@@ -1154,9 +1137,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
static const struct phylink_mac_ops stmmac_phylink_mac_ops = { static const struct phylink_mac_ops stmmac_phylink_mac_ops = {
.validate = stmmac_validate, .validate = stmmac_validate,
.mac_pcs_get_state = stmmac_mac_pcs_get_state,
.mac_config = stmmac_mac_config, .mac_config = stmmac_mac_config,
.mac_an_restart = stmmac_mac_an_restart,
.mac_link_down = stmmac_mac_link_down, .mac_link_down = stmmac_mac_link_down,
.mac_link_up = stmmac_mac_link_up, .mac_link_up = stmmac_mac_link_up,
}; };
...@@ -1233,6 +1214,7 @@ static int stmmac_init_phy(struct net_device *dev) ...@@ -1233,6 +1214,7 @@ static int stmmac_init_phy(struct net_device *dev)
static int stmmac_phy_setup(struct stmmac_priv *priv) static int stmmac_phy_setup(struct stmmac_priv *priv)
{ {
struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node);
int mode = priv->plat->phy_interface; int mode = priv->plat->phy_interface;
struct phylink *phylink; struct phylink *phylink;
...@@ -1240,8 +1222,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) ...@@ -1240,8 +1222,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
priv->phylink_config.dev = &priv->dev->dev; priv->phylink_config.dev = &priv->dev->dev;
priv->phylink_config.type = PHYLINK_NETDEV; priv->phylink_config.type = PHYLINK_NETDEV;
priv->phylink_config.pcs_poll = true; priv->phylink_config.pcs_poll = true;
priv->phylink_config.ovr_an_inband = priv->phylink_config.ovr_an_inband = mdio_bus_data->xpcs_an_inband;
priv->plat->mdio_bus_data->xpcs_an_inband;
if (!fwnode) if (!fwnode)
fwnode = dev_fwnode(priv->device); fwnode = dev_fwnode(priv->device);
...@@ -1251,6 +1232,12 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) ...@@ -1251,6 +1232,12 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
if (IS_ERR(phylink)) if (IS_ERR(phylink))
return PTR_ERR(phylink); return PTR_ERR(phylink);
if (mdio_bus_data->has_xpcs) {
struct mdio_xpcs_args *xpcs = priv->hw->xpcs;
phylink_set_pcs(phylink, &xpcs->pcs);
}
priv->phylink = phylink; priv->phylink = phylink;
return 0; return 0;
} }
...@@ -3638,6 +3625,7 @@ static int stmmac_request_irq(struct net_device *dev) ...@@ -3638,6 +3625,7 @@ static int stmmac_request_irq(struct net_device *dev)
int stmmac_open(struct net_device *dev) int stmmac_open(struct net_device *dev)
{ {
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(dev);
int mode = priv->plat->phy_interface;
int bfsize = 0; int bfsize = 0;
u32 chan; u32 chan;
int ret; int ret;
...@@ -3650,7 +3638,8 @@ int stmmac_open(struct net_device *dev) ...@@ -3650,7 +3638,8 @@ int stmmac_open(struct net_device *dev)
if (priv->hw->pcs != STMMAC_PCS_TBI && if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI && priv->hw->pcs != STMMAC_PCS_RTBI &&
priv->hw->xpcs_args.an_mode != DW_AN_C73) { (!priv->hw->xpcs ||
xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73)) {
ret = stmmac_init_phy(dev); ret = stmmac_init_phy(dev);
if (ret) { if (ret) {
netdev_err(priv->dev, netdev_err(priv->dev,
......
...@@ -444,14 +444,6 @@ int stmmac_mdio_register(struct net_device *ndev) ...@@ -444,14 +444,6 @@ int stmmac_mdio_register(struct net_device *ndev)
max_addr = PHY_MAX_ADDR; max_addr = PHY_MAX_ADDR;
} }
if (mdio_bus_data->has_xpcs) {
priv->hw->xpcs = mdio_xpcs_get_ops();
if (!priv->hw->xpcs) {
err = -ENODEV;
goto bus_register_fail;
}
}
if (mdio_bus_data->needs_reset) if (mdio_bus_data->needs_reset)
new_bus->reset = &stmmac_mdio_reset; new_bus->reset = &stmmac_mdio_reset;
...@@ -510,25 +502,27 @@ int stmmac_mdio_register(struct net_device *ndev) ...@@ -510,25 +502,27 @@ int stmmac_mdio_register(struct net_device *ndev)
} }
/* Try to probe the XPCS by scanning all addresses. */ /* Try to probe the XPCS by scanning all addresses. */
if (priv->hw->xpcs) { if (mdio_bus_data->has_xpcs) {
struct mdio_xpcs_args *xpcs = &priv->hw->xpcs_args; int mode = priv->plat->phy_interface;
int ret, mode = priv->plat->phy_interface; struct mdio_device *mdiodev;
max_addr = PHY_MAX_ADDR; struct mdio_xpcs_args *xpcs;
xpcs->bus = new_bus; for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
mdiodev = mdio_device_create(new_bus, addr);
if (IS_ERR(mdiodev))
continue;
found = 0; xpcs = xpcs_create(mdiodev, mode);
for (addr = 0; addr < max_addr; addr++) { if (IS_ERR_OR_NULL(xpcs)) {
xpcs->addr = addr; mdio_device_free(mdiodev);
continue;
}
ret = stmmac_xpcs_probe(priv, xpcs, mode); priv->hw->xpcs = xpcs;
if (!ret) {
found = 1;
break; break;
} }
}
if (!found && !mdio_node) { if (!priv->hw->xpcs) {
dev_warn(dev, "No XPCS found\n"); dev_warn(dev, "No XPCS found\n");
err = -ENODEV; err = -ENODEV;
goto no_xpcs_found; goto no_xpcs_found;
...@@ -560,6 +554,11 @@ int stmmac_mdio_unregister(struct net_device *ndev) ...@@ -560,6 +554,11 @@ int stmmac_mdio_unregister(struct net_device *ndev)
if (!priv->mii) if (!priv->mii)
return 0; return 0;
if (priv->hw->xpcs) {
mdio_device_free(priv->hw->xpcs->mdiodev);
xpcs_destroy(priv->hw->xpcs);
}
mdiobus_unregister(priv->mii); mdiobus_unregister(priv->mii);
priv->mii->priv = NULL; priv->mii->priv = NULL;
mdiobus_free(priv->mii); mdiobus_free(priv->mii);
......
This diff is collapsed.
...@@ -14,35 +14,21 @@ ...@@ -14,35 +14,21 @@
#define DW_AN_C73 1 #define DW_AN_C73 1
#define DW_AN_C37_SGMII 2 #define DW_AN_C37_SGMII 2
struct xpcs_id;
struct mdio_xpcs_args { struct mdio_xpcs_args {
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported); struct mdio_device *mdiodev;
struct mii_bus *bus; const struct xpcs_id *id;
int addr; struct phylink_pcs pcs;
int an_mode;
}; };
struct mdio_xpcs_ops { int xpcs_get_an_mode(struct mdio_xpcs_args *xpcs, phy_interface_t interface);
int (*validate)(struct mdio_xpcs_args *xpcs, void xpcs_validate(struct mdio_xpcs_args *xpcs, unsigned long *supported,
unsigned long *supported,
struct phylink_link_state *state);
int (*config)(struct mdio_xpcs_args *xpcs,
const struct phylink_link_state *state);
int (*get_state)(struct mdio_xpcs_args *xpcs,
struct phylink_link_state *state); struct phylink_link_state *state);
int (*link_up)(struct mdio_xpcs_args *xpcs, int speed, int xpcs_config_eee(struct mdio_xpcs_args *xpcs, int mult_fact_100ns,
phy_interface_t interface);
int (*probe)(struct mdio_xpcs_args *xpcs, phy_interface_t interface);
int (*config_eee)(struct mdio_xpcs_args *xpcs, int mult_fact_100ns,
int enable); int enable);
}; struct mdio_xpcs_args *xpcs_create(struct mdio_device *mdiodev,
phy_interface_t interface);
#if IS_ENABLED(CONFIG_PCS_XPCS) void xpcs_destroy(struct mdio_xpcs_args *xpcs);
struct mdio_xpcs_ops *mdio_xpcs_get_ops(void);
#else
static inline struct mdio_xpcs_ops *mdio_xpcs_get_ops(void)
{
return NULL;
}
#endif
#endif /* __LINUX_PCS_XPCS_H */ #endif /* __LINUX_PCS_XPCS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment