Tue, Oct 13, 2020 at 03:48:47PM CEST, vladimir.olt...@nxp.com wrote: >Add devlink integration into the mscc_ocelot switchdev driver. Only the >probed interfaces are registered with devlink, because for convenience, >struct devlink_port was included into struct ocelot_port_private, which >is only initialized for the ports that are used. > >Note that the felix DSA driver is already integrated with devlink by >default, since that is a thing that the DSA core takes care of. > >Signed-off-by: Vladimir Oltean <vladimir.olt...@nxp.com> >--- > drivers/net/ethernet/mscc/ocelot.h | 4 + > drivers/net/ethernet/mscc/ocelot_net.c | 92 ++++++++++++++++++++++ > drivers/net/ethernet/mscc/ocelot_vsc7514.c | 7 ++ > include/soc/mscc/ocelot.h | 1 + > 4 files changed, 104 insertions(+) > >diff --git a/drivers/net/ethernet/mscc/ocelot.h >b/drivers/net/ethernet/mscc/ocelot.h >index 8eae68e0fd0b..3fee5f565920 100644 >--- a/drivers/net/ethernet/mscc/ocelot.h >+++ b/drivers/net/ethernet/mscc/ocelot.h >@@ -65,6 +65,8 @@ struct ocelot_port_private { > struct phy *serdes; > > struct ocelot_port_tc tc; >+ >+ struct devlink_port devlink_port; > }; > > struct ocelot_dump_ctx { >@@ -106,6 +108,8 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, >u32 reg); > > int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target, > struct phy_device *phy); >+int ocelot_devlink_init(struct ocelot *ocelot); >+void ocelot_devlink_teardown(struct ocelot *ocelot); > > extern struct notifier_block ocelot_netdevice_nb; > extern struct notifier_block ocelot_switchdev_nb; >diff --git a/drivers/net/ethernet/mscc/ocelot_net.c >b/drivers/net/ethernet/mscc/ocelot_net.c >index d3c03942546d..a11e5e7a0228 100644 >--- a/drivers/net/ethernet/mscc/ocelot_net.c >+++ b/drivers/net/ethernet/mscc/ocelot_net.c >@@ -8,6 +8,98 @@ > #include "ocelot.h" > #include "ocelot_vcap.h" > >+struct ocelot_devlink_private { >+ struct ocelot *ocelot; >+}; >+ >+static const struct devlink_ops ocelot_devlink_ops = { >+}; >+ >+static int ocelot_port_devlink_init(struct ocelot *ocelot, int port) >+{ >+ struct ocelot_port *ocelot_port = ocelot->ports[port]; >+ struct devlink *dl = ocelot->devlink; >+ struct devlink_port_attrs attrs = {}; >+ struct ocelot_port_private *priv; >+ struct devlink_port *dlp; >+ >+ if (!ocelot_port) >+ return 0; >+ >+ priv = container_of(ocelot_port, struct ocelot_port_private, port); >+ dlp = &priv->devlink_port; >+ >+ attrs.phys.port_number = port; >+ >+ if (priv->dev) >+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; >+ else >+ attrs.flavour = DEVLINK_PORT_FLAVOUR_UNUSED; >+ >+ devlink_port_attrs_set(dlp, &attrs); >+ >+ return devlink_port_register(dl, dlp, port);
You are missing devlink_port_type_eth_set() >+} >+ >+static void ocelot_port_devlink_teardown(struct ocelot *ocelot, int port) >+{ >+ struct ocelot_port *ocelot_port = ocelot->ports[port]; >+ struct ocelot_port_private *priv; >+ struct devlink_port *dlp; >+ >+ if (!ocelot_port) >+ return; >+ >+ priv = container_of(ocelot_port, struct ocelot_port_private, port); >+ dlp = &priv->devlink_port; >+ >+ devlink_port_unregister(dlp); >+} >+ >+int ocelot_devlink_init(struct ocelot *ocelot) >+{ >+ struct ocelot_devlink_private *dl_priv; >+ int port, err; >+ >+ ocelot->devlink = devlink_alloc(&ocelot_devlink_ops, sizeof(*dl_priv)); >+ if (!ocelot->devlink) >+ return -ENOMEM; >+ dl_priv = devlink_priv(ocelot->devlink); >+ dl_priv->ocelot = ocelot; >+ >+ err = devlink_register(ocelot->devlink, ocelot->dev); >+ if (err) >+ goto free_devlink; >+ >+ for (port = 0; port < ocelot->num_phys_ports; port++) { >+ err = ocelot_port_devlink_init(ocelot, port); >+ if (err) { >+ while (port-- > 0) >+ ocelot_port_devlink_teardown(ocelot, port); >+ goto unregister_devlink; >+ } >+ } >+ >+ return 0; >+ >+unregister_devlink: >+ devlink_unregister(ocelot->devlink); >+free_devlink: >+ devlink_free(ocelot->devlink); >+ return err; >+} >+ >+void ocelot_devlink_teardown(struct ocelot *ocelot) >+{ >+ int port; >+ >+ for (port = 0; port < ocelot->num_phys_ports; port++) >+ ocelot_port_devlink_teardown(ocelot, port); >+ >+ devlink_unregister(ocelot->devlink); >+ devlink_free(ocelot->devlink); >+} >+ > int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv, > struct flow_cls_offload *f, > bool ingress) >diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c >b/drivers/net/ethernet/mscc/ocelot_vsc7514.c >index ea55f4d20ecc..6512ddeafd50 100644 >--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c >+++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c >@@ -1292,6 +1292,12 @@ static int mscc_ocelot_probe(struct platform_device >*pdev) > } > } > >+ err = ocelot_devlink_init(ocelot); >+ if (err) { >+ mscc_ocelot_release_ports(ocelot); >+ goto out_put_ports; >+ } >+ > register_netdevice_notifier(&ocelot_netdevice_nb); > register_switchdev_notifier(&ocelot_switchdev_nb); > register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb); >@@ -1307,6 +1313,7 @@ static int mscc_ocelot_remove(struct platform_device >*pdev) > { > struct ocelot *ocelot = platform_get_drvdata(pdev); > >+ ocelot_devlink_teardown(ocelot); > ocelot_deinit_timestamp(ocelot); > mscc_ocelot_release_ports(ocelot); > ocelot_deinit(ocelot); >diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h >index c6153c73dbfe..19ce7ea11163 100644 >--- a/include/soc/mscc/ocelot.h >+++ b/include/soc/mscc/ocelot.h >@@ -599,6 +599,7 @@ struct ocelot_port { > > struct ocelot { > struct device *dev; >+ struct devlink *devlink; > > const struct ocelot_ops *ops; > struct regmap *targets[TARGET_MAX]; >-- >2.25.1 >