@@ -503,7 +503,7 @@ struct mac_device_info {
const struct stmmac_hwtimestamp *ptp;
const struct stmmac_tc_ops *tc;
const struct stmmac_mmc_ops *mmc;
- struct mdio_xpcs_args xpcs_args;
+ struct mdio_xpcs_args *xpcs;
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
void __iomem *pcsr; /* vpointer to device CSRs */
@@ -720,8 +720,7 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
netdev_warn(priv->dev,
"Setting EEE tx-lpi is not supported\n");
- ret = xpcs_config_eee(&priv->hw->xpcs_args,
- priv->plat->mult_fact_100ns,
+ ret = xpcs_config_eee(priv->hw->xpcs, priv->plat->mult_fact_100ns,
edata->eee_enabled);
if (ret)
return ret;
@@ -996,7 +996,7 @@ static void stmmac_validate(struct phylink_config *config,
linkmode_andnot(state->advertising, state->advertising, mask);
/* If PCS is supported, check which modes it supports. */
- xpcs_validate(&priv->hw->xpcs_args, supported, state);
+ xpcs_validate(priv->hw->xpcs, supported, state);
}
static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
@@ -1222,7 +1222,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
return PTR_ERR(phylink);
if (mdio_bus_data->has_xpcs) {
- struct mdio_xpcs_args *xpcs = &priv->hw->xpcs_args;
+ struct mdio_xpcs_args *xpcs = priv->hw->xpcs;
phylink_set_pcs(phylink, &xpcs->pcs);
}
@@ -3625,7 +3625,7 @@ int stmmac_open(struct net_device *dev)
if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI &&
- priv->hw->xpcs_args.an_mode != DW_AN_C73) {
+ priv->hw->xpcs->an_mode != DW_AN_C73) {
ret = stmmac_init_phy(dev);
if (ret) {
netdev_err(priv->dev,
@@ -503,25 +503,25 @@ int stmmac_mdio_register(struct net_device *ndev)
/* Try to probe the XPCS by scanning all addresses. */
if (mdio_bus_data->has_xpcs) {
- struct mdio_xpcs_args *xpcs = &priv->hw->xpcs_args;
- int ret;
-
- max_addr = PHY_MAX_ADDR;
-
- xpcs->bus = new_bus;
-
- found = 0;
- for (addr = 0; addr < max_addr; addr++) {
- xpcs->addr = addr;
-
- ret = xpcs_probe(xpcs);
- if (!ret) {
- found = 1;
- break;
+ struct mdio_device *mdiodev;
+ struct mdio_xpcs_args *xpcs;
+
+ for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
+ mdiodev = mdio_device_create(new_bus, addr);
+ if (IS_ERR(mdiodev))
+ continue;
+
+ xpcs = xpcs_create(mdiodev);
+ if (IS_ERR_OR_NULL(xpcs)) {
+ mdio_device_free(mdiodev);
+ continue;
}
+
+ priv->hw->xpcs = xpcs;
+ break;
}
- if (!found && !mdio_node) {
+ if (!priv->hw->xpcs) {
dev_warn(dev, "No XPCS found\n");
err = -ENODEV;
goto no_xpcs_found;
@@ -221,15 +221,19 @@ static struct xpcs_id {
static int xpcs_read(struct mdio_xpcs_args *xpcs, int dev, u32 reg)
{
u32 reg_addr = mdiobus_c45_addr(dev, reg);
+ struct mii_bus *bus = xpcs->mdiodev->bus;
+ int addr = xpcs->mdiodev->addr;
- return mdiobus_read(xpcs->bus, xpcs->addr, reg_addr);
+ return mdiobus_read(bus, addr, reg_addr);
}
static int xpcs_write(struct mdio_xpcs_args *xpcs, int dev, u32 reg, u16 val)
{
u32 reg_addr = mdiobus_c45_addr(dev, reg);
+ struct mii_bus *bus = xpcs->mdiodev->bus;
+ int addr = xpcs->mdiodev->addr;
- return mdiobus_write(xpcs->bus, xpcs->addr, reg_addr, val);
+ return mdiobus_write(bus, addr, reg_addr, val);
}
static int xpcs_read_vendor(struct mdio_xpcs_args *xpcs, int dev, u32 reg)
@@ -294,7 +298,7 @@ static int xpcs_soft_reset(struct mdio_xpcs_args *xpcs)
#define xpcs_warn(__xpcs, __state, __args...) \
({ \
if ((__state)->link) \
- dev_warn(&(__xpcs)->bus->dev, ##__args); \
+ dev_warn(&(__xpcs)->mdiodev->dev, ##__args); \
})
static int xpcs_read_fault_c73(struct mdio_xpcs_args *xpcs,
@@ -963,10 +967,19 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = {
.pcs_link_up = xpcs_link_up,
};
-int xpcs_probe(struct mdio_xpcs_args *xpcs)
+struct mdio_xpcs_args *xpcs_create(struct mdio_device *mdiodev)
{
- u32 xpcs_id = xpcs_get_id(xpcs);
- int i;
+ struct mdio_xpcs_args *xpcs;
+ u32 xpcs_id;
+ int i, ret;
+
+ xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
+ if (!xpcs)
+ return NULL;
+
+ xpcs->mdiodev = mdiodev;
+
+ xpcs_id = xpcs_get_id(xpcs);
for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
struct xpcs_id *entry = &xpcs_id_list[i];
@@ -983,11 +996,20 @@ int xpcs_probe(struct mdio_xpcs_args *xpcs)
xpcs->pcs.ops = &xpcs_phylink_ops;
xpcs->pcs.poll = true;
- return xpcs_soft_reset(xpcs);
+ ret = xpcs_soft_reset(xpcs);
+ if (ret)
+ goto out;
+
+ return xpcs;
}
- return -ENODEV;
+ ret = -ENODEV;
+
+out:
+ kfree(xpcs);
+
+ return ERR_PTR(ret);
}
-EXPORT_SYMBOL_GPL(xpcs_probe);
+EXPORT_SYMBOL_GPL(xpcs_create);
MODULE_LICENSE("GPL v2");
@@ -18,10 +18,9 @@ struct xpcs_id;
struct mdio_xpcs_args {
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
+ struct mdio_device *mdiodev;
struct phylink_pcs pcs;
- struct mii_bus *bus;
struct xpcs_id *id;
- int addr;
int an_mode;
};
@@ -29,6 +28,6 @@ void xpcs_validate(struct mdio_xpcs_args *xpcs, unsigned long *supported,
struct phylink_link_state *state);
int xpcs_config_eee(struct mdio_xpcs_args *xpcs, int mult_fact_100ns,
int enable);
-int xpcs_probe(struct mdio_xpcs_args *xpcs);
+struct mdio_xpcs_args *xpcs_create(struct mdio_device *mdiodev);
#endif /* __LINUX_PCS_XPCS_H */