net: dsa: felix: Add support for MRP
authorHoratiu Vultur <horatiu.vultur@microchip.com>
Tue, 16 Feb 2021 21:42:05 +0000 (22:42 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 16 Feb 2021 22:47:46 +0000 (14:47 -0800)
Implement functions 'port_mrp_add', 'port_mrp_del',
'port_mrp_add_ring_role' and 'port_mrp_del_ring_role' to call the mrp
functions from ocelot.

Also all MRP frames that arrive to CPU on queue number OCELOT_MRP_CPUQ
will be forward by the SW.

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/ocelot/felix.c
net/dsa/tag_ocelot.c

index 4a300ef..628afb4 100644 (file)
@@ -1582,6 +1582,40 @@ static int felix_sb_occ_tc_port_bind_get(struct dsa_switch *ds, int port,
                                              pool_type, p_cur, p_max);
 }
 
+static int felix_mrp_add(struct dsa_switch *ds, int port,
+                        const struct switchdev_obj_mrp *mrp)
+{
+       struct ocelot *ocelot = ds->priv;
+
+       return ocelot_mrp_add(ocelot, port, mrp);
+}
+
+static int felix_mrp_del(struct dsa_switch *ds, int port,
+                        const struct switchdev_obj_mrp *mrp)
+{
+       struct ocelot *ocelot = ds->priv;
+
+       return ocelot_mrp_add(ocelot, port, mrp);
+}
+
+static int
+felix_mrp_add_ring_role(struct dsa_switch *ds, int port,
+                       const struct switchdev_obj_ring_role_mrp *mrp)
+{
+       struct ocelot *ocelot = ds->priv;
+
+       return ocelot_mrp_add_ring_role(ocelot, port, mrp);
+}
+
+static int
+felix_mrp_del_ring_role(struct dsa_switch *ds, int port,
+                       const struct switchdev_obj_ring_role_mrp *mrp)
+{
+       struct ocelot *ocelot = ds->priv;
+
+       return ocelot_mrp_del_ring_role(ocelot, port, mrp);
+}
+
 const struct dsa_switch_ops felix_switch_ops = {
        .get_tag_protocol               = felix_get_tag_protocol,
        .change_tag_protocol            = felix_change_tag_protocol,
@@ -1636,6 +1670,10 @@ const struct dsa_switch_ops felix_switch_ops = {
        .devlink_sb_occ_max_clear       = felix_sb_occ_max_clear,
        .devlink_sb_occ_port_pool_get   = felix_sb_occ_port_pool_get,
        .devlink_sb_occ_tc_port_bind_get= felix_sb_occ_tc_port_bind_get,
+       .port_mrp_add                   = felix_mrp_add,
+       .port_mrp_del                   = felix_mrp_del,
+       .port_mrp_add_ring_role         = felix_mrp_add_ring_role,
+       .port_mrp_del_ring_role         = felix_mrp_del_ring_role,
 };
 
 struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port)
index f9df9ca..743809b 100644 (file)
@@ -83,6 +83,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
        struct dsa_port *dp;
        u8 *extraction;
        u16 vlan_tpid;
+       u64 cpuq;
 
        /* Revert skb->data by the amount consumed by the DSA master,
         * so it points to the beginning of the frame.
@@ -112,6 +113,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
        ocelot_xfh_get_qos_class(extraction, &qos_class);
        ocelot_xfh_get_tag_type(extraction, &tag_type);
        ocelot_xfh_get_vlan_tci(extraction, &vlan_tci);
+       ocelot_xfh_get_cpuq(extraction, &cpuq);
 
        skb->dev = dsa_master_find_slave(netdev, 0, src_port);
        if (!skb->dev)
@@ -126,6 +128,12 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
        skb->offload_fwd_mark = 1;
        skb->priority = qos_class;
 
+#if IS_ENABLED(CONFIG_BRIDGE_MRP)
+       if (eth_hdr(skb)->h_proto == cpu_to_be16(ETH_P_MRP) &&
+           cpuq & BIT(OCELOT_MRP_CPUQ))
+               skb->offload_fwd_mark = 0;
+#endif
+
        /* Ocelot switches copy frames unmodified to the CPU. However, it is
         * possible for the user to request a VLAN modification through
         * VCAP_IS1_ACT_VID_REPLACE_ENA. In this case, what will happen is that