OSDN Git Service

net: mscc: ocelot: add MAC table stream learn and lookup operations
authorXiaoliang Yang <xiaoliang.yang_1@nxp.com>
Thu, 18 Nov 2021 10:11:57 +0000 (18:11 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Nov 2021 12:07:23 +0000 (12:07 +0000)
ocelot_mact_learn_streamdata() can be used in VSC9959 to overwrite an
FDB entry with stream data. The stream data includes SFID and SSID which
can be used for PSFP and FRER set.

ocelot_mact_lookup() can be used to check if the given {DMAC, VID} FDB
entry is exist, and also can retrieve the DEST_IDX and entry type for
the FDB entry.

Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot.h
include/soc/mscc/ocelot.h

index e6c18b5..9e98191 100644 (file)
@@ -61,9 +61,9 @@ static void ocelot_mact_select(struct ocelot *ocelot,
 
 }
 
-int ocelot_mact_learn(struct ocelot *ocelot, int port,
-                     const unsigned char mac[ETH_ALEN],
-                     unsigned int vid, enum macaccess_entry_type type)
+static int __ocelot_mact_learn(struct ocelot *ocelot, int port,
+                              const unsigned char mac[ETH_ALEN],
+                              unsigned int vid, enum macaccess_entry_type type)
 {
        u32 cmd = ANA_TABLES_MACACCESS_VALID |
                ANA_TABLES_MACACCESS_DEST_IDX(port) |
@@ -83,8 +83,6 @@ 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 */
@@ -92,9 +90,20 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
 
        err = ocelot_mact_wait_for_completion(ocelot);
 
+       return err;
+}
+
+int ocelot_mact_learn(struct ocelot *ocelot, int port,
+                     const unsigned char mac[ETH_ALEN],
+                     unsigned int vid, enum macaccess_entry_type type)
+{
+       int ret;
+
+       mutex_lock(&ocelot->mact_lock);
+       ret = __ocelot_mact_learn(ocelot, port, mac, vid, type);
        mutex_unlock(&ocelot->mact_lock);
 
-       return err;
+       return ret;
 }
 EXPORT_SYMBOL(ocelot_mact_learn);
 
@@ -120,6 +129,66 @@ int ocelot_mact_forget(struct ocelot *ocelot,
 }
 EXPORT_SYMBOL(ocelot_mact_forget);
 
+int ocelot_mact_lookup(struct ocelot *ocelot, int *dst_idx,
+                      const unsigned char mac[ETH_ALEN],
+                      unsigned int vid, enum macaccess_entry_type *type)
+{
+       int val;
+
+       mutex_lock(&ocelot->mact_lock);
+
+       ocelot_mact_select(ocelot, mac, vid);
+
+       /* Issue a read command with MACACCESS_VALID=1. */
+       ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
+                    ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_READ),
+                    ANA_TABLES_MACACCESS);
+
+       if (ocelot_mact_wait_for_completion(ocelot)) {
+               mutex_unlock(&ocelot->mact_lock);
+               return -ETIMEDOUT;
+       }
+
+       /* Read back the entry flags */
+       val = ocelot_read(ocelot, ANA_TABLES_MACACCESS);
+
+       mutex_unlock(&ocelot->mact_lock);
+
+       if (!(val & ANA_TABLES_MACACCESS_VALID))
+               return -ENOENT;
+
+       *dst_idx = ANA_TABLES_MACACCESS_DEST_IDX_X(val);
+       *type = ANA_TABLES_MACACCESS_ENTRYTYPE_X(val);
+
+       return 0;
+}
+EXPORT_SYMBOL(ocelot_mact_lookup);
+
+int ocelot_mact_learn_streamdata(struct ocelot *ocelot, int dst_idx,
+                                const unsigned char mac[ETH_ALEN],
+                                unsigned int vid,
+                                enum macaccess_entry_type type,
+                                int sfid, int ssid)
+{
+       int ret;
+
+       mutex_lock(&ocelot->mact_lock);
+
+       ocelot_write(ocelot,
+                    (sfid < 0 ? 0 : ANA_TABLES_STREAMDATA_SFID_VALID) |
+                    ANA_TABLES_STREAMDATA_SFID(sfid) |
+                    (ssid < 0 ? 0 : ANA_TABLES_STREAMDATA_SSID_VALID) |
+                    ANA_TABLES_STREAMDATA_SSID(ssid),
+                    ANA_TABLES_STREAMDATA);
+
+       ret = __ocelot_mact_learn(ocelot, dst_idx, mac, vid, type);
+
+       mutex_unlock(&ocelot->mact_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(ocelot_mact_learn_streamdata);
+
 static void ocelot_mact_init(struct ocelot *ocelot)
 {
        /* Configure the learning mode entries attributes:
index e43da09..1eb0b5a 100644 (file)
@@ -55,19 +55,6 @@ struct ocelot_dump_ctx {
        int idx;
 };
 
-/* 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
index fef3a36..1d5ff11 100644 (file)
@@ -593,6 +593,19 @@ enum ocelot_sb_pool {
        OCELOT_SB_POOL_NUM,
 };
 
+/* 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,
+};
+
 #define OCELOT_QUIRK_PCS_PERFORMS_RATE_ADAPTATION      BIT(0)
 #define OCELOT_QUIRK_QSGMII_PORTS_MUST_BE_UP           BIT(1)
 
@@ -870,6 +883,15 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
                                bool tx_pause, bool rx_pause,
                                unsigned long quirks);
 
+int ocelot_mact_lookup(struct ocelot *ocelot, int *dst_idx,
+                      const unsigned char mac[ETH_ALEN],
+                      unsigned int vid, enum macaccess_entry_type *type);
+int ocelot_mact_learn_streamdata(struct ocelot *ocelot, int dst_idx,
+                                const unsigned char mac[ETH_ALEN],
+                                unsigned int vid,
+                                enum macaccess_entry_type type,
+                                int sfid, int ssid);
+
 #if IS_ENABLED(CONFIG_BRIDGE_MRP)
 int ocelot_mrp_add(struct ocelot *ocelot, int port,
                   const struct switchdev_obj_mrp *mrp);