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,
|
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
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 {
|
||||||
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 {
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче