Commit 0568c3bf authored by Xiaoliang Yang's avatar Xiaoliang Yang Committed by David S. Miller

net: mscc: ocelot: add MAC table stream learn and lookup operations

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: default avatarXiaoliang Yang <xiaoliang.yang_1@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f6ef47e5
...@@ -61,9 +61,9 @@ static void ocelot_mact_select(struct ocelot *ocelot, ...@@ -61,9 +61,9 @@ static void ocelot_mact_select(struct ocelot *ocelot,
} }
int ocelot_mact_learn(struct ocelot *ocelot, int port, static int __ocelot_mact_learn(struct ocelot *ocelot, int port,
const unsigned char mac[ETH_ALEN], const unsigned char mac[ETH_ALEN],
unsigned int vid, enum macaccess_entry_type type) unsigned int vid, enum macaccess_entry_type type)
{ {
u32 cmd = ANA_TABLES_MACACCESS_VALID | u32 cmd = ANA_TABLES_MACACCESS_VALID |
ANA_TABLES_MACACCESS_DEST_IDX(port) | ANA_TABLES_MACACCESS_DEST_IDX(port) |
...@@ -83,8 +83,6 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, ...@@ -83,8 +83,6 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
if (mc_ports & BIT(ocelot->num_phys_ports)) if (mc_ports & BIT(ocelot->num_phys_ports))
cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY; cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY;
mutex_lock(&ocelot->mact_lock);
ocelot_mact_select(ocelot, mac, vid); ocelot_mact_select(ocelot, mac, vid);
/* Issue a write command */ /* Issue a write command */
...@@ -92,9 +90,20 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, ...@@ -92,9 +90,20 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
err = ocelot_mact_wait_for_completion(ocelot); 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); mutex_unlock(&ocelot->mact_lock);
return err; return ret;
} }
EXPORT_SYMBOL(ocelot_mact_learn); EXPORT_SYMBOL(ocelot_mact_learn);
...@@ -120,6 +129,66 @@ int ocelot_mact_forget(struct ocelot *ocelot, ...@@ -120,6 +129,66 @@ int ocelot_mact_forget(struct ocelot *ocelot,
} }
EXPORT_SYMBOL(ocelot_mact_forget); 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) static void ocelot_mact_init(struct ocelot *ocelot)
{ {
/* Configure the learning mode entries attributes: /* Configure the learning mode entries attributes:
......
...@@ -55,19 +55,6 @@ struct ocelot_dump_ctx { ...@@ -55,19 +55,6 @@ struct ocelot_dump_ctx {
int idx; 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 /* A (PGID) port mask structure, encoding the 2^ocelot->num_phys_ports
* possibilities of egress port masks for L2 multicast traffic. * possibilities of egress port masks for L2 multicast traffic.
* For a switch with 9 user ports, there are 512 possible port masks, but the * For a switch with 9 user ports, there are 512 possible port masks, but the
......
...@@ -593,6 +593,19 @@ enum ocelot_sb_pool { ...@@ -593,6 +593,19 @@ enum ocelot_sb_pool {
OCELOT_SB_POOL_NUM, 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_PCS_PERFORMS_RATE_ADAPTATION BIT(0)
#define OCELOT_QUIRK_QSGMII_PORTS_MUST_BE_UP BIT(1) #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, ...@@ -870,6 +883,15 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
bool tx_pause, bool rx_pause, bool tx_pause, bool rx_pause,
unsigned long quirks); 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) #if IS_ENABLED(CONFIG_BRIDGE_MRP)
int ocelot_mrp_add(struct ocelot *ocelot, int port, int ocelot_mrp_add(struct ocelot *ocelot, int port,
const struct switchdev_obj_mrp *mrp); const struct switchdev_obj_mrp *mrp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment