aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.15/771-v6.0-11-net-dsa-qca8k-move-port-mirror-functions-to-common-c.patch
diff options
context:
space:
mode:
authorChristian Marangi <ansuelsmth@gmail.com>2022-09-12 18:40:16 +0200
committerChristian Marangi <ansuelsmth@gmail.com>2022-09-19 15:19:53 +0200
commit7ace30aeb6ff58b4de845dd4722b281afd0c7eae (patch)
tree41c627ab344f5b8012610cccf5592d5876bc6586 /target/linux/generic/backport-5.15/771-v6.0-11-net-dsa-qca8k-move-port-mirror-functions-to-common-c.patch
parentddcebda08b26142d47eb3c2009d48d12781d76a3 (diff)
downloadupstream-7ace30aeb6ff58b4de845dd4722b281afd0c7eae.tar.gz
upstream-7ace30aeb6ff58b4de845dd4722b281afd0c7eae.tar.bz2
upstream-7ace30aeb6ff58b4de845dd4722b281afd0c7eae.zip
generic: 5.15: qca8k: backport code split patch
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>
Diffstat (limited to 'target/linux/generic/backport-5.15/771-v6.0-11-net-dsa-qca8k-move-port-mirror-functions-to-common-c.patch')
-rw-r--r--target/linux/generic/backport-5.15/771-v6.0-11-net-dsa-qca8k-move-port-mirror-functions-to-common-c.patch232
1 files changed, 232 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.15/771-v6.0-11-net-dsa-qca8k-move-port-mirror-functions-to-common-c.patch b/target/linux/generic/backport-5.15/771-v6.0-11-net-dsa-qca8k-move-port-mirror-functions-to-common-c.patch
new file mode 100644
index 0000000000..c1336d4a92
--- /dev/null
+++ b/target/linux/generic/backport-5.15/771-v6.0-11-net-dsa-qca8k-move-port-mirror-functions-to-common-c.patch
@@ -0,0 +1,232 @@
+From 742d37a84d3f7bb60d9b2d9ada9ad4e599f65ebf Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Wed, 27 Jul 2022 13:35:20 +0200
+Subject: [PATCH 11/14] net: dsa: qca8k: move port mirror functions to common
+ code
+
+The same port mirror functions are used by drivers based on qca8k family
+switch. Move them to common code to make them accessible also by other
+drivers.
+
+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 | 93 ------------------------------
+ drivers/net/dsa/qca/qca8k-common.c | 91 +++++++++++++++++++++++++++++
+ drivers/net/dsa/qca/qca8k.h | 7 +++
+ 3 files changed, 98 insertions(+), 93 deletions(-)
+
+--- a/drivers/net/dsa/qca/qca8k-8xxx.c
++++ b/drivers/net/dsa/qca/qca8k-8xxx.c
+@@ -1838,99 +1838,6 @@ exit:
+ }
+
+ static int
+-qca8k_port_mirror_add(struct dsa_switch *ds, int port,
+- struct dsa_mall_mirror_tc_entry *mirror,
+- bool ingress)
+-{
+- struct qca8k_priv *priv = ds->priv;
+- int monitor_port, ret;
+- u32 reg, val;
+-
+- /* Check for existent entry */
+- if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
+- return -EEXIST;
+-
+- ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val);
+- if (ret)
+- return ret;
+-
+- /* QCA83xx can have only one port set to mirror mode.
+- * Check that the correct port is requested and return error otherwise.
+- * When no mirror port is set, the values is set to 0xF
+- */
+- monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
+- if (monitor_port != 0xF && monitor_port != mirror->to_local_port)
+- return -EEXIST;
+-
+- /* Set the monitor port */
+- val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM,
+- mirror->to_local_port);
+- ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
+- QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
+- if (ret)
+- return ret;
+-
+- if (ingress) {
+- reg = QCA8K_PORT_LOOKUP_CTRL(port);
+- val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
+- } else {
+- reg = QCA8K_REG_PORT_HOL_CTRL1(port);
+- val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
+- }
+-
+- ret = regmap_update_bits(priv->regmap, reg, val, val);
+- if (ret)
+- return ret;
+-
+- /* Track mirror port for tx and rx to decide when the
+- * mirror port has to be disabled.
+- */
+- if (ingress)
+- priv->mirror_rx |= BIT(port);
+- else
+- priv->mirror_tx |= BIT(port);
+-
+- return 0;
+-}
+-
+-static void
+-qca8k_port_mirror_del(struct dsa_switch *ds, int port,
+- struct dsa_mall_mirror_tc_entry *mirror)
+-{
+- struct qca8k_priv *priv = ds->priv;
+- u32 reg, val;
+- int ret;
+-
+- if (mirror->ingress) {
+- reg = QCA8K_PORT_LOOKUP_CTRL(port);
+- val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
+- } else {
+- reg = QCA8K_REG_PORT_HOL_CTRL1(port);
+- val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
+- }
+-
+- ret = regmap_clear_bits(priv->regmap, reg, val);
+- if (ret)
+- goto err;
+-
+- if (mirror->ingress)
+- priv->mirror_rx &= ~BIT(port);
+- else
+- priv->mirror_tx &= ~BIT(port);
+-
+- /* No port set to send packet to mirror port. Disable mirror port */
+- if (!priv->mirror_rx && !priv->mirror_tx) {
+- val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF);
+- ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
+- QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
+- if (ret)
+- goto err;
+- }
+-err:
+- dev_err(priv->dev, "Failed to del mirror port from %d", port);
+-}
+-
+-static int
+ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+ struct netlink_ext_ack *extack)
+ {
+--- a/drivers/net/dsa/qca/qca8k-common.c
++++ b/drivers/net/dsa/qca/qca8k-common.c
+@@ -741,3 +741,94 @@ int qca8k_port_mdb_del(struct dsa_switch
+
+ return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
+ }
++
++int qca8k_port_mirror_add(struct dsa_switch *ds, int port,
++ struct dsa_mall_mirror_tc_entry *mirror,
++ bool ingress)
++{
++ struct qca8k_priv *priv = ds->priv;
++ int monitor_port, ret;
++ u32 reg, val;
++
++ /* Check for existent entry */
++ if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
++ return -EEXIST;
++
++ ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val);
++ if (ret)
++ return ret;
++
++ /* QCA83xx can have only one port set to mirror mode.
++ * Check that the correct port is requested and return error otherwise.
++ * When no mirror port is set, the values is set to 0xF
++ */
++ monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
++ if (monitor_port != 0xF && monitor_port != mirror->to_local_port)
++ return -EEXIST;
++
++ /* Set the monitor port */
++ val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM,
++ mirror->to_local_port);
++ ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
++ QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
++ if (ret)
++ return ret;
++
++ if (ingress) {
++ reg = QCA8K_PORT_LOOKUP_CTRL(port);
++ val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
++ } else {
++ reg = QCA8K_REG_PORT_HOL_CTRL1(port);
++ val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
++ }
++
++ ret = regmap_update_bits(priv->regmap, reg, val, val);
++ if (ret)
++ return ret;
++
++ /* Track mirror port for tx and rx to decide when the
++ * mirror port has to be disabled.
++ */
++ if (ingress)
++ priv->mirror_rx |= BIT(port);
++ else
++ priv->mirror_tx |= BIT(port);
++
++ return 0;
++}
++
++void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
++ struct dsa_mall_mirror_tc_entry *mirror)
++{
++ struct qca8k_priv *priv = ds->priv;
++ u32 reg, val;
++ int ret;
++
++ if (mirror->ingress) {
++ reg = QCA8K_PORT_LOOKUP_CTRL(port);
++ val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
++ } else {
++ reg = QCA8K_REG_PORT_HOL_CTRL1(port);
++ val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
++ }
++
++ ret = regmap_clear_bits(priv->regmap, reg, val);
++ if (ret)
++ goto err;
++
++ if (mirror->ingress)
++ priv->mirror_rx &= ~BIT(port);
++ else
++ priv->mirror_tx &= ~BIT(port);
++
++ /* No port set to send packet to mirror port. Disable mirror port */
++ if (!priv->mirror_rx && !priv->mirror_tx) {
++ val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF);
++ ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
++ QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
++ if (ret)
++ goto err;
++ }
++err:
++ dev_err(priv->dev, "Failed to del mirror port from %d", port);
++}
+--- a/drivers/net/dsa/qca/qca8k.h
++++ b/drivers/net/dsa/qca/qca8k.h
+@@ -480,4 +480,11 @@ int qca8k_port_mdb_add(struct dsa_switch
+ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_mdb *mdb);
+
++/* Common port mirror function */
++int qca8k_port_mirror_add(struct dsa_switch *ds, int port,
++ struct dsa_mall_mirror_tc_entry *mirror,
++ bool ingress);
++void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
++ struct dsa_mall_mirror_tc_entry *mirror);
++
+ #endif /* __QCA8K_H */