--- v5
+++ v4
@@ -1,188 +1,88 @@
From: Vladimir Oltean <vladimir.oltean@nxp.com>
-DSA would like to remove the rtnl_lock from its
-SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE handlers, and the felix driver uses
-the same MAC table functions as ocelot.
-
-This means that the MAC table functions will no longer be implicitly
-serialized with respect to each other by the rtnl_mutex, we need to add
-a dedicated lock in ocelot for the non-atomic operations of selecting a
-MAC table row, reading/writing what we want and polling for completion.
+Felix DSA needs to use this struct to export MAC table write and lookup
+operations as well, for its stream identification functions, so export
+them in preparation of that.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
---
- drivers/net/ethernet/mscc/ocelot.c | 53 +++++++++++++++++++++++-------
- include/soc/mscc/ocelot.h | 3 ++
- 2 files changed, 44 insertions(+), 12 deletions(-)
+ drivers/net/ethernet/mscc/ocelot.c | 6 ------
+ drivers/net/ethernet/mscc/ocelot.h | 13 -------------
+ include/soc/mscc/ocelot.h | 19 +++++++++++++++++++
+ 3 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
-index c581b955efb3..9f481cf19931 100644
+index c581b955efb3..39a5cee81677 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -20,11 +20,13 @@ struct ocelot_mact_entry {
- enum macaccess_entry_type type;
- };
+@@ -14,12 +14,6 @@
+ #define TABLE_UPDATE_SLEEP_US 10
+ #define TABLE_UPDATE_TIMEOUT_US 100000
-+/* Must be called with &ocelot->mact_lock held */
+-struct ocelot_mact_entry {
+- u8 mac[ETH_ALEN];
+- u16 vid;
+- enum macaccess_entry_type type;
+-};
+-
static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot)
{
return ocelot_read(ocelot, ANA_TABLES_MACACCESS);
- }
+diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
+index 1952d6a1b98a..a77050b13d18 100644
+--- a/drivers/net/ethernet/mscc/ocelot.h
++++ b/drivers/net/ethernet/mscc/ocelot.h
+@@ -54,19 +54,6 @@ struct ocelot_dump_ctx {
+ int idx;
+ };
-+/* Must be called with &ocelot->mact_lock held */
- static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot)
- {
- u32 val;
-@@ -36,6 +38,7 @@ static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot)
- TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US);
- }
-
-+/* Must be called with &ocelot->mact_lock held */
- static void ocelot_mact_select(struct ocelot *ocelot,
- const unsigned char mac[ETH_ALEN],
- unsigned int vid)
-@@ -67,6 +70,7 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
- ANA_TABLES_MACACCESS_ENTRYTYPE(type) |
- ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN);
- unsigned int mc_ports;
-+ int err;
-
- /* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */
- if (type == ENTRYTYPE_MACv4)
-@@ -79,18 +83,28 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
- if (mc_ports & BIT(ocelot->num_phys_ports))
- cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY;
-
-+ mutex_lock(&ocelot->mact_lock);
-+
- ocelot_mact_select(ocelot, mac, vid);
-
- /* Issue a write command */
- ocelot_write(ocelot, cmd, ANA_TABLES_MACACCESS);
-
-- return ocelot_mact_wait_for_completion(ocelot);
-+ err = ocelot_mact_wait_for_completion(ocelot);
-+
-+ mutex_unlock(&ocelot->mact_lock);
-+
-+ return err;
- }
- EXPORT_SYMBOL(ocelot_mact_learn);
-
- int ocelot_mact_forget(struct ocelot *ocelot,
- const unsigned char mac[ETH_ALEN], unsigned int vid)
- {
-+ int err;
-+
-+ mutex_lock(&ocelot->mact_lock);
-+
- ocelot_mact_select(ocelot, mac, vid);
-
- /* Issue a forget command */
-@@ -98,7 +112,11 @@ int ocelot_mact_forget(struct ocelot *ocelot,
- ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET),
- ANA_TABLES_MACACCESS);
-
-- return ocelot_mact_wait_for_completion(ocelot);
-+ err = ocelot_mact_wait_for_completion(ocelot);
-+
-+ mutex_unlock(&ocelot->mact_lock);
-+
-+ return err;
- }
- EXPORT_SYMBOL(ocelot_mact_forget);
-
-@@ -114,7 +132,9 @@ static void ocelot_mact_init(struct ocelot *ocelot)
- | ANA_AGENCTRL_LEARN_IGNORE_VLAN,
- ANA_AGENCTRL);
-
-- /* Clear the MAC table */
-+ /* Clear the MAC table. We are not concurrent with anyone, so
-+ * holding &ocelot->mact_lock is pointless.
-+ */
- ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS);
- }
-
-@@ -1028,6 +1048,7 @@ int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
- }
- EXPORT_SYMBOL(ocelot_port_fdb_do_dump);
-
-+/* Must be called with &ocelot->mact_lock held */
- static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
- struct ocelot_mact_entry *entry)
- {
-@@ -1078,33 +1099,40 @@ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
- int ocelot_fdb_dump(struct ocelot *ocelot, int port,
- dsa_fdb_dump_cb_t *cb, void *data)
- {
-+ int err = 0;
- int i, j;
-
-+ /* We could take the lock just around ocelot_mact_read, but doing so
-+ * thousands of times in a row seems rather pointless and inefficient.
-+ */
-+ mutex_lock(&ocelot->mact_lock);
-+
- /* Loop through all the mac tables entries. */
- for (i = 0; i < ocelot->num_mact_rows; i++) {
- for (j = 0; j < 4; j++) {
- struct ocelot_mact_entry entry;
- bool is_static;
-- int ret;
-
-- ret = ocelot_mact_read(ocelot, port, i, j, &entry);
-+ err = ocelot_mact_read(ocelot, port, i, j, &entry);
- /* If the entry is invalid (wrong port, invalid...),
- * skip it.
- */
-- if (ret == -EINVAL)
-+ if (err == -EINVAL)
- continue;
-- else if (ret)
-- return ret;
-+ else if (err)
-+ break;
-
- is_static = (entry.type == ENTRYTYPE_LOCKED);
-
-- ret = cb(entry.mac, entry.vid, is_static, data);
-- if (ret)
-- return ret;
-+ err = cb(entry.mac, entry.vid, is_static, data);
-+ if (err)
-+ break;
- }
- }
-
-- return 0;
-+ mutex_unlock(&ocelot->mact_lock);
-+
-+ return err;
- }
- EXPORT_SYMBOL(ocelot_fdb_dump);
-
-@@ -2085,6 +2113,7 @@ int ocelot_init(struct ocelot *ocelot)
-
- mutex_init(&ocelot->stats_lock);
- mutex_init(&ocelot->ptp_lock);
-+ mutex_init(&ocelot->mact_lock);
- spin_lock_init(&ocelot->ptp_clock_lock);
- snprintf(queue_name, sizeof(queue_name), "%s-stats",
- dev_name(ocelot->dev));
+-/* MAC table entry types.
+- * ENTRYTYPE_NORMAL is subject to aging.
+- * ENTRYTYPE_LOCKED is not subject to aging.
+- * ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast.
+- * ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast.
+- */
+-enum macaccess_entry_type {
+- ENTRYTYPE_NORMAL = 0,
+- ENTRYTYPE_LOCKED,
+- ENTRYTYPE_MACv4,
+- ENTRYTYPE_MACv6,
+-};
+-
+ /* A (PGID) port mask structure, encoding the 2^ocelot->num_phys_ports
+ * possibilities of egress port masks for L2 multicast traffic.
+ * For a switch with 9 user ports, there are 512 possible port masks, but the
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
-index 06706a9fd5b1..682cd058096c 100644
+index 06706a9fd5b1..32b3c60d6046 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
-@@ -674,6 +674,9 @@ struct ocelot {
- struct delayed_work stats_work;
- struct workqueue_struct *stats_queue;
+@@ -698,6 +698,25 @@ struct ocelot_skb_cb {
+ u8 ts_id;
+ };
-+ /* Lock for serializing access to the MAC table */
-+ struct mutex mact_lock;
++/* MAC table entry types.
++ * ENTRYTYPE_NORMAL is subject to aging.
++ * ENTRYTYPE_LOCKED is not subject to aging.
++ * ENTRYTYPE_MACv4 is not subject to aging. For IPv4 multicast.
++ * ENTRYTYPE_MACv6 is not subject to aging. For IPv6 multicast.
++ */
++enum macaccess_entry_type {
++ ENTRYTYPE_NORMAL = 0,
++ ENTRYTYPE_LOCKED,
++ ENTRYTYPE_MACv4,
++ ENTRYTYPE_MACv6,
++};
+
- struct workqueue_struct *owq;
++struct ocelot_mact_entry {
++ u8 mac[ETH_ALEN];
++ u16 vid;
++ enum macaccess_entry_type type;
++};
++
+ #define OCELOT_SKB_CB(skb) \
+ ((struct ocelot_skb_cb *)((skb)->cb))
- u8 ptp:1;
--
2.17.1