Backport upstream code split patch for qca8k needed for ipq40xx target to correctly implement a DSA driver. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
		
			
				
	
	
		
			449 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			449 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From c5290f636624b98e76a82bd63ffec0a8a9daa620 Mon Sep 17 00:00:00 2001
 | 
						|
From: Christian Marangi <ansuelsmth@gmail.com>
 | 
						|
Date: Wed, 27 Jul 2022 13:35:21 +0200
 | 
						|
Subject: [PATCH 12/14] net: dsa: qca8k: move port VLAN functions to common
 | 
						|
 code
 | 
						|
 | 
						|
The same port VLAN functions are used by drivers based on qca8k family
 | 
						|
switch. Move them to common code to make them accessible also by other
 | 
						|
drivers.
 | 
						|
Also drop exposing busy_wait and make it static.
 | 
						|
 | 
						|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 | 
						|
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
 | 
						|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
						|
---
 | 
						|
 drivers/net/dsa/qca/qca8k-8xxx.c   | 182 -----------------------------
 | 
						|
 drivers/net/dsa/qca/qca8k-common.c | 179 +++++++++++++++++++++++++++-
 | 
						|
 drivers/net/dsa/qca/qca8k.h        |  10 +-
 | 
						|
 3 files changed, 187 insertions(+), 184 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
 | 
						|
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
 | 
						|
@@ -15,7 +15,6 @@
 | 
						|
 #include <linux/of_net.h>
 | 
						|
 #include <linux/of_mdio.h>
 | 
						|
 #include <linux/of_platform.h>
 | 
						|
-#include <linux/if_bridge.h>
 | 
						|
 #include <linux/mdio.h>
 | 
						|
 #include <linux/phylink.h>
 | 
						|
 #include <linux/gpio/consumer.h>
 | 
						|
@@ -442,122 +441,6 @@ static struct regmap_config qca8k_regmap
 | 
						|
 };
 | 
						|
 
 | 
						|
 static int
 | 
						|
-qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid)
 | 
						|
-{
 | 
						|
-	u32 reg;
 | 
						|
-	int ret;
 | 
						|
-
 | 
						|
-	/* Set the command and VLAN index */
 | 
						|
-	reg = QCA8K_VTU_FUNC1_BUSY;
 | 
						|
-	reg |= cmd;
 | 
						|
-	reg |= FIELD_PREP(QCA8K_VTU_FUNC1_VID_MASK, vid);
 | 
						|
-
 | 
						|
-	/* Write the function register triggering the table access */
 | 
						|
-	ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
 | 
						|
-	if (ret)
 | 
						|
-		return ret;
 | 
						|
-
 | 
						|
-	/* wait for completion */
 | 
						|
-	ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY);
 | 
						|
-	if (ret)
 | 
						|
-		return ret;
 | 
						|
-
 | 
						|
-	/* Check for table full violation when adding an entry */
 | 
						|
-	if (cmd == QCA8K_VLAN_LOAD) {
 | 
						|
-		ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, ®);
 | 
						|
-		if (ret < 0)
 | 
						|
-			return ret;
 | 
						|
-		if (reg & QCA8K_VTU_FUNC1_FULL)
 | 
						|
-			return -ENOMEM;
 | 
						|
-	}
 | 
						|
-
 | 
						|
-	return 0;
 | 
						|
-}
 | 
						|
-
 | 
						|
-static int
 | 
						|
-qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid, bool untagged)
 | 
						|
-{
 | 
						|
-	u32 reg;
 | 
						|
-	int ret;
 | 
						|
-
 | 
						|
-	/*
 | 
						|
-	   We do the right thing with VLAN 0 and treat it as untagged while
 | 
						|
-	   preserving the tag on egress.
 | 
						|
-	 */
 | 
						|
-	if (vid == 0)
 | 
						|
-		return 0;
 | 
						|
-
 | 
						|
-	mutex_lock(&priv->reg_mutex);
 | 
						|
-	ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
 | 
						|
-	if (ret < 0)
 | 
						|
-		goto out;
 | 
						|
-
 | 
						|
-	ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®);
 | 
						|
-	if (ret < 0)
 | 
						|
-		goto out;
 | 
						|
-	reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
 | 
						|
-	reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
 | 
						|
-	if (untagged)
 | 
						|
-		reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(port);
 | 
						|
-	else
 | 
						|
-		reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(port);
 | 
						|
-
 | 
						|
-	ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
 | 
						|
-	if (ret)
 | 
						|
-		goto out;
 | 
						|
-	ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
 | 
						|
-
 | 
						|
-out:
 | 
						|
-	mutex_unlock(&priv->reg_mutex);
 | 
						|
-
 | 
						|
-	return ret;
 | 
						|
-}
 | 
						|
-
 | 
						|
-static int
 | 
						|
-qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid)
 | 
						|
-{
 | 
						|
-	u32 reg, mask;
 | 
						|
-	int ret, i;
 | 
						|
-	bool del;
 | 
						|
-
 | 
						|
-	mutex_lock(&priv->reg_mutex);
 | 
						|
-	ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
 | 
						|
-	if (ret < 0)
 | 
						|
-		goto out;
 | 
						|
-
 | 
						|
-	ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®);
 | 
						|
-	if (ret < 0)
 | 
						|
-		goto out;
 | 
						|
-	reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
 | 
						|
-	reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(port);
 | 
						|
-
 | 
						|
-	/* Check if we're the last member to be removed */
 | 
						|
-	del = true;
 | 
						|
-	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
 | 
						|
-		mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i);
 | 
						|
-
 | 
						|
-		if ((reg & mask) != mask) {
 | 
						|
-			del = false;
 | 
						|
-			break;
 | 
						|
-		}
 | 
						|
-	}
 | 
						|
-
 | 
						|
-	if (del) {
 | 
						|
-		ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid);
 | 
						|
-	} else {
 | 
						|
-		ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
 | 
						|
-		if (ret)
 | 
						|
-			goto out;
 | 
						|
-		ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
 | 
						|
-	}
 | 
						|
-
 | 
						|
-out:
 | 
						|
-	mutex_unlock(&priv->reg_mutex);
 | 
						|
-
 | 
						|
-	return ret;
 | 
						|
-}
 | 
						|
-
 | 
						|
-static int
 | 
						|
 qca8k_phy_eth_busy_wait(struct qca8k_mgmt_eth_data *mgmt_eth_data,
 | 
						|
 			struct sk_buff *read_skb, u32 *val)
 | 
						|
 {
 | 
						|
@@ -1836,71 +1719,6 @@ exit:
 | 
						|
 
 | 
						|
 	return ret;
 | 
						|
 }
 | 
						|
-
 | 
						|
-static int
 | 
						|
-qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
 | 
						|
-			  struct netlink_ext_ack *extack)
 | 
						|
-{
 | 
						|
-	struct qca8k_priv *priv = ds->priv;
 | 
						|
-	int ret;
 | 
						|
-
 | 
						|
-	if (vlan_filtering) {
 | 
						|
-		ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | 
						|
-				QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
 | 
						|
-				QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE);
 | 
						|
-	} else {
 | 
						|
-		ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | 
						|
-				QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
 | 
						|
-				QCA8K_PORT_LOOKUP_VLAN_MODE_NONE);
 | 
						|
-	}
 | 
						|
-
 | 
						|
-	return ret;
 | 
						|
-}
 | 
						|
-
 | 
						|
-static int
 | 
						|
-qca8k_port_vlan_add(struct dsa_switch *ds, int port,
 | 
						|
-		    const struct switchdev_obj_port_vlan *vlan,
 | 
						|
-		    struct netlink_ext_ack *extack)
 | 
						|
-{
 | 
						|
-	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
 | 
						|
-	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
 | 
						|
-	struct qca8k_priv *priv = ds->priv;
 | 
						|
-	int ret;
 | 
						|
-
 | 
						|
-	ret = qca8k_vlan_add(priv, port, vlan->vid, untagged);
 | 
						|
-	if (ret) {
 | 
						|
-		dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret);
 | 
						|
-		return ret;
 | 
						|
-	}
 | 
						|
-
 | 
						|
-	if (pvid) {
 | 
						|
-		ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port),
 | 
						|
-				QCA8K_EGREES_VLAN_PORT_MASK(port),
 | 
						|
-				QCA8K_EGREES_VLAN_PORT(port, vlan->vid));
 | 
						|
-		if (ret)
 | 
						|
-			return ret;
 | 
						|
-
 | 
						|
-		ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port),
 | 
						|
-				  QCA8K_PORT_VLAN_CVID(vlan->vid) |
 | 
						|
-				  QCA8K_PORT_VLAN_SVID(vlan->vid));
 | 
						|
-	}
 | 
						|
-
 | 
						|
-	return ret;
 | 
						|
-}
 | 
						|
-
 | 
						|
-static int
 | 
						|
-qca8k_port_vlan_del(struct dsa_switch *ds, int port,
 | 
						|
-		    const struct switchdev_obj_port_vlan *vlan)
 | 
						|
-{
 | 
						|
-	struct qca8k_priv *priv = ds->priv;
 | 
						|
-	int ret;
 | 
						|
-
 | 
						|
-	ret = qca8k_vlan_del(priv, port, vlan->vid);
 | 
						|
-	if (ret)
 | 
						|
-		dev_err(priv->dev, "Failed to delete VLAN from port %d (%d)", port, ret);
 | 
						|
-
 | 
						|
-	return ret;
 | 
						|
-}
 | 
						|
 
 | 
						|
 static u32 qca8k_get_phy_flags(struct dsa_switch *ds, int port)
 | 
						|
 {
 | 
						|
--- a/drivers/net/dsa/qca/qca8k-common.c
 | 
						|
+++ b/drivers/net/dsa/qca/qca8k-common.c
 | 
						|
@@ -141,7 +141,7 @@ static int qca8k_bulk_write(struct qca8k
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
-int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
 | 
						|
+static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
 | 
						|
 {
 | 
						|
 	u32 val;
 | 
						|
 
 | 
						|
@@ -354,6 +354,120 @@ exit:
 | 
						|
 	return ret;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static int qca8k_vlan_access(struct qca8k_priv *priv,
 | 
						|
+			     enum qca8k_vlan_cmd cmd, u16 vid)
 | 
						|
+{
 | 
						|
+	u32 reg;
 | 
						|
+	int ret;
 | 
						|
+
 | 
						|
+	/* Set the command and VLAN index */
 | 
						|
+	reg = QCA8K_VTU_FUNC1_BUSY;
 | 
						|
+	reg |= cmd;
 | 
						|
+	reg |= FIELD_PREP(QCA8K_VTU_FUNC1_VID_MASK, vid);
 | 
						|
+
 | 
						|
+	/* Write the function register triggering the table access */
 | 
						|
+	ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
 | 
						|
+	if (ret)
 | 
						|
+		return ret;
 | 
						|
+
 | 
						|
+	/* wait for completion */
 | 
						|
+	ret = qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY);
 | 
						|
+	if (ret)
 | 
						|
+		return ret;
 | 
						|
+
 | 
						|
+	/* Check for table full violation when adding an entry */
 | 
						|
+	if (cmd == QCA8K_VLAN_LOAD) {
 | 
						|
+		ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC1, ®);
 | 
						|
+		if (ret < 0)
 | 
						|
+			return ret;
 | 
						|
+		if (reg & QCA8K_VTU_FUNC1_FULL)
 | 
						|
+			return -ENOMEM;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int qca8k_vlan_add(struct qca8k_priv *priv, u8 port, u16 vid,
 | 
						|
+			  bool untagged)
 | 
						|
+{
 | 
						|
+	u32 reg;
 | 
						|
+	int ret;
 | 
						|
+
 | 
						|
+	/* We do the right thing with VLAN 0 and treat it as untagged while
 | 
						|
+	 * preserving the tag on egress.
 | 
						|
+	 */
 | 
						|
+	if (vid == 0)
 | 
						|
+		return 0;
 | 
						|
+
 | 
						|
+	mutex_lock(&priv->reg_mutex);
 | 
						|
+	ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
 | 
						|
+	if (ret < 0)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®);
 | 
						|
+	if (ret < 0)
 | 
						|
+		goto out;
 | 
						|
+	reg |= QCA8K_VTU_FUNC0_VALID | QCA8K_VTU_FUNC0_IVL_EN;
 | 
						|
+	reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
 | 
						|
+	if (untagged)
 | 
						|
+		reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_UNTAG(port);
 | 
						|
+	else
 | 
						|
+		reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_TAG(port);
 | 
						|
+
 | 
						|
+	ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
 | 
						|
+	if (ret)
 | 
						|
+		goto out;
 | 
						|
+	ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
 | 
						|
+
 | 
						|
+out:
 | 
						|
+	mutex_unlock(&priv->reg_mutex);
 | 
						|
+
 | 
						|
+	return ret;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int qca8k_vlan_del(struct qca8k_priv *priv, u8 port, u16 vid)
 | 
						|
+{
 | 
						|
+	u32 reg, mask;
 | 
						|
+	int ret, i;
 | 
						|
+	bool del;
 | 
						|
+
 | 
						|
+	mutex_lock(&priv->reg_mutex);
 | 
						|
+	ret = qca8k_vlan_access(priv, QCA8K_VLAN_READ, vid);
 | 
						|
+	if (ret < 0)
 | 
						|
+		goto out;
 | 
						|
+
 | 
						|
+	ret = qca8k_read(priv, QCA8K_REG_VTU_FUNC0, ®);
 | 
						|
+	if (ret < 0)
 | 
						|
+		goto out;
 | 
						|
+	reg &= ~QCA8K_VTU_FUNC0_EG_MODE_PORT_MASK(port);
 | 
						|
+	reg |= QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(port);
 | 
						|
+
 | 
						|
+	/* Check if we're the last member to be removed */
 | 
						|
+	del = true;
 | 
						|
+	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
 | 
						|
+		mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i);
 | 
						|
+
 | 
						|
+		if ((reg & mask) != mask) {
 | 
						|
+			del = false;
 | 
						|
+			break;
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	if (del) {
 | 
						|
+		ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid);
 | 
						|
+	} else {
 | 
						|
+		ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
 | 
						|
+		if (ret)
 | 
						|
+			goto out;
 | 
						|
+		ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+out:
 | 
						|
+	mutex_unlock(&priv->reg_mutex);
 | 
						|
+
 | 
						|
+	return ret;
 | 
						|
+}
 | 
						|
+
 | 
						|
 int qca8k_mib_init(struct qca8k_priv *priv)
 | 
						|
 {
 | 
						|
 	int ret;
 | 
						|
@@ -832,3 +946,66 @@ void qca8k_port_mirror_del(struct dsa_sw
 | 
						|
 err:
 | 
						|
 	dev_err(priv->dev, "Failed to del mirror port from %d", port);
 | 
						|
 }
 | 
						|
+
 | 
						|
+int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port,
 | 
						|
+			      bool vlan_filtering,
 | 
						|
+			      struct netlink_ext_ack *extack)
 | 
						|
+{
 | 
						|
+	struct qca8k_priv *priv = ds->priv;
 | 
						|
+	int ret;
 | 
						|
+
 | 
						|
+	if (vlan_filtering) {
 | 
						|
+		ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | 
						|
+				QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
 | 
						|
+				QCA8K_PORT_LOOKUP_VLAN_MODE_SECURE);
 | 
						|
+	} else {
 | 
						|
+		ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
 | 
						|
+				QCA8K_PORT_LOOKUP_VLAN_MODE_MASK,
 | 
						|
+				QCA8K_PORT_LOOKUP_VLAN_MODE_NONE);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return ret;
 | 
						|
+}
 | 
						|
+
 | 
						|
+int qca8k_port_vlan_add(struct dsa_switch *ds, int port,
 | 
						|
+			const struct switchdev_obj_port_vlan *vlan,
 | 
						|
+			struct netlink_ext_ack *extack)
 | 
						|
+{
 | 
						|
+	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
 | 
						|
+	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
 | 
						|
+	struct qca8k_priv *priv = ds->priv;
 | 
						|
+	int ret;
 | 
						|
+
 | 
						|
+	ret = qca8k_vlan_add(priv, port, vlan->vid, untagged);
 | 
						|
+	if (ret) {
 | 
						|
+		dev_err(priv->dev, "Failed to add VLAN to port %d (%d)", port, ret);
 | 
						|
+		return ret;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	if (pvid) {
 | 
						|
+		ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port),
 | 
						|
+				QCA8K_EGREES_VLAN_PORT_MASK(port),
 | 
						|
+				QCA8K_EGREES_VLAN_PORT(port, vlan->vid));
 | 
						|
+		if (ret)
 | 
						|
+			return ret;
 | 
						|
+
 | 
						|
+		ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port),
 | 
						|
+				  QCA8K_PORT_VLAN_CVID(vlan->vid) |
 | 
						|
+				  QCA8K_PORT_VLAN_SVID(vlan->vid));
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return ret;
 | 
						|
+}
 | 
						|
+
 | 
						|
+int qca8k_port_vlan_del(struct dsa_switch *ds, int port,
 | 
						|
+			const struct switchdev_obj_port_vlan *vlan)
 | 
						|
+{
 | 
						|
+	struct qca8k_priv *priv = ds->priv;
 | 
						|
+	int ret;
 | 
						|
+
 | 
						|
+	ret = qca8k_vlan_del(priv, port, vlan->vid);
 | 
						|
+	if (ret)
 | 
						|
+		dev_err(priv->dev, "Failed to delete VLAN from port %d (%d)", port, ret);
 | 
						|
+
 | 
						|
+	return ret;
 | 
						|
+}
 | 
						|
--- a/drivers/net/dsa/qca/qca8k.h
 | 
						|
+++ b/drivers/net/dsa/qca/qca8k.h
 | 
						|
@@ -431,7 +431,6 @@ int qca8k_write(struct qca8k_priv *priv,
 | 
						|
 int qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val);
 | 
						|
 
 | 
						|
 /* Common ops function */
 | 
						|
-int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask);
 | 
						|
 void qca8k_fdb_flush(struct qca8k_priv *priv);
 | 
						|
 
 | 
						|
 /* Common ethtool stats function */
 | 
						|
@@ -487,4 +486,13 @@ int qca8k_port_mirror_add(struct dsa_swi
 | 
						|
 void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
 | 
						|
 			   struct dsa_mall_mirror_tc_entry *mirror);
 | 
						|
 
 | 
						|
+/* Common port VLAN function */
 | 
						|
+int qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
 | 
						|
+			      struct netlink_ext_ack *extack);
 | 
						|
+int qca8k_port_vlan_add(struct dsa_switch *ds, int port,
 | 
						|
+			const struct switchdev_obj_port_vlan *vlan,
 | 
						|
+			struct netlink_ext_ack *extack);
 | 
						|
+int qca8k_port_vlan_del(struct dsa_switch *ds, int port,
 | 
						|
+			const struct switchdev_obj_port_vlan *vlan);
 | 
						|
+
 | 
						|
 #endif /* __QCA8K_H */
 |