All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver
@ 2020-08-07 11:13 hongbo.wang
  2020-08-07 11:13 ` [PATCH v5 1/2] net: dsa: Add protocol support for 802.1AD when adding or deleting vlan for dsa switch port hongbo.wang
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: hongbo.wang @ 2020-08-07 11:13 UTC (permalink / raw)
  To: xiaoliang.yang_1, allan.nielsen, po.liu, claudiu.manoil,
	alexandru.marginean, vladimir.oltean, leoyang.li, mingkai.hu,
	andrew, f.fainelli, vivien.didelot, davem, jiri, idosch, kuba,
	vinicius.gomes, nikolay, roopa, netdev, linux-kernel,
	horatiu.vultur, alexandre.belloni, UNGLinuxDriver, ivecera
  Cc: hongbo.wang

From: "hongbo.wang" <hongbo.wang@nxp.com>

1. the patch 0001* is for setting single port into 802.1AD(QinQ) mode,
before this patch, the function dsa_slave_vlan_rx_add_vid didn't pass 
the parameter "proto" to next port level, so switch's port can't get
parameter "proto"
  after applying this patch, the following command can be supported:
  ip link set br0 type bridge vlan_protocol 802.1ad
  ip link add link swp1 name swp1.100 type vlan protocol 802.1ad id 100

2. the patch 0002* is for setting QinQ related registers in ocelot 
switch driver, after applying this patch, the switch(VSC99599)'s port can
enable or disable QinQ mode.

3. Version log
v5:
a. add devlink to enable qinq_mode of ocelot's single port
b. modify br_switchdev_port_vlan_add to pass bridge's vlan_proto to port driver
c. enable NETIF_F_HW_VLAN_STAG_FILTER in ocelot driver
v4:
a. modify slave.c to support "ip set br0 type bridge vlan_protocol 802.1ad"
b. modify ocelot.c, if enable QinQ, set VLAN_AWARE_ENA and VLAN_POP_CNT per
   port when vlan_filter=1
v3: combine two patches to one post

hongbo.wang (2):
  net: dsa: Add protocol support for 802.1AD when adding or  deleting
    vlan for dsa switch port
  net: dsa: ocelot: Add support for QinQ Operation

 drivers/net/dsa/ocelot/felix.c     | 124 +++++++++++++++++++++++++++++
 drivers/net/ethernet/mscc/ocelot.c |  40 ++++++++--
 include/net/switchdev.h            |   1 +
 include/soc/mscc/ocelot.h          |   4 +
 net/bridge/br_switchdev.c          |  22 +++++
 net/dsa/dsa_priv.h                 |   4 +-
 net/dsa/port.c                     |   6 +-
 net/dsa/slave.c                    |  53 +++++++-----
 net/dsa/tag_8021q.c                |   4 +-
 9 files changed, 228 insertions(+), 30 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v5 1/2] net: dsa: Add protocol support for 802.1AD when adding or  deleting vlan for dsa switch port
  2020-08-07 11:13 [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver hongbo.wang
@ 2020-08-07 11:13 ` hongbo.wang
  2020-08-07 11:25   ` Nikolay Aleksandrov
  2020-08-07 11:13 ` [PATCH v5 2/2] net: dsa: ocelot: Add support for QinQ Operation hongbo.wang
  2020-08-08  0:24 ` [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver David Miller
  2 siblings, 1 reply; 5+ messages in thread
From: hongbo.wang @ 2020-08-07 11:13 UTC (permalink / raw)
  To: xiaoliang.yang_1, allan.nielsen, po.liu, claudiu.manoil,
	alexandru.marginean, vladimir.oltean, leoyang.li, mingkai.hu,
	andrew, f.fainelli, vivien.didelot, davem, jiri, idosch, kuba,
	vinicius.gomes, nikolay, roopa, netdev, linux-kernel,
	horatiu.vultur, alexandre.belloni, UNGLinuxDriver, ivecera
  Cc: hongbo.wang

From: "hongbo.wang" <hongbo.wang@nxp.com>

the following command will be supported:

Set bridge's vlan protocol:
    ip link set br0 type bridge vlan_protocol 802.1ad
Add VLAN:
    ip link add link swp1 name swp1.100 type vlan protocol 802.1ad id 100
Delete VLAN:
    ip link del link swp1 name swp1.100

Signed-off-by: hongbo.wang <hongbo.wang@nxp.com>
---
 include/net/switchdev.h   |  1 +
 net/bridge/br_switchdev.c | 22 ++++++++++++++++
 net/dsa/dsa_priv.h        |  4 +--
 net/dsa/port.c            |  6 +++--
 net/dsa/slave.c           | 53 ++++++++++++++++++++++++++-------------
 net/dsa/tag_8021q.c       |  4 +--
 6 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index ff2246914301..7594ea82879f 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -97,6 +97,7 @@ struct switchdev_obj_port_vlan {
 	u16 flags;
 	u16 vid_begin;
 	u16 vid_end;
+	u16 proto;
 };
 
 #define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 015209bf44aa..bcfa00d6d5eb 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -146,6 +146,26 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
 	}
 }
 
+static u16 br_switchdev_get_bridge_vlan_proto(struct net_device *dev)
+{
+	u16 vlan_proto = ETH_P_8021Q;
+	struct net_device *br = NULL;
+	struct net_bridge_port *p;
+
+	if (netif_is_bridge_master(dev)) {
+		br = dev;
+	} else if (netif_is_bridge_port(dev)) {
+		p = br_port_get_rcu(dev);
+		if (p && p->br)
+			br = p->br->dev;
+	}
+
+	if (br)
+		br_vlan_get_proto(br, &vlan_proto);
+
+	return vlan_proto;
+}
+
 int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
 			       struct netlink_ext_ack *extack)
 {
@@ -157,6 +177,7 @@ int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
 		.vid_end = vid,
 	};
 
+	v.proto = br_switchdev_get_bridge_vlan_proto(dev);
 	return switchdev_port_obj_add(dev, &v.obj, extack);
 }
 
@@ -169,5 +190,6 @@ int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
 		.vid_end = vid,
 	};
 
+	v.proto = br_switchdev_get_bridge_vlan_proto(dev);
 	return switchdev_port_obj_del(dev, &v.obj);
 }
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 1653e3377cb3..52685b9875e5 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -164,8 +164,8 @@ int dsa_port_vlan_add(struct dsa_port *dp,
 		      struct switchdev_trans *trans);
 int dsa_port_vlan_del(struct dsa_port *dp,
 		      const struct switchdev_obj_port_vlan *vlan);
-int dsa_port_vid_add(struct dsa_port *dp, u16 vid, u16 flags);
-int dsa_port_vid_del(struct dsa_port *dp, u16 vid);
+int dsa_port_vid_add(struct dsa_port *dp, u16 vid, u16 proto, u16 flags);
+int dsa_port_vid_del(struct dsa_port *dp, u16 vid, u16 proto);
 int dsa_port_link_register_of(struct dsa_port *dp);
 void dsa_port_link_unregister_of(struct dsa_port *dp);
 extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index e23ece229c7e..c98bbac3980a 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -433,13 +433,14 @@ int dsa_port_vlan_del(struct dsa_port *dp,
 	return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
 }
 
-int dsa_port_vid_add(struct dsa_port *dp, u16 vid, u16 flags)
+int dsa_port_vid_add(struct dsa_port *dp, u16 vid, u16 proto, u16 flags)
 {
 	struct switchdev_obj_port_vlan vlan = {
 		.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
 		.flags = flags,
 		.vid_begin = vid,
 		.vid_end = vid,
+		.proto = proto,
 	};
 	struct switchdev_trans trans;
 	int err;
@@ -454,12 +455,13 @@ int dsa_port_vid_add(struct dsa_port *dp, u16 vid, u16 flags)
 }
 EXPORT_SYMBOL(dsa_port_vid_add);
 
-int dsa_port_vid_del(struct dsa_port *dp, u16 vid)
+int dsa_port_vid_del(struct dsa_port *dp, u16 vid, u16 proto)
 {
 	struct switchdev_obj_port_vlan vlan = {
 		.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
 		.vid_begin = vid,
 		.vid_end = vid,
+		.proto = proto,
 	};
 
 	return dsa_port_vlan_del(dp, &vlan);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 41d60eeefdbd..f01deda00492 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -328,6 +328,7 @@ static int dsa_slave_vlan_add(struct net_device *dev,
 	 * it doesn't make sense to program a PVID, so clear this flag.
 	 */
 	vlan.flags &= ~BRIDGE_VLAN_INFO_PVID;
+	vlan.proto = ETH_P_8021Q;
 
 	err = dsa_port_vlan_add(dp->cpu_dp, &vlan, trans);
 	if (err)
@@ -1229,11 +1230,38 @@ static int dsa_slave_get_ts_info(struct net_device *dev,
 	return ds->ops->get_ts_info(ds, p->dp->index, ts);
 }
 
+static bool dsa_slave_skip_vlan_configuration(struct dsa_port *dp,
+					      u16 vlan_proto, u16 vid)
+{
+	struct bridge_vlan_info info;
+	bool change_proto = false;
+	u16 br_proto = 0;
+	int ret;
+
+	/* when changing bridge's vlan protocol, it will change bridge
+	 * port's protocol firstly, then set bridge's protocol. if it's
+	 * changing vlan protocol, should not return -EBUSY.
+	 */
+	ret = br_vlan_get_proto(dp->bridge_dev, &br_proto);
+	if (ret == 0 && br_proto != vlan_proto)
+		change_proto = true;
+
+	/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
+	 * device, respectively the VID is not found, returning
+	 * 0 means success, which is a failure for us here.
+	 */
+	ret = br_vlan_get_info(dp->bridge_dev, vid, &info);
+	if (ret == 0 && !change_proto)
+		return true;
+	else
+		return false;
+}
+
 static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
 				     u16 vid)
 {
 	struct dsa_port *dp = dsa_slave_to_port(dev);
-	struct bridge_vlan_info info;
+	u16 vlan_proto = ntohs(proto);
 	int ret;
 
 	/* Check for a possible bridge VLAN entry now since there is no
@@ -1243,20 +1271,15 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
 		if (dsa_port_skip_vlan_configuration(dp))
 			return 0;
 
-		/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
-		 * device, respectively the VID is not found, returning
-		 * 0 means success, which is a failure for us here.
-		 */
-		ret = br_vlan_get_info(dp->bridge_dev, vid, &info);
-		if (ret == 0)
+		if (dsa_slave_skip_vlan_configuration(dp, vlan_proto, vid))
 			return -EBUSY;
 	}
 
-	ret = dsa_port_vid_add(dp, vid, 0);
+	ret = dsa_port_vid_add(dp, vid, vlan_proto, 0);
 	if (ret)
 		return ret;
 
-	ret = dsa_port_vid_add(dp->cpu_dp, vid, 0);
+	ret = dsa_port_vid_add(dp->cpu_dp, vid, ETH_P_8021Q, 0);
 	if (ret)
 		return ret;
 
@@ -1267,8 +1290,7 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
 				      u16 vid)
 {
 	struct dsa_port *dp = dsa_slave_to_port(dev);
-	struct bridge_vlan_info info;
-	int ret;
+	u16 vlan_proto = ntohs(proto);
 
 	/* Check for a possible bridge VLAN entry now since there is no
 	 * need to emulate the switchdev prepare + commit phase.
@@ -1277,19 +1299,14 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
 		if (dsa_port_skip_vlan_configuration(dp))
 			return 0;
 
-		/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
-		 * device, respectively the VID is not found, returning
-		 * 0 means success, which is a failure for us here.
-		 */
-		ret = br_vlan_get_info(dp->bridge_dev, vid, &info);
-		if (ret == 0)
+		if (dsa_slave_skip_vlan_configuration(dp, vlan_proto, vid))
 			return -EBUSY;
 	}
 
 	/* Do not deprogram the CPU port as it may be shared with other user
 	 * ports which can be members of this VLAN as well.
 	 */
-	return dsa_port_vid_del(dp, vid);
+	return dsa_port_vid_del(dp, vid, vlan_proto);
 }
 
 struct dsa_hw_port {
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 780b2a15ac9b..4c93988e61a3 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -152,9 +152,9 @@ static int dsa_8021q_vid_apply(struct dsa_switch *ds, int port, u16 vid,
 	struct dsa_port *dp = dsa_to_port(ds, port);
 
 	if (enabled)
-		return dsa_port_vid_add(dp, vid, flags);
+		return dsa_port_vid_add(dp, vid, ETH_P_8021Q, flags);
 
-	return dsa_port_vid_del(dp, vid);
+	return dsa_port_vid_del(dp, vid, ETH_P_8021Q);
 }
 
 /* RX VLAN tagging (left) and TX VLAN tagging (right) setup shown for a single
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v5 2/2] net: dsa: ocelot: Add support for QinQ Operation
  2020-08-07 11:13 [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver hongbo.wang
  2020-08-07 11:13 ` [PATCH v5 1/2] net: dsa: Add protocol support for 802.1AD when adding or deleting vlan for dsa switch port hongbo.wang
@ 2020-08-07 11:13 ` hongbo.wang
  2020-08-08  0:24 ` [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver David Miller
  2 siblings, 0 replies; 5+ messages in thread
From: hongbo.wang @ 2020-08-07 11:13 UTC (permalink / raw)
  To: xiaoliang.yang_1, allan.nielsen, po.liu, claudiu.manoil,
	alexandru.marginean, vladimir.oltean, leoyang.li, mingkai.hu,
	andrew, f.fainelli, vivien.didelot, davem, jiri, idosch, kuba,
	vinicius.gomes, nikolay, roopa, netdev, linux-kernel,
	horatiu.vultur, alexandre.belloni, UNGLinuxDriver, ivecera
  Cc: hongbo.wang

From: "hongbo.wang" <hongbo.wang@nxp.com>

This feature can be test in the following case:
Customer <-----> swp0  <-----> swp1 <-----> ISP

Customer will send and receive packets with single VLAN tag(CTAG),
ISP will send and receive packets with double VLAN tag(STAG and CTAG).
This refers to "4.3.3 Provider Bridges and Q-in-Q Operation" in
VSC99599_1_00_TS.pdf.

The related test commands:
1.
devlink dev param set pci/0000:00:00.5 name qinq_port_bitmap \
value 2 cmode runtime

ip link add dev br0 type bridge vlan_protocol 802.1ad
ip link set dev swp0 master br0
ip link set dev swp1 master br0

2.
ip link set dev br0 type bridge vlan_filtering 1
bridge vlan add dev swp0 vid 100 pvid
bridge vlan add dev swp1 vid 100
Result:
Customer(tpid:8100 vid:111) -> swp0 -> swp1 -> ISP(STAG \
                tpid:88A8 vid:100, CTAG tpid:8100 vid:111)

3.
bridge vlan del dev swp0 vid 1 pvid
bridge vlan add dev swp0 vid 100 pvid untagged
Result:
ISP(tpid:88A8 vid:100 tpid:8100 vid:222) -> swp1 -> swp0 ->\
		Customer(tpid:8100 vid:222)

Signed-off-by: hongbo.wang <hongbo.wang@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c     | 124 +++++++++++++++++++++++++++++
 drivers/net/ethernet/mscc/ocelot.c |  40 ++++++++--
 include/soc/mscc/ocelot.h          |   4 +
 3 files changed, 162 insertions(+), 6 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index c69d9592a2b7..f9d50af4be65 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -147,9 +147,26 @@ static void felix_vlan_add(struct dsa_switch *ds, int port,
 				vid, port, err);
 			return;
 		}
+
+		if (vlan->proto == ETH_P_8021AD) {
+			if (!ocelot->qinq_enable) {
+				ocelot->qinq_enable = true;
+				kref_init(&ocelot->qinq_refcount);
+			} else {
+				kref_get(&ocelot->qinq_refcount);
+			}
+		}
 	}
 }
 
+static void felix_vlan_qinq_release(struct kref *ref)
+{
+	struct ocelot *ocelot;
+
+	ocelot = container_of(ref, struct ocelot, qinq_refcount);
+	ocelot->qinq_enable = false;
+}
+
 static int felix_vlan_del(struct dsa_switch *ds, int port,
 			  const struct switchdev_obj_port_vlan *vlan)
 {
@@ -164,7 +181,11 @@ static int felix_vlan_del(struct dsa_switch *ds, int port,
 				vid, port, err);
 			return err;
 		}
+
+		if (ocelot->qinq_enable && vlan->proto == ETH_P_8021AD)
+			kref_put(&ocelot->qinq_refcount, felix_vlan_qinq_release);
 	}
+
 	return 0;
 }
 
@@ -172,9 +193,13 @@ static int felix_port_enable(struct dsa_switch *ds, int port,
 			     struct phy_device *phy)
 {
 	struct ocelot *ocelot = ds->priv;
+	struct net_device *slave;
 
 	ocelot_port_enable(ocelot, port, phy);
 
+	slave = dsa_to_port(ds, port)->slave;
+	slave->features |= NETIF_F_HW_VLAN_STAG_FILTER;
+
 	return 0;
 }
 
@@ -568,6 +593,97 @@ static struct ptp_clock_info ocelot_ptp_clock_info = {
 	.enable		= ocelot_ptp_enable,
 };
 
+static int felix_qinq_port_bitmap_get(struct dsa_switch *ds, u32 *bitmap)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct ocelot_port *ocelot_port;
+	int port;
+
+	*bitmap = 0;
+	for (port = 0; port < ds->num_ports; port++) {
+		ocelot_port = ocelot->ports[port];
+		if (ocelot_port->qinq_mode)
+			*bitmap |= 0x01 << port;
+	}
+
+	return 0;
+}
+
+static int felix_qinq_port_bitmap_set(struct dsa_switch *ds, u32 bitmap)
+{
+	struct ocelot *ocelot = ds->priv;
+	struct ocelot_port *ocelot_port;
+	int port;
+
+	for (port = 0; port < ds->num_ports; port++) {
+		ocelot_port = ocelot->ports[port];
+		if (bitmap & (0x01 << port))
+			ocelot_port->qinq_mode = true;
+		else
+			ocelot_port->qinq_mode = false;
+	}
+
+	return 0;
+}
+
+enum felix_devlink_param_id {
+	FELIX_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
+	FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP,
+};
+
+static int felix_devlink_param_get(struct dsa_switch *ds, u32 id,
+				   struct devlink_param_gset_ctx *ctx)
+{
+	int err;
+
+	switch (id) {
+	case FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP:
+		err = felix_qinq_port_bitmap_get(ds, &ctx->val.vu32);
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		break;
+	}
+
+	return err;
+}
+
+static int felix_devlink_param_set(struct dsa_switch *ds, u32 id,
+				   struct devlink_param_gset_ctx *ctx)
+{
+	int err;
+
+	switch (id) {
+	case FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP:
+		err = felix_qinq_port_bitmap_set(ds, ctx->val.vu32);
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		break;
+	}
+
+	return err;
+}
+
+static const struct devlink_param felix_devlink_params[] = {
+	DSA_DEVLINK_PARAM_DRIVER(FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP,
+				 "qinq_port_bitmap",
+				 DEVLINK_PARAM_TYPE_U32,
+				 BIT(DEVLINK_PARAM_CMODE_RUNTIME)),
+};
+
+static int felix_setup_devlink_params(struct dsa_switch *ds)
+{
+	return dsa_devlink_params_register(ds, felix_devlink_params,
+					   ARRAY_SIZE(felix_devlink_params));
+}
+
+static void felix_teardown_devlink_params(struct dsa_switch *ds)
+{
+	dsa_devlink_params_unregister(ds, felix_devlink_params,
+				      ARRAY_SIZE(felix_devlink_params));
+}
+
 /* Hardware initialization done here so that we can allocate structures with
  * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
  * us to allocate structures twice (leak memory) and map PCI memory twice
@@ -632,6 +748,10 @@ static int felix_setup(struct dsa_switch *ds)
 	 */
 	ds->pcs_poll = true;
 
+	err = felix_setup_devlink_params(ds);
+	if (err < 0)
+		return err;
+
 	return 0;
 }
 
@@ -643,6 +763,8 @@ static void felix_teardown(struct dsa_switch *ds)
 	if (felix->info->mdio_bus_free)
 		felix->info->mdio_bus_free(ocelot);
 
+	felix_teardown_devlink_params(ds);
+
 	ocelot_deinit_timestamp(ocelot);
 	/* stop workqueue thread */
 	ocelot_deinit(ocelot);
@@ -817,6 +939,8 @@ const struct dsa_switch_ops felix_switch_ops = {
 	.cls_flower_del		= felix_cls_flower_del,
 	.cls_flower_stats	= felix_cls_flower_stats,
 	.port_setup_tc          = felix_port_setup_tc,
+	.devlink_param_get	= felix_devlink_param_get,
+	.devlink_param_set	= felix_devlink_param_set,
 };
 
 static int __init felix_init(void)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 867c680f5917..073c08989e21 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -143,6 +143,8 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
 				       u16 vid)
 {
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
+	u32 port_tpid = 0;
+	u32 tag_tpid = 0;
 	u32 val = 0;
 
 	if (ocelot_port->vid != vid) {
@@ -156,8 +158,14 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
 		ocelot_port->vid = vid;
 	}
 
-	ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid),
-		       REW_PORT_VLAN_CFG_PORT_VID_M,
+	if (ocelot->qinq_enable && ocelot_port->qinq_mode)
+		port_tpid = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021AD);
+	else
+		port_tpid = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q);
+
+	ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid) | port_tpid,
+		       REW_PORT_VLAN_CFG_PORT_VID_M |
+		       REW_PORT_VLAN_CFG_PORT_TPID_M,
 		       REW_PORT_VLAN_CFG, port);
 
 	if (ocelot_port->vlan_aware && !ocelot_port->vid)
@@ -180,12 +188,19 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
 		else
 			/* Tag all frames */
 			val = REW_TAG_CFG_TAG_CFG(3);
+
+		if (ocelot->qinq_enable && ocelot_port->qinq_mode)
+			tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(1);
+		else
+			tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(0);
 	} else {
 		/* Port tagging disabled. */
 		val = REW_TAG_CFG_TAG_CFG(0);
+		tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(0);
 	}
-	ocelot_rmw_gix(ocelot, val,
-		       REW_TAG_CFG_TAG_CFG_M,
+
+	ocelot_rmw_gix(ocelot, val | tag_tpid,
+		       REW_TAG_CFG_TAG_CFG_M | REW_TAG_CFG_TAG_TPID_CFG_M,
 		       REW_TAG_CFG, port);
 
 	return 0;
@@ -204,6 +219,15 @@ void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
 		      ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
 	else
 		val = 0;
+
+	/* if switch is enabled for QinQ, the port for LAN should set
+	 * VLAN_CFG.VLAN_POP_CNT=0 && VLAN_CFG.VLAN_AWARE_ENA=0.
+	 * the port for MAN should set VLAN_CFG.VLAN_POP_CNT=1 &&
+	 * VLAN_CFG.VLAN_AWARE_ENA=1. referring to 4.3.3 in VSC9959_1_00_TS.pdf
+	 */
+	if (ocelot->qinq_enable && !ocelot_port->qinq_mode)
+		val = 0;
+
 	ocelot_rmw_gix(ocelot, val,
 		       ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
 		       ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
@@ -217,10 +241,14 @@ EXPORT_SYMBOL(ocelot_port_vlan_filtering);
 static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid)
 {
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
+	u32 tag_type = 0;
+
+	if (ocelot->qinq_enable && ocelot_port->qinq_mode)
+		tag_type = ANA_PORT_VLAN_CFG_VLAN_TAG_TYPE;
 
 	ocelot_rmw_gix(ocelot,
-		       ANA_PORT_VLAN_CFG_VLAN_VID(pvid),
-		       ANA_PORT_VLAN_CFG_VLAN_VID_M,
+		       ANA_PORT_VLAN_CFG_VLAN_VID(pvid) | tag_type,
+		       ANA_PORT_VLAN_CFG_VLAN_VID_M | tag_type,
 		       ANA_PORT_VLAN_CFG, port);
 
 	ocelot_port->pvid = pvid;
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index da369b12005f..8d0f9f9ec0b2 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -556,6 +556,7 @@ struct ocelot_port {
 	struct regmap			*target;
 
 	bool				vlan_aware;
+	bool				qinq_mode;
 
 	/* Ingress default VLAN (pvid) */
 	u16				pvid;
@@ -632,6 +633,9 @@ struct ocelot {
 	/* Protects the PTP clock */
 	spinlock_t			ptp_clock_lock;
 	struct ptp_pin_desc		ptp_pins[OCELOT_PTP_PINS_NUM];
+
+	bool				qinq_enable;
+	struct kref			qinq_refcount;
 };
 
 struct ocelot_policer {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v5 1/2] net: dsa: Add protocol support for 802.1AD when adding or deleting vlan for dsa switch port
  2020-08-07 11:13 ` [PATCH v5 1/2] net: dsa: Add protocol support for 802.1AD when adding or deleting vlan for dsa switch port hongbo.wang
@ 2020-08-07 11:25   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 5+ messages in thread
From: Nikolay Aleksandrov @ 2020-08-07 11:25 UTC (permalink / raw)
  To: hongbo.wang, xiaoliang.yang_1, allan.nielsen, po.liu,
	claudiu.manoil, alexandru.marginean, vladimir.oltean, leoyang.li,
	mingkai.hu, andrew, f.fainelli, vivien.didelot, davem, jiri,
	idosch, kuba, vinicius.gomes, roopa, netdev, linux-kernel,
	horatiu.vultur, alexandre.belloni, UNGLinuxDriver, ivecera

On 07/08/2020 14:13, hongbo.wang@nxp.com wrote:
> From: "hongbo.wang" <hongbo.wang@nxp.com>
> 
> the following command will be supported:
> 
> Set bridge's vlan protocol:
>     ip link set br0 type bridge vlan_protocol 802.1ad
> Add VLAN:
>     ip link add link swp1 name swp1.100 type vlan protocol 802.1ad id 100
> Delete VLAN:
>     ip link del link swp1 name swp1.100
> 
> Signed-off-by: hongbo.wang <hongbo.wang@nxp.com>
> ---
>  include/net/switchdev.h   |  1 +
>  net/bridge/br_switchdev.c | 22 ++++++++++++++++
>  net/dsa/dsa_priv.h        |  4 +--
>  net/dsa/port.c            |  6 +++--
>  net/dsa/slave.c           | 53 ++++++++++++++++++++++++++-------------
>  net/dsa/tag_8021q.c       |  4 +--
>  6 files changed, 66 insertions(+), 24 deletions(-)
> 

Hi,
Please put the bridge changes in a separate patch with proper description.
Reviewers would easily miss these bridge changes. Also I believe net-next
is currently closed and that's where these patches should be targeted (i.e.
have net-next after PATCH in the subject). Few more comments below.

Thanks,
 Nik

> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> index ff2246914301..7594ea82879f 100644
> --- a/include/net/switchdev.h
> +++ b/include/net/switchdev.h
> @@ -97,6 +97,7 @@ struct switchdev_obj_port_vlan {
>  	u16 flags;
>  	u16 vid_begin;
>  	u16 vid_end;
> +	u16 proto;
>  };
>  
>  #define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \
> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
> index 015209bf44aa..bcfa00d6d5eb 100644
> --- a/net/bridge/br_switchdev.c
> +++ b/net/bridge/br_switchdev.c
> @@ -146,6 +146,26 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
>  	}
>  }
>  
> +static u16 br_switchdev_get_bridge_vlan_proto(struct net_device *dev)

const

> +{
> +	u16 vlan_proto = ETH_P_8021Q;
> +	struct net_device *br = NULL;
> +	struct net_bridge_port *p;
> +
> +	if (netif_is_bridge_master(dev)) {
> +		br = dev;
> +	} else if (netif_is_bridge_port(dev)) {

You can use br_port_get_rtnl_rcu() and just check if p is not NULL.
But in general these helpers are used only on bridge devices, I don't think you
can reach them with a device that's not either a bridge or a port. So you can just
check if it's a bridge master else it's a port.

> +		p = br_port_get_rcu(dev);
> +		if (p && p->br)

No need to check for p->br, it always exists.

> +			br = p->br->dev;
> +	}
> +
> +	if (br)
> +		br_vlan_get_proto(br, &vlan_proto);
> +
> +	return vlan_proto;
> +}
> +
>  int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
>  			       struct netlink_ext_ack *extack)
>  {
> @@ -157,6 +177,7 @@ int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
>  		.vid_end = vid,
>  	};
>  
> +	v.proto = br_switchdev_get_bridge_vlan_proto(dev);
>  	return switchdev_port_obj_add(dev, &v.obj, extack);
>  }
>  
> @@ -169,5 +190,6 @@ int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
>  		.vid_end = vid,
>  	};
>  
> +	v.proto = br_switchdev_get_bridge_vlan_proto(dev);
>  	return switchdev_port_obj_del(dev, &v.obj);
>  }

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver
  2020-08-07 11:13 [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver hongbo.wang
  2020-08-07 11:13 ` [PATCH v5 1/2] net: dsa: Add protocol support for 802.1AD when adding or deleting vlan for dsa switch port hongbo.wang
  2020-08-07 11:13 ` [PATCH v5 2/2] net: dsa: ocelot: Add support for QinQ Operation hongbo.wang
@ 2020-08-08  0:24 ` David Miller
  2 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2020-08-08  0:24 UTC (permalink / raw)
  To: hongbo.wang
  Cc: xiaoliang.yang_1, allan.nielsen, po.liu, claudiu.manoil,
	alexandru.marginean, vladimir.oltean, leoyang.li, mingkai.hu,
	andrew, f.fainelli, vivien.didelot, jiri, idosch, kuba,
	vinicius.gomes, nikolay, roopa, netdev, linux-kernel,
	horatiu.vultur, alexandre.belloni, UNGLinuxDriver, ivecera

From: hongbo.wang@nxp.com
Date: Fri,  7 Aug 2020 19:13:47 +0800

> From: "hongbo.wang" <hongbo.wang@nxp.com>
> 
> 1. the patch 0001* is for setting single port into 802.1AD(QinQ) mode,
> before this patch, the function dsa_slave_vlan_rx_add_vid didn't pass 
> the parameter "proto" to next port level, so switch's port can't get
> parameter "proto"
>   after applying this patch, the following command can be supported:
>   ip link set br0 type bridge vlan_protocol 802.1ad
>   ip link add link swp1 name swp1.100 type vlan protocol 802.1ad id 100
> 
> 2. the patch 0002* is for setting QinQ related registers in ocelot 
> switch driver, after applying this patch, the switch(VSC99599)'s port can
> enable or disable QinQ mode.
> 
> 3. Version log
> v5:
> a. add devlink to enable qinq_mode of ocelot's single port
> b. modify br_switchdev_port_vlan_add to pass bridge's vlan_proto to port driver
> c. enable NETIF_F_HW_VLAN_STAG_FILTER in ocelot driver
> v4:
> a. modify slave.c to support "ip set br0 type bridge vlan_protocol 802.1ad"
> b. modify ocelot.c, if enable QinQ, set VLAN_AWARE_ENA and VLAN_POP_CNT per
>    port when vlan_filter=1
> v3: combine two patches to one post

Please defer new feature changes, like this, until the net-next tree is open
again.  It is closed right now.

Thank you.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-08-08  0:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-07 11:13 [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver hongbo.wang
2020-08-07 11:13 ` [PATCH v5 1/2] net: dsa: Add protocol support for 802.1AD when adding or deleting vlan for dsa switch port hongbo.wang
2020-08-07 11:25   ` Nikolay Aleksandrov
2020-08-07 11:13 ` [PATCH v5 2/2] net: dsa: ocelot: Add support for QinQ Operation hongbo.wang
2020-08-08  0:24 ` [PATCH v5 0/2] Add 802.1AD protocol support for dsa switch and ocelot driver David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.