net: dsa: qca8k: move port mirror functions to common code
authorChristian Marangi <ansuelsmth@gmail.com>
Wed, 27 Jul 2022 11:35:20 +0000 (13:35 +0200)
committerJakub Kicinski <kuba@kernel.org>
Fri, 29 Jul 2022 05:24:39 +0000 (22:24 -0700)
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
drivers/net/dsa/qca/qca8k-common.c
drivers/net/dsa/qca/qca8k.h

index bf4dd1cd0f9d8149e40628ad75191adbc584f830..f6ea5a82da9ef6d94ea2ddfbd630d60c98a96ef2 100644 (file)
@@ -1687,99 +1687,6 @@ exit:
        return ret;
 }
 
-static int
-qca8k_port_mirror_add(struct dsa_switch *ds, int port,
-                     struct dsa_mall_mirror_tc_entry *mirror,
-                     bool ingress, struct netlink_ext_ack *extack)
-{
-       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)
index 8e92837781ee5dd65cbf006f44cd63bf49a1f120..c0a088418c20eb1343b0131dcd676b2983255a4a 100644 (file)
@@ -746,3 +746,94 @@ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
 
        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 netlink_ext_ack *extack)
+{
+       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);
+}
index 9da7928de83ca62f2cf5b1ea75322dd7ccce5957..3a2131b7abfa2bbc8b6c5ca2840ca5e37978ef8e 100644 (file)
@@ -494,4 +494,11 @@ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
                       const struct switchdev_obj_port_mdb *mdb,
                       struct dsa_db db);
 
+/* Common port mirror function */
+int qca8k_port_mirror_add(struct dsa_switch *ds, int port,
+                         struct dsa_mall_mirror_tc_entry *mirror,
+                         bool ingress, struct netlink_ext_ack *extack);
+void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
+                          struct dsa_mall_mirror_tc_entry *mirror);
+
 #endif /* __QCA8K_H */