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: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Xiaoliang Yang 2021-11-18 18:11:57 +08:00 коммит произвёл David S. Miller
Родитель f6ef47e5bd
Коммит 0568c3bf3f
3 изменённых файлов: 97 добавлений и 19 удалений

Просмотреть файл

@ -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:

Просмотреть файл

@ -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

Просмотреть файл

@ -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);