]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: dsa: qca8k: move port FDB/MDB function to common code
authorChristian Marangi <ansuelsmth@gmail.com>
Wed, 27 Jul 2022 11:35:19 +0000 (13:35 +0200)
committerJakub Kicinski <kuba@kernel.org>
Fri, 29 Jul 2022 05:24:39 +0000 (22:24 -0700)
The same port FDB/MDB function are used by drivers based on qca8k family
switch. Move them to common code to make them accessible also by other
drivers.
Also drop bulk read/write functions and make them 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
drivers/net/dsa/qca/qca8k-common.c
drivers/net/dsa/qca/qca8k.h

index 1815863502c9f0214dce3ea6574f754724336856..bf4dd1cd0f9d8149e40628ad75191adbc584f830 100644 (file)
@@ -441,217 +441,6 @@ static struct regmap_config qca8k_regmap_config = {
        .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
 };
 
-static int
-qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
-{
-       u32 reg[3];
-       int ret;
-
-       /* load the ARL table into an array */
-       ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg));
-       if (ret)
-               return ret;
-
-       /* vid - 83:72 */
-       fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]);
-       /* aging - 67:64 */
-       fdb->aging = FIELD_GET(QCA8K_ATU_STATUS_MASK, reg[2]);
-       /* portmask - 54:48 */
-       fdb->port_mask = FIELD_GET(QCA8K_ATU_PORT_MASK, reg[1]);
-       /* mac - 47:0 */
-       fdb->mac[0] = FIELD_GET(QCA8K_ATU_ADDR0_MASK, reg[1]);
-       fdb->mac[1] = FIELD_GET(QCA8K_ATU_ADDR1_MASK, reg[1]);
-       fdb->mac[2] = FIELD_GET(QCA8K_ATU_ADDR2_MASK, reg[0]);
-       fdb->mac[3] = FIELD_GET(QCA8K_ATU_ADDR3_MASK, reg[0]);
-       fdb->mac[4] = FIELD_GET(QCA8K_ATU_ADDR4_MASK, reg[0]);
-       fdb->mac[5] = FIELD_GET(QCA8K_ATU_ADDR5_MASK, reg[0]);
-
-       return 0;
-}
-
-static void
-qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, const u8 *mac,
-               u8 aging)
-{
-       u32 reg[3] = { 0 };
-
-       /* vid - 83:72 */
-       reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid);
-       /* aging - 67:64 */
-       reg[2] |= FIELD_PREP(QCA8K_ATU_STATUS_MASK, aging);
-       /* portmask - 54:48 */
-       reg[1] = FIELD_PREP(QCA8K_ATU_PORT_MASK, port_mask);
-       /* mac - 47:0 */
-       reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR0_MASK, mac[0]);
-       reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR1_MASK, mac[1]);
-       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR2_MASK, mac[2]);
-       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR3_MASK, mac[3]);
-       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR4_MASK, mac[4]);
-       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]);
-
-       /* load the array into the ARL table */
-       qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg));
-}
-
-static int
-qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port)
-{
-       u32 reg;
-       int ret;
-
-       /* Set the command and FDB index */
-       reg = QCA8K_ATU_FUNC_BUSY;
-       reg |= cmd;
-       if (port >= 0) {
-               reg |= QCA8K_ATU_FUNC_PORT_EN;
-               reg |= FIELD_PREP(QCA8K_ATU_FUNC_PORT_MASK, port);
-       }
-
-       /* Write the function register triggering the table access */
-       ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
-       if (ret)
-               return ret;
-
-       /* wait for completion */
-       ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY);
-       if (ret)
-               return ret;
-
-       /* Check for table full violation when adding an entry */
-       if (cmd == QCA8K_FDB_LOAD) {
-               ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, &reg);
-               if (ret < 0)
-                       return ret;
-               if (reg & QCA8K_ATU_FUNC_FULL)
-                       return -1;
-       }
-
-       return 0;
-}
-
-static int
-qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb, int port)
-{
-       int ret;
-
-       qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging);
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port);
-       if (ret < 0)
-               return ret;
-
-       return qca8k_fdb_read(priv, fdb);
-}
-
-static int
-qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac, u16 port_mask,
-             u16 vid, u8 aging)
-{
-       int ret;
-
-       mutex_lock(&priv->reg_mutex);
-       qca8k_fdb_write(priv, vid, port_mask, mac, aging);
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
-       mutex_unlock(&priv->reg_mutex);
-
-       return ret;
-}
-
-static int
-qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac, u16 port_mask, u16 vid)
-{
-       int ret;
-
-       mutex_lock(&priv->reg_mutex);
-       qca8k_fdb_write(priv, vid, port_mask, mac, 0);
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
-       mutex_unlock(&priv->reg_mutex);
-
-       return ret;
-}
-
-static void
-qca8k_fdb_flush(struct qca8k_priv *priv)
-{
-       mutex_lock(&priv->reg_mutex);
-       qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1);
-       mutex_unlock(&priv->reg_mutex);
-}
-
-static int
-qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
-                           const u8 *mac, u16 vid)
-{
-       struct qca8k_fdb fdb = { 0 };
-       int ret;
-
-       mutex_lock(&priv->reg_mutex);
-
-       qca8k_fdb_write(priv, vid, 0, mac, 0);
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
-       if (ret < 0)
-               goto exit;
-
-       ret = qca8k_fdb_read(priv, &fdb);
-       if (ret < 0)
-               goto exit;
-
-       /* Rule exist. Delete first */
-       if (!fdb.aging) {
-               ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
-               if (ret)
-                       goto exit;
-       }
-
-       /* Add port to fdb portmask */
-       fdb.port_mask |= port_mask;
-
-       qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
-
-exit:
-       mutex_unlock(&priv->reg_mutex);
-       return ret;
-}
-
-static int
-qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
-                        const u8 *mac, u16 vid)
-{
-       struct qca8k_fdb fdb = { 0 };
-       int ret;
-
-       mutex_lock(&priv->reg_mutex);
-
-       qca8k_fdb_write(priv, vid, 0, mac, 0);
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
-       if (ret < 0)
-               goto exit;
-
-       /* Rule doesn't exist. Why delete? */
-       if (!fdb.aging) {
-               ret = -EINVAL;
-               goto exit;
-       }
-
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
-       if (ret)
-               goto exit;
-
-       /* Only port in the rule is this port. Don't re insert */
-       if (fdb.port_mask == port_mask)
-               goto exit;
-
-       /* Remove port from port mask */
-       fdb.port_mask &= ~port_mask;
-
-       qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
-       ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
-
-exit:
-       mutex_unlock(&priv->reg_mutex);
-       return ret;
-}
-
 static int
 qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid)
 {
@@ -1898,101 +1687,6 @@ exit:
        return ret;
 }
 
-static void
-qca8k_port_fast_age(struct dsa_switch *ds, int port)
-{
-       struct qca8k_priv *priv = ds->priv;
-
-       mutex_lock(&priv->reg_mutex);
-       qca8k_fdb_access(priv, QCA8K_FDB_FLUSH_PORT, port);
-       mutex_unlock(&priv->reg_mutex);
-}
-
-static int
-qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
-                     u16 port_mask, u16 vid)
-{
-       /* Set the vid to the port vlan id if no vid is set */
-       if (!vid)
-               vid = QCA8K_PORT_VID_DEF;
-
-       return qca8k_fdb_add(priv, addr, port_mask, vid,
-                            QCA8K_ATU_STATUS_STATIC);
-}
-
-static int
-qca8k_port_fdb_add(struct dsa_switch *ds, int port,
-                  const unsigned char *addr, u16 vid,
-                  struct dsa_db db)
-{
-       struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
-       u16 port_mask = BIT(port);
-
-       return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
-}
-
-static int
-qca8k_port_fdb_del(struct dsa_switch *ds, int port,
-                  const unsigned char *addr, u16 vid,
-                  struct dsa_db db)
-{
-       struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
-       u16 port_mask = BIT(port);
-
-       if (!vid)
-               vid = QCA8K_PORT_VID_DEF;
-
-       return qca8k_fdb_del(priv, addr, port_mask, vid);
-}
-
-static int
-qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
-                   dsa_fdb_dump_cb_t *cb, void *data)
-{
-       struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
-       struct qca8k_fdb _fdb = { 0 };
-       int cnt = QCA8K_NUM_FDB_RECORDS;
-       bool is_static;
-       int ret = 0;
-
-       mutex_lock(&priv->reg_mutex);
-       while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
-               if (!_fdb.aging)
-                       break;
-               is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC);
-               ret = cb(_fdb.mac, _fdb.vid, is_static, data);
-               if (ret)
-                       break;
-       }
-       mutex_unlock(&priv->reg_mutex);
-
-       return 0;
-}
-
-static int
-qca8k_port_mdb_add(struct dsa_switch *ds, int port,
-                  const struct switchdev_obj_port_mdb *mdb,
-                  struct dsa_db db)
-{
-       struct qca8k_priv *priv = ds->priv;
-       const u8 *addr = mdb->addr;
-       u16 vid = mdb->vid;
-
-       return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
-}
-
-static int
-qca8k_port_mdb_del(struct dsa_switch *ds, int port,
-                  const struct switchdev_obj_port_mdb *mdb,
-                  struct dsa_db db)
-{
-       struct qca8k_priv *priv = ds->priv;
-       const u8 *addr = mdb->addr;
-       u16 vid = mdb->vid;
-
-       return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
-}
-
 static int
 qca8k_port_mirror_add(struct dsa_switch *ds, int port,
                      struct dsa_mall_mirror_tc_entry *mirror,
index e25df4b23b9ae6e9fcc6a32ec64b9560747b3963..8e92837781ee5dd65cbf006f44cd63bf49a1f120 100644 (file)
@@ -102,7 +102,7 @@ const struct regmap_access_table qca8k_readable_table = {
 };
 
 /* TODO: remove these extra ops when we can support regmap bulk read/write */
-int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
+static int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
 {
        int i, count = len / sizeof(u32), ret;
 
@@ -120,7 +120,7 @@ int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
 }
 
 /* TODO: remove these extra ops when we can support regmap bulk read/write */
-int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
+static int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
 {
        int i, count = len / sizeof(u32), ret;
        u32 tmp;
@@ -148,6 +148,211 @@ int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask)
                                       QCA8K_BUSY_WAIT_TIMEOUT * USEC_PER_MSEC);
 }
 
+static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb)
+{
+       u32 reg[3];
+       int ret;
+
+       /* load the ARL table into an array */
+       ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg));
+       if (ret)
+               return ret;
+
+       /* vid - 83:72 */
+       fdb->vid = FIELD_GET(QCA8K_ATU_VID_MASK, reg[2]);
+       /* aging - 67:64 */
+       fdb->aging = FIELD_GET(QCA8K_ATU_STATUS_MASK, reg[2]);
+       /* portmask - 54:48 */
+       fdb->port_mask = FIELD_GET(QCA8K_ATU_PORT_MASK, reg[1]);
+       /* mac - 47:0 */
+       fdb->mac[0] = FIELD_GET(QCA8K_ATU_ADDR0_MASK, reg[1]);
+       fdb->mac[1] = FIELD_GET(QCA8K_ATU_ADDR1_MASK, reg[1]);
+       fdb->mac[2] = FIELD_GET(QCA8K_ATU_ADDR2_MASK, reg[0]);
+       fdb->mac[3] = FIELD_GET(QCA8K_ATU_ADDR3_MASK, reg[0]);
+       fdb->mac[4] = FIELD_GET(QCA8K_ATU_ADDR4_MASK, reg[0]);
+       fdb->mac[5] = FIELD_GET(QCA8K_ATU_ADDR5_MASK, reg[0]);
+
+       return 0;
+}
+
+static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask,
+                           const u8 *mac, u8 aging)
+{
+       u32 reg[3] = { 0 };
+
+       /* vid - 83:72 */
+       reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid);
+       /* aging - 67:64 */
+       reg[2] |= FIELD_PREP(QCA8K_ATU_STATUS_MASK, aging);
+       /* portmask - 54:48 */
+       reg[1] = FIELD_PREP(QCA8K_ATU_PORT_MASK, port_mask);
+       /* mac - 47:0 */
+       reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR0_MASK, mac[0]);
+       reg[1] |= FIELD_PREP(QCA8K_ATU_ADDR1_MASK, mac[1]);
+       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR2_MASK, mac[2]);
+       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR3_MASK, mac[3]);
+       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR4_MASK, mac[4]);
+       reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]);
+
+       /* load the array into the ARL table */
+       qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg));
+}
+
+static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd,
+                           int port)
+{
+       u32 reg;
+       int ret;
+
+       /* Set the command and FDB index */
+       reg = QCA8K_ATU_FUNC_BUSY;
+       reg |= cmd;
+       if (port >= 0) {
+               reg |= QCA8K_ATU_FUNC_PORT_EN;
+               reg |= FIELD_PREP(QCA8K_ATU_FUNC_PORT_MASK, port);
+       }
+
+       /* Write the function register triggering the table access */
+       ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
+       if (ret)
+               return ret;
+
+       /* wait for completion */
+       ret = qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY);
+       if (ret)
+               return ret;
+
+       /* Check for table full violation when adding an entry */
+       if (cmd == QCA8K_FDB_LOAD) {
+               ret = qca8k_read(priv, QCA8K_REG_ATU_FUNC, &reg);
+               if (ret < 0)
+                       return ret;
+               if (reg & QCA8K_ATU_FUNC_FULL)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int qca8k_fdb_next(struct qca8k_priv *priv, struct qca8k_fdb *fdb,
+                         int port)
+{
+       int ret;
+
+       qca8k_fdb_write(priv, fdb->vid, fdb->port_mask, fdb->mac, fdb->aging);
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_NEXT, port);
+       if (ret < 0)
+               return ret;
+
+       return qca8k_fdb_read(priv, fdb);
+}
+
+static int qca8k_fdb_add(struct qca8k_priv *priv, const u8 *mac,
+                        u16 port_mask, u16 vid, u8 aging)
+{
+       int ret;
+
+       mutex_lock(&priv->reg_mutex);
+       qca8k_fdb_write(priv, vid, port_mask, mac, aging);
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
+       mutex_unlock(&priv->reg_mutex);
+
+       return ret;
+}
+
+static int qca8k_fdb_del(struct qca8k_priv *priv, const u8 *mac,
+                        u16 port_mask, u16 vid)
+{
+       int ret;
+
+       mutex_lock(&priv->reg_mutex);
+       qca8k_fdb_write(priv, vid, port_mask, mac, 0);
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
+       mutex_unlock(&priv->reg_mutex);
+
+       return ret;
+}
+
+void qca8k_fdb_flush(struct qca8k_priv *priv)
+{
+       mutex_lock(&priv->reg_mutex);
+       qca8k_fdb_access(priv, QCA8K_FDB_FLUSH, -1);
+       mutex_unlock(&priv->reg_mutex);
+}
+
+static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
+                                      const u8 *mac, u16 vid)
+{
+       struct qca8k_fdb fdb = { 0 };
+       int ret;
+
+       mutex_lock(&priv->reg_mutex);
+
+       qca8k_fdb_write(priv, vid, 0, mac, 0);
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
+       if (ret < 0)
+               goto exit;
+
+       ret = qca8k_fdb_read(priv, &fdb);
+       if (ret < 0)
+               goto exit;
+
+       /* Rule exist. Delete first */
+       if (!fdb.aging) {
+               ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
+               if (ret)
+                       goto exit;
+       }
+
+       /* Add port to fdb portmask */
+       fdb.port_mask |= port_mask;
+
+       qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
+
+exit:
+       mutex_unlock(&priv->reg_mutex);
+       return ret;
+}
+
+static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
+                                   const u8 *mac, u16 vid)
+{
+       struct qca8k_fdb fdb = { 0 };
+       int ret;
+
+       mutex_lock(&priv->reg_mutex);
+
+       qca8k_fdb_write(priv, vid, 0, mac, 0);
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
+       if (ret < 0)
+               goto exit;
+
+       /* Rule doesn't exist. Why delete? */
+       if (!fdb.aging) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
+       if (ret)
+               goto exit;
+
+       /* Only port in the rule is this port. Don't re insert */
+       if (fdb.port_mask == port_mask)
+               goto exit;
+
+       /* Remove port from port mask */
+       fdb.port_mask &= ~port_mask;
+
+       qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
+       ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
+
+exit:
+       mutex_unlock(&priv->reg_mutex);
+       return ret;
+}
+
 int qca8k_mib_init(struct qca8k_priv *priv)
 {
        int ret;
@@ -369,6 +574,15 @@ void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
                  QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
 }
 
+void qca8k_port_fast_age(struct dsa_switch *ds, int port)
+{
+       struct qca8k_priv *priv = ds->priv;
+
+       mutex_lock(&priv->reg_mutex);
+       qca8k_fdb_access(priv, QCA8K_FDB_FLUSH_PORT, port);
+       mutex_unlock(&priv->reg_mutex);
+}
+
 int qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
 {
        struct qca8k_priv *priv = ds->priv;
@@ -453,3 +667,82 @@ int qca8k_port_max_mtu(struct dsa_switch *ds, int port)
 {
        return QCA8K_MAX_MTU;
 }
+
+int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
+                         u16 port_mask, u16 vid)
+{
+       /* Set the vid to the port vlan id if no vid is set */
+       if (!vid)
+               vid = QCA8K_PORT_VID_DEF;
+
+       return qca8k_fdb_add(priv, addr, port_mask, vid,
+                            QCA8K_ATU_STATUS_STATIC);
+}
+
+int qca8k_port_fdb_add(struct dsa_switch *ds, int port,
+                      const unsigned char *addr, u16 vid,
+                      struct dsa_db db)
+{
+       struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+       u16 port_mask = BIT(port);
+
+       return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
+}
+
+int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
+                      const unsigned char *addr, u16 vid,
+                      struct dsa_db db)
+{
+       struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+       u16 port_mask = BIT(port);
+
+       if (!vid)
+               vid = QCA8K_PORT_VID_DEF;
+
+       return qca8k_fdb_del(priv, addr, port_mask, vid);
+}
+
+int qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
+                       dsa_fdb_dump_cb_t *cb, void *data)
+{
+       struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+       struct qca8k_fdb _fdb = { 0 };
+       int cnt = QCA8K_NUM_FDB_RECORDS;
+       bool is_static;
+       int ret = 0;
+
+       mutex_lock(&priv->reg_mutex);
+       while (cnt-- && !qca8k_fdb_next(priv, &_fdb, port)) {
+               if (!_fdb.aging)
+                       break;
+               is_static = (_fdb.aging == QCA8K_ATU_STATUS_STATIC);
+               ret = cb(_fdb.mac, _fdb.vid, is_static, data);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&priv->reg_mutex);
+
+       return 0;
+}
+
+int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
+                      const struct switchdev_obj_port_mdb *mdb,
+                      struct dsa_db db)
+{
+       struct qca8k_priv *priv = ds->priv;
+       const u8 *addr = mdb->addr;
+       u16 vid = mdb->vid;
+
+       return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
+}
+
+int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
+                      const struct switchdev_obj_port_mdb *mdb,
+                      struct dsa_db db)
+{
+       struct qca8k_priv *priv = ds->priv;
+       const u8 *addr = mdb->addr;
+       u16 vid = mdb->vid;
+
+       return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
+}
index e7d4df253b8c028b66c96864527442577fe423f5..9da7928de83ca62f2cf5b1ea75322dd7ccce5957 100644 (file)
@@ -438,11 +438,9 @@ int qca8k_read(struct qca8k_priv *priv, u32 reg, u32 *val);
 int qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val);
 int qca8k_rmw(struct qca8k_priv *priv, u32 reg, u32 mask, u32 write_val);
 
-int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len);
-int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len);
-
 /* 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 */
 void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data);
@@ -473,6 +471,27 @@ int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu);
 int qca8k_port_max_mtu(struct dsa_switch *ds, int port);
 
 /* Common fast age function */
+void qca8k_port_fast_age(struct dsa_switch *ds, int port);
 int qca8k_set_ageing_time(struct dsa_switch *ds, unsigned int msecs);
 
+/* Common FDB function */
+int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
+                         u16 port_mask, u16 vid);
+int qca8k_port_fdb_add(struct dsa_switch *ds, int port,
+                      const unsigned char *addr, u16 vid,
+                      struct dsa_db db);
+int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
+                      const unsigned char *addr, u16 vid,
+                      struct dsa_db db);
+int qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
+                       dsa_fdb_dump_cb_t *cb, void *data);
+
+/* Common MDB function */
+int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
+                      const struct switchdev_obj_port_mdb *mdb,
+                      struct dsa_db db);
+int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
+                      const struct switchdev_obj_port_mdb *mdb,
+                      struct dsa_db db);
+
 #endif /* __QCA8K_H */