@@ -1365,12 +1365,9 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = {
.pcs_link_up = xpcs_link_up,
};
-static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
- phy_interface_t interface)
+static struct dw_xpcs *xpcs_create_data(struct mdio_device *mdiodev)
{
struct dw_xpcs *xpcs;
- u32 xpcs_id;
- int i, ret;
xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
if (!xpcs)
@@ -1378,59 +1375,89 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
mdio_device_get(mdiodev);
xpcs->mdiodev = mdiodev;
+ xpcs->pcs.ops = &xpcs_phylink_ops;
+ xpcs->pcs.neg_mode = true;
+ xpcs->pcs.poll = true;
+
+ return xpcs;
+}
+
+static void xpcs_free_data(struct dw_xpcs *xpcs)
+{
+ mdio_device_put(xpcs->mdiodev);
+ kfree(xpcs);
+}
+
+static int xpcs_init_id(struct dw_xpcs *xpcs)
+{
+ u32 xpcs_id;
+ int i, ret;
xpcs_id = xpcs_get_id(xpcs);
for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
const struct xpcs_id *entry = &xpcs_id_list[i];
- const struct xpcs_compat *compat;
if ((xpcs_id & entry->mask) != entry->id)
continue;
xpcs->id = entry;
- compat = xpcs_find_compat(entry, interface);
- if (!compat) {
- ret = -ENODEV;
- goto out;
- }
+ break;
+ }
- ret = xpcs_dev_flag(xpcs);
- if (ret)
- goto out;
+ if (!xpcs->id)
+ return -ENODEV;
- xpcs->pcs.ops = &xpcs_phylink_ops;
- xpcs->pcs.neg_mode = true;
+ ret = xpcs_dev_flag(xpcs);
+ if (ret < 0)
+ return ret;
- if (xpcs->dev_flag != DW_DEV_TXGBE) {
- xpcs->pcs.poll = true;
+ return 0;
+}
- ret = xpcs_soft_reset(xpcs, compat);
- if (ret)
- goto out;
- }
+static int xpcs_init_iface(struct dw_xpcs *xpcs, phy_interface_t interface)
+{
+ const struct xpcs_compat *compat;
- return xpcs;
+ compat = xpcs_find_compat(xpcs->id, interface);
+ if (!compat)
+ return -EINVAL;
+
+ if (xpcs->dev_flag == DW_DEV_TXGBE) {
+ xpcs->pcs.poll = false;
+ return 0;
}
- ret = -ENODEV;
+ return xpcs_soft_reset(xpcs, compat);
+}
+
+static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
+ phy_interface_t interface)
+{
+ struct dw_xpcs *xpcs;
+ int ret;
+
+ xpcs = xpcs_create_data(mdiodev);
+ if (IS_ERR(xpcs))
+ return xpcs;
+
+ ret = xpcs_init_id(xpcs);
+ if (ret)
+ goto out;
+
+ ret = xpcs_init_iface(xpcs, interface);
+ if (ret)
+ goto out;
+
+ return xpcs;
out:
- mdio_device_put(mdiodev);
- kfree(xpcs);
+ xpcs_free_data(xpcs);
return ERR_PTR(ret);
}
-void xpcs_destroy(struct dw_xpcs *xpcs)
-{
- if (xpcs)
- mdio_device_put(xpcs->mdiodev);
- kfree(xpcs);
-}
-EXPORT_SYMBOL_GPL(xpcs_destroy);
-
struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
phy_interface_t interface)
{
@@ -1455,5 +1482,14 @@ struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
}
EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
+void xpcs_destroy(struct dw_xpcs *xpcs)
+{
+ if (!xpcs)
+ return;
+
+ xpcs_free_data(xpcs);
+}
+EXPORT_SYMBOL_GPL(xpcs_destroy);
+
MODULE_DESCRIPTION("Synopsys DesignWare XPCS library");
MODULE_LICENSE("GPL v2");