}
 
-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) |
        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 */
 
        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);
 
 }
 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:
 
        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)
 
                                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);