123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- From ba8f870dfa635113ce6e8095a5eb1835ecde2e9e Mon Sep 17 00:00:00 2001
- From: Ansuel Smith <[email protected]>
- Date: Mon, 22 Nov 2021 16:23:48 +0100
- Subject: net: dsa: qca8k: add support for mdb_add/del
- Add support for mdb add/del function. The ARL table is used to insert
- the rule. The rule will be searched, deleted and reinserted with the
- port mask updated. The function will check if the rule has to be updated
- or insert directly with no deletion of the old rule.
- If every port is removed from the port mask, the rule is removed.
- The rule is set STATIC in the ARL table (aka it doesn't age) to not be
- flushed by fast age function.
- Signed-off-by: Ansuel Smith <[email protected]>
- Reviewed-by: Vladimir Oltean <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- drivers/net/dsa/qca8k.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 99 insertions(+)
- diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
- index 45e769b9166b8..67742fbd80409 100644
- --- a/drivers/net/dsa/qca8k.c
- +++ b/drivers/net/dsa/qca8k.c
- @@ -435,6 +435,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv)
- 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)
- {
- @@ -1925,6 +2000,28 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
- return 0;
- }
-
- +static int
- +qca8k_port_mdb_add(struct dsa_switch *ds, int port,
- + const struct switchdev_obj_port_mdb *mdb)
- +{
- + 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 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_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
- struct netlink_ext_ack *extack)
- @@ -2033,6 +2130,8 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
- .port_fdb_add = qca8k_port_fdb_add,
- .port_fdb_del = qca8k_port_fdb_del,
- .port_fdb_dump = qca8k_port_fdb_dump,
- + .port_mdb_add = qca8k_port_mdb_add,
- + .port_mdb_del = qca8k_port_mdb_del,
- .port_vlan_filtering = qca8k_port_vlan_filtering,
- .port_vlan_add = qca8k_port_vlan_add,
- .port_vlan_del = qca8k_port_vlan_del,
- --
- cgit 1.2.3-1.el7
|