--- v5
+++ v4
@@ -1,97 +1,69 @@
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
+Some chips in the ocelot series such as VSC9959 support Per-Stream
+Filtering and Policing(PSFP), which is processing after VCAP blocks.
+We set this block on chain 30000 and set vcap IS2 chain to goto PSFP
+chain if hardware support.
-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: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
---
- drivers/net/ethernet/mscc/ocelot.c | 50 ++++++++++++++++++++++++++++++
- include/soc/mscc/ocelot.h | 5 +++
- 2 files changed, 55 insertions(+)
+ drivers/net/ethernet/mscc/ocelot_flower.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
-diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
-index 35006b0fb963..dc65247b91be 100644
---- a/drivers/net/ethernet/mscc/ocelot.c
-+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -114,6 +114,56 @@ int ocelot_mact_forget(struct ocelot *ocelot,
+diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
+index 8b843d3c9189..ce812194e44c 100644
+--- a/drivers/net/ethernet/mscc/ocelot_flower.c
++++ b/drivers/net/ethernet/mscc/ocelot_flower.c
+@@ -20,6 +20,9 @@
+ (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
+ #define VCAP_IS2_CHAIN(lookup, pag) \
+ (2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
++/* PSFP chain and block ID */
++#define PSFP_BLOCK_ID OCELOT_NUM_VCAP_BLOCKS
++#define OCELOT_PSFP_CHAIN (3 * VCAP_BLOCK)
+
+ static int ocelot_chain_to_block(int chain, bool ingress)
+ {
+@@ -46,6 +49,9 @@ static int ocelot_chain_to_block(int chain, bool ingress)
+ if (chain == VCAP_IS2_CHAIN(lookup, pag))
+ return VCAP_IS2;
+
++ if (chain == OCELOT_PSFP_CHAIN)
++ return PSFP_BLOCK_ID;
++
+ return -EOPNOTSUPP;
}
- EXPORT_SYMBOL(ocelot_mact_forget);
-+int ocelot_mact_lookup(struct ocelot *ocelot, int *dst_idx,
-+ struct ocelot_mact_entry *entry)
-+{
-+ int val;
+@@ -84,7 +90,8 @@ static bool ocelot_is_goto_target_valid(int goto_target, int chain,
+ goto_target == VCAP_IS1_CHAIN(1) ||
+ goto_target == VCAP_IS1_CHAIN(2) ||
+ goto_target == VCAP_IS2_CHAIN(0, 0) ||
+- goto_target == VCAP_IS2_CHAIN(1, 0));
++ goto_target == VCAP_IS2_CHAIN(1, 0) ||
++ goto_target == OCELOT_PSFP_CHAIN);
+
+ if (chain == VCAP_IS1_CHAIN(0))
+ return (goto_target == VCAP_IS1_CHAIN(1));
+@@ -111,7 +118,11 @@ static bool ocelot_is_goto_target_valid(int goto_target, int chain,
+ if (chain == VCAP_IS2_CHAIN(0, pag))
+ return (goto_target == VCAP_IS2_CHAIN(1, pag));
+
+- /* VCAP IS2 lookup 1 cannot jump anywhere */
++ /* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */
++ for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
++ if (chain == VCAP_IS2_CHAIN(1, pag))
++ return (goto_target == OCELOT_PSFP_CHAIN);
+
-+ mutex_lock(&ocelot->mact_lock);
-+
-+ ocelot_mact_select(ocelot, entry->mac, entry->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);
-+ entry->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,
-+ struct ocelot_mact_entry *entry, u32 data)
-+{
-+ int ret;
-+
-+ mutex_lock(&ocelot->mact_lock);
-+ ocelot_write(ocelot, data, ANA_TABLES_STREAMDATA);
-+ mutex_unlock(&ocelot->mact_lock);
-+
-+ ret = ocelot_mact_learn(ocelot, dst_idx, entry->mac, entry->vid,
-+ entry->type);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(ocelot_mact_learn_streamdata);
-+
- static void ocelot_mact_init(struct ocelot *ocelot)
- {
- /* Configure the learning mode entries attributes:
-diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
-index e6773f4d09ce..455293652257 100644
---- a/include/soc/mscc/ocelot.h
-+++ b/include/soc/mscc/ocelot.h
-@@ -926,6 +926,11 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
- bool tx_pause, bool rx_pause,
- unsigned long quirks);
+ return false;
+ }
-+int ocelot_mact_lookup(struct ocelot *ocelot, int *dst_idx,
-+ struct ocelot_mact_entry *entry);
-+int ocelot_mact_learn_streamdata(struct ocelot *ocelot, int dst_idx,
-+ struct ocelot_mact_entry *entry, u32 data);
-+
- #if IS_ENABLED(CONFIG_BRIDGE_MRP)
- int ocelot_mrp_add(struct ocelot *ocelot, int port,
- const struct switchdev_obj_mrp *mrp);
+@@ -353,7 +364,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
+
+ if (filter->goto_target == -1) {
+ if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
+- chain == 0) {
++ chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
+ allow_missing_goto_target = true;
+ } else {
+ NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
--
2.17.1