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:
Родитель
f6ef47e5bd
Коммит
0568c3bf3f
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче