]> Git Repo - linux.git/blobdiff - drivers/net/dsa/dsa_loop.c
enetc: Migrate to PHYLINK and PCS_LYNX
[linux.git] / drivers / net / dsa / dsa_loop.c
index 400207c5c7dedb5c9ea1da84e5657253aac4fc96..e38906ae8f235d24b47f676eb9a0e7b060fbc22f 100644 (file)
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/if_bridge.h>
+#include <linux/dsa/loop.h>
 #include <net/dsa.h>
 
 #include "dsa_loop.h"
 
-struct dsa_loop_vlan {
-       u16 members;
-       u16 untagged;
-};
-
-struct dsa_loop_mib_entry {
-       char name[ETH_GSTRING_LEN];
-       unsigned long val;
-};
-
-enum dsa_loop_mib_counters {
-       DSA_LOOP_PHY_READ_OK,
-       DSA_LOOP_PHY_READ_ERR,
-       DSA_LOOP_PHY_WRITE_OK,
-       DSA_LOOP_PHY_WRITE_ERR,
-       __DSA_LOOP_CNT_MAX,
-};
-
 static struct dsa_loop_mib_entry dsa_loop_mibs[] = {
        [DSA_LOOP_PHY_READ_OK]  = { "phy_read_ok", },
        [DSA_LOOP_PHY_READ_ERR] = { "phy_read_err", },
@@ -43,22 +26,54 @@ static struct dsa_loop_mib_entry dsa_loop_mibs[] = {
        [DSA_LOOP_PHY_WRITE_ERR] = { "phy_write_err", },
 };
 
-struct dsa_loop_port {
-       struct dsa_loop_mib_entry mib[__DSA_LOOP_CNT_MAX];
+static struct phy_device *phydevs[PHY_MAX_ADDR];
+
+enum dsa_loop_devlink_resource_id {
+       DSA_LOOP_DEVLINK_PARAM_ID_VTU,
 };
 
-#define DSA_LOOP_VLANS 5
+static u64 dsa_loop_devlink_vtu_get(void *priv)
+{
+       struct dsa_loop_priv *ps = priv;
+       unsigned int i, count = 0;
+       struct dsa_loop_vlan *vl;
 
-struct dsa_loop_priv {
-       struct mii_bus  *bus;
-       unsigned int    port_base;
-       struct dsa_loop_vlan vlans[DSA_LOOP_VLANS];
-       struct net_device *netdev;
-       struct dsa_loop_port ports[DSA_MAX_PORTS];
-       u16 pvid;
-};
+       for (i = 0; i < ARRAY_SIZE(ps->vlans); i++) {
+               vl = &ps->vlans[i];
+               if (vl->members)
+                       count++;
+       }
 
-static struct phy_device *phydevs[PHY_MAX_ADDR];
+       return count;
+}
+
+static int dsa_loop_setup_devlink_resources(struct dsa_switch *ds)
+{
+       struct devlink_resource_size_params size_params;
+       struct dsa_loop_priv *ps = ds->priv;
+       int err;
+
+       devlink_resource_size_params_init(&size_params, ARRAY_SIZE(ps->vlans),
+                                         ARRAY_SIZE(ps->vlans),
+                                         1, DEVLINK_RESOURCE_UNIT_ENTRY);
+
+       err = dsa_devlink_resource_register(ds, "VTU", ARRAY_SIZE(ps->vlans),
+                                           DSA_LOOP_DEVLINK_PARAM_ID_VTU,
+                                           DEVLINK_RESOURCE_ID_PARENT_TOP,
+                                           &size_params);
+       if (err)
+               goto out;
+
+       dsa_devlink_resource_occ_get_register(ds,
+                                             DSA_LOOP_DEVLINK_PARAM_ID_VTU,
+                                             dsa_loop_devlink_vtu_get, ps);
+
+       return 0;
+
+out:
+       dsa_devlink_resources_unregister(ds);
+       return err;
+}
 
 static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds,
                                                   int port,
@@ -80,7 +95,12 @@ static int dsa_loop_setup(struct dsa_switch *ds)
 
        dev_dbg(ds->dev, "%s\n", __func__);
 
-       return 0;
+       return dsa_loop_setup_devlink_resources(ds);
+}
+
+static void dsa_loop_teardown(struct dsa_switch *ds)
+{
+       dsa_devlink_resources_unregister(ds);
 }
 
 static int dsa_loop_get_sset_count(struct dsa_switch *ds, int port, int sset)
@@ -170,7 +190,8 @@ static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
 }
 
 static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                       bool vlan_filtering)
+                                       bool vlan_filtering,
+                                       struct switchdev_trans *trans)
 {
        dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
                __func__, port, vlan_filtering);
@@ -191,7 +212,7 @@ dsa_loop_port_vlan_prepare(struct dsa_switch *ds, int port,
        /* Just do a sleeping operation to make lockdep checks effective */
        mdiobus_read(bus, ps->port_base + port, MII_BMSR);
 
-       if (vlan->vid_end > DSA_LOOP_VLANS)
+       if (vlan->vid_end > ARRAY_SIZE(ps->vlans))
                return -ERANGE;
 
        return 0;
@@ -224,7 +245,7 @@ static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
        }
 
        if (pvid)
-               ps->pvid = vid;
+               ps->ports[port].pvid = vid;
 }
 
 static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
@@ -234,7 +255,7 @@ static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
        struct dsa_loop_priv *ps = ds->priv;
        struct mii_bus *bus = ps->bus;
        struct dsa_loop_vlan *vl;
-       u16 vid, pvid = ps->pvid;
+       u16 vid, pvid = ps->ports[port].pvid;
 
        /* Just do a sleeping operation to make lockdep checks effective */
        mdiobus_read(bus, ps->port_base + port, MII_BMSR);
@@ -252,14 +273,30 @@ static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
                dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
                        __func__, port, vid, untagged ? "un" : "", pvid);
        }
-       ps->pvid = pvid;
+       ps->ports[port].pvid = pvid;
+
+       return 0;
+}
+
+static int dsa_loop_port_change_mtu(struct dsa_switch *ds, int port,
+                                   int new_mtu)
+{
+       struct dsa_loop_priv *priv = ds->priv;
+
+       priv->ports[port].mtu = new_mtu;
 
        return 0;
 }
 
+static int dsa_loop_port_max_mtu(struct dsa_switch *ds, int port)
+{
+       return ETH_MAX_MTU;
+}
+
 static const struct dsa_switch_ops dsa_loop_driver = {
        .get_tag_protocol       = dsa_loop_get_protocol,
        .setup                  = dsa_loop_setup,
+       .teardown               = dsa_loop_teardown,
        .get_strings            = dsa_loop_get_strings,
        .get_ethtool_stats      = dsa_loop_get_ethtool_stats,
        .get_sset_count         = dsa_loop_get_sset_count,
@@ -273,6 +310,8 @@ static const struct dsa_switch_ops dsa_loop_driver = {
        .port_vlan_prepare      = dsa_loop_port_vlan_prepare,
        .port_vlan_add          = dsa_loop_port_vlan_add,
        .port_vlan_del          = dsa_loop_port_vlan_del,
+       .port_change_mtu        = dsa_loop_port_change_mtu,
+       .port_max_mtu           = dsa_loop_port_max_mtu,
 };
 
 static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
@@ -280,19 +319,17 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
        struct dsa_loop_pdata *pdata = mdiodev->dev.platform_data;
        struct dsa_loop_priv *ps;
        struct dsa_switch *ds;
+       int ret;
 
        if (!pdata)
                return -ENODEV;
 
-       dev_info(&mdiodev->dev, "%s: 0x%0x\n",
-                pdata->name, pdata->enabled_ports);
-
        ds = devm_kzalloc(&mdiodev->dev, sizeof(*ds), GFP_KERNEL);
        if (!ds)
                return -ENOMEM;
 
        ds->dev = &mdiodev->dev;
-       ds->num_ports = DSA_MAX_PORTS;
+       ds->num_ports = DSA_LOOP_NUM_PORTS;
 
        ps = devm_kzalloc(&mdiodev->dev, sizeof(*ps), GFP_KERNEL);
        if (!ps)
@@ -307,11 +344,17 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
        ds->dev = &mdiodev->dev;
        ds->ops = &dsa_loop_driver;
        ds->priv = ps;
+       ds->configure_vlan_while_not_filtering = true;
        ps->bus = mdiodev->bus;
 
        dev_set_drvdata(&mdiodev->dev, ds);
 
-       return dsa_register_switch(ds);
+       ret = dsa_register_switch(ds);
+       if (!ret)
+               dev_info(&mdiodev->dev, "%s: 0x%0x\n",
+                        pdata->name, pdata->enabled_ports);
+
+       return ret;
 }
 
 static void dsa_loop_drv_remove(struct mdio_device *mdiodev)
This page took 0.038619 seconds and 4 git commands to generate.