netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA
@ 2020-02-24 13:08 Vladimir Oltean
  2020-02-24 13:08 ` [PATCH net-next 01/10] net: mscc: ocelot: make ocelot_ace_rule support multiple ports Vladimir Oltean
                   ` (10 more replies)
  0 siblings, 11 replies; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

This series is a proposal on how to wire up the tc-flower callbacks into
DSA. The example taken is the Microchip Felix switch, whose core
implementation is actually located in drivers/net/ethernet/mscc/.

The proposal is largely a compromise solution. The DSA middle layer
handles just enough to get to the interesting stuff (FLOW_CLS_REPLACE,
FLOW_CLS_DESTROY, FLOW_CLS_STATS), but also thin enough to let drivers
decide what filter keys and actions they support without worrying that
the DSA middle layer will grow exponentially. I am far from being an
expert, so I am asking reviewers to please voice your opinion if you
think it can be done differently, with better results.

The bulk of the work was actually refactoring the ocelot driver enough
to allow the VCAP (Versatile Content-Aware Processor) code for vsc7514
and the vsc9959 switch cores to live together.

Flow block offloads have not been tested yet, only filters attached to a
single port. It might be as simple as replacing ocelot_ace_rule_create
with something smarter, it might be more complicated, I haven't tried
yet.

I should point out that the tc-matchall filter offload is not
implemented in the same manner in current mainline. Florian has already
went all the way down into exposing actual per-action callbacks,
starting with port mirroring. Because currently only mirred is supported
by this DSA mid layer, everything else will return -EOPNOTSUPP. So even
though ocelot supports matchall (aka port-based) policers, we don't have
a call path to call into them.  Personally I think that this is not
going to scale for tc-matchall (there may be policers, traps, drops,
VLAN retagging, etc etc), and that we should consider replacing the port
mirroring callbacks in DSA with simple accessors to
TC_CLSMATCHALL_REPLACE and TC_CLSMATCHALL_DESTROY, just like for flower.
That means that drivers which currently implement the port mirroring
callbacks will need to have some extra "if" conditions now, in order for
them to call their port mirroring implementations.

Vladimir Oltean (9):
  net: mscc: ocelot: simplify tc-flower offload structures
  net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names
    with "ace"
  net: mscc: ocelot: return directly in
    ocelot_cls_flower_{replace,destroy}
  net: mscc: ocelot: don't rely on preprocessor for vcap key/action
    packing
  net: mscc: ocelot: remove port_pcs_init indirection for VSC7514
  net: mscc: ocelot: parameterize the vcap_is2 properties
  net: dsa: Refactor matchall mirred action to separate function
  net: dsa: Add bypass operations for the flower classifier-action
    filter
  net: dsa: felix: Wire up the ocelot cls_flower methods

Yangbo Lu (1):
  net: mscc: ocelot: make ocelot_ace_rule support multiple ports

 drivers/net/dsa/ocelot/felix.c            |  31 ++
 drivers/net/dsa/ocelot/felix.h            |   3 +
 drivers/net/dsa/ocelot/felix_vsc9959.c    | 126 ++++++
 drivers/net/ethernet/mscc/ocelot.c        |  20 +-
 drivers/net/ethernet/mscc/ocelot_ace.c    | 472 +++++++++++-----------
 drivers/net/ethernet/mscc/ocelot_ace.h    |  26 +-
 drivers/net/ethernet/mscc/ocelot_board.c  | 151 +++++--
 drivers/net/ethernet/mscc/ocelot_flower.c | 256 ++++--------
 drivers/net/ethernet/mscc/ocelot_tc.c     |  22 +-
 drivers/net/ethernet/mscc/ocelot_vcap.h   | 403 ------------------
 include/net/dsa.h                         |   6 +
 include/soc/mscc/ocelot.h                 |  20 +-
 include/soc/mscc/ocelot_vcap.h            | 205 ++++++++++
 net/dsa/slave.c                           | 128 ++++--
 14 files changed, 954 insertions(+), 915 deletions(-)
 delete mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h
 create mode 100644 include/soc/mscc/ocelot_vcap.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH net-next 01/10] net: mscc: ocelot: make ocelot_ace_rule support multiple ports
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-27  8:02   ` Allan W. Nielsen
  2020-02-24 13:08 ` [PATCH net-next 02/10] net: mscc: ocelot: simplify tc-flower offload structures Vladimir Oltean
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Yangbo Lu <yangbo.lu@nxp.com>

The ocelot_ace_rule is port specific now. Make it flexible to
be able to support multiple ports too.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_ace.c    | 14 +++++++-------
 drivers/net/ethernet/mscc/ocelot_ace.h    |  4 ++--
 drivers/net/ethernet/mscc/ocelot_flower.c |  8 ++++----
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
index 86fc6e6b46dd..18670645d47f 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -352,7 +352,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 	data.type = IS2_ACTION_TYPE_NORMAL;
 
 	VCAP_KEY_ANY_SET(PAG);
-	VCAP_KEY_SET(IGR_PORT_MASK, 0, ~BIT(ace->chip_port));
+	VCAP_KEY_SET(IGR_PORT_MASK, 0, ~ace->ingress_port_mask);
 	VCAP_KEY_BIT_SET(FIRST, OCELOT_VCAP_BIT_1);
 	VCAP_KEY_BIT_SET(HOST_MATCH, OCELOT_VCAP_BIT_ANY);
 	VCAP_KEY_BIT_SET(L2_MC, ace->dmac_mc);
@@ -576,7 +576,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 
 static void is2_entry_get(struct ocelot_ace_rule *rule, int ix)
 {
-	struct ocelot *op = rule->port->ocelot;
+	struct ocelot *op = rule->ocelot;
 	struct vcap_data data;
 	int row = (ix / 2);
 	u32 cnt;
@@ -655,11 +655,11 @@ int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule)
 	/* Move down the rules to make place for the new rule */
 	for (i = acl_block->count - 1; i > index; i--) {
 		ace = ocelot_ace_rule_get_rule_index(acl_block, i);
-		is2_entry_set(rule->port->ocelot, i, ace);
+		is2_entry_set(rule->ocelot, i, ace);
 	}
 
 	/* Now insert the new rule */
-	is2_entry_set(rule->port->ocelot, index, rule);
+	is2_entry_set(rule->ocelot, index, rule);
 	return 0;
 }
 
@@ -697,11 +697,11 @@ int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule)
 	/* Move up all the blocks over the deleted rule */
 	for (i = index; i < acl_block->count; i++) {
 		ace = ocelot_ace_rule_get_rule_index(acl_block, i);
-		is2_entry_set(rule->port->ocelot, i, ace);
+		is2_entry_set(rule->ocelot, i, ace);
 	}
 
 	/* Now delete the last rule, because it is duplicated */
-	is2_entry_set(rule->port->ocelot, acl_block->count, &del_ace);
+	is2_entry_set(rule->ocelot, acl_block->count, &del_ace);
 
 	return 0;
 }
@@ -717,7 +717,7 @@ int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule)
 	/* After we get the result we need to clear the counters */
 	tmp = ocelot_ace_rule_get_rule_index(acl_block, index);
 	tmp->stats.pkts = 0;
-	is2_entry_set(rule->port->ocelot, index, tmp);
+	is2_entry_set(rule->ocelot, index, tmp);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h
index c08e3e8482e7..2927ac83741b 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.h
+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
@@ -186,14 +186,14 @@ struct ocelot_ace_stats {
 
 struct ocelot_ace_rule {
 	struct list_head list;
-	struct ocelot_port *port;
+	struct ocelot *ocelot;
 
 	u16 prio;
 	u32 id;
 
 	enum ocelot_ace_action action;
 	struct ocelot_ace_stats stats;
-	int chip_port;
+	u16 ingress_port_mask;
 
 	enum ocelot_vcap_bit dmac_mc;
 	enum ocelot_vcap_bit dmac_bc;
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 3d65b99b9734..ffd2bb50cfc3 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -177,8 +177,8 @@ struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
 	if (!rule)
 		return NULL;
 
-	rule->port = &block->priv->port;
-	rule->chip_port = block->priv->chip_port;
+	rule->ocelot = block->priv->port.ocelot;
+	rule->ingress_port_mask = BIT(block->priv->chip_port);
 	return rule;
 }
 
@@ -213,7 +213,7 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
 	int ret;
 
 	rule.prio = f->common.prio;
-	rule.port = &port_block->priv->port;
+	rule.ocelot = port_block->priv->port.ocelot;
 	rule.id = f->cookie;
 
 	ret = ocelot_ace_rule_offload_del(&rule);
@@ -231,7 +231,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
 	int ret;
 
 	rule.prio = f->common.prio;
-	rule.port = &port_block->priv->port;
+	rule.ocelot = port_block->priv->port.ocelot;
 	rule.id = f->cookie;
 	ret = ocelot_ace_rule_stats_update(&rule);
 	if (ret)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 02/10] net: mscc: ocelot: simplify tc-flower offload structures
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
  2020-02-24 13:08 ` [PATCH net-next 01/10] net: mscc: ocelot: make ocelot_ace_rule support multiple ports Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-27  8:08   ` Allan W. Nielsen
  2020-02-24 13:08 ` [PATCH net-next 03/10] net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names with "ace" Vladimir Oltean
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The ocelot tc-flower offload binds a second flow block callback (apart
from the one for matchall) just because it uses a different block
private structure (ocelot_port_private for matchall, ocelot_port_block
for flower).

But ocelot_port_block just appears to be boilerplate, and doesn't help
with anything in particular at all, it's just useless glue between the
(global!) struct ocelot_acl_block *block pointer, and a per-netdevice
struct ocelot_port_private *priv.

So let's just simplify that, and make struct ocelot_port_private be the
private structure for the block offload. This makes us able to use the
same flow callback as in the case of matchall.

This also reveals that the struct ocelot_acl_block *block is used rather
strangely, as mentioned above: it is defined globally, allocated at
probe time, and freed at unbind time. So just move the structure to the
main ocelot structure, which gives further opportunity for
simplification.

Also get rid of backpointers from struct ocelot_acl_block and struct
ocelot_ace_rule back to struct ocelot, by reworking the function
prototypes, where necessary, to use a more DSA-friendly "struct ocelot
*ocelot, int port" format.

And finally, remove the debugging prints that were added during
development, since they provide no useful information at this point.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c        |   1 -
 drivers/net/ethernet/mscc/ocelot_ace.c    |  81 +++++------
 drivers/net/ethernet/mscc/ocelot_ace.h    |  24 ++--
 drivers/net/ethernet/mscc/ocelot_flower.c | 155 ++++------------------
 drivers/net/ethernet/mscc/ocelot_tc.c     |  22 +--
 include/soc/mscc/ocelot.h                 |   7 +
 6 files changed, 75 insertions(+), 215 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index b85e4fe9466d..3de8267180e2 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2502,7 +2502,6 @@ void ocelot_deinit(struct ocelot *ocelot)
 	cancel_delayed_work(&ocelot->stats_work);
 	destroy_workqueue(ocelot->stats_queue);
 	mutex_destroy(&ocelot->stats_lock);
-	ocelot_ace_deinit();
 	if (ocelot->ptp_clock)
 		ptp_clock_unregister(ocelot->ptp_clock);
 
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
index 18670645d47f..375c7c6aa7d5 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -12,8 +12,6 @@
 
 #define OCELOT_POLICER_DISCARD 0x17f
 
-static struct ocelot_acl_block *acl_block;
-
 struct vcap_props {
 	const char *name; /* Symbolic name */
 	u16 tg_width; /* Type-group width (in bits) */
@@ -574,15 +572,15 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 	vcap_row_cmd(ocelot, row, VCAP_CMD_WRITE, VCAP_SEL_ALL);
 }
 
-static void is2_entry_get(struct ocelot_ace_rule *rule, int ix)
+static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
+			  int ix)
 {
-	struct ocelot *op = rule->ocelot;
 	struct vcap_data data;
 	int row = (ix / 2);
 	u32 cnt;
 
-	vcap_row_cmd(op, row, VCAP_CMD_READ, VCAP_SEL_COUNTER);
-	vcap_cache2action(op, &data);
+	vcap_row_cmd(ocelot, row, VCAP_CMD_READ, VCAP_SEL_COUNTER);
+	vcap_cache2action(ocelot, &data);
 	data.tg_sw = VCAP_TG_HALF;
 	is2_data_get(&data, ix);
 	cnt = vcap_data_get(data.counter, data.counter_offset,
@@ -641,25 +639,27 @@ ocelot_ace_rule_get_rule_index(struct ocelot_acl_block *block, int index)
 	return NULL;
 }
 
-int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule)
+int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
+				struct ocelot_ace_rule *rule)
 {
+	struct ocelot_acl_block *block = &ocelot->acl_block;
 	struct ocelot_ace_rule *ace;
 	int i, index;
 
 	/* Add rule to the linked list */
-	ocelot_ace_rule_add(acl_block, rule);
+	ocelot_ace_rule_add(block, rule);
 
 	/* Get the index of the inserted rule */
-	index = ocelot_ace_rule_get_index_id(acl_block, rule);
+	index = ocelot_ace_rule_get_index_id(block, rule);
 
 	/* Move down the rules to make place for the new rule */
-	for (i = acl_block->count - 1; i > index; i--) {
-		ace = ocelot_ace_rule_get_rule_index(acl_block, i);
-		is2_entry_set(rule->ocelot, i, ace);
+	for (i = block->count - 1; i > index; i--) {
+		ace = ocelot_ace_rule_get_rule_index(block, i);
+		is2_entry_set(ocelot, i, ace);
 	}
 
 	/* Now insert the new rule */
-	is2_entry_set(rule->ocelot, index, rule);
+	is2_entry_set(ocelot, index, rule);
 	return 0;
 }
 
@@ -680,8 +680,10 @@ static void ocelot_ace_rule_del(struct ocelot_acl_block *block,
 	block->count--;
 }
 
-int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule)
+int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
+				struct ocelot_ace_rule *rule)
 {
+	struct ocelot_acl_block *block = &ocelot->acl_block;
 	struct ocelot_ace_rule del_ace;
 	struct ocelot_ace_rule *ace;
 	int i, index;
@@ -689,59 +691,41 @@ int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule)
 	memset(&del_ace, 0, sizeof(del_ace));
 
 	/* Gets index of the rule */
-	index = ocelot_ace_rule_get_index_id(acl_block, rule);
+	index = ocelot_ace_rule_get_index_id(block, rule);
 
 	/* Delete rule */
-	ocelot_ace_rule_del(acl_block, rule);
+	ocelot_ace_rule_del(block, rule);
 
 	/* Move up all the blocks over the deleted rule */
-	for (i = index; i < acl_block->count; i++) {
-		ace = ocelot_ace_rule_get_rule_index(acl_block, i);
-		is2_entry_set(rule->ocelot, i, ace);
+	for (i = index; i < block->count; i++) {
+		ace = ocelot_ace_rule_get_rule_index(block, i);
+		is2_entry_set(ocelot, i, ace);
 	}
 
 	/* Now delete the last rule, because it is duplicated */
-	is2_entry_set(rule->ocelot, acl_block->count, &del_ace);
+	is2_entry_set(ocelot, block->count, &del_ace);
 
 	return 0;
 }
 
-int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule)
+int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
+				 struct ocelot_ace_rule *rule)
 {
+	struct ocelot_acl_block *block = &ocelot->acl_block;
 	struct ocelot_ace_rule *tmp;
 	int index;
 
-	index = ocelot_ace_rule_get_index_id(acl_block, rule);
-	is2_entry_get(rule, index);
+	index = ocelot_ace_rule_get_index_id(block, rule);
+	is2_entry_get(ocelot, rule, index);
 
 	/* After we get the result we need to clear the counters */
-	tmp = ocelot_ace_rule_get_rule_index(acl_block, index);
+	tmp = ocelot_ace_rule_get_rule_index(block, index);
 	tmp->stats.pkts = 0;
-	is2_entry_set(rule->ocelot, index, tmp);
+	is2_entry_set(ocelot, index, tmp);
 
 	return 0;
 }
 
-static struct ocelot_acl_block *ocelot_acl_block_create(struct ocelot *ocelot)
-{
-	struct ocelot_acl_block *block;
-
-	block = kzalloc(sizeof(*block), GFP_KERNEL);
-	if (!block)
-		return NULL;
-
-	INIT_LIST_HEAD(&block->rules);
-	block->count = 0;
-	block->ocelot = ocelot;
-
-	return block;
-}
-
-static void ocelot_acl_block_destroy(struct ocelot_acl_block *block)
-{
-	kfree(block);
-}
-
 int ocelot_ace_init(struct ocelot *ocelot)
 {
 	struct vcap_data data;
@@ -771,12 +755,7 @@ int ocelot_ace_init(struct ocelot *ocelot)
 	ocelot_write_gix(ocelot, 0x3fffff, ANA_POL_CIR_STATE,
 			 OCELOT_POLICER_DISCARD);
 
-	acl_block = ocelot_acl_block_create(ocelot);
+	INIT_LIST_HEAD(&ocelot->acl_block.rules);
 
 	return 0;
 }
-
-void ocelot_ace_deinit(void)
-{
-	ocelot_acl_block_destroy(acl_block);
-}
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h
index 2927ac83741b..b9a5868e3f15 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.h
+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
@@ -186,7 +186,6 @@ struct ocelot_ace_stats {
 
 struct ocelot_ace_rule {
 	struct list_head list;
-	struct ocelot *ocelot;
 
 	u16 prio;
 	u32 id;
@@ -211,22 +210,17 @@ struct ocelot_ace_rule {
 	} frame;
 };
 
-struct ocelot_acl_block {
-	struct list_head rules;
-	struct ocelot *ocelot;
-	int count;
-};
-
-int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule);
-int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule);
-int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule);
+int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
+				struct ocelot_ace_rule *rule);
+int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
+				struct ocelot_ace_rule *rule);
+int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
+				 struct ocelot_ace_rule *rule);
 
 int ocelot_ace_init(struct ocelot *ocelot);
-void ocelot_ace_deinit(void);
 
-int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
-				      struct flow_block_offload *f);
-void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
-					 struct flow_block_offload *f);
+int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv,
+			       struct flow_cls_offload *f,
+			       bool ingress);
 
 #endif /* _MSCC_OCELOT_ACE_H_ */
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index ffd2bb50cfc3..b9673df6dbc5 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -8,11 +8,6 @@
 
 #include "ocelot_ace.h"
 
-struct ocelot_port_block {
-	struct ocelot_acl_block *block;
-	struct ocelot_port_private *priv;
-};
-
 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
 				      struct ocelot_ace_rule *rule)
 {
@@ -168,8 +163,8 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
 }
 
 static
-struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
-					       struct ocelot_port_block *block)
+struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port,
+					       struct flow_cls_offload *f)
 {
 	struct ocelot_ace_rule *rule;
 
@@ -177,18 +172,17 @@ struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
 	if (!rule)
 		return NULL;
 
-	rule->ocelot = block->priv->port.ocelot;
-	rule->ingress_port_mask = BIT(block->priv->chip_port);
+	rule->ingress_port_mask = BIT(port);
 	return rule;
 }
 
-static int ocelot_flower_replace(struct flow_cls_offload *f,
-				 struct ocelot_port_block *port_block)
+int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
+			      struct flow_cls_offload *f, bool ingress)
 {
 	struct ocelot_ace_rule *rule;
 	int ret;
 
-	rule = ocelot_ace_rule_create(f, port_block);
+	rule = ocelot_ace_rule_create(ocelot, port, f);
 	if (!rule)
 		return -ENOMEM;
 
@@ -198,159 +192,66 @@ static int ocelot_flower_replace(struct flow_cls_offload *f,
 		return ret;
 	}
 
-	ret = ocelot_ace_rule_offload_add(rule);
+	ret = ocelot_ace_rule_offload_add(ocelot, rule);
 	if (ret)
 		return ret;
 
-	port_block->priv->tc.offload_cnt++;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
 
-static int ocelot_flower_destroy(struct flow_cls_offload *f,
-				 struct ocelot_port_block *port_block)
+int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
+			      struct flow_cls_offload *f, bool ingress)
 {
 	struct ocelot_ace_rule rule;
 	int ret;
 
 	rule.prio = f->common.prio;
-	rule.ocelot = port_block->priv->port.ocelot;
 	rule.id = f->cookie;
 
-	ret = ocelot_ace_rule_offload_del(&rule);
+	ret = ocelot_ace_rule_offload_del(ocelot, &rule);
 	if (ret)
 		return ret;
 
-	port_block->priv->tc.offload_cnt--;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
 
-static int ocelot_flower_stats_update(struct flow_cls_offload *f,
-				      struct ocelot_port_block *port_block)
+int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
+			    struct flow_cls_offload *f, bool ingress)
 {
 	struct ocelot_ace_rule rule;
 	int ret;
 
 	rule.prio = f->common.prio;
-	rule.ocelot = port_block->priv->port.ocelot;
 	rule.id = f->cookie;
-	ret = ocelot_ace_rule_stats_update(&rule);
+	ret = ocelot_ace_rule_stats_update(ocelot, &rule);
 	if (ret)
 		return ret;
 
 	flow_stats_update(&f->stats, 0x0, rule.stats.pkts, 0x0);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
 
-static int ocelot_setup_tc_cls_flower(struct flow_cls_offload *f,
-				      struct ocelot_port_block *port_block)
+int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv,
+			       struct flow_cls_offload *f,
+			       bool ingress)
 {
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
+
+	if (!ingress)
+		return -EOPNOTSUPP;
+
 	switch (f->command) {
 	case FLOW_CLS_REPLACE:
-		return ocelot_flower_replace(f, port_block);
+		return ocelot_cls_flower_replace(ocelot, port, f, ingress);
 	case FLOW_CLS_DESTROY:
-		return ocelot_flower_destroy(f, port_block);
+		return ocelot_cls_flower_destroy(ocelot, port, f, ingress);
 	case FLOW_CLS_STATS:
-		return ocelot_flower_stats_update(f, port_block);
+		return ocelot_cls_flower_stats(ocelot, port, f, ingress);
 	default:
 		return -EOPNOTSUPP;
 	}
 }
-
-static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type,
-					   void *type_data, void *cb_priv)
-{
-	struct ocelot_port_block *port_block = cb_priv;
-
-	if (!tc_cls_can_offload_and_chain0(port_block->priv->dev, type_data))
-		return -EOPNOTSUPP;
-
-	switch (type) {
-	case TC_SETUP_CLSFLOWER:
-		return ocelot_setup_tc_cls_flower(type_data, cb_priv);
-	case TC_SETUP_CLSMATCHALL:
-		return 0;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static struct ocelot_port_block*
-ocelot_port_block_create(struct ocelot_port_private *priv)
-{
-	struct ocelot_port_block *port_block;
-
-	port_block = kzalloc(sizeof(*port_block), GFP_KERNEL);
-	if (!port_block)
-		return NULL;
-
-	port_block->priv = priv;
-
-	return port_block;
-}
-
-static void ocelot_port_block_destroy(struct ocelot_port_block *block)
-{
-	kfree(block);
-}
-
-static void ocelot_tc_block_unbind(void *cb_priv)
-{
-	struct ocelot_port_block *port_block = cb_priv;
-
-	ocelot_port_block_destroy(port_block);
-}
-
-int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
-				      struct flow_block_offload *f)
-{
-	struct ocelot_port_block *port_block;
-	struct flow_block_cb *block_cb;
-	int ret;
-
-	if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
-		return -EOPNOTSUPP;
-
-	block_cb = flow_block_cb_lookup(f->block,
-					ocelot_setup_tc_block_cb_flower, priv);
-	if (!block_cb) {
-		port_block = ocelot_port_block_create(priv);
-		if (!port_block)
-			return -ENOMEM;
-
-		block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower,
-					       priv, port_block,
-					       ocelot_tc_block_unbind);
-		if (IS_ERR(block_cb)) {
-			ret = PTR_ERR(block_cb);
-			goto err_cb_register;
-		}
-		flow_block_cb_add(block_cb, f);
-		list_add_tail(&block_cb->driver_list, f->driver_block_list);
-	} else {
-		port_block = flow_block_cb_priv(block_cb);
-	}
-
-	flow_block_cb_incref(block_cb);
-	return 0;
-
-err_cb_register:
-	ocelot_port_block_destroy(port_block);
-
-	return ret;
-}
-
-void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
-					 struct flow_block_offload *f)
-{
-	struct flow_block_cb *block_cb;
-
-	block_cb = flow_block_cb_lookup(f->block,
-					ocelot_setup_tc_block_cb_flower, priv);
-	if (!block_cb)
-		return;
-
-	if (!flow_block_cb_decref(block_cb)) {
-		flow_block_cb_remove(block_cb, f);
-		list_del(&block_cb->driver_list);
-	}
-}
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index a4f7fbd76507..3ff5ef41eccf 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -20,9 +20,6 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port_private *priv,
 	int port = priv->chip_port;
 	int err;
 
-	netdev_dbg(priv->dev, "%s: port %u command %d cookie %lu\n",
-		   __func__, port, f->command, f->cookie);
-
 	if (!ingress) {
 		NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported");
 		return -EOPNOTSUPP;
@@ -99,17 +96,10 @@ static int ocelot_setup_tc_block_cb(enum tc_setup_type type,
 
 	switch (type) {
 	case TC_SETUP_CLSMATCHALL:
-		netdev_dbg(priv->dev, "tc_block_cb: TC_SETUP_CLSMATCHALL %s\n",
-			   ingress ? "ingress" : "egress");
-
 		return ocelot_setup_tc_cls_matchall(priv, type_data, ingress);
 	case TC_SETUP_CLSFLOWER:
-		return 0;
+		return ocelot_setup_tc_cls_flower(priv, type_data, ingress);
 	default:
-		netdev_dbg(priv->dev, "tc_block_cb: type %d %s\n",
-			   type,
-			   ingress ? "ingress" : "egress");
-
 		return -EOPNOTSUPP;
 	}
 }
@@ -137,10 +127,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
 {
 	struct flow_block_cb *block_cb;
 	flow_setup_cb_t *cb;
-	int err;
-
-	netdev_dbg(priv->dev, "tc_block command %d, binder_type %d\n",
-		   f->command, f->binder_type);
 
 	if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
 		cb = ocelot_setup_tc_block_cb_ig;
@@ -162,11 +148,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
 		if (IS_ERR(block_cb))
 			return PTR_ERR(block_cb);
 
-		err = ocelot_setup_tc_block_flower_bind(priv, f);
-		if (err < 0) {
-			flow_block_cb_free(block_cb);
-			return err;
-		}
 		flow_block_cb_add(block_cb, f);
 		list_add_tail(&block_cb->driver_list, f->driver_block_list);
 		return 0;
@@ -175,7 +156,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
 		if (!block_cb)
 			return -ENOENT;
 
-		ocelot_setup_tc_block_flower_unbind(priv, f);
 		flow_block_cb_remove(block_cb, f);
 		list_del(&block_cb->driver_list);
 		return 0;
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 068f96b1a83e..74e7c63adad4 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -406,6 +406,11 @@ struct ocelot_ops {
 	int (*reset)(struct ocelot *ocelot);
 };
 
+struct ocelot_acl_block {
+	struct list_head rules;
+	int count;
+};
+
 struct ocelot_port {
 	struct ocelot			*ocelot;
 
@@ -455,6 +460,8 @@ struct ocelot {
 
 	struct list_head		multicast;
 
+	struct ocelot_acl_block		acl_block;
+
 	/* Workqueue to check statistics for overflow with its lock */
 	struct mutex			stats_lock;
 	u64				*stats;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 03/10] net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names with "ace"
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
  2020-02-24 13:08 ` [PATCH net-next 01/10] net: mscc: ocelot: make ocelot_ace_rule support multiple ports Vladimir Oltean
  2020-02-24 13:08 ` [PATCH net-next 02/10] net: mscc: ocelot: simplify tc-flower offload structures Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-27  8:09   ` Allan W. Nielsen
  2020-02-24 13:08 ` [PATCH net-next 04/10] net: mscc: ocelot: return directly in ocelot_cls_flower_{replace,destroy} Vladimir Oltean
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The "ocelot_rule" variable name is both annoyingly long trying to
distinguish itself from struct flow_rule *rule =
flow_cls_offload_flow_rule(f), as well as actually different from the
"ace" variable name which is used all over the place in ocelot_ace.c and
is referring to the same structure.

And the "rule" variable name is, confusingly, different from f->rule,
but sometimes one has to look up to the beginning of the function to get
an understanding of what structure type is actually being handled.

So let's use the "ace" name wherever possible ("Access Control Entry").

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_flower.c | 102 +++++++++++-----------
 1 file changed, 51 insertions(+), 51 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index b9673df6dbc5..698e9fee6b1a 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -9,7 +9,7 @@
 #include "ocelot_ace.h"
 
 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
-				      struct ocelot_ace_rule *rule)
+				      struct ocelot_ace_rule *ace)
 {
 	const struct flow_action_entry *a;
 	int i;
@@ -20,10 +20,10 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
 	flow_action_for_each(i, a, &f->rule->action) {
 		switch (a->id) {
 		case FLOW_ACTION_DROP:
-			rule->action = OCELOT_ACL_ACTION_DROP;
+			ace->action = OCELOT_ACL_ACTION_DROP;
 			break;
 		case FLOW_ACTION_TRAP:
-			rule->action = OCELOT_ACL_ACTION_TRAP;
+			ace->action = OCELOT_ACL_ACTION_TRAP;
 			break;
 		default:
 			return -EOPNOTSUPP;
@@ -34,7 +34,7 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
 }
 
 static int ocelot_flower_parse(struct flow_cls_offload *f,
-			       struct ocelot_ace_rule *ocelot_rule)
+			       struct ocelot_ace_rule *ace)
 {
 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
 	struct flow_dissector *dissector = rule->match.dissector;
@@ -79,14 +79,14 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
 			return -EOPNOTSUPP;
 
 		flow_rule_match_eth_addrs(rule, &match);
-		ocelot_rule->type = OCELOT_ACE_TYPE_ETYPE;
-		ether_addr_copy(ocelot_rule->frame.etype.dmac.value,
+		ace->type = OCELOT_ACE_TYPE_ETYPE;
+		ether_addr_copy(ace->frame.etype.dmac.value,
 				match.key->dst);
-		ether_addr_copy(ocelot_rule->frame.etype.smac.value,
+		ether_addr_copy(ace->frame.etype.smac.value,
 				match.key->src);
-		ether_addr_copy(ocelot_rule->frame.etype.dmac.mask,
+		ether_addr_copy(ace->frame.etype.dmac.mask,
 				match.mask->dst);
-		ether_addr_copy(ocelot_rule->frame.etype.smac.mask,
+		ether_addr_copy(ace->frame.etype.smac.mask,
 				match.mask->src);
 		goto finished_key_parsing;
 	}
@@ -96,17 +96,17 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
 
 		flow_rule_match_basic(rule, &match);
 		if (ntohs(match.key->n_proto) == ETH_P_IP) {
-			ocelot_rule->type = OCELOT_ACE_TYPE_IPV4;
-			ocelot_rule->frame.ipv4.proto.value[0] =
+			ace->type = OCELOT_ACE_TYPE_IPV4;
+			ace->frame.ipv4.proto.value[0] =
 				match.key->ip_proto;
-			ocelot_rule->frame.ipv4.proto.mask[0] =
+			ace->frame.ipv4.proto.mask[0] =
 				match.mask->ip_proto;
 		}
 		if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
-			ocelot_rule->type = OCELOT_ACE_TYPE_IPV6;
-			ocelot_rule->frame.ipv6.proto.value[0] =
+			ace->type = OCELOT_ACE_TYPE_IPV6;
+			ace->frame.ipv6.proto.value[0] =
 				match.key->ip_proto;
-			ocelot_rule->frame.ipv6.proto.mask[0] =
+			ace->frame.ipv6.proto.mask[0] =
 				match.mask->ip_proto;
 		}
 	}
@@ -117,16 +117,16 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
 		u8 *tmp;
 
 		flow_rule_match_ipv4_addrs(rule, &match);
-		tmp = &ocelot_rule->frame.ipv4.sip.value.addr[0];
+		tmp = &ace->frame.ipv4.sip.value.addr[0];
 		memcpy(tmp, &match.key->src, 4);
 
-		tmp = &ocelot_rule->frame.ipv4.sip.mask.addr[0];
+		tmp = &ace->frame.ipv4.sip.mask.addr[0];
 		memcpy(tmp, &match.mask->src, 4);
 
-		tmp = &ocelot_rule->frame.ipv4.dip.value.addr[0];
+		tmp = &ace->frame.ipv4.dip.value.addr[0];
 		memcpy(tmp, &match.key->dst, 4);
 
-		tmp = &ocelot_rule->frame.ipv4.dip.mask.addr[0];
+		tmp = &ace->frame.ipv4.dip.mask.addr[0];
 		memcpy(tmp, &match.mask->dst, 4);
 	}
 
@@ -139,60 +139,60 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
 		struct flow_match_ports match;
 
 		flow_rule_match_ports(rule, &match);
-		ocelot_rule->frame.ipv4.sport.value = ntohs(match.key->src);
-		ocelot_rule->frame.ipv4.sport.mask = ntohs(match.mask->src);
-		ocelot_rule->frame.ipv4.dport.value = ntohs(match.key->dst);
-		ocelot_rule->frame.ipv4.dport.mask = ntohs(match.mask->dst);
+		ace->frame.ipv4.sport.value = ntohs(match.key->src);
+		ace->frame.ipv4.sport.mask = ntohs(match.mask->src);
+		ace->frame.ipv4.dport.value = ntohs(match.key->dst);
+		ace->frame.ipv4.dport.mask = ntohs(match.mask->dst);
 	}
 
 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
 		struct flow_match_vlan match;
 
 		flow_rule_match_vlan(rule, &match);
-		ocelot_rule->type = OCELOT_ACE_TYPE_ANY;
-		ocelot_rule->vlan.vid.value = match.key->vlan_id;
-		ocelot_rule->vlan.vid.mask = match.mask->vlan_id;
-		ocelot_rule->vlan.pcp.value[0] = match.key->vlan_priority;
-		ocelot_rule->vlan.pcp.mask[0] = match.mask->vlan_priority;
+		ace->type = OCELOT_ACE_TYPE_ANY;
+		ace->vlan.vid.value = match.key->vlan_id;
+		ace->vlan.vid.mask = match.mask->vlan_id;
+		ace->vlan.pcp.value[0] = match.key->vlan_priority;
+		ace->vlan.pcp.mask[0] = match.mask->vlan_priority;
 	}
 
 finished_key_parsing:
-	ocelot_rule->prio = f->common.prio;
-	ocelot_rule->id = f->cookie;
-	return ocelot_flower_parse_action(f, ocelot_rule);
+	ace->prio = f->common.prio;
+	ace->id = f->cookie;
+	return ocelot_flower_parse_action(f, ace);
 }
 
 static
 struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port,
 					       struct flow_cls_offload *f)
 {
-	struct ocelot_ace_rule *rule;
+	struct ocelot_ace_rule *ace;
 
-	rule = kzalloc(sizeof(*rule), GFP_KERNEL);
-	if (!rule)
+	ace = kzalloc(sizeof(*ace), GFP_KERNEL);
+	if (!ace)
 		return NULL;
 
-	rule->ingress_port_mask = BIT(port);
-	return rule;
+	ace->ingress_port_mask = BIT(port);
+	return ace;
 }
 
 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
 			      struct flow_cls_offload *f, bool ingress)
 {
-	struct ocelot_ace_rule *rule;
+	struct ocelot_ace_rule *ace;
 	int ret;
 
-	rule = ocelot_ace_rule_create(ocelot, port, f);
-	if (!rule)
+	ace = ocelot_ace_rule_create(ocelot, port, f);
+	if (!ace)
 		return -ENOMEM;
 
-	ret = ocelot_flower_parse(f, rule);
+	ret = ocelot_flower_parse(f, ace);
 	if (ret) {
-		kfree(rule);
+		kfree(ace);
 		return ret;
 	}
 
-	ret = ocelot_ace_rule_offload_add(ocelot, rule);
+	ret = ocelot_ace_rule_offload_add(ocelot, ace);
 	if (ret)
 		return ret;
 
@@ -203,13 +203,13 @@ EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
 			      struct flow_cls_offload *f, bool ingress)
 {
-	struct ocelot_ace_rule rule;
+	struct ocelot_ace_rule ace;
 	int ret;
 
-	rule.prio = f->common.prio;
-	rule.id = f->cookie;
+	ace.prio = f->common.prio;
+	ace.id = f->cookie;
 
-	ret = ocelot_ace_rule_offload_del(ocelot, &rule);
+	ret = ocelot_ace_rule_offload_del(ocelot, &ace);
 	if (ret)
 		return ret;
 
@@ -220,16 +220,16 @@ EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
 			    struct flow_cls_offload *f, bool ingress)
 {
-	struct ocelot_ace_rule rule;
+	struct ocelot_ace_rule ace;
 	int ret;
 
-	rule.prio = f->common.prio;
-	rule.id = f->cookie;
-	ret = ocelot_ace_rule_stats_update(ocelot, &rule);
+	ace.prio = f->common.prio;
+	ace.id = f->cookie;
+	ret = ocelot_ace_rule_stats_update(ocelot, &ace);
 	if (ret)
 		return ret;
 
-	flow_stats_update(&f->stats, 0x0, rule.stats.pkts, 0x0);
+	flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0x0);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 04/10] net: mscc: ocelot: return directly in ocelot_cls_flower_{replace,destroy}
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (2 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 03/10] net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names with "ace" Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-27  8:10   ` Allan W. Nielsen
  2020-02-24 13:08 ` [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing Vladimir Oltean
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

There is no need to check the "ret" variable, one can just return the
function result back to the caller.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_flower.c | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 698e9fee6b1a..8993dadf063c 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -192,11 +192,7 @@ int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
 		return ret;
 	}
 
-	ret = ocelot_ace_rule_offload_add(ocelot, ace);
-	if (ret)
-		return ret;
-
-	return 0;
+	return ocelot_ace_rule_offload_add(ocelot, ace);
 }
 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
 
@@ -204,16 +200,11 @@ int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
 			      struct flow_cls_offload *f, bool ingress)
 {
 	struct ocelot_ace_rule ace;
-	int ret;
 
 	ace.prio = f->common.prio;
 	ace.id = f->cookie;
 
-	ret = ocelot_ace_rule_offload_del(ocelot, &ace);
-	if (ret)
-		return ret;
-
-	return 0;
+	return ocelot_ace_rule_offload_del(ocelot, &ace);
 }
 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (3 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 04/10] net: mscc: ocelot: return directly in ocelot_cls_flower_{replace,destroy} Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-24 23:21   ` David Miller
                     ` (2 more replies)
  2020-02-24 13:08 ` [PATCH net-next 06/10] net: mscc: ocelot: remove port_pcs_init indirection for VSC7514 Vladimir Oltean
                   ` (5 subsequent siblings)
  10 siblings, 3 replies; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The IGR_PORT_MASK key width is different between the 11-port VSC7514 and
the 6-port VSC9959 switches. And since IGR_PORT_MASK is one of the first
fields of a VCAP key entry, it means that all further field
offset/length pairs are shifted between the 2.

The ocelot driver performs packing of VCAP half keys with the help of
some preprocessor macros:

- A set of macros for defining the HKO (Half Key Offset) and HKL (Half
  Key Length) of each possible key field. The offset of each field is
  defined as the sum between the offset and the sum of the previous
  field.

- A set of accessors on top of vcap_key_set for shorter (aka less
  typing) access to the HKO and HKL of each key field.

Since the field offsets and lengths are different between switches,
defining them through the preprocessor isn't going to fly. So introduce
a structure holding (offset, length) pairs and instantiate it in
ocelot_board.c for VSC7514. In a future patch, a similar structure will
be instantiated in felix_vsc9959.c for NXP LS1028A.

The accessors also need to go. They are based on macro name
concatenation, which is horrible to understand and follow.

An "ocelot" backpointer to the driver private structure was added into
struct vcap_data, to avoid refactoring all functions that operate on
that structure (since they now need to access the VCAP key packing table
through struct ocelot). This is not the prettiest thing to do, but
avoids some extra refactoring for now.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_ace.c   | 285 +++++++++-------
 drivers/net/ethernet/mscc/ocelot_board.c | 102 ++++++
 drivers/net/ethernet/mscc/ocelot_vcap.h  | 403 -----------------------
 include/soc/mscc/ocelot.h                |   3 +
 include/soc/mscc/ocelot_vcap.h           | 184 +++++++++++
 5 files changed, 460 insertions(+), 517 deletions(-)
 delete mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h
 create mode 100644 include/soc/mscc/ocelot_vcap.h

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
index 375c7c6aa7d5..c838e681963f 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -6,8 +6,8 @@
 #include <linux/iopoll.h>
 #include <linux/proc_fs.h>
 
+#include <soc/mscc/ocelot_vcap.h>
 #include "ocelot_ace.h"
-#include "ocelot_vcap.h"
 #include "ocelot_s2.h"
 
 #define OCELOT_POLICER_DISCARD 0x17f
@@ -47,7 +47,7 @@ static const struct vcap_props vcap_is2 = {
 	.action_type_width = 1,
 	.action_table = {
 		{
-			.width = (IS2_AO_ACL_ID + IS2_AL_ACL_ID),
+			.width = 49,
 			.count = 2
 		},
 		{
@@ -78,6 +78,7 @@ enum vcap_cmd {
 #define VCAP_COUNTER_WIDTH 4 /* Max counter width (32bit words) */
 
 struct vcap_data {
+	struct ocelot *ocelot;
 	u32 entry[VCAP_ENTRY_WIDTH]; /* ENTRY_DAT */
 	u32 mask[VCAP_ENTRY_WIDTH]; /* MASK_DAT */
 	u32 action[VCAP_ENTRY_WIDTH]; /* ACTION_DAT */
@@ -240,22 +241,41 @@ static u32 vcap_data_get(u32 *data, u32 offset, u32 len)
 	return value;
 }
 
-static void vcap_key_set(struct vcap_data *data, u32 offset, u32 width,
-			 u32 value, u32 mask)
+static void vcap_key_field_set(struct vcap_data *data, u32 offset, u32 width,
+			       u32 value, u32 mask)
 {
 	vcap_data_set(data->entry, offset + data->key_offset, width, value);
 	vcap_data_set(data->mask, offset + data->key_offset, width, mask);
 }
 
-static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val,
-			       u8 *msk, u32 count)
+static void vcap_key_set(struct vcap_data *data,
+			 enum vcap_is2_half_key_field field,
+			 u32 value, u32 mask)
+{
+	struct ocelot *ocelot = data->ocelot;
+	u32 offset = ocelot->vcap_is2_keys[field].offset;
+	u32 length = ocelot->vcap_is2_keys[field].length;
+
+	vcap_key_field_set(data, offset, length, value, mask);
+}
+
+static void vcap_key_bytes_set(struct vcap_data *data,
+			       enum vcap_is2_half_key_field field,
+			       u8 *val, u8 *msk)
 {
+	struct ocelot *ocelot = data->ocelot;
+	u32 offset = ocelot->vcap_is2_keys[field].offset;
+	u32 count  = ocelot->vcap_is2_keys[field].length;
 	u32 i, j, n = 0, value = 0, mask = 0;
 
+	WARN_ON(count % 8);
+
 	/* Data wider than 32 bits are split up in chunks of maximum 32 bits.
 	 * The 32 LSB of the data are written to the 32 MSB of the TCAM.
 	 */
-	offset += (count * 8);
+	offset += count;
+	count /= 8;
+
 	for (i = 0; i < count; i++) {
 		j = (count - i - 1);
 		value += (val[j] << n);
@@ -263,7 +283,7 @@ static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val,
 		n += 8;
 		if (n == ENTRY_WIDTH || (i + 1) == count) {
 			offset -= n;
-			vcap_key_set(data, offset, n, value, mask);
+			vcap_key_field_set(data, offset, n, value, mask);
 			n = 0;
 			value = 0;
 			mask = 0;
@@ -271,55 +291,65 @@ static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val,
 	}
 }
 
-static void vcap_key_l4_port_set(struct vcap_data *data, u32 offset,
+static void vcap_key_l4_port_set(struct vcap_data *data,
+				 enum vcap_is2_half_key_field field,
 				 struct ocelot_vcap_udp_tcp *port)
 {
-	vcap_key_set(data, offset, 16, port->value, port->mask);
+	struct ocelot *ocelot = data->ocelot;
+	u32 offset = ocelot->vcap_is2_keys[field].offset;
+	u32 length = ocelot->vcap_is2_keys[field].length;
+
+	WARN_ON(length != 16);
+
+	vcap_key_field_set(data, offset, length, port->value, port->mask);
 }
 
-static void vcap_key_bit_set(struct vcap_data *data, u32 offset,
+static void vcap_key_bit_set(struct vcap_data *data,
+			     enum vcap_is2_half_key_field field,
 			     enum ocelot_vcap_bit val)
 {
-	vcap_key_set(data, offset, 1, val == OCELOT_VCAP_BIT_1 ? 1 : 0,
-		     val == OCELOT_VCAP_BIT_ANY ? 0 : 1);
-}
+	struct ocelot *ocelot = data->ocelot;
+	u32 offset = ocelot->vcap_is2_keys[field].offset;
+	u32 length = ocelot->vcap_is2_keys[field].length;
+	u32 value = (val == OCELOT_VCAP_BIT_1 ? 1 : 0);
+	u32 msk = (val == OCELOT_VCAP_BIT_ANY ? 0 : 1);
 
-#define VCAP_KEY_SET(fld, val, msk) \
-	vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, val, msk)
-#define VCAP_KEY_ANY_SET(fld) \
-	vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, 0, 0)
-#define VCAP_KEY_BIT_SET(fld, val) vcap_key_bit_set(&data, IS2_HKO_##fld, val)
-#define VCAP_KEY_BYTES_SET(fld, val, msk) \
-	vcap_key_bytes_set(&data, IS2_HKO_##fld, val, msk, IS2_HKL_##fld / 8)
+	WARN_ON(length != 1);
 
-static void vcap_action_set(struct vcap_data *data, u32 offset, u32 width,
-			    u32 value)
-{
-	vcap_data_set(data->action, offset + data->action_offset, width, value);
+	vcap_key_field_set(data, offset, length, value, msk);
 }
 
-#define VCAP_ACT_SET(fld, val) \
-	vcap_action_set(data, IS2_AO_##fld, IS2_AL_##fld, val)
+static void vcap_action_set(struct vcap_data *data,
+			    enum vcap_is2_action_field field, u32 value)
+{
+	struct ocelot *ocelot = data->ocelot;
+	int offset = ocelot->vcap_is2_actions[field].offset;
+	int length = ocelot->vcap_is2_actions[field].length;
+
+	vcap_data_set(data->action, offset + data->action_offset, length,
+		      value);
+}
 
 static void is2_action_set(struct vcap_data *data,
 			   enum ocelot_ace_action action)
 {
 	switch (action) {
 	case OCELOT_ACL_ACTION_DROP:
-		VCAP_ACT_SET(PORT_MASK, 0x0);
-		VCAP_ACT_SET(MASK_MODE, 0x1);
-		VCAP_ACT_SET(POLICE_ENA, 0x1);
-		VCAP_ACT_SET(POLICE_IDX, OCELOT_POLICER_DISCARD);
-		VCAP_ACT_SET(CPU_QU_NUM, 0x0);
-		VCAP_ACT_SET(CPU_COPY_ENA, 0x0);
+		vcap_action_set(data, VCAP_IS2_ACT_PORT_MASK, 0);
+		vcap_action_set(data, VCAP_IS2_ACT_MASK_MODE, 1);
+		vcap_action_set(data, VCAP_IS2_ACT_POLICE_ENA, 1);
+		vcap_action_set(data, VCAP_IS2_ACT_POLICE_IDX,
+				OCELOT_POLICER_DISCARD);
+		vcap_action_set(data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
+		vcap_action_set(data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
 		break;
 	case OCELOT_ACL_ACTION_TRAP:
-		VCAP_ACT_SET(PORT_MASK, 0x0);
-		VCAP_ACT_SET(MASK_MODE, 0x1);
-		VCAP_ACT_SET(POLICE_ENA, 0x0);
-		VCAP_ACT_SET(POLICE_IDX, 0x0);
-		VCAP_ACT_SET(CPU_QU_NUM, 0x0);
-		VCAP_ACT_SET(CPU_COPY_ENA, 0x1);
+		vcap_action_set(data, VCAP_IS2_ACT_PORT_MASK, 0);
+		vcap_action_set(data, VCAP_IS2_ACT_MASK_MODE, 1);
+		vcap_action_set(data, VCAP_IS2_ACT_POLICE_ENA, 0);
+		vcap_action_set(data, VCAP_IS2_ACT_POLICE_IDX, 0);
+		vcap_action_set(data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
+		vcap_action_set(data, VCAP_IS2_ACT_CPU_COPY_ENA, 1);
 		break;
 	}
 }
@@ -336,6 +366,8 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 	memset(&payload, 0, sizeof(payload));
 	memset(&data, 0, sizeof(data));
 
+	data.ocelot = ocelot;
+
 	/* Read row */
 	vcap_row_cmd(ocelot, row, VCAP_CMD_READ, VCAP_SEL_ALL);
 	vcap_cache2entry(ocelot, &data);
@@ -349,53 +381,63 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 
 	data.type = IS2_ACTION_TYPE_NORMAL;
 
-	VCAP_KEY_ANY_SET(PAG);
-	VCAP_KEY_SET(IGR_PORT_MASK, 0, ~ace->ingress_port_mask);
-	VCAP_KEY_BIT_SET(FIRST, OCELOT_VCAP_BIT_1);
-	VCAP_KEY_BIT_SET(HOST_MATCH, OCELOT_VCAP_BIT_ANY);
-	VCAP_KEY_BIT_SET(L2_MC, ace->dmac_mc);
-	VCAP_KEY_BIT_SET(L2_BC, ace->dmac_bc);
-	VCAP_KEY_BIT_SET(VLAN_TAGGED, tag->tagged);
-	VCAP_KEY_SET(VID, tag->vid.value, tag->vid.mask);
-	VCAP_KEY_SET(PCP, tag->pcp.value[0], tag->pcp.mask[0]);
-	VCAP_KEY_BIT_SET(DEI, tag->dei);
+	vcap_key_set(&data, VCAP_IS2_HK_PAG, 0, 0);
+	vcap_key_set(&data, VCAP_IS2_HK_IGR_PORT_MASK, 0,
+		     ~ace->ingress_port_mask);
+	vcap_key_bit_set(&data, VCAP_IS2_HK_FIRST, OCELOT_VCAP_BIT_1);
+	vcap_key_bit_set(&data, VCAP_IS2_HK_HOST_MATCH, OCELOT_VCAP_BIT_ANY);
+	vcap_key_bit_set(&data, VCAP_IS2_HK_L2_MC, ace->dmac_mc);
+	vcap_key_bit_set(&data, VCAP_IS2_HK_L2_BC, ace->dmac_bc);
+	vcap_key_bit_set(&data, VCAP_IS2_HK_VLAN_TAGGED, tag->tagged);
+	vcap_key_set(&data, VCAP_IS2_HK_VID, tag->vid.value, tag->vid.mask);
+	vcap_key_set(&data, VCAP_IS2_HK_PCP, tag->pcp.value[0],
+		     tag->pcp.mask[0]);
+	vcap_key_bit_set(&data, VCAP_IS2_HK_DEI, tag->dei);
 
 	switch (ace->type) {
 	case OCELOT_ACE_TYPE_ETYPE: {
 		struct ocelot_ace_frame_etype *etype = &ace->frame.etype;
 
 		type = IS2_TYPE_ETYPE;
-		VCAP_KEY_BYTES_SET(L2_DMAC, etype->dmac.value,
-				   etype->dmac.mask);
-		VCAP_KEY_BYTES_SET(L2_SMAC, etype->smac.value,
-				   etype->smac.mask);
-		VCAP_KEY_BYTES_SET(MAC_ETYPE_ETYPE, etype->etype.value,
-				   etype->etype.mask);
-		VCAP_KEY_ANY_SET(MAC_ETYPE_L2_PAYLOAD); // Clear unused bits
-		vcap_key_bytes_set(&data, IS2_HKO_MAC_ETYPE_L2_PAYLOAD,
-				   etype->data.value, etype->data.mask, 2);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L2_DMAC,
+				   etype->dmac.value, etype->dmac.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L2_SMAC,
+				   etype->smac.value, etype->smac.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_MAC_ETYPE_ETYPE,
+				   etype->etype.value, etype->etype.mask);
+		/* Clear unused bits */
+		vcap_key_set(&data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0, 0, 0);
+		vcap_key_set(&data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1, 0, 0);
+		vcap_key_set(&data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2, 0, 0);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0,
+				   etype->data.value, etype->data.mask);
 		break;
 	}
 	case OCELOT_ACE_TYPE_LLC: {
 		struct ocelot_ace_frame_llc *llc = &ace->frame.llc;
 
 		type = IS2_TYPE_LLC;
-		VCAP_KEY_BYTES_SET(L2_DMAC, llc->dmac.value, llc->dmac.mask);
-		VCAP_KEY_BYTES_SET(L2_SMAC, llc->smac.value, llc->smac.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L2_DMAC,
+				   llc->dmac.value, llc->dmac.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L2_SMAC,
+				   llc->smac.value, llc->smac.mask);
 		for (i = 0; i < 4; i++) {
 			payload.value[i] = llc->llc.value[i];
 			payload.mask[i] = llc->llc.mask[i];
 		}
-		VCAP_KEY_BYTES_SET(MAC_LLC_L2_LLC, payload.value, payload.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_MAC_LLC_L2_LLC,
+				   payload.value, payload.mask);
 		break;
 	}
 	case OCELOT_ACE_TYPE_SNAP: {
 		struct ocelot_ace_frame_snap *snap = &ace->frame.snap;
 
 		type = IS2_TYPE_SNAP;
-		VCAP_KEY_BYTES_SET(L2_DMAC, snap->dmac.value, snap->dmac.mask);
-		VCAP_KEY_BYTES_SET(L2_SMAC, snap->smac.value, snap->smac.mask);
-		VCAP_KEY_BYTES_SET(MAC_SNAP_L2_SNAP,
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L2_DMAC,
+				   snap->dmac.value, snap->dmac.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L2_SMAC,
+				   snap->smac.value, snap->smac.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_MAC_SNAP_L2_SNAP,
 				   ace->frame.snap.snap.value,
 				   ace->frame.snap.snap.mask);
 		break;
@@ -404,26 +446,32 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 		struct ocelot_ace_frame_arp *arp = &ace->frame.arp;
 
 		type = IS2_TYPE_ARP;
-		VCAP_KEY_BYTES_SET(MAC_ARP_L2_SMAC, arp->smac.value,
-				   arp->smac.mask);
-		VCAP_KEY_BIT_SET(MAC_ARP_ARP_ADDR_SPACE_OK, arp->ethernet);
-		VCAP_KEY_BIT_SET(MAC_ARP_ARP_PROTO_SPACE_OK, arp->ip);
-		VCAP_KEY_BIT_SET(MAC_ARP_ARP_LEN_OK, arp->length);
-		VCAP_KEY_BIT_SET(MAC_ARP_ARP_TGT_MATCH, arp->dmac_match);
-		VCAP_KEY_BIT_SET(MAC_ARP_ARP_SENDER_MATCH, arp->smac_match);
-		VCAP_KEY_BIT_SET(MAC_ARP_ARP_OPCODE_UNKNOWN, arp->unknown);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_MAC_ARP_SMAC,
+				   arp->smac.value, arp->smac.mask);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK,
+				 arp->ethernet);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK,
+				 arp->ip);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_MAC_ARP_LEN_OK,
+				 arp->length);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_MAC_ARP_TARGET_MATCH,
+				 arp->dmac_match);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_MAC_ARP_SENDER_MATCH,
+				 arp->smac_match);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN,
+				 arp->unknown);
 
 		/* OPCODE is inverse, bit 0 is reply flag, bit 1 is RARP flag */
 		val = ((arp->req == OCELOT_VCAP_BIT_0 ? 1 : 0) |
 		       (arp->arp == OCELOT_VCAP_BIT_0 ? 2 : 0));
 		msk = ((arp->req == OCELOT_VCAP_BIT_ANY ? 0 : 1) |
 		       (arp->arp == OCELOT_VCAP_BIT_ANY ? 0 : 2));
-		VCAP_KEY_SET(MAC_ARP_ARP_OPCODE, val, msk);
-		vcap_key_bytes_set(&data, IS2_HKO_MAC_ARP_L3_IP4_DIP,
-				   arp->dip.value.addr, arp->dip.mask.addr, 4);
-		vcap_key_bytes_set(&data, IS2_HKO_MAC_ARP_L3_IP4_SIP,
-				   arp->sip.value.addr, arp->sip.mask.addr, 4);
-		VCAP_KEY_ANY_SET(MAC_ARP_DIP_EQ_SIP);
+		vcap_key_set(&data, VCAP_IS2_HK_MAC_ARP_OPCODE, val, msk);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP,
+				   arp->dip.value.addr, arp->dip.mask.addr);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP,
+				   arp->sip.value.addr, arp->sip.mask.addr);
+		vcap_key_set(&data, VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP, 0, 0);
 		break;
 	}
 	case OCELOT_ACE_TYPE_IPV4:
@@ -491,18 +539,19 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 			seq_zero = ipv6->seq_zero;
 		}
 
-		VCAP_KEY_BIT_SET(IP4,
+		vcap_key_bit_set(&data, VCAP_IS2_HK_IP4,
 				 ipv4 ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0);
-		VCAP_KEY_BIT_SET(L3_FRAGMENT, fragment);
-		VCAP_KEY_ANY_SET(L3_FRAG_OFS_GT0);
-		VCAP_KEY_BIT_SET(L3_OPTIONS, options);
-		VCAP_KEY_BIT_SET(L3_TTL_GT0, ttl);
-		VCAP_KEY_BYTES_SET(L3_TOS, ds.value, ds.mask);
-		vcap_key_bytes_set(&data, IS2_HKO_L3_IP4_DIP, dip.value.addr,
-				   dip.mask.addr, 4);
-		vcap_key_bytes_set(&data, IS2_HKO_L3_IP4_SIP, sip.value.addr,
-				   sip.mask.addr, 4);
-		VCAP_KEY_BIT_SET(DIP_EQ_SIP, sip_eq_dip);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_L3_FRAGMENT, fragment);
+		vcap_key_set(&data, VCAP_IS2_HK_L3_FRAG_OFS_GT0, 0, 0);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_L3_OPTIONS, options);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_IP4_L3_TTL_GT0, ttl);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L3_TOS,
+				   ds.value, ds.mask);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L3_IP4_DIP,
+				   dip.value.addr, dip.mask.addr);
+		vcap_key_bytes_set(&data, VCAP_IS2_HK_L3_IP4_SIP,
+				   sip.value.addr, sip.mask.addr);
+		vcap_key_bit_set(&data, VCAP_IS2_HK_DIP_EQ_SIP, sip_eq_dip);
 		val = proto.value[0];
 		msk = proto.mask[0];
 		type = IS2_TYPE_IP_UDP_TCP;
@@ -510,25 +559,24 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 			/* UDP/TCP protocol match */
 			tcp = (val == 6 ?
 			       OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_TCP, tcp);
-			vcap_key_l4_port_set(&data,
-					     IS2_HKO_IP4_TCP_UDP_L4_DPORT,
+			vcap_key_bit_set(&data, VCAP_IS2_HK_TCP, tcp);
+			vcap_key_l4_port_set(&data, VCAP_IS2_HK_L4_DPORT,
 					     dport);
-			vcap_key_l4_port_set(&data,
-					     IS2_HKO_IP4_TCP_UDP_L4_SPORT,
+			vcap_key_l4_port_set(&data, VCAP_IS2_HK_L4_SPORT,
 					     sport);
-			VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_RNG);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_SPORT_EQ_DPORT,
+			vcap_key_set(&data, VCAP_IS2_HK_L4_RNG, 0, 0);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_SPORT_EQ_DPORT,
 					 sport_eq_dport);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_SEQUENCE_EQ0, seq_zero);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_FIN, tcp_fin);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_SYN, tcp_syn);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_RST, tcp_rst);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_PSH, tcp_psh);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_ACK, tcp_ack);
-			VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_URG, tcp_urg);
-			VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_DOM);
-			VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_VER);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_SEQUENCE_EQ0,
+					 seq_zero);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_FIN, tcp_fin);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_SYN, tcp_syn);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_RST, tcp_rst);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_PSH, tcp_psh);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_ACK, tcp_ack);
+			vcap_key_bit_set(&data, VCAP_IS2_HK_L4_URG, tcp_urg);
+			vcap_key_set(&data, VCAP_IS2_HK_L4_1588_DOM, 0, 0);
+			vcap_key_set(&data, VCAP_IS2_HK_L4_1588_VER, 0, 0);
 		} else {
 			if (msk == 0) {
 				/* Any IP protocol match */
@@ -541,10 +589,12 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 					payload.mask[i] = ip_data->mask[i];
 				}
 			}
-			VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PROTO, proto.value,
-					   proto.mask);
-			VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PAYLOAD, payload.value,
-					   payload.mask);
+			vcap_key_bytes_set(&data,
+					   VCAP_IS2_HK_IP4_L3_PROTO,
+					   proto.value, proto.mask);
+			vcap_key_bytes_set(&data,
+					   VCAP_IS2_HK_L3_PAYLOAD,
+					   payload.value, payload.mask);
 		}
 		break;
 	}
@@ -553,15 +603,17 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 		type = 0;
 		type_mask = 0;
 		count = (vcap_is2.entry_width / 2);
-		for (i = (IS2_HKO_PCP + IS2_HKL_PCP); i < count;
-		     i += ENTRY_WIDTH) {
-			/* Clear entry data */
-			vcap_key_set(&data, i, min(32u, count - i), 0, 0);
+		/* Iterate over the non-common part of the key and
+		 * clear entry data
+		 */
+		for (i = ocelot->vcap_is2_keys[VCAP_IS2_HK_L2_DMAC].offset;
+		     i < count; i += ENTRY_WIDTH) {
+			vcap_key_field_set(&data, i, min(32u, count - i), 0, 0);
 		}
 		break;
 	}
 
-	VCAP_KEY_SET(TYPE, type, type_mask);
+	vcap_key_set(&data, VCAP_IS2_TYPE, type, type_mask);
 	is2_action_set(&data, ace->action);
 	vcap_data_set(data.counter, data.counter_offset, vcap_is2.counter_width,
 		      ace->stats.pkts);
@@ -579,6 +631,8 @@ static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
 	int row = (ix / 2);
 	u32 cnt;
 
+	data.ocelot = ocelot;
+
 	vcap_row_cmd(ocelot, row, VCAP_CMD_READ, VCAP_SEL_COUNTER);
 	vcap_cache2action(ocelot, &data);
 	data.tg_sw = VCAP_TG_HALF;
@@ -731,6 +785,9 @@ int ocelot_ace_init(struct ocelot *ocelot)
 	struct vcap_data data;
 
 	memset(&data, 0, sizeof(data));
+
+	data.ocelot = ocelot;
+
 	vcap_entry2cache(ocelot, &data);
 	ocelot_write(ocelot, vcap_is2.entry_count, S2_CORE_MV_CFG);
 	vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY);
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 1135a18019c7..8b83a10083e2 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -14,6 +14,7 @@
 #include <linux/skbuff.h>
 #include <net/switchdev.h>
 
+#include <soc/mscc/ocelot_vcap.h>
 #include "ocelot.h"
 
 #define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0))
@@ -262,6 +263,104 @@ static const struct ocelot_ops ocelot_ops = {
 	.reset			= ocelot_reset,
 };
 
+struct vcap_field vsc7514_vcap_is2_keys[] = {
+	/* Common: 46 bits */
+	[VCAP_IS2_TYPE]				= {  0,   4},
+	[VCAP_IS2_HK_FIRST]			= {  4,   1},
+	[VCAP_IS2_HK_PAG]			= {  5,   8},
+	[VCAP_IS2_HK_IGR_PORT_MASK]		= { 13,  12},
+	[VCAP_IS2_HK_RSV2]			= { 25,   1},
+	[VCAP_IS2_HK_HOST_MATCH]		= { 26,   1},
+	[VCAP_IS2_HK_L2_MC]			= { 27,   1},
+	[VCAP_IS2_HK_L2_BC]			= { 28,   1},
+	[VCAP_IS2_HK_VLAN_TAGGED]		= { 29,   1},
+	[VCAP_IS2_HK_VID]			= { 30,  12},
+	[VCAP_IS2_HK_DEI]			= { 42,   1},
+	[VCAP_IS2_HK_PCP]			= { 43,   3},
+	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */
+	[VCAP_IS2_HK_L2_DMAC]			= { 46,  48},
+	[VCAP_IS2_HK_L2_SMAC]			= { 94,  48},
+	/* MAC_ETYPE (TYPE=000) */
+	[VCAP_IS2_HK_MAC_ETYPE_ETYPE]		= {142,  16},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0]	= {158,  16},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1]	= {174,   8},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2]	= {182,   3},
+	/* MAC_LLC (TYPE=001) */
+	[VCAP_IS2_HK_MAC_LLC_L2_LLC]		= {142,  40},
+	/* MAC_SNAP (TYPE=010) */
+	[VCAP_IS2_HK_MAC_SNAP_L2_SNAP]		= {142,  40},
+	/* MAC_ARP (TYPE=011) */
+	[VCAP_IS2_HK_MAC_ARP_SMAC]		= { 46,  48},
+	[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK]	= { 94,   1},
+	[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK]	= { 95,   1},
+	[VCAP_IS2_HK_MAC_ARP_LEN_OK]		= { 96,   1},
+	[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH]	= { 97,   1},
+	[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH]	= { 98,   1},
+	[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN]	= { 99,   1},
+	[VCAP_IS2_HK_MAC_ARP_OPCODE]		= {100,   2},
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP]	= {102,  32},
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP]	= {134,  32},
+	[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP]	= {166,   1},
+	/* IP4_TCP_UDP / IP4_OTHER common */
+	[VCAP_IS2_HK_IP4]			= { 46,   1},
+	[VCAP_IS2_HK_L3_FRAGMENT]		= { 47,   1},
+	[VCAP_IS2_HK_L3_FRAG_OFS_GT0]		= { 48,   1},
+	[VCAP_IS2_HK_L3_OPTIONS]		= { 49,   1},
+	[VCAP_IS2_HK_IP4_L3_TTL_GT0]		= { 50,   1},
+	[VCAP_IS2_HK_L3_TOS]			= { 51,   8},
+	[VCAP_IS2_HK_L3_IP4_DIP]		= { 59,  32},
+	[VCAP_IS2_HK_L3_IP4_SIP]		= { 91,  32},
+	[VCAP_IS2_HK_DIP_EQ_SIP]		= {123,   1},
+	/* IP4_TCP_UDP (TYPE=100) */
+	[VCAP_IS2_HK_TCP]			= {124,   1},
+	[VCAP_IS2_HK_L4_SPORT]			= {125,  16},
+	[VCAP_IS2_HK_L4_DPORT]			= {141,  16},
+	[VCAP_IS2_HK_L4_RNG]			= {157,   8},
+	[VCAP_IS2_HK_L4_SPORT_EQ_DPORT]		= {165,   1},
+	[VCAP_IS2_HK_L4_SEQUENCE_EQ0]		= {166,   1},
+	[VCAP_IS2_HK_L4_URG]			= {167,   1},
+	[VCAP_IS2_HK_L4_ACK]			= {168,   1},
+	[VCAP_IS2_HK_L4_PSH]			= {169,   1},
+	[VCAP_IS2_HK_L4_RST]			= {170,   1},
+	[VCAP_IS2_HK_L4_SYN]			= {171,   1},
+	[VCAP_IS2_HK_L4_FIN]			= {172,   1},
+	[VCAP_IS2_HK_L4_1588_DOM]		= {173,   8},
+	[VCAP_IS2_HK_L4_1588_VER]		= {181,   4},
+	/* IP4_OTHER (TYPE=101) */
+	[VCAP_IS2_HK_IP4_L3_PROTO]		= {124,   8},
+	[VCAP_IS2_HK_L3_PAYLOAD]		= {132,  56},
+	/* IP6_STD (TYPE=110) */
+	[VCAP_IS2_HK_IP6_L3_TTL_GT0]		= { 46,   1},
+	[VCAP_IS2_HK_L3_IP6_SIP]		= { 47, 128},
+	[VCAP_IS2_HK_IP6_L3_PROTO]		= {175,   8},
+	/* OAM (TYPE=111) */
+	[VCAP_IS2_HK_OAM_MEL_FLAGS]		= {142,   7},
+	[VCAP_IS2_HK_OAM_VER]			= {149,   5},
+	[VCAP_IS2_HK_OAM_OPCODE]		= {154,   8},
+	[VCAP_IS2_HK_OAM_FLAGS]			= {162,   8},
+	[VCAP_IS2_HK_OAM_MEPID]			= {170,  16},
+	[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0]		= {186,   1},
+	[VCAP_IS2_HK_OAM_IS_Y1731]		= {187,   1},
+};
+
+struct vcap_field vsc7514_vcap_is2_actions[] = {
+	[VCAP_IS2_ACT_HIT_ME_ONCE]		= {  0,  1},
+	[VCAP_IS2_ACT_CPU_COPY_ENA]		= {  1,  1},
+	[VCAP_IS2_ACT_CPU_QU_NUM]		= {  2,  3},
+	[VCAP_IS2_ACT_MASK_MODE]		= {  5,  2},
+	[VCAP_IS2_ACT_MIRROR_ENA]		= {  7,  1},
+	[VCAP_IS2_ACT_LRN_DIS]			= {  8,  1},
+	[VCAP_IS2_ACT_POLICE_ENA]		= {  9,  1},
+	[VCAP_IS2_ACT_POLICE_IDX]		= { 10,  9},
+	[VCAP_IS2_ACT_POLICE_VCAP_ONLY]		= { 19,  1},
+	[VCAP_IS2_ACT_PORT_MASK]		= { 20, 11},
+	[VCAP_IS2_ACT_REW_OP]			= { 31,  9},
+	[VCAP_IS2_ACT_SMAC_REPLACE_ENA]		= { 40,  1},
+	[VCAP_IS2_ACT_RSV]			= { 41,  2},
+	[VCAP_IS2_ACT_ACL_ID]			= { 43,  6},
+	[VCAP_IS2_ACT_HIT_CNT]			= { 49, 32},
+};
+
 static int mscc_ocelot_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -362,6 +461,9 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
 				     sizeof(struct ocelot_port *), GFP_KERNEL);
 
+	ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
+	ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
+
 	ocelot_init(ocelot);
 	ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports,
 			    OCELOT_TAG_PREFIX_NONE, OCELOT_TAG_PREFIX_NONE);
diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h
deleted file mode 100644
index e22eac1da783..000000000000
--- a/drivers/net/ethernet/mscc/ocelot_vcap.h
+++ /dev/null
@@ -1,403 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
- * Microsemi Ocelot Switch driver
- * Copyright (c) 2019 Microsemi Corporation
- */
-
-#ifndef _OCELOT_VCAP_H_
-#define _OCELOT_VCAP_H_
-
-/* =================================================================
- *  VCAP Common
- * =================================================================
- */
-
-/* VCAP Type-Group values */
-#define VCAP_TG_NONE 0 /* Entry is invalid */
-#define VCAP_TG_FULL 1 /* Full entry */
-#define VCAP_TG_HALF 2 /* Half entry */
-#define VCAP_TG_QUARTER 3 /* Quarter entry */
-
-/* =================================================================
- *  VCAP IS2
- * =================================================================
- */
-
-#define VCAP_IS2_CNT 64
-#define VCAP_IS2_ENTRY_WIDTH 376
-#define VCAP_IS2_ACTION_WIDTH 99
-#define VCAP_PORT_CNT 11
-
-/* IS2 half key types */
-#define IS2_TYPE_ETYPE 0
-#define IS2_TYPE_LLC 1
-#define IS2_TYPE_SNAP 2
-#define IS2_TYPE_ARP 3
-#define IS2_TYPE_IP_UDP_TCP 4
-#define IS2_TYPE_IP_OTHER 5
-#define IS2_TYPE_IPV6 6
-#define IS2_TYPE_OAM 7
-#define IS2_TYPE_SMAC_SIP6 8
-#define IS2_TYPE_ANY 100 /* Pseudo type */
-
-/* IS2 half key type mask for matching any IP */
-#define IS2_TYPE_MASK_IP_ANY 0xe
-
-/* IS2 action types */
-#define IS2_ACTION_TYPE_NORMAL 0
-#define IS2_ACTION_TYPE_SMAC_SIP 1
-
-/* IS2 MASK_MODE values */
-#define IS2_ACT_MASK_MODE_NONE 0
-#define IS2_ACT_MASK_MODE_FILTER 1
-#define IS2_ACT_MASK_MODE_POLICY 2
-#define IS2_ACT_MASK_MODE_REDIR 3
-
-/* IS2 REW_OP values */
-#define IS2_ACT_REW_OP_NONE 0
-#define IS2_ACT_REW_OP_PTP_ONE 2
-#define IS2_ACT_REW_OP_PTP_TWO 3
-#define IS2_ACT_REW_OP_SPECIAL 8
-#define IS2_ACT_REW_OP_PTP_ORG 9
-#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_1 (IS2_ACT_REW_OP_PTP_ONE | (1 << 3))
-#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_2 (IS2_ACT_REW_OP_PTP_ONE | (2 << 3))
-#define IS2_ACT_REW_OP_PTP_ONE_ADD_DELAY (IS2_ACT_REW_OP_PTP_ONE | (1 << 5))
-#define IS2_ACT_REW_OP_PTP_ONE_ADD_SUB BIT(7)
-
-#define VCAP_PORT_WIDTH 4
-
-/* IS2 quarter key - SMAC_SIP4 */
-#define IS2_QKO_IGR_PORT 0
-#define IS2_QKL_IGR_PORT VCAP_PORT_WIDTH
-#define IS2_QKO_L2_SMAC (IS2_QKO_IGR_PORT + IS2_QKL_IGR_PORT)
-#define IS2_QKL_L2_SMAC 48
-#define IS2_QKO_L3_IP4_SIP (IS2_QKO_L2_SMAC + IS2_QKL_L2_SMAC)
-#define IS2_QKL_L3_IP4_SIP 32
-
-/* IS2 half key - common */
-#define IS2_HKO_TYPE 0
-#define IS2_HKL_TYPE 4
-#define IS2_HKO_FIRST (IS2_HKO_TYPE + IS2_HKL_TYPE)
-#define IS2_HKL_FIRST 1
-#define IS2_HKO_PAG (IS2_HKO_FIRST + IS2_HKL_FIRST)
-#define IS2_HKL_PAG 8
-#define IS2_HKO_IGR_PORT_MASK (IS2_HKO_PAG + IS2_HKL_PAG)
-#define IS2_HKL_IGR_PORT_MASK (VCAP_PORT_CNT + 1)
-#define IS2_HKO_SERVICE_FRM (IS2_HKO_IGR_PORT_MASK + IS2_HKL_IGR_PORT_MASK)
-#define IS2_HKL_SERVICE_FRM 1
-#define IS2_HKO_HOST_MATCH (IS2_HKO_SERVICE_FRM + IS2_HKL_SERVICE_FRM)
-#define IS2_HKL_HOST_MATCH 1
-#define IS2_HKO_L2_MC (IS2_HKO_HOST_MATCH + IS2_HKL_HOST_MATCH)
-#define IS2_HKL_L2_MC 1
-#define IS2_HKO_L2_BC (IS2_HKO_L2_MC + IS2_HKL_L2_MC)
-#define IS2_HKL_L2_BC 1
-#define IS2_HKO_VLAN_TAGGED (IS2_HKO_L2_BC + IS2_HKL_L2_BC)
-#define IS2_HKL_VLAN_TAGGED 1
-#define IS2_HKO_VID (IS2_HKO_VLAN_TAGGED + IS2_HKL_VLAN_TAGGED)
-#define IS2_HKL_VID 12
-#define IS2_HKO_DEI (IS2_HKO_VID + IS2_HKL_VID)
-#define IS2_HKL_DEI 1
-#define IS2_HKO_PCP (IS2_HKO_DEI + IS2_HKL_DEI)
-#define IS2_HKL_PCP 3
-
-/* IS2 half key - MAC_ETYPE/MAC_LLC/MAC_SNAP/OAM common */
-#define IS2_HKO_L2_DMAC (IS2_HKO_PCP + IS2_HKL_PCP)
-#define IS2_HKL_L2_DMAC 48
-#define IS2_HKO_L2_SMAC (IS2_HKO_L2_DMAC + IS2_HKL_L2_DMAC)
-#define IS2_HKL_L2_SMAC 48
-
-/* IS2 half key - MAC_ETYPE */
-#define IS2_HKO_MAC_ETYPE_ETYPE (IS2_HKO_L2_SMAC + IS2_HKL_L2_SMAC)
-#define IS2_HKL_MAC_ETYPE_ETYPE 16
-#define IS2_HKO_MAC_ETYPE_L2_PAYLOAD                                           \
-	(IS2_HKO_MAC_ETYPE_ETYPE + IS2_HKL_MAC_ETYPE_ETYPE)
-#define IS2_HKL_MAC_ETYPE_L2_PAYLOAD 27
-
-/* IS2 half key - MAC_LLC */
-#define IS2_HKO_MAC_LLC_L2_LLC IS2_HKO_MAC_ETYPE_ETYPE
-#define IS2_HKL_MAC_LLC_L2_LLC 40
-
-/* IS2 half key - MAC_SNAP */
-#define IS2_HKO_MAC_SNAP_L2_SNAP IS2_HKO_MAC_ETYPE_ETYPE
-#define IS2_HKL_MAC_SNAP_L2_SNAP 40
-
-/* IS2 half key - ARP */
-#define IS2_HKO_MAC_ARP_L2_SMAC IS2_HKO_L2_DMAC
-#define IS2_HKL_MAC_ARP_L2_SMAC 48
-#define IS2_HKO_MAC_ARP_ARP_ADDR_SPACE_OK                                      \
-	(IS2_HKO_MAC_ARP_L2_SMAC + IS2_HKL_MAC_ARP_L2_SMAC)
-#define IS2_HKL_MAC_ARP_ARP_ADDR_SPACE_OK 1
-#define IS2_HKO_MAC_ARP_ARP_PROTO_SPACE_OK                                     \
-	(IS2_HKO_MAC_ARP_ARP_ADDR_SPACE_OK + IS2_HKL_MAC_ARP_ARP_ADDR_SPACE_OK)
-#define IS2_HKL_MAC_ARP_ARP_PROTO_SPACE_OK 1
-#define IS2_HKO_MAC_ARP_ARP_LEN_OK                                             \
-	(IS2_HKO_MAC_ARP_ARP_PROTO_SPACE_OK +                                  \
-	 IS2_HKL_MAC_ARP_ARP_PROTO_SPACE_OK)
-#define IS2_HKL_MAC_ARP_ARP_LEN_OK 1
-#define IS2_HKO_MAC_ARP_ARP_TGT_MATCH                                          \
-	(IS2_HKO_MAC_ARP_ARP_LEN_OK + IS2_HKL_MAC_ARP_ARP_LEN_OK)
-#define IS2_HKL_MAC_ARP_ARP_TGT_MATCH 1
-#define IS2_HKO_MAC_ARP_ARP_SENDER_MATCH                                       \
-	(IS2_HKO_MAC_ARP_ARP_TGT_MATCH + IS2_HKL_MAC_ARP_ARP_TGT_MATCH)
-#define IS2_HKL_MAC_ARP_ARP_SENDER_MATCH 1
-#define IS2_HKO_MAC_ARP_ARP_OPCODE_UNKNOWN                                     \
-	(IS2_HKO_MAC_ARP_ARP_SENDER_MATCH + IS2_HKL_MAC_ARP_ARP_SENDER_MATCH)
-#define IS2_HKL_MAC_ARP_ARP_OPCODE_UNKNOWN 1
-#define IS2_HKO_MAC_ARP_ARP_OPCODE                                             \
-	(IS2_HKO_MAC_ARP_ARP_OPCODE_UNKNOWN +                                  \
-	 IS2_HKL_MAC_ARP_ARP_OPCODE_UNKNOWN)
-#define IS2_HKL_MAC_ARP_ARP_OPCODE 2
-#define IS2_HKO_MAC_ARP_L3_IP4_DIP                                             \
-	(IS2_HKO_MAC_ARP_ARP_OPCODE + IS2_HKL_MAC_ARP_ARP_OPCODE)
-#define IS2_HKL_MAC_ARP_L3_IP4_DIP 32
-#define IS2_HKO_MAC_ARP_L3_IP4_SIP                                             \
-	(IS2_HKO_MAC_ARP_L3_IP4_DIP + IS2_HKL_MAC_ARP_L3_IP4_DIP)
-#define IS2_HKL_MAC_ARP_L3_IP4_SIP 32
-#define IS2_HKO_MAC_ARP_DIP_EQ_SIP                                             \
-	(IS2_HKO_MAC_ARP_L3_IP4_SIP + IS2_HKL_MAC_ARP_L3_IP4_SIP)
-#define IS2_HKL_MAC_ARP_DIP_EQ_SIP 1
-
-/* IS2 half key - IP4_TCP_UDP/IP4_OTHER common */
-#define IS2_HKO_IP4 IS2_HKO_L2_DMAC
-#define IS2_HKL_IP4 1
-#define IS2_HKO_L3_FRAGMENT (IS2_HKO_IP4 + IS2_HKL_IP4)
-#define IS2_HKL_L3_FRAGMENT 1
-#define IS2_HKO_L3_FRAG_OFS_GT0 (IS2_HKO_L3_FRAGMENT + IS2_HKL_L3_FRAGMENT)
-#define IS2_HKL_L3_FRAG_OFS_GT0 1
-#define IS2_HKO_L3_OPTIONS (IS2_HKO_L3_FRAG_OFS_GT0 + IS2_HKL_L3_FRAG_OFS_GT0)
-#define IS2_HKL_L3_OPTIONS 1
-#define IS2_HKO_L3_TTL_GT0 (IS2_HKO_L3_OPTIONS + IS2_HKL_L3_OPTIONS)
-#define IS2_HKL_L3_TTL_GT0 1
-#define IS2_HKO_L3_TOS (IS2_HKO_L3_TTL_GT0 + IS2_HKL_L3_TTL_GT0)
-#define IS2_HKL_L3_TOS 8
-#define IS2_HKO_L3_IP4_DIP (IS2_HKO_L3_TOS + IS2_HKL_L3_TOS)
-#define IS2_HKL_L3_IP4_DIP 32
-#define IS2_HKO_L3_IP4_SIP (IS2_HKO_L3_IP4_DIP + IS2_HKL_L3_IP4_DIP)
-#define IS2_HKL_L3_IP4_SIP 32
-#define IS2_HKO_DIP_EQ_SIP (IS2_HKO_L3_IP4_SIP + IS2_HKL_L3_IP4_SIP)
-#define IS2_HKL_DIP_EQ_SIP 1
-
-/* IS2 half key - IP4_TCP_UDP */
-#define IS2_HKO_IP4_TCP_UDP_TCP (IS2_HKO_DIP_EQ_SIP + IS2_HKL_DIP_EQ_SIP)
-#define IS2_HKL_IP4_TCP_UDP_TCP 1
-#define IS2_HKO_IP4_TCP_UDP_L4_DPORT                                           \
-	(IS2_HKO_IP4_TCP_UDP_TCP + IS2_HKL_IP4_TCP_UDP_TCP)
-#define IS2_HKL_IP4_TCP_UDP_L4_DPORT 16
-#define IS2_HKO_IP4_TCP_UDP_L4_SPORT                                           \
-	(IS2_HKO_IP4_TCP_UDP_L4_DPORT + IS2_HKL_IP4_TCP_UDP_L4_DPORT)
-#define IS2_HKL_IP4_TCP_UDP_L4_SPORT 16
-#define IS2_HKO_IP4_TCP_UDP_L4_RNG                                             \
-	(IS2_HKO_IP4_TCP_UDP_L4_SPORT + IS2_HKL_IP4_TCP_UDP_L4_SPORT)
-#define IS2_HKL_IP4_TCP_UDP_L4_RNG 8
-#define IS2_HKO_IP4_TCP_UDP_SPORT_EQ_DPORT                                     \
-	(IS2_HKO_IP4_TCP_UDP_L4_RNG + IS2_HKL_IP4_TCP_UDP_L4_RNG)
-#define IS2_HKL_IP4_TCP_UDP_SPORT_EQ_DPORT 1
-#define IS2_HKO_IP4_TCP_UDP_SEQUENCE_EQ0                                       \
-	(IS2_HKO_IP4_TCP_UDP_SPORT_EQ_DPORT +                                  \
-	 IS2_HKL_IP4_TCP_UDP_SPORT_EQ_DPORT)
-#define IS2_HKL_IP4_TCP_UDP_SEQUENCE_EQ0 1
-#define IS2_HKO_IP4_TCP_UDP_L4_FIN                                             \
-	(IS2_HKO_IP4_TCP_UDP_SEQUENCE_EQ0 + IS2_HKL_IP4_TCP_UDP_SEQUENCE_EQ0)
-#define IS2_HKL_IP4_TCP_UDP_L4_FIN 1
-#define IS2_HKO_IP4_TCP_UDP_L4_SYN                                             \
-	(IS2_HKO_IP4_TCP_UDP_L4_FIN + IS2_HKL_IP4_TCP_UDP_L4_FIN)
-#define IS2_HKL_IP4_TCP_UDP_L4_SYN 1
-#define IS2_HKO_IP4_TCP_UDP_L4_RST                                             \
-	(IS2_HKO_IP4_TCP_UDP_L4_SYN + IS2_HKL_IP4_TCP_UDP_L4_SYN)
-#define IS2_HKL_IP4_TCP_UDP_L4_RST 1
-#define IS2_HKO_IP4_TCP_UDP_L4_PSH                                             \
-	(IS2_HKO_IP4_TCP_UDP_L4_RST + IS2_HKL_IP4_TCP_UDP_L4_RST)
-#define IS2_HKL_IP4_TCP_UDP_L4_PSH 1
-#define IS2_HKO_IP4_TCP_UDP_L4_ACK                                             \
-	(IS2_HKO_IP4_TCP_UDP_L4_PSH + IS2_HKL_IP4_TCP_UDP_L4_PSH)
-#define IS2_HKL_IP4_TCP_UDP_L4_ACK 1
-#define IS2_HKO_IP4_TCP_UDP_L4_URG                                             \
-	(IS2_HKO_IP4_TCP_UDP_L4_ACK + IS2_HKL_IP4_TCP_UDP_L4_ACK)
-#define IS2_HKL_IP4_TCP_UDP_L4_URG 1
-#define IS2_HKO_IP4_TCP_UDP_L4_1588_DOM                                        \
-	(IS2_HKO_IP4_TCP_UDP_L4_URG + IS2_HKL_IP4_TCP_UDP_L4_URG)
-#define IS2_HKL_IP4_TCP_UDP_L4_1588_DOM 8
-#define IS2_HKO_IP4_TCP_UDP_L4_1588_VER                                        \
-	(IS2_HKO_IP4_TCP_UDP_L4_1588_DOM + IS2_HKL_IP4_TCP_UDP_L4_1588_DOM)
-#define IS2_HKL_IP4_TCP_UDP_L4_1588_VER 4
-
-/* IS2 half key - IP4_OTHER */
-#define IS2_HKO_IP4_OTHER_L3_PROTO IS2_HKO_IP4_TCP_UDP_TCP
-#define IS2_HKL_IP4_OTHER_L3_PROTO 8
-#define IS2_HKO_IP4_OTHER_L3_PAYLOAD                                           \
-	(IS2_HKO_IP4_OTHER_L3_PROTO + IS2_HKL_IP4_OTHER_L3_PROTO)
-#define IS2_HKL_IP4_OTHER_L3_PAYLOAD 56
-
-/* IS2 half key - IP6_STD */
-#define IS2_HKO_IP6_STD_L3_TTL_GT0 IS2_HKO_L2_DMAC
-#define IS2_HKL_IP6_STD_L3_TTL_GT0 1
-#define IS2_HKO_IP6_STD_L3_IP6_SIP                                             \
-	(IS2_HKO_IP6_STD_L3_TTL_GT0 + IS2_HKL_IP6_STD_L3_TTL_GT0)
-#define IS2_HKL_IP6_STD_L3_IP6_SIP 128
-#define IS2_HKO_IP6_STD_L3_PROTO                                               \
-	(IS2_HKO_IP6_STD_L3_IP6_SIP + IS2_HKL_IP6_STD_L3_IP6_SIP)
-#define IS2_HKL_IP6_STD_L3_PROTO 8
-
-/* IS2 half key - OAM */
-#define IS2_HKO_OAM_OAM_MEL_FLAGS IS2_HKO_MAC_ETYPE_ETYPE
-#define IS2_HKL_OAM_OAM_MEL_FLAGS 7
-#define IS2_HKO_OAM_OAM_VER                                                    \
-	(IS2_HKO_OAM_OAM_MEL_FLAGS + IS2_HKL_OAM_OAM_MEL_FLAGS)
-#define IS2_HKL_OAM_OAM_VER 5
-#define IS2_HKO_OAM_OAM_OPCODE (IS2_HKO_OAM_OAM_VER + IS2_HKL_OAM_OAM_VER)
-#define IS2_HKL_OAM_OAM_OPCODE 8
-#define IS2_HKO_OAM_OAM_FLAGS (IS2_HKO_OAM_OAM_OPCODE + IS2_HKL_OAM_OAM_OPCODE)
-#define IS2_HKL_OAM_OAM_FLAGS 8
-#define IS2_HKO_OAM_OAM_MEPID (IS2_HKO_OAM_OAM_FLAGS + IS2_HKL_OAM_OAM_FLAGS)
-#define IS2_HKL_OAM_OAM_MEPID 16
-#define IS2_HKO_OAM_OAM_CCM_CNTS_EQ0                                           \
-	(IS2_HKO_OAM_OAM_MEPID + IS2_HKL_OAM_OAM_MEPID)
-#define IS2_HKL_OAM_OAM_CCM_CNTS_EQ0 1
-
-/* IS2 half key - SMAC_SIP6 */
-#define IS2_HKO_SMAC_SIP6_IGR_PORT IS2_HKL_TYPE
-#define IS2_HKL_SMAC_SIP6_IGR_PORT VCAP_PORT_WIDTH
-#define IS2_HKO_SMAC_SIP6_L2_SMAC                                              \
-	(IS2_HKO_SMAC_SIP6_IGR_PORT + IS2_HKL_SMAC_SIP6_IGR_PORT)
-#define IS2_HKL_SMAC_SIP6_L2_SMAC 48
-#define IS2_HKO_SMAC_SIP6_L3_IP6_SIP                                           \
-	(IS2_HKO_SMAC_SIP6_L2_SMAC + IS2_HKL_SMAC_SIP6_L2_SMAC)
-#define IS2_HKL_SMAC_SIP6_L3_IP6_SIP 128
-
-/* IS2 full key - common */
-#define IS2_FKO_TYPE 0
-#define IS2_FKL_TYPE 2
-#define IS2_FKO_FIRST (IS2_FKO_TYPE + IS2_FKL_TYPE)
-#define IS2_FKL_FIRST 1
-#define IS2_FKO_PAG (IS2_FKO_FIRST + IS2_FKL_FIRST)
-#define IS2_FKL_PAG 8
-#define IS2_FKO_IGR_PORT_MASK (IS2_FKO_PAG + IS2_FKL_PAG)
-#define IS2_FKL_IGR_PORT_MASK (VCAP_PORT_CNT + 1)
-#define IS2_FKO_SERVICE_FRM (IS2_FKO_IGR_PORT_MASK + IS2_FKL_IGR_PORT_MASK)
-#define IS2_FKL_SERVICE_FRM 1
-#define IS2_FKO_HOST_MATCH (IS2_FKO_SERVICE_FRM + IS2_FKL_SERVICE_FRM)
-#define IS2_FKL_HOST_MATCH 1
-#define IS2_FKO_L2_MC (IS2_FKO_HOST_MATCH + IS2_FKL_HOST_MATCH)
-#define IS2_FKL_L2_MC 1
-#define IS2_FKO_L2_BC (IS2_FKO_L2_MC + IS2_FKL_L2_MC)
-#define IS2_FKL_L2_BC 1
-#define IS2_FKO_VLAN_TAGGED (IS2_FKO_L2_BC + IS2_FKL_L2_BC)
-#define IS2_FKL_VLAN_TAGGED 1
-#define IS2_FKO_VID (IS2_FKO_VLAN_TAGGED + IS2_FKL_VLAN_TAGGED)
-#define IS2_FKL_VID 12
-#define IS2_FKO_DEI (IS2_FKO_VID + IS2_FKL_VID)
-#define IS2_FKL_DEI 1
-#define IS2_FKO_PCP (IS2_FKO_DEI + IS2_FKL_DEI)
-#define IS2_FKL_PCP 3
-
-/* IS2 full key - IP6_TCP_UDP/IP6_OTHER common */
-#define IS2_FKO_L3_TTL_GT0 (IS2_FKO_PCP + IS2_FKL_PCP)
-#define IS2_FKL_L3_TTL_GT0 1
-#define IS2_FKO_L3_TOS (IS2_FKO_L3_TTL_GT0 + IS2_FKL_L3_TTL_GT0)
-#define IS2_FKL_L3_TOS 8
-#define IS2_FKO_L3_IP6_DIP (IS2_FKO_L3_TOS + IS2_FKL_L3_TOS)
-#define IS2_FKL_L3_IP6_DIP 128
-#define IS2_FKO_L3_IP6_SIP (IS2_FKO_L3_IP6_DIP + IS2_FKL_L3_IP6_DIP)
-#define IS2_FKL_L3_IP6_SIP 128
-#define IS2_FKO_DIP_EQ_SIP (IS2_FKO_L3_IP6_SIP + IS2_FKL_L3_IP6_SIP)
-#define IS2_FKL_DIP_EQ_SIP 1
-
-/* IS2 full key - IP6_TCP_UDP */
-#define IS2_FKO_IP6_TCP_UDP_TCP (IS2_FKO_DIP_EQ_SIP + IS2_FKL_DIP_EQ_SIP)
-#define IS2_FKL_IP6_TCP_UDP_TCP 1
-#define IS2_FKO_IP6_TCP_UDP_L4_DPORT                                           \
-	(IS2_FKO_IP6_TCP_UDP_TCP + IS2_FKL_IP6_TCP_UDP_TCP)
-#define IS2_FKL_IP6_TCP_UDP_L4_DPORT 16
-#define IS2_FKO_IP6_TCP_UDP_L4_SPORT                                           \
-	(IS2_FKO_IP6_TCP_UDP_L4_DPORT + IS2_FKL_IP6_TCP_UDP_L4_DPORT)
-#define IS2_FKL_IP6_TCP_UDP_L4_SPORT 16
-#define IS2_FKO_IP6_TCP_UDP_L4_RNG                                             \
-	(IS2_FKO_IP6_TCP_UDP_L4_SPORT + IS2_FKL_IP6_TCP_UDP_L4_SPORT)
-#define IS2_FKL_IP6_TCP_UDP_L4_RNG 8
-#define IS2_FKO_IP6_TCP_UDP_SPORT_EQ_DPORT                                     \
-	(IS2_FKO_IP6_TCP_UDP_L4_RNG + IS2_FKL_IP6_TCP_UDP_L4_RNG)
-#define IS2_FKL_IP6_TCP_UDP_SPORT_EQ_DPORT 1
-#define IS2_FKO_IP6_TCP_UDP_SEQUENCE_EQ0                                       \
-	(IS2_FKO_IP6_TCP_UDP_SPORT_EQ_DPORT +                                  \
-	 IS2_FKL_IP6_TCP_UDP_SPORT_EQ_DPORT)
-#define IS2_FKL_IP6_TCP_UDP_SEQUENCE_EQ0 1
-#define IS2_FKO_IP6_TCP_UDP_L4_FIN                                             \
-	(IS2_FKO_IP6_TCP_UDP_SEQUENCE_EQ0 + IS2_FKL_IP6_TCP_UDP_SEQUENCE_EQ0)
-#define IS2_FKL_IP6_TCP_UDP_L4_FIN 1
-#define IS2_FKO_IP6_TCP_UDP_L4_SYN                                             \
-	(IS2_FKO_IP6_TCP_UDP_L4_FIN + IS2_FKL_IP6_TCP_UDP_L4_FIN)
-#define IS2_FKL_IP6_TCP_UDP_L4_SYN 1
-#define IS2_FKO_IP6_TCP_UDP_L4_RST                                             \
-	(IS2_FKO_IP6_TCP_UDP_L4_SYN + IS2_FKL_IP6_TCP_UDP_L4_SYN)
-#define IS2_FKL_IP6_TCP_UDP_L4_RST 1
-#define IS2_FKO_IP6_TCP_UDP_L4_PSH                                             \
-	(IS2_FKO_IP6_TCP_UDP_L4_RST + IS2_FKL_IP6_TCP_UDP_L4_RST)
-#define IS2_FKL_IP6_TCP_UDP_L4_PSH 1
-#define IS2_FKO_IP6_TCP_UDP_L4_ACK                                             \
-	(IS2_FKO_IP6_TCP_UDP_L4_PSH + IS2_FKL_IP6_TCP_UDP_L4_PSH)
-#define IS2_FKL_IP6_TCP_UDP_L4_ACK 1
-#define IS2_FKO_IP6_TCP_UDP_L4_URG                                             \
-	(IS2_FKO_IP6_TCP_UDP_L4_ACK + IS2_FKL_IP6_TCP_UDP_L4_ACK)
-#define IS2_FKL_IP6_TCP_UDP_L4_URG 1
-#define IS2_FKO_IP6_TCP_UDP_L4_1588_DOM                                        \
-	(IS2_FKO_IP6_TCP_UDP_L4_URG + IS2_FKL_IP6_TCP_UDP_L4_URG)
-#define IS2_FKL_IP6_TCP_UDP_L4_1588_DOM 8
-#define IS2_FKO_IP6_TCP_UDP_L4_1588_VER                                        \
-	(IS2_FKO_IP6_TCP_UDP_L4_1588_DOM + IS2_FKL_IP6_TCP_UDP_L4_1588_DOM)
-#define IS2_FKL_IP6_TCP_UDP_L4_1588_VER 4
-
-/* IS2 full key - IP6_OTHER */
-#define IS2_FKO_IP6_OTHER_L3_PROTO IS2_FKO_IP6_TCP_UDP_TCP
-#define IS2_FKL_IP6_OTHER_L3_PROTO 8
-#define IS2_FKO_IP6_OTHER_L3_PAYLOAD                                           \
-	(IS2_FKO_IP6_OTHER_L3_PROTO + IS2_FKL_IP6_OTHER_L3_PROTO)
-#define IS2_FKL_IP6_OTHER_L3_PAYLOAD 56
-
-/* IS2 full key - CUSTOM */
-#define IS2_FKO_CUSTOM_CUSTOM_TYPE IS2_FKO_L3_TTL_GT0
-#define IS2_FKL_CUSTOM_CUSTOM_TYPE 1
-#define IS2_FKO_CUSTOM_CUSTOM                                                  \
-	(IS2_FKO_CUSTOM_CUSTOM_TYPE + IS2_FKL_CUSTOM_CUSTOM_TYPE)
-#define IS2_FKL_CUSTOM_CUSTOM 320
-
-/* IS2 action - BASE_TYPE */
-#define IS2_AO_HIT_ME_ONCE 0
-#define IS2_AL_HIT_ME_ONCE 1
-#define IS2_AO_CPU_COPY_ENA (IS2_AO_HIT_ME_ONCE + IS2_AL_HIT_ME_ONCE)
-#define IS2_AL_CPU_COPY_ENA 1
-#define IS2_AO_CPU_QU_NUM (IS2_AO_CPU_COPY_ENA + IS2_AL_CPU_COPY_ENA)
-#define IS2_AL_CPU_QU_NUM 3
-#define IS2_AO_MASK_MODE (IS2_AO_CPU_QU_NUM + IS2_AL_CPU_QU_NUM)
-#define IS2_AL_MASK_MODE 2
-#define IS2_AO_MIRROR_ENA (IS2_AO_MASK_MODE + IS2_AL_MASK_MODE)
-#define IS2_AL_MIRROR_ENA 1
-#define IS2_AO_LRN_DIS (IS2_AO_MIRROR_ENA + IS2_AL_MIRROR_ENA)
-#define IS2_AL_LRN_DIS 1
-#define IS2_AO_POLICE_ENA (IS2_AO_LRN_DIS + IS2_AL_LRN_DIS)
-#define IS2_AL_POLICE_ENA 1
-#define IS2_AO_POLICE_IDX (IS2_AO_POLICE_ENA + IS2_AL_POLICE_ENA)
-#define IS2_AL_POLICE_IDX 9
-#define IS2_AO_POLICE_VCAP_ONLY (IS2_AO_POLICE_IDX + IS2_AL_POLICE_IDX)
-#define IS2_AL_POLICE_VCAP_ONLY 1
-#define IS2_AO_PORT_MASK (IS2_AO_POLICE_VCAP_ONLY + IS2_AL_POLICE_VCAP_ONLY)
-#define IS2_AL_PORT_MASK VCAP_PORT_CNT
-#define IS2_AO_REW_OP (IS2_AO_PORT_MASK + IS2_AL_PORT_MASK)
-#define IS2_AL_REW_OP 9
-#define IS2_AO_LM_CNT_DIS (IS2_AO_REW_OP + IS2_AL_REW_OP)
-#define IS2_AL_LM_CNT_DIS 1
-#define IS2_AO_ISDX_ENA                                                        \
-	(IS2_AO_LM_CNT_DIS + IS2_AL_LM_CNT_DIS + 1) /* Reserved bit */
-#define IS2_AL_ISDX_ENA 1
-#define IS2_AO_ACL_ID (IS2_AO_ISDX_ENA + IS2_AL_ISDX_ENA)
-#define IS2_AL_ACL_ID 6
-
-/* IS2 action - SMAC_SIP */
-#define IS2_AO_SMAC_SIP_CPU_COPY_ENA 0
-#define IS2_AL_SMAC_SIP_CPU_COPY_ENA 1
-#define IS2_AO_SMAC_SIP_CPU_QU_NUM 1
-#define IS2_AL_SMAC_SIP_CPU_QU_NUM 3
-#define IS2_AO_SMAC_SIP_FWD_KILL_ENA 4
-#define IS2_AL_SMAC_SIP_FWD_KILL_ENA 1
-#define IS2_AO_SMAC_SIP_HOST_MATCH 5
-#define IS2_AL_SMAC_SIP_HOST_MATCH 1
-
-#endif /* _OCELOT_VCAP_H_ */
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 74e7c63adad4..f63266a4ca70 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -462,6 +462,9 @@ struct ocelot {
 
 	struct ocelot_acl_block		acl_block;
 
+	struct vcap_field		*vcap_is2_keys;
+	struct vcap_field		*vcap_is2_actions;
+
 	/* Workqueue to check statistics for overflow with its lock */
 	struct mutex			stats_lock;
 	u64				*stats;
diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h
new file mode 100644
index 000000000000..0783f0ffc813
--- /dev/null
+++ b/include/soc/mscc/ocelot_vcap.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ * Microsemi Ocelot Switch driver
+ * Copyright (c) 2019 Microsemi Corporation
+ */
+
+#ifndef _OCELOT_VCAP_H_
+#define _OCELOT_VCAP_H_
+
+/* =================================================================
+ *  VCAP Common
+ * =================================================================
+ */
+
+/* VCAP Type-Group values */
+#define VCAP_TG_NONE 0 /* Entry is invalid */
+#define VCAP_TG_FULL 1 /* Full entry */
+#define VCAP_TG_HALF 2 /* Half entry */
+#define VCAP_TG_QUARTER 3 /* Quarter entry */
+
+/* =================================================================
+ *  VCAP IS2
+ * =================================================================
+ */
+
+#define VCAP_IS2_CNT 64
+#define VCAP_IS2_ENTRY_WIDTH 376
+#define VCAP_IS2_ACTION_WIDTH 99
+#define VCAP_PORT_CNT 11
+
+/* IS2 half key types */
+#define IS2_TYPE_ETYPE 0
+#define IS2_TYPE_LLC 1
+#define IS2_TYPE_SNAP 2
+#define IS2_TYPE_ARP 3
+#define IS2_TYPE_IP_UDP_TCP 4
+#define IS2_TYPE_IP_OTHER 5
+#define IS2_TYPE_IPV6 6
+#define IS2_TYPE_OAM 7
+#define IS2_TYPE_SMAC_SIP6 8
+#define IS2_TYPE_ANY 100 /* Pseudo type */
+
+/* IS2 half key type mask for matching any IP */
+#define IS2_TYPE_MASK_IP_ANY 0xe
+
+/* IS2 action types */
+#define IS2_ACTION_TYPE_NORMAL 0
+#define IS2_ACTION_TYPE_SMAC_SIP 1
+
+/* IS2 MASK_MODE values */
+#define IS2_ACT_MASK_MODE_NONE 0
+#define IS2_ACT_MASK_MODE_FILTER 1
+#define IS2_ACT_MASK_MODE_POLICY 2
+#define IS2_ACT_MASK_MODE_REDIR 3
+
+/* IS2 REW_OP values */
+#define IS2_ACT_REW_OP_NONE 0
+#define IS2_ACT_REW_OP_PTP_ONE 2
+#define IS2_ACT_REW_OP_PTP_TWO 3
+#define IS2_ACT_REW_OP_SPECIAL 8
+#define IS2_ACT_REW_OP_PTP_ORG 9
+#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_1 (IS2_ACT_REW_OP_PTP_ONE | (1 << 3))
+#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_2 (IS2_ACT_REW_OP_PTP_ONE | (2 << 3))
+#define IS2_ACT_REW_OP_PTP_ONE_ADD_DELAY (IS2_ACT_REW_OP_PTP_ONE | (1 << 5))
+#define IS2_ACT_REW_OP_PTP_ONE_ADD_SUB BIT(7)
+
+#define VCAP_PORT_WIDTH 4
+
+/* IS2 quarter key - SMAC_SIP4 */
+#define IS2_QKO_IGR_PORT 0
+#define IS2_QKL_IGR_PORT VCAP_PORT_WIDTH
+#define IS2_QKO_L2_SMAC (IS2_QKO_IGR_PORT + IS2_QKL_IGR_PORT)
+#define IS2_QKL_L2_SMAC 48
+#define IS2_QKO_L3_IP4_SIP (IS2_QKO_L2_SMAC + IS2_QKL_L2_SMAC)
+#define IS2_QKL_L3_IP4_SIP 32
+
+enum vcap_is2_half_key_field {
+	/* Common */
+	VCAP_IS2_TYPE,
+	VCAP_IS2_HK_FIRST,
+	VCAP_IS2_HK_PAG,
+	VCAP_IS2_HK_RSV1,
+	VCAP_IS2_HK_IGR_PORT_MASK,
+	VCAP_IS2_HK_RSV2,
+	VCAP_IS2_HK_HOST_MATCH,
+	VCAP_IS2_HK_L2_MC,
+	VCAP_IS2_HK_L2_BC,
+	VCAP_IS2_HK_VLAN_TAGGED,
+	VCAP_IS2_HK_VID,
+	VCAP_IS2_HK_DEI,
+	VCAP_IS2_HK_PCP,
+	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */
+	VCAP_IS2_HK_L2_DMAC,
+	VCAP_IS2_HK_L2_SMAC,
+	/* MAC_ETYPE (TYPE=000) */
+	VCAP_IS2_HK_MAC_ETYPE_ETYPE,
+	VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0,
+	VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1,
+	VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2,
+	/* MAC_LLC (TYPE=001) */
+	VCAP_IS2_HK_MAC_LLC_DMAC,
+	VCAP_IS2_HK_MAC_LLC_SMAC,
+	VCAP_IS2_HK_MAC_LLC_L2_LLC,
+	/* MAC_SNAP (TYPE=010) */
+	VCAP_IS2_HK_MAC_SNAP_SMAC,
+	VCAP_IS2_HK_MAC_SNAP_DMAC,
+	VCAP_IS2_HK_MAC_SNAP_L2_SNAP,
+	/* MAC_ARP (TYPE=011) */
+	VCAP_IS2_HK_MAC_ARP_SMAC,
+	VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK,
+	VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK,
+	VCAP_IS2_HK_MAC_ARP_LEN_OK,
+	VCAP_IS2_HK_MAC_ARP_TARGET_MATCH,
+	VCAP_IS2_HK_MAC_ARP_SENDER_MATCH,
+	VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN,
+	VCAP_IS2_HK_MAC_ARP_OPCODE,
+	VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP,
+	VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP,
+	VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP,
+	/* IP4_TCP_UDP / IP4_OTHER common */
+	VCAP_IS2_HK_IP4,
+	VCAP_IS2_HK_L3_FRAGMENT,
+	VCAP_IS2_HK_L3_FRAG_OFS_GT0,
+	VCAP_IS2_HK_L3_OPTIONS,
+	VCAP_IS2_HK_IP4_L3_TTL_GT0,
+	VCAP_IS2_HK_L3_TOS,
+	VCAP_IS2_HK_L3_IP4_DIP,
+	VCAP_IS2_HK_L3_IP4_SIP,
+	VCAP_IS2_HK_DIP_EQ_SIP,
+	/* IP4_TCP_UDP (TYPE=100) */
+	VCAP_IS2_HK_TCP,
+	VCAP_IS2_HK_L4_SPORT,
+	VCAP_IS2_HK_L4_DPORT,
+	VCAP_IS2_HK_L4_RNG,
+	VCAP_IS2_HK_L4_SPORT_EQ_DPORT,
+	VCAP_IS2_HK_L4_SEQUENCE_EQ0,
+	VCAP_IS2_HK_L4_URG,
+	VCAP_IS2_HK_L4_ACK,
+	VCAP_IS2_HK_L4_PSH,
+	VCAP_IS2_HK_L4_RST,
+	VCAP_IS2_HK_L4_SYN,
+	VCAP_IS2_HK_L4_FIN,
+	VCAP_IS2_HK_L4_1588_DOM,
+	VCAP_IS2_HK_L4_1588_VER,
+	/* IP4_OTHER (TYPE=101) */
+	VCAP_IS2_HK_IP4_L3_PROTO,
+	VCAP_IS2_HK_L3_PAYLOAD,
+	/* IP6_STD (TYPE=110) */
+	VCAP_IS2_HK_IP6_L3_TTL_GT0,
+	VCAP_IS2_HK_IP6_L3_PROTO,
+	VCAP_IS2_HK_L3_IP6_SIP,
+	/* OAM (TYPE=111) */
+	VCAP_IS2_HK_OAM_MEL_FLAGS,
+	VCAP_IS2_HK_OAM_VER,
+	VCAP_IS2_HK_OAM_OPCODE,
+	VCAP_IS2_HK_OAM_FLAGS,
+	VCAP_IS2_HK_OAM_MEPID,
+	VCAP_IS2_HK_OAM_CCM_CNTS_EQ0,
+	VCAP_IS2_HK_OAM_IS_Y1731,
+};
+
+struct vcap_field {
+	int offset;
+	int length;
+};
+
+enum vcap_is2_action_field {
+	VCAP_IS2_ACT_HIT_ME_ONCE,
+	VCAP_IS2_ACT_CPU_COPY_ENA,
+	VCAP_IS2_ACT_CPU_QU_NUM,
+	VCAP_IS2_ACT_MASK_MODE,
+	VCAP_IS2_ACT_MIRROR_ENA,
+	VCAP_IS2_ACT_LRN_DIS,
+	VCAP_IS2_ACT_POLICE_ENA,
+	VCAP_IS2_ACT_POLICE_IDX,
+	VCAP_IS2_ACT_POLICE_VCAP_ONLY,
+	VCAP_IS2_ACT_PORT_MASK,
+	VCAP_IS2_ACT_REW_OP,
+	VCAP_IS2_ACT_SMAC_REPLACE_ENA,
+	VCAP_IS2_ACT_RSV,
+	VCAP_IS2_ACT_ACL_ID,
+	VCAP_IS2_ACT_HIT_CNT,
+};
+
+#endif /* _OCELOT_VCAP_H_ */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 06/10] net: mscc: ocelot: remove port_pcs_init indirection for VSC7514
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (4 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-27  8:13   ` Allan W. Nielsen
  2020-02-24 13:08 ` [PATCH net-next 07/10] net: mscc: ocelot: parameterize the vcap_is2 properties Vladimir Oltean
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The Felix driver is now using its own PHYLINK instance, not calling into
ocelot_adjust_link. So the port_pcs_init function pointer is an
unnecessary indirection. Remove it.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c       | 19 +++++++++++++++++--
 drivers/net/ethernet/mscc/ocelot_board.c | 24 ------------------------
 include/soc/mscc/ocelot.h                |  3 ---
 3 files changed, 17 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 3de8267180e2..2fc10b89bbcb 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -442,8 +442,23 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port,
 	ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
 			   mode, DEV_MAC_MODE_CFG);
 
-	if (ocelot->ops->pcs_init)
-		ocelot->ops->pcs_init(ocelot, port);
+	/* Disable HDX fast control */
+	ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
+			   DEV_PORT_MISC);
+
+	/* SGMII only for now */
+	ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
+			   PCS1G_MODE_CFG);
+	ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
+
+	/* Enable PCS */
+	ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
+
+	/* No aneg on SGMII */
+	ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
+
+	/* No loopback */
+	ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
 
 	/* Enable MAC module */
 	ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 8b83a10083e2..5e21d0cc8335 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -212,29 +212,6 @@ static const struct of_device_id mscc_ocelot_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
 
-static void ocelot_port_pcs_init(struct ocelot *ocelot, int port)
-{
-	struct ocelot_port *ocelot_port = ocelot->ports[port];
-
-	/* Disable HDX fast control */
-	ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
-			   DEV_PORT_MISC);
-
-	/* SGMII only for now */
-	ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
-			   PCS1G_MODE_CFG);
-	ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
-
-	/* Enable PCS */
-	ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
-
-	/* No aneg on SGMII */
-	ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
-
-	/* No loopback */
-	ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
-}
-
 static int ocelot_reset(struct ocelot *ocelot)
 {
 	int retries = 100;
@@ -259,7 +236,6 @@ static int ocelot_reset(struct ocelot *ocelot)
 }
 
 static const struct ocelot_ops ocelot_ops = {
-	.pcs_init		= ocelot_port_pcs_init,
 	.reset			= ocelot_reset,
 };
 
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index f63266a4ca70..31bcbc1ab2f9 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -402,7 +402,6 @@ enum ocelot_tag_prefix {
 struct ocelot;
 
 struct ocelot_ops {
-	void (*pcs_init)(struct ocelot *ocelot, int port);
 	int (*reset)(struct ocelot *ocelot);
 };
 
@@ -479,8 +478,6 @@ struct ocelot {
 	struct mutex			ptp_lock;
 	/* Protects the PTP clock */
 	spinlock_t			ptp_clock_lock;
-
-	void (*port_pcs_init)(struct ocelot_port *port);
 };
 
 #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 07/10] net: mscc: ocelot: parameterize the vcap_is2 properties
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (5 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 06/10] net: mscc: ocelot: remove port_pcs_init indirection for VSC7514 Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-27  8:47   ` Allan W. Nielsen
  2020-02-24 13:08 ` [PATCH net-next 08/10] net: dsa: Refactor matchall mirred action to separate function Vladimir Oltean
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Remove the definitions for the VCAP IS2 table from ocelot_ace.c, since
it is specific to VSC7514.

The VSC9959 VCAP IS2 table supports more rules (1024 instead of 64) and
has a different width for the action (89 bits instead of 99).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_ace.c   | 108 ++++++++---------------
 drivers/net/ethernet/mscc/ocelot_board.c |  25 ++++++
 include/soc/mscc/ocelot.h                |   1 +
 include/soc/mscc/ocelot_vcap.h           |  37 ++++++--
 4 files changed, 94 insertions(+), 77 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
index c838e681963f..76809ffd5d99 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -11,53 +11,7 @@
 #include "ocelot_s2.h"
 
 #define OCELOT_POLICER_DISCARD 0x17f
-
-struct vcap_props {
-	const char *name; /* Symbolic name */
-	u16 tg_width; /* Type-group width (in bits) */
-	u16 sw_count; /* Sub word count */
-	u16 entry_count; /* Entry count */
-	u16 entry_words; /* Number of entry words */
-	u16 entry_width; /* Entry width (in bits) */
-	u16 action_count; /* Action count */
-	u16 action_words; /* Number of action words */
-	u16 action_width; /* Action width (in bits) */
-	u16 action_type_width; /* Action type width (in bits) */
-	struct {
-		u16 width; /* Action type width (in bits) */
-		u16 count; /* Action type sub word count */
-	} action_table[2];
-	u16 counter_words; /* Number of counter words */
-	u16 counter_width; /* Counter width (in bits) */
-};
-
 #define ENTRY_WIDTH 32
-#define BITS_TO_32BIT(x) (1 + (((x) - 1) / ENTRY_WIDTH))
-
-static const struct vcap_props vcap_is2 = {
-	.name = "IS2",
-	.tg_width = 2,
-	.sw_count = 4,
-	.entry_count = VCAP_IS2_CNT,
-	.entry_words = BITS_TO_32BIT(VCAP_IS2_ENTRY_WIDTH),
-	.entry_width = VCAP_IS2_ENTRY_WIDTH,
-	.action_count = (VCAP_IS2_CNT + VCAP_PORT_CNT + 2),
-	.action_words = BITS_TO_32BIT(VCAP_IS2_ACTION_WIDTH),
-	.action_width = (VCAP_IS2_ACTION_WIDTH),
-	.action_type_width = 1,
-	.action_table = {
-		{
-			.width = 49,
-			.count = 2
-		},
-		{
-			.width = 6,
-			.count = 4
-		},
-	},
-	.counter_words = BITS_TO_32BIT(4 * ENTRY_WIDTH),
-	.counter_width = ENTRY_WIDTH,
-};
 
 enum vcap_sel {
 	VCAP_SEL_ENTRY = 0x1,
@@ -101,11 +55,13 @@ static u32 vcap_s2_read_update_ctrl(struct ocelot *oc)
 
 static void vcap_cmd(struct ocelot *oc, u16 ix, int cmd, int sel)
 {
+	const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
+
 	u32 value = (S2_CORE_UPDATE_CTRL_UPDATE_CMD(cmd) |
 		     S2_CORE_UPDATE_CTRL_UPDATE_ADDR(ix) |
 		     S2_CORE_UPDATE_CTRL_UPDATE_SHOT);
 
-	if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2.entry_count)
+	if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2->entry_count)
 		return;
 
 	if (!(sel & VCAP_SEL_ENTRY))
@@ -126,14 +82,18 @@ static void vcap_cmd(struct ocelot *oc, u16 ix, int cmd, int sel)
 /* Convert from 0-based row to VCAP entry row and run command */
 static void vcap_row_cmd(struct ocelot *oc, u32 row, int cmd, int sel)
 {
-	vcap_cmd(oc, vcap_is2.entry_count - row - 1, cmd, sel);
+	const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
+
+	vcap_cmd(oc, vcap_is2->entry_count - row - 1, cmd, sel);
 }
 
 static void vcap_entry2cache(struct ocelot *oc, struct vcap_data *data)
 {
+	const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
+	u32 entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH);
 	u32 i;
 
-	for (i = 0; i < vcap_is2.entry_words; i++) {
+	for (i = 0; i < entry_words; i++) {
 		ocelot_write_rix(oc, data->entry[i], S2_CACHE_ENTRY_DAT, i);
 		ocelot_write_rix(oc, ~data->mask[i], S2_CACHE_MASK_DAT, i);
 	}
@@ -142,9 +102,11 @@ static void vcap_entry2cache(struct ocelot *oc, struct vcap_data *data)
 
 static void vcap_cache2entry(struct ocelot *oc, struct vcap_data *data)
 {
+	const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
+	u32 entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH);
 	u32 i;
 
-	for (i = 0; i < vcap_is2.entry_words; i++) {
+	for (i = 0; i < entry_words; i++) {
 		data->entry[i] = ocelot_read_rix(oc, S2_CACHE_ENTRY_DAT, i);
 		// Invert mask
 		data->mask[i] = ~ocelot_read_rix(oc, S2_CACHE_MASK_DAT, i);
@@ -154,46 +116,51 @@ static void vcap_cache2entry(struct ocelot *oc, struct vcap_data *data)
 
 static void vcap_action2cache(struct ocelot *oc, struct vcap_data *data)
 {
+	const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
+	u32 action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH);
 	u32 i, width, mask;
 
 	/* Encode action type */
-	width = vcap_is2.action_type_width;
+	width = vcap_is2->action_type_width;
 	if (width) {
 		mask = GENMASK(width, 0);
 		data->action[0] = ((data->action[0] & ~mask) | data->type);
 	}
 
-	for (i = 0; i < vcap_is2.action_words; i++)
+	for (i = 0; i < action_words; i++)
 		ocelot_write_rix(oc, data->action[i], S2_CACHE_ACTION_DAT, i);
 
-	for (i = 0; i < vcap_is2.counter_words; i++)
+	for (i = 0; i < vcap_is2->counter_words; i++)
 		ocelot_write_rix(oc, data->counter[i], S2_CACHE_CNT_DAT, i);
 }
 
 static void vcap_cache2action(struct ocelot *oc, struct vcap_data *data)
 {
+	const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
+	u32 action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH);
 	u32 i, width;
 
-	for (i = 0; i < vcap_is2.action_words; i++)
+	for (i = 0; i < action_words; i++)
 		data->action[i] = ocelot_read_rix(oc, S2_CACHE_ACTION_DAT, i);
 
-	for (i = 0; i < vcap_is2.counter_words; i++)
+	for (i = 0; i < vcap_is2->counter_words; i++)
 		data->counter[i] = ocelot_read_rix(oc, S2_CACHE_CNT_DAT, i);
 
 	/* Extract action type */
-	width = vcap_is2.action_type_width;
+	width = vcap_is2->action_type_width;
 	data->type = (width ? (data->action[0] & GENMASK(width, 0)) : 0);
 }
 
 /* Calculate offsets for entry */
 static void is2_data_get(struct vcap_data *data, int ix)
 {
-	u32 i, col, offset, count, cnt, base, width = vcap_is2.tg_width;
+	const struct vcap_props *vcap_is2 = &data->ocelot->vcap[VCAP_IS2];
+	u32 i, col, offset, count, cnt, base, width = vcap_is2->tg_width;
 
 	count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4);
 	col = (ix % 2);
-	cnt = (vcap_is2.sw_count / count);
-	base = (vcap_is2.sw_count - col * cnt - cnt);
+	cnt = (vcap_is2->sw_count / count);
+	base = (vcap_is2->sw_count - col * cnt - cnt);
 	data->tg_value = 0;
 	data->tg_mask = 0;
 	for (i = 0; i < cnt; i++) {
@@ -204,13 +171,13 @@ static void is2_data_get(struct vcap_data *data, int ix)
 
 	/* Calculate key/action/counter offsets */
 	col = (count - col - 1);
-	data->key_offset = (base * vcap_is2.entry_width) / vcap_is2.sw_count;
-	data->counter_offset = (cnt * col * vcap_is2.counter_width);
+	data->key_offset = (base * vcap_is2->entry_width) / vcap_is2->sw_count;
+	data->counter_offset = (cnt * col * vcap_is2->counter_width);
 	i = data->type;
-	width = vcap_is2.action_table[i].width;
-	cnt = vcap_is2.action_table[i].count;
+	width = vcap_is2->action_table[i].width;
+	cnt = vcap_is2->action_table[i].count;
 	data->action_offset =
-		(((cnt * col * width) / count) + vcap_is2.action_type_width);
+		(((cnt * col * width) / count) + vcap_is2->action_type_width);
 }
 
 static void vcap_data_set(u32 *data, u32 offset, u32 len, u32 value)
@@ -357,6 +324,7 @@ static void is2_action_set(struct vcap_data *data,
 static void is2_entry_set(struct ocelot *ocelot, int ix,
 			  struct ocelot_ace_rule *ace)
 {
+	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];
 	u32 val, msk, type, type_mask = 0xf, i, count;
 	struct ocelot_ace_vlan *tag = &ace->vlan;
 	struct ocelot_vcap_u64 payload;
@@ -602,7 +570,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 	default:
 		type = 0;
 		type_mask = 0;
-		count = (vcap_is2.entry_width / 2);
+		count = vcap_is2->entry_width / 2;
 		/* Iterate over the non-common part of the key and
 		 * clear entry data
 		 */
@@ -615,7 +583,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 
 	vcap_key_set(&data, VCAP_IS2_TYPE, type, type_mask);
 	is2_action_set(&data, ace->action);
-	vcap_data_set(data.counter, data.counter_offset, vcap_is2.counter_width,
+	vcap_data_set(data.counter, data.counter_offset, vcap_is2->counter_width,
 		      ace->stats.pkts);
 
 	/* Write row */
@@ -627,6 +595,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
 			  int ix)
 {
+	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];
 	struct vcap_data data;
 	int row = (ix / 2);
 	u32 cnt;
@@ -638,7 +607,7 @@ static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
 	data.tg_sw = VCAP_TG_HALF;
 	is2_data_get(&data, ix);
 	cnt = vcap_data_get(data.counter, data.counter_offset,
-			    vcap_is2.counter_width);
+			    vcap_is2->counter_width);
 
 	rule->stats.pkts = cnt;
 }
@@ -782,6 +751,7 @@ int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
 
 int ocelot_ace_init(struct ocelot *ocelot)
 {
+	const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];
 	struct vcap_data data;
 
 	memset(&data, 0, sizeof(data));
@@ -789,11 +759,11 @@ int ocelot_ace_init(struct ocelot *ocelot)
 	data.ocelot = ocelot;
 
 	vcap_entry2cache(ocelot, &data);
-	ocelot_write(ocelot, vcap_is2.entry_count, S2_CORE_MV_CFG);
+	ocelot_write(ocelot, vcap_is2->entry_count, S2_CORE_MV_CFG);
 	vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY);
 
 	vcap_action2cache(ocelot, &data);
-	ocelot_write(ocelot, vcap_is2.action_count, S2_CORE_MV_CFG);
+	ocelot_write(ocelot, vcap_is2->action_count, S2_CORE_MV_CFG);
 	vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE,
 		 VCAP_SEL_ACTION | VCAP_SEL_COUNTER);
 
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 5e21d0cc8335..1d6d2b48a92f 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -337,6 +337,30 @@ struct vcap_field vsc7514_vcap_is2_actions[] = {
 	[VCAP_IS2_ACT_HIT_CNT]			= { 49, 32},
 };
 
+static const struct vcap_props vsc7514_vcap_props[] = {
+	[VCAP_IS2] = {
+		.tg_width = 2,
+		.sw_count = 4,
+		.entry_count = 64,
+		.entry_width = 376,
+		.action_count = 64 + 11 + 2,
+		.action_width = 99,
+		.action_type_width = 1,
+		.action_table = {
+			[IS2_ACTION_TYPE_NORMAL] = {
+				.width = 49,
+				.count = 2
+			},
+			[IS2_ACTION_TYPE_SMAC_SIP] = {
+				.width = 6,
+				.count = 4
+			},
+		},
+		.counter_words = 4,
+		.counter_width = 32,
+	},
+};
+
 static int mscc_ocelot_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -439,6 +463,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 
 	ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
 	ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
+	ocelot->vcap = vsc7514_vcap_props;
 
 	ocelot_init(ocelot);
 	ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports,
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 31bcbc1ab2f9..0cbd61d1c30c 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -463,6 +463,7 @@ struct ocelot {
 
 	struct vcap_field		*vcap_is2_keys;
 	struct vcap_field		*vcap_is2_actions;
+	const struct vcap_props		*vcap;
 
 	/* Workqueue to check statistics for overflow with its lock */
 	struct mutex			stats_lock;
diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h
index 0783f0ffc813..5748373ab4d3 100644
--- a/include/soc/mscc/ocelot_vcap.h
+++ b/include/soc/mscc/ocelot_vcap.h
@@ -11,6 +11,30 @@
  * =================================================================
  */
 
+enum {
+	/* VCAP_IS1, */
+	VCAP_IS2,
+	/* VCAP_ES0, */
+};
+
+struct vcap_props {
+	u16 tg_width; /* Type-group width (in bits) */
+	u16 sw_count; /* Sub word count */
+	u16 entry_count; /* Entry count */
+	u16 entry_words; /* Number of entry words */
+	u16 entry_width; /* Entry width (in bits) */
+	u16 action_count; /* Action count */
+	u16 action_words; /* Number of action words */
+	u16 action_width; /* Action width (in bits) */
+	u16 action_type_width; /* Action type width (in bits) */
+	struct {
+		u16 width; /* Action type width (in bits) */
+		u16 count; /* Action type sub word count */
+	} action_table[2];
+	u16 counter_words; /* Number of counter words */
+	u16 counter_width; /* Counter width (in bits) */
+};
+
 /* VCAP Type-Group values */
 #define VCAP_TG_NONE 0 /* Entry is invalid */
 #define VCAP_TG_FULL 1 /* Full entry */
@@ -22,11 +46,6 @@
  * =================================================================
  */
 
-#define VCAP_IS2_CNT 64
-#define VCAP_IS2_ENTRY_WIDTH 376
-#define VCAP_IS2_ACTION_WIDTH 99
-#define VCAP_PORT_CNT 11
-
 /* IS2 half key types */
 #define IS2_TYPE_ETYPE 0
 #define IS2_TYPE_LLC 1
@@ -42,9 +61,11 @@
 /* IS2 half key type mask for matching any IP */
 #define IS2_TYPE_MASK_IP_ANY 0xe
 
-/* IS2 action types */
-#define IS2_ACTION_TYPE_NORMAL 0
-#define IS2_ACTION_TYPE_SMAC_SIP 1
+enum {
+	IS2_ACTION_TYPE_NORMAL,
+	IS2_ACTION_TYPE_SMAC_SIP,
+	IS2_ACTION_TYPE_MAX,
+};
 
 /* IS2 MASK_MODE values */
 #define IS2_ACT_MASK_MODE_NONE 0
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 08/10] net: dsa: Refactor matchall mirred action to separate function
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (6 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 07/10] net: mscc: ocelot: parameterize the vcap_is2 properties Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-24 13:08 ` [PATCH net-next 09/10] net: dsa: Add bypass operations for the flower classifier-action filter Vladimir Oltean
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Make room for other actions for the matchall filter by keeping the
mirred argument parsing self-contained in its own function.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/slave.c | 68 +++++++++++++++++++++++++++----------------------
 1 file changed, 38 insertions(+), 30 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 088c886e609e..8cd28e88431e 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -846,57 +846,65 @@ dsa_slave_mall_tc_entry_find(struct net_device *dev, unsigned long cookie)
 	return NULL;
 }
 
-static int dsa_slave_add_cls_matchall(struct net_device *dev,
-				      struct tc_cls_matchall_offload *cls,
-				      bool ingress)
+static int
+dsa_slave_add_cls_matchall_mirred(struct net_device *dev,
+				  struct tc_cls_matchall_offload *cls,
+				  bool ingress)
 {
 	struct dsa_port *dp = dsa_slave_to_port(dev);
 	struct dsa_slave_priv *p = netdev_priv(dev);
+	struct dsa_mall_mirror_tc_entry *mirror;
 	struct dsa_mall_tc_entry *mall_tc_entry;
-	__be16 protocol = cls->common.protocol;
 	struct dsa_switch *ds = dp->ds;
 	struct flow_action_entry *act;
 	struct dsa_port *to_dp;
-	int err = -EOPNOTSUPP;
+	int err;
+
+	act = &cls->rule->action.entries[0];
 
 	if (!ds->ops->port_mirror_add)
 		return err;
 
-	if (!flow_offload_has_one_action(&cls->rule->action))
-		return err;
+	if (!act->dev)
+		return -EINVAL;
 
-	act = &cls->rule->action.entries[0];
+	if (!dsa_slave_dev_check(act->dev))
+		return -EOPNOTSUPP;
 
-	if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) {
-		struct dsa_mall_mirror_tc_entry *mirror;
+	mall_tc_entry = kzalloc(sizeof(*mall_tc_entry), GFP_KERNEL);
+	if (!mall_tc_entry)
+		return -ENOMEM;
 
-		if (!act->dev)
-			return -EINVAL;
+	mall_tc_entry->cookie = cls->cookie;
+	mall_tc_entry->type = DSA_PORT_MALL_MIRROR;
+	mirror = &mall_tc_entry->mirror;
 
-		if (!dsa_slave_dev_check(act->dev))
-			return -EOPNOTSUPP;
+	to_dp = dsa_slave_to_port(act->dev);
 
-		mall_tc_entry = kzalloc(sizeof(*mall_tc_entry), GFP_KERNEL);
-		if (!mall_tc_entry)
-			return -ENOMEM;
+	mirror->to_local_port = to_dp->index;
+	mirror->ingress = ingress;
 
-		mall_tc_entry->cookie = cls->cookie;
-		mall_tc_entry->type = DSA_PORT_MALL_MIRROR;
-		mirror = &mall_tc_entry->mirror;
+	err = ds->ops->port_mirror_add(ds, dp->index, mirror, ingress);
+	if (err) {
+		kfree(mall_tc_entry);
+		return err;
+	}
 
-		to_dp = dsa_slave_to_port(act->dev);
+	list_add_tail(&mall_tc_entry->list, &p->mall_tc_list);
 
-		mirror->to_local_port = to_dp->index;
-		mirror->ingress = ingress;
+	return err;
+}
 
-		err = ds->ops->port_mirror_add(ds, dp->index, mirror, ingress);
-		if (err) {
-			kfree(mall_tc_entry);
-			return err;
-		}
+static int dsa_slave_add_cls_matchall(struct net_device *dev,
+				      struct tc_cls_matchall_offload *cls,
+				      bool ingress)
+{
+	int err = -EOPNOTSUPP;
 
-		list_add_tail(&mall_tc_entry->list, &p->mall_tc_list);
-	}
+	if (cls->common.protocol == htons(ETH_P_ALL) &&
+	    flow_offload_has_one_action(&cls->rule->action) &&
+	    cls->rule->action.entries[0].id == FLOW_ACTION_MIRRED)
+		err = dsa_slave_add_cls_matchall_mirred(dev, cls, ingress);
 
 	return 0;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 09/10] net: dsa: Add bypass operations for the flower classifier-action filter
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (7 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 08/10] net: dsa: Refactor matchall mirred action to separate function Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-24 13:08 ` [PATCH net-next 10/10] net: dsa: felix: Wire up the ocelot cls_flower methods Vladimir Oltean
  2020-02-25 14:45 ` [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Horatiu Vultur
  10 siblings, 0 replies; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Due to the immense variety of classification keys and actions available
for tc-flower, as well as due to potentially very different DSA switch
capabilities, it doesn't make a lot of sense for the DSA mid layer to
even attempt to interpret these. So just pass them on to the underlying
switch driver.

DSA implements just the standard boilerplate for binding and unbinding
flow blocks to ports, since nobody wants to deal with that.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/net/dsa.h |  6 +++++
 net/dsa/slave.c   | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 63495e3443ac..6cb87f037120 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -538,6 +538,12 @@ struct dsa_switch_ops {
 	/*
 	 * TC integration
 	 */
+	int	(*cls_flower_add)(struct dsa_switch *ds, int port,
+				  struct flow_cls_offload *cls, bool ingress);
+	int	(*cls_flower_del)(struct dsa_switch *ds, int port,
+				  struct flow_cls_offload *cls, bool ingress);
+	int	(*cls_flower_stats)(struct dsa_switch *ds, int port,
+				    struct flow_cls_offload *cls, bool ingress);
 	int	(*port_mirror_add)(struct dsa_switch *ds, int port,
 				   struct dsa_mall_mirror_tc_entry *mirror,
 				   bool ingress);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 8cd28e88431e..5f07f1ca91a9 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -954,6 +954,64 @@ static int dsa_slave_setup_tc_cls_matchall(struct net_device *dev,
 	}
 }
 
+static int dsa_slave_add_cls_flower(struct net_device *dev,
+				    struct flow_cls_offload *cls,
+				    bool ingress)
+{
+	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct dsa_switch *ds = dp->ds;
+	int port = dp->index;
+
+	if (!ds->ops->cls_flower_add)
+		return -EOPNOTSUPP;
+
+	return ds->ops->cls_flower_add(ds, port, cls, ingress);
+}
+
+static int dsa_slave_del_cls_flower(struct net_device *dev,
+				    struct flow_cls_offload *cls,
+				    bool ingress)
+{
+	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct dsa_switch *ds = dp->ds;
+	int port = dp->index;
+
+	if (!ds->ops->cls_flower_del)
+		return -EOPNOTSUPP;
+
+	return ds->ops->cls_flower_del(ds, port, cls, ingress);
+}
+
+static int dsa_slave_stats_cls_flower(struct net_device *dev,
+				      struct flow_cls_offload *cls,
+				      bool ingress)
+{
+	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct dsa_switch *ds = dp->ds;
+	int port = dp->index;
+
+	if (!ds->ops->cls_flower_stats)
+		return -EOPNOTSUPP;
+
+	return ds->ops->cls_flower_stats(ds, port, cls, ingress);
+}
+
+static int dsa_slave_setup_tc_cls_flower(struct net_device *dev,
+					 struct flow_cls_offload *cls,
+					 bool ingress)
+{
+	switch (cls->command) {
+	case FLOW_CLS_REPLACE:
+		return dsa_slave_add_cls_flower(dev, cls, ingress);
+	case FLOW_CLS_DESTROY:
+		return dsa_slave_del_cls_flower(dev, cls, ingress);
+	case FLOW_CLS_STATS:
+		return dsa_slave_stats_cls_flower(dev, cls, ingress);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static int dsa_slave_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
 				       void *cb_priv, bool ingress)
 {
@@ -965,6 +1023,8 @@ static int dsa_slave_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
 	switch (type) {
 	case TC_SETUP_CLSMATCHALL:
 		return dsa_slave_setup_tc_cls_matchall(dev, type_data, ingress);
+	case TC_SETUP_CLSFLOWER:
+		return dsa_slave_setup_tc_cls_flower(dev, type_data, ingress);
 	default:
 		return -EOPNOTSUPP;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 10/10] net: dsa: felix: Wire up the ocelot cls_flower methods
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (8 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 09/10] net: dsa: Add bypass operations for the flower classifier-action filter Vladimir Oltean
@ 2020-02-24 13:08 ` Vladimir Oltean
  2020-02-25 14:45 ` [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Horatiu Vultur
  10 siblings, 0 replies; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-24 13:08 UTC (permalink / raw)
  To: davem
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Export the cls_flower methods from the ocelot driver and hook them up to
the DSA passthrough layer.

Tables for the VCAP IS2 parameters, as well as half key packing (field
offsets and lengths) need to be defined for the VSC9959 core, as they
are different from Ocelot, mainly due to the different port count.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/ocelot/felix.c         |  31 ++++++
 drivers/net/dsa/ocelot/felix.h         |   3 +
 drivers/net/dsa/ocelot/felix_vsc9959.c | 126 +++++++++++++++++++++++++
 include/soc/mscc/ocelot.h              |   6 ++
 4 files changed, 166 insertions(+)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 35124ef7e75b..6624393bd2ca 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -2,6 +2,7 @@
 /* Copyright 2019 NXP Semiconductors
  */
 #include <uapi/linux/if_bridge.h>
+#include <soc/mscc/ocelot_vcap.h>
 #include <soc/mscc/ocelot_qsys.h>
 #include <soc/mscc/ocelot_sys.h>
 #include <soc/mscc/ocelot_dev.h>
@@ -399,6 +400,9 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
 	ocelot->stats_layout	= felix->info->stats_layout;
 	ocelot->num_stats	= felix->info->num_stats;
 	ocelot->shared_queue_sz	= felix->info->shared_queue_sz;
+	ocelot->vcap_is2_keys	= felix->info->vcap_is2_keys;
+	ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
+	ocelot->vcap		= felix->info->vcap;
 	ocelot->ops		= felix->info->ops;
 
 	port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
@@ -593,6 +597,30 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port,
 	return false;
 }
 
+static int felix_cls_flower_add(struct dsa_switch *ds, int port,
+				struct flow_cls_offload *cls, bool ingress)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_cls_flower_replace(ocelot, port, cls, ingress);
+}
+
+static int felix_cls_flower_del(struct dsa_switch *ds, int port,
+				struct flow_cls_offload *cls, bool ingress)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_cls_flower_destroy(ocelot, port, cls, ingress);
+}
+
+static int felix_cls_flower_stats(struct dsa_switch *ds, int port,
+				  struct flow_cls_offload *cls, bool ingress)
+{
+	struct ocelot *ocelot = ds->priv;
+
+	return ocelot_cls_flower_stats(ocelot, port, cls, ingress);
+}
+
 static const struct dsa_switch_ops felix_switch_ops = {
 	.get_tag_protocol	= felix_get_tag_protocol,
 	.setup			= felix_setup,
@@ -624,6 +652,9 @@ static const struct dsa_switch_ops felix_switch_ops = {
 	.port_hwtstamp_set	= felix_hwtstamp_set,
 	.port_rxtstamp		= felix_rxtstamp,
 	.port_txtstamp		= felix_txtstamp,
+	.cls_flower_add		= felix_cls_flower_add,
+	.cls_flower_del		= felix_cls_flower_del,
+	.cls_flower_stats	= felix_cls_flower_stats,
 };
 
 static struct felix_info *felix_instance_tbl[] = {
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 3a7580015b62..82d46f260041 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -18,6 +18,9 @@ struct felix_info {
 	const struct ocelot_stat_layout	*stats_layout;
 	unsigned int			num_stats;
 	int				num_ports;
+	struct vcap_field		*vcap_is2_keys;
+	struct vcap_field		*vcap_is2_actions;
+	const struct vcap_props		*vcap;
 	int				switch_pci_bar;
 	int				imdio_pci_bar;
 	int	(*mdio_bus_alloc)(struct ocelot *ocelot);
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 93800e81cdd4..d741aad8629d 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -3,6 +3,7 @@
  * Copyright 2018-2019 NXP Semiconductors
  */
 #include <linux/fsl/enetc_mdio.h>
+#include <soc/mscc/ocelot_vcap.h>
 #include <soc/mscc/ocelot_sys.h>
 #include <soc/mscc/ocelot.h>
 #include <linux/iopoll.h>
@@ -547,6 +548,128 @@ static const struct ocelot_stat_layout vsc9959_stats_layout[] = {
 	{ .offset = 0x111,	.name = "drop_green_prio_7", },
 };
 
+struct vcap_field vsc9959_vcap_is2_keys[] = {
+	/* Common: 41 bits */
+	[VCAP_IS2_TYPE]				= {  0,   4},
+	[VCAP_IS2_HK_FIRST]			= {  4,   1},
+	[VCAP_IS2_HK_PAG]			= {  5,   8},
+	[VCAP_IS2_HK_IGR_PORT_MASK]		= { 13,   7},
+	[VCAP_IS2_HK_RSV2]			= { 20,   1},
+	[VCAP_IS2_HK_HOST_MATCH]		= { 21,   1},
+	[VCAP_IS2_HK_L2_MC]			= { 22,   1},
+	[VCAP_IS2_HK_L2_BC]			= { 23,   1},
+	[VCAP_IS2_HK_VLAN_TAGGED]		= { 24,   1},
+	[VCAP_IS2_HK_VID]			= { 25,  12},
+	[VCAP_IS2_HK_DEI]			= { 37,   1},
+	[VCAP_IS2_HK_PCP]			= { 38,   3},
+	/* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */
+	[VCAP_IS2_HK_L2_DMAC]			= { 41,  48},
+	[VCAP_IS2_HK_L2_SMAC]			= { 89,  48},
+	/* MAC_ETYPE (TYPE=000) */
+	[VCAP_IS2_HK_MAC_ETYPE_ETYPE]		= {137,  16},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0]	= {153,  16},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1]	= {169,   8},
+	[VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2]	= {177,   3},
+	/* MAC_LLC (TYPE=001) */
+	[VCAP_IS2_HK_MAC_LLC_L2_LLC]		= {137,  40},
+	/* MAC_SNAP (TYPE=010) */
+	[VCAP_IS2_HK_MAC_SNAP_L2_SNAP]		= {137,  40},
+	/* MAC_ARP (TYPE=011) */
+	[VCAP_IS2_HK_MAC_ARP_SMAC]		= { 41,  48},
+	[VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK]	= { 89,   1},
+	[VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK]	= { 90,   1},
+	[VCAP_IS2_HK_MAC_ARP_LEN_OK]		= { 91,   1},
+	[VCAP_IS2_HK_MAC_ARP_TARGET_MATCH]	= { 92,   1},
+	[VCAP_IS2_HK_MAC_ARP_SENDER_MATCH]	= { 93,   1},
+	[VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN]	= { 94,   1},
+	[VCAP_IS2_HK_MAC_ARP_OPCODE]		= { 95,   2},
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP]	= { 97,  32},
+	[VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP]	= {129,  32},
+	[VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP]	= {161,   1},
+	/* IP4_TCP_UDP / IP4_OTHER common */
+	[VCAP_IS2_HK_IP4]			= { 41,   1},
+	[VCAP_IS2_HK_L3_FRAGMENT]		= { 42,   1},
+	[VCAP_IS2_HK_L3_FRAG_OFS_GT0]		= { 43,   1},
+	[VCAP_IS2_HK_L3_OPTIONS]		= { 44,   1},
+	[VCAP_IS2_HK_IP4_L3_TTL_GT0]		= { 45,   1},
+	[VCAP_IS2_HK_L3_TOS]			= { 46,   8},
+	[VCAP_IS2_HK_L3_IP4_DIP]		= { 54,  32},
+	[VCAP_IS2_HK_L3_IP4_SIP]		= { 86,  32},
+	[VCAP_IS2_HK_DIP_EQ_SIP]		= {118,   1},
+	/* IP4_TCP_UDP (TYPE=100) */
+	[VCAP_IS2_HK_TCP]			= {119,   1},
+	[VCAP_IS2_HK_L4_SPORT]			= {120,  16},
+	[VCAP_IS2_HK_L4_DPORT]			= {136,  16},
+	[VCAP_IS2_HK_L4_RNG]			= {152,   8},
+	[VCAP_IS2_HK_L4_SPORT_EQ_DPORT]		= {160,   1},
+	[VCAP_IS2_HK_L4_SEQUENCE_EQ0]		= {161,   1},
+	[VCAP_IS2_HK_L4_URG]			= {162,   1},
+	[VCAP_IS2_HK_L4_ACK]			= {163,   1},
+	[VCAP_IS2_HK_L4_PSH]			= {164,   1},
+	[VCAP_IS2_HK_L4_RST]			= {165,   1},
+	[VCAP_IS2_HK_L4_SYN]			= {166,   1},
+	[VCAP_IS2_HK_L4_FIN]			= {167,   1},
+	[VCAP_IS2_HK_L4_1588_DOM]		= {168,   8},
+	[VCAP_IS2_HK_L4_1588_VER]		= {176,   4},
+	/* IP4_OTHER (TYPE=101) */
+	[VCAP_IS2_HK_IP4_L3_PROTO]		= {119,   8},
+	[VCAP_IS2_HK_L3_PAYLOAD]		= {127,  56},
+	/* IP6_STD (TYPE=110) */
+	[VCAP_IS2_HK_IP6_L3_TTL_GT0]		= { 41,   1},
+	[VCAP_IS2_HK_L3_IP6_SIP]		= { 42, 128},
+	[VCAP_IS2_HK_IP6_L3_PROTO]		= {170,   8},
+	/* OAM (TYPE=111) */
+	[VCAP_IS2_HK_OAM_MEL_FLAGS]		= {137,   7},
+	[VCAP_IS2_HK_OAM_VER]			= {144,   5},
+	[VCAP_IS2_HK_OAM_OPCODE]		= {149,   8},
+	[VCAP_IS2_HK_OAM_FLAGS]			= {157,   8},
+	[VCAP_IS2_HK_OAM_MEPID]			= {165,  16},
+	[VCAP_IS2_HK_OAM_CCM_CNTS_EQ0]		= {181,   1},
+	[VCAP_IS2_HK_OAM_IS_Y1731]		= {182,   1},
+};
+
+struct vcap_field vsc9959_vcap_is2_actions[] = {
+	[VCAP_IS2_ACT_HIT_ME_ONCE]		= {  0,  1},
+	[VCAP_IS2_ACT_CPU_COPY_ENA]		= {  1,  1},
+	[VCAP_IS2_ACT_CPU_QU_NUM]		= {  2,  3},
+	[VCAP_IS2_ACT_MASK_MODE]		= {  5,  2},
+	[VCAP_IS2_ACT_MIRROR_ENA]		= {  7,  1},
+	[VCAP_IS2_ACT_LRN_DIS]			= {  8,  1},
+	[VCAP_IS2_ACT_POLICE_ENA]		= {  9,  1},
+	[VCAP_IS2_ACT_POLICE_IDX]		= { 10,  9},
+	[VCAP_IS2_ACT_POLICE_VCAP_ONLY]		= { 19,  1},
+	[VCAP_IS2_ACT_PORT_MASK]		= { 20, 11},
+	[VCAP_IS2_ACT_REW_OP]			= { 31,  9},
+	[VCAP_IS2_ACT_SMAC_REPLACE_ENA]		= { 40,  1},
+	[VCAP_IS2_ACT_RSV]			= { 41,  2},
+	[VCAP_IS2_ACT_ACL_ID]			= { 43,  6},
+	[VCAP_IS2_ACT_HIT_CNT]			= { 49, 32},
+};
+
+static const struct vcap_props vsc9959_vcap_props[] = {
+	[VCAP_IS2] = {
+		.tg_width = 2,
+		.sw_count = 4,
+		.entry_count = 1024,
+		.entry_width = 376,
+		.action_count = 1024 + 6 + 2,
+		.action_width = 89,
+		.action_type_width = 1,
+		.action_table = {
+			[IS2_ACTION_TYPE_NORMAL] = {
+				.width = 44,
+				.count = 2
+			},
+			[IS2_ACTION_TYPE_SMAC_SIP] = {
+				.width = 6,
+				.count = 4
+			},
+		},
+		.counter_words = 4,
+		.counter_width = 32,
+	},
+};
+
 #define VSC9959_INIT_TIMEOUT			50000
 #define VSC9959_GCB_RST_SLEEP			100
 #define VSC9959_SYS_RAMINIT_SLEEP		80
@@ -1088,6 +1211,9 @@ struct felix_info felix_info_vsc9959 = {
 	.ops			= &vsc9959_ops,
 	.stats_layout		= vsc9959_stats_layout,
 	.num_stats		= ARRAY_SIZE(vsc9959_stats_layout),
+	.vcap_is2_keys		= vsc9959_vcap_is2_keys,
+	.vcap_is2_actions	= vsc9959_vcap_is2_actions,
+	.vcap			= vsc9959_vcap_props,
 	.shared_queue_sz	= 128 * 1024,
 	.num_ports		= 6,
 	.switch_pci_bar		= 4,
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 0cbd61d1c30c..6db8d9652e34 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -549,5 +549,11 @@ int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
 int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
 				 struct sk_buff *skb);
 void ocelot_get_txtstamp(struct ocelot *ocelot);
+int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
+			      struct flow_cls_offload *f, bool ingress);
+int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
+			      struct flow_cls_offload *f, bool ingress);
+int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
+			    struct flow_cls_offload *f, bool ingress);
 
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing
  2020-02-24 13:08 ` [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing Vladimir Oltean
@ 2020-02-24 23:21   ` David Miller
  2020-02-25  4:58   ` kbuild test robot
  2020-02-25  4:58   ` [RFC PATCH] net: mscc: ocelot: vsc7514_vcap_is2_keys[] can be static kbuild test robot
  2 siblings, 0 replies; 22+ messages in thread
From: David Miller @ 2020-02-24 23:21 UTC (permalink / raw)
  To: olteanv
  Cc: horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev, UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1,
	yangbo.lu, po.liu, jiri, idosch, kuba

From: Vladimir Oltean <olteanv@gmail.com>
Date: Mon, 24 Feb 2020 15:08:26 +0200

> +static void vcap_key_set(struct vcap_data *data,
> +			 enum vcap_is2_half_key_field field,
> +			 u32 value, u32 mask)
> +{
> +	struct ocelot *ocelot = data->ocelot;
> +	u32 offset = ocelot->vcap_is2_keys[field].offset;
> +	u32 length = ocelot->vcap_is2_keys[field].length;

I know it is a pain in dependency chains of variables like this, but
please use reverse christmas tree ordering.

And likewise for the rest of your submission.

Thank you.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing
  2020-02-24 13:08 ` [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing Vladimir Oltean
  2020-02-24 23:21   ` David Miller
@ 2020-02-25  4:58   ` kbuild test robot
  2020-02-25  4:58   ` [RFC PATCH] net: mscc: ocelot: vsc7514_vcap_is2_keys[] can be static kbuild test robot
  2 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2020-02-25  4:58 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: kbuild-all, davem, horatiu.vultur, alexandre.belloni, andrew,
	f.fainelli, vivien.didelot, joergen.andreasen, allan.nielsen,
	claudiu.manoil, netdev, UNGLinuxDriver, alexandru.marginean,
	xiaoliang.yang_1, yangbo.lu, po.liu, jiri, idosch, kuba

Hi Vladimir,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]
[also build test WARNING on net/master linus/master v5.6-rc3 next-20200224]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Vladimir-Oltean/Wire-up-Ocelot-tc-flower-to-Felix-DSA/20200224-231012
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git c3e042f54107376cfbbd215e11878a2a75e1e228
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.1-173-ge0787745-dirty
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)

>> drivers/net/ethernet/mscc/ocelot_board.c:266:19: sparse: sparse: symbol 'vsc7514_vcap_is2_keys' was not declared. Should it be static?
>> drivers/net/ethernet/mscc/ocelot_board.c:346:19: sparse: sparse: symbol 'vsc7514_vcap_is2_actions' was not declared. Should it be static?

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [RFC PATCH] net: mscc: ocelot: vsc7514_vcap_is2_keys[] can be static
  2020-02-24 13:08 ` [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing Vladimir Oltean
  2020-02-24 23:21   ` David Miller
  2020-02-25  4:58   ` kbuild test robot
@ 2020-02-25  4:58   ` kbuild test robot
  2 siblings, 0 replies; 22+ messages in thread
From: kbuild test robot @ 2020-02-25  4:58 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: kbuild-all, davem, horatiu.vultur, alexandre.belloni, andrew,
	f.fainelli, vivien.didelot, joergen.andreasen, allan.nielsen,
	claudiu.manoil, netdev, UNGLinuxDriver, alexandru.marginean,
	xiaoliang.yang_1, yangbo.lu, po.liu, jiri, idosch, kuba


Fixes: b33f9830eb55 ("net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing")
Signed-off-by: kbuild test robot <lkp@intel.com>
---
 ocelot_board.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 8b83a10083e2e..186f181deffee 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -263,7 +263,7 @@ static const struct ocelot_ops ocelot_ops = {
 	.reset			= ocelot_reset,
 };
 
-struct vcap_field vsc7514_vcap_is2_keys[] = {
+static struct vcap_field vsc7514_vcap_is2_keys[] = {
 	/* Common: 46 bits */
 	[VCAP_IS2_TYPE]				= {  0,   4},
 	[VCAP_IS2_HK_FIRST]			= {  4,   1},
@@ -343,7 +343,7 @@ struct vcap_field vsc7514_vcap_is2_keys[] = {
 	[VCAP_IS2_HK_OAM_IS_Y1731]		= {187,   1},
 };
 
-struct vcap_field vsc7514_vcap_is2_actions[] = {
+static struct vcap_field vsc7514_vcap_is2_actions[] = {
 	[VCAP_IS2_ACT_HIT_ME_ONCE]		= {  0,  1},
 	[VCAP_IS2_ACT_CPU_COPY_ENA]		= {  1,  1},
 	[VCAP_IS2_ACT_CPU_QU_NUM]		= {  2,  3},

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA
  2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
                   ` (9 preceding siblings ...)
  2020-02-24 13:08 ` [PATCH net-next 10/10] net: dsa: felix: Wire up the ocelot cls_flower methods Vladimir Oltean
@ 2020-02-25 14:45 ` Horatiu Vultur
  2020-02-25 16:06   ` Vladimir Oltean
  10 siblings, 1 reply; 22+ messages in thread
From: Horatiu Vultur @ 2020-02-25 14:45 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, alexandre.belloni, andrew, f.fainelli, vivien.didelot,
	joergen.andreasen, allan.nielsen, claudiu.manoil, netdev,
	UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1, yangbo.lu,
	po.liu, jiri, idosch, kuba

The 02/24/2020 15:08, Vladimir Oltean wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
> 
> This series is a proposal on how to wire up the tc-flower callbacks into
> DSA. The example taken is the Microchip Felix switch, whose core
> implementation is actually located in drivers/net/ethernet/mscc/.
> 
> The proposal is largely a compromise solution. The DSA middle layer
> handles just enough to get to the interesting stuff (FLOW_CLS_REPLACE,
> FLOW_CLS_DESTROY, FLOW_CLS_STATS), but also thin enough to let drivers
> decide what filter keys and actions they support without worrying that
> the DSA middle layer will grow exponentially. I am far from being an
> expert, so I am asking reviewers to please voice your opinion if you
> think it can be done differently, with better results.
> 
> The bulk of the work was actually refactoring the ocelot driver enough
> to allow the VCAP (Versatile Content-Aware Processor) code for vsc7514
> and the vsc9959 switch cores to live together.
> 
> Flow block offloads have not been tested yet, only filters attached to a
> single port. It might be as simple as replacing ocelot_ace_rule_create
> with something smarter, it might be more complicated, I haven't tried
> yet.
> 
> I should point out that the tc-matchall filter offload is not
> implemented in the same manner in current mainline. Florian has already
> went all the way down into exposing actual per-action callbacks,
> starting with port mirroring. Because currently only mirred is supported
> by this DSA mid layer, everything else will return -EOPNOTSUPP. So even
> though ocelot supports matchall (aka port-based) policers, we don't have
> a call path to call into them.  Personally I think that this is not
> going to scale for tc-matchall (there may be policers, traps, drops,
> VLAN retagging, etc etc), and that we should consider replacing the port
> mirroring callbacks in DSA with simple accessors to
> TC_CLSMATCHALL_REPLACE and TC_CLSMATCHALL_DESTROY, just like for flower.
> That means that drivers which currently implement the port mirroring
> callbacks will need to have some extra "if" conditions now, in order for
> them to call their port mirroring implementations.
> 
> Vladimir Oltean (9):
>   net: mscc: ocelot: simplify tc-flower offload structures
>   net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names
>     with "ace"
>   net: mscc: ocelot: return directly in
>     ocelot_cls_flower_{replace,destroy}
>   net: mscc: ocelot: don't rely on preprocessor for vcap key/action
>     packing
>   net: mscc: ocelot: remove port_pcs_init indirection for VSC7514
>   net: mscc: ocelot: parameterize the vcap_is2 properties
>   net: dsa: Refactor matchall mirred action to separate function
>   net: dsa: Add bypass operations for the flower classifier-action
>     filter
>   net: dsa: felix: Wire up the ocelot cls_flower methods
> 
> Yangbo Lu (1):
>   net: mscc: ocelot: make ocelot_ace_rule support multiple ports
> 
>  drivers/net/dsa/ocelot/felix.c            |  31 ++
>  drivers/net/dsa/ocelot/felix.h            |   3 +
>  drivers/net/dsa/ocelot/felix_vsc9959.c    | 126 ++++++
>  drivers/net/ethernet/mscc/ocelot.c        |  20 +-
>  drivers/net/ethernet/mscc/ocelot_ace.c    | 472 +++++++++++-----------
>  drivers/net/ethernet/mscc/ocelot_ace.h    |  26 +-
>  drivers/net/ethernet/mscc/ocelot_board.c  | 151 +++++--
>  drivers/net/ethernet/mscc/ocelot_flower.c | 256 ++++--------
>  drivers/net/ethernet/mscc/ocelot_tc.c     |  22 +-
>  drivers/net/ethernet/mscc/ocelot_vcap.h   | 403 ------------------
>  include/net/dsa.h                         |   6 +
>  include/soc/mscc/ocelot.h                 |  20 +-
>  include/soc/mscc/ocelot_vcap.h            | 205 ++++++++++
>  net/dsa/slave.c                           | 128 ++++--
>  14 files changed, 954 insertions(+), 915 deletions(-)
>  delete mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h
>  create mode 100644 include/soc/mscc/ocelot_vcap.h
> 
> --
> 2.17.1
> 

Hi Vladimir,

From my point, it looks OK the changes to Ocelot.
Also I managed to run some tests and they are passing.

-- 
/Horatiu

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA
  2020-02-25 14:45 ` [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Horatiu Vultur
@ 2020-02-25 16:06   ` Vladimir Oltean
  0 siblings, 0 replies; 22+ messages in thread
From: Vladimir Oltean @ 2020-02-25 16:06 UTC (permalink / raw)
  To: Horatiu Vultur
  Cc: David S. Miller, Alexandre Belloni, Andrew Lunn,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Claudiu Manoil, netdev,
	Microchip Linux Driver Support, Alexandru Marginean,
	Xiaoliang Yang, Y.b. Lu, Po Liu, Jiri Pirko, Ido Schimmel,
	Jakub Kicinski

Hi Horatiu,

On Tue, 25 Feb 2020 at 16:45, Horatiu Vultur
<horatiu.vultur@microchip.com> wrote:
>
> The 02/24/2020 15:08, Vladimir Oltean wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >
> > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> >
> > This series is a proposal on how to wire up the tc-flower callbacks into
> > DSA. The example taken is the Microchip Felix switch, whose core
> > implementation is actually located in drivers/net/ethernet/mscc/.
> >
> > The proposal is largely a compromise solution. The DSA middle layer
> > handles just enough to get to the interesting stuff (FLOW_CLS_REPLACE,
> > FLOW_CLS_DESTROY, FLOW_CLS_STATS), but also thin enough to let drivers
> > decide what filter keys and actions they support without worrying that
> > the DSA middle layer will grow exponentially. I am far from being an
> > expert, so I am asking reviewers to please voice your opinion if you
> > think it can be done differently, with better results.
> >
> > The bulk of the work was actually refactoring the ocelot driver enough
> > to allow the VCAP (Versatile Content-Aware Processor) code for vsc7514
> > and the vsc9959 switch cores to live together.
> >
> > Flow block offloads have not been tested yet, only filters attached to a
> > single port. It might be as simple as replacing ocelot_ace_rule_create
> > with something smarter, it might be more complicated, I haven't tried
> > yet.
> >
> > I should point out that the tc-matchall filter offload is not
> > implemented in the same manner in current mainline. Florian has already
> > went all the way down into exposing actual per-action callbacks,
> > starting with port mirroring. Because currently only mirred is supported
> > by this DSA mid layer, everything else will return -EOPNOTSUPP. So even
> > though ocelot supports matchall (aka port-based) policers, we don't have
> > a call path to call into them.  Personally I think that this is not
> > going to scale for tc-matchall (there may be policers, traps, drops,
> > VLAN retagging, etc etc), and that we should consider replacing the port
> > mirroring callbacks in DSA with simple accessors to
> > TC_CLSMATCHALL_REPLACE and TC_CLSMATCHALL_DESTROY, just like for flower.
> > That means that drivers which currently implement the port mirroring
> > callbacks will need to have some extra "if" conditions now, in order for
> > them to call their port mirroring implementations.
> >
> > Vladimir Oltean (9):
> >   net: mscc: ocelot: simplify tc-flower offload structures
> >   net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names
> >     with "ace"
> >   net: mscc: ocelot: return directly in
> >     ocelot_cls_flower_{replace,destroy}
> >   net: mscc: ocelot: don't rely on preprocessor for vcap key/action
> >     packing
> >   net: mscc: ocelot: remove port_pcs_init indirection for VSC7514
> >   net: mscc: ocelot: parameterize the vcap_is2 properties
> >   net: dsa: Refactor matchall mirred action to separate function
> >   net: dsa: Add bypass operations for the flower classifier-action
> >     filter
> >   net: dsa: felix: Wire up the ocelot cls_flower methods
> >
> > Yangbo Lu (1):
> >   net: mscc: ocelot: make ocelot_ace_rule support multiple ports
> >
> >  drivers/net/dsa/ocelot/felix.c            |  31 ++
> >  drivers/net/dsa/ocelot/felix.h            |   3 +
> >  drivers/net/dsa/ocelot/felix_vsc9959.c    | 126 ++++++
> >  drivers/net/ethernet/mscc/ocelot.c        |  20 +-
> >  drivers/net/ethernet/mscc/ocelot_ace.c    | 472 +++++++++++-----------
> >  drivers/net/ethernet/mscc/ocelot_ace.h    |  26 +-
> >  drivers/net/ethernet/mscc/ocelot_board.c  | 151 +++++--
> >  drivers/net/ethernet/mscc/ocelot_flower.c | 256 ++++--------
> >  drivers/net/ethernet/mscc/ocelot_tc.c     |  22 +-
> >  drivers/net/ethernet/mscc/ocelot_vcap.h   | 403 ------------------
> >  include/net/dsa.h                         |   6 +
> >  include/soc/mscc/ocelot.h                 |  20 +-
> >  include/soc/mscc/ocelot_vcap.h            | 205 ++++++++++
> >  net/dsa/slave.c                           | 128 ++++--
> >  14 files changed, 954 insertions(+), 915 deletions(-)
> >  delete mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h
> >  create mode 100644 include/soc/mscc/ocelot_vcap.h
> >
> > --
> > 2.17.1
> >
>
> Hi Vladimir,
>
> From my point, it looks OK the changes to Ocelot.
> Also I managed to run some tests and they are passing.
>

Thanks, I really appreciate you trying out the patches. Having the
VCAP IS2 already implemented and working for Felix with minimal
changes is also huge.
I'll wait for further comments from the flow offload people, DSA
people or anybody else, and if the timeout expires I'll send a v2
addressing the Kbuild and David's reverse Christmas tree complaints.

> --
> /Horatiu

Regards,
-Vladimir

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 01/10] net: mscc: ocelot: make ocelot_ace_rule support multiple ports
  2020-02-24 13:08 ` [PATCH net-next 01/10] net: mscc: ocelot: make ocelot_ace_rule support multiple ports Vladimir Oltean
@ 2020-02-27  8:02   ` Allan W. Nielsen
  0 siblings, 0 replies; 22+ messages in thread
From: Allan W. Nielsen @ 2020-02-27  8:02 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, claudiu.manoil, netdev,
	UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1, yangbo.lu,
	po.liu, jiri, idosch, kuba

On 24.02.2020 15:08, Vladimir Oltean wrote:
>EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
>From: Yangbo Lu <yangbo.lu@nxp.com>
>
>The ocelot_ace_rule is port specific now. Make it flexible to
>be able to support multiple ports too.
>
>Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
>Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
>---
> drivers/net/ethernet/mscc/ocelot_ace.c    | 14 +++++++-------
> drivers/net/ethernet/mscc/ocelot_ace.h    |  4 ++--
> drivers/net/ethernet/mscc/ocelot_flower.c |  8 ++++----
> 3 files changed, 13 insertions(+), 13 deletions(-)
>
>diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
>index 86fc6e6b46dd..18670645d47f 100644
>--- a/drivers/net/ethernet/mscc/ocelot_ace.c
>+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
>@@ -352,7 +352,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
>        data.type = IS2_ACTION_TYPE_NORMAL;
>
>        VCAP_KEY_ANY_SET(PAG);
>-       VCAP_KEY_SET(IGR_PORT_MASK, 0, ~BIT(ace->chip_port));
>+       VCAP_KEY_SET(IGR_PORT_MASK, 0, ~ace->ingress_port_mask);
>        VCAP_KEY_BIT_SET(FIRST, OCELOT_VCAP_BIT_1);
>        VCAP_KEY_BIT_SET(HOST_MATCH, OCELOT_VCAP_BIT_ANY);
>        VCAP_KEY_BIT_SET(L2_MC, ace->dmac_mc);
>@@ -576,7 +576,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
>
> static void is2_entry_get(struct ocelot_ace_rule *rule, int ix)
> {
>-       struct ocelot *op = rule->port->ocelot;
>+       struct ocelot *op = rule->ocelot;
>        struct vcap_data data;
>        int row = (ix / 2);
>        u32 cnt;
>@@ -655,11 +655,11 @@ int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule)
>        /* Move down the rules to make place for the new rule */
>        for (i = acl_block->count - 1; i > index; i--) {
>                ace = ocelot_ace_rule_get_rule_index(acl_block, i);
>-               is2_entry_set(rule->port->ocelot, i, ace);
>+               is2_entry_set(rule->ocelot, i, ace);
>        }
>
>        /* Now insert the new rule */
>-       is2_entry_set(rule->port->ocelot, index, rule);
>+       is2_entry_set(rule->ocelot, index, rule);
>        return 0;
> }
>
>@@ -697,11 +697,11 @@ int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule)
>        /* Move up all the blocks over the deleted rule */
>        for (i = index; i < acl_block->count; i++) {
>                ace = ocelot_ace_rule_get_rule_index(acl_block, i);
>-               is2_entry_set(rule->port->ocelot, i, ace);
>+               is2_entry_set(rule->ocelot, i, ace);
>        }
>
>        /* Now delete the last rule, because it is duplicated */
>-       is2_entry_set(rule->port->ocelot, acl_block->count, &del_ace);
>+       is2_entry_set(rule->ocelot, acl_block->count, &del_ace);
>
>        return 0;
> }
>@@ -717,7 +717,7 @@ int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule)
>        /* After we get the result we need to clear the counters */
>        tmp = ocelot_ace_rule_get_rule_index(acl_block, index);
>        tmp->stats.pkts = 0;
>-       is2_entry_set(rule->port->ocelot, index, tmp);
>+       is2_entry_set(rule->ocelot, index, tmp);
>
>        return 0;
> }
>diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h
>index c08e3e8482e7..2927ac83741b 100644
>--- a/drivers/net/ethernet/mscc/ocelot_ace.h
>+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
>@@ -186,14 +186,14 @@ struct ocelot_ace_stats {
>
> struct ocelot_ace_rule {
>        struct list_head list;
>-       struct ocelot_port *port;
>+       struct ocelot *ocelot;
>
>        u16 prio;
>        u32 id;
>
>        enum ocelot_ace_action action;
>        struct ocelot_ace_stats stats;
>-       int chip_port;
>+       u16 ingress_port_mask;
>
>        enum ocelot_vcap_bit dmac_mc;
>        enum ocelot_vcap_bit dmac_bc;
>diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
>index 3d65b99b9734..ffd2bb50cfc3 100644
>--- a/drivers/net/ethernet/mscc/ocelot_flower.c
>+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
>@@ -177,8 +177,8 @@ struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
>        if (!rule)
>                return NULL;
>
>-       rule->port = &block->priv->port;
>-       rule->chip_port = block->priv->chip_port;
>+       rule->ocelot = block->priv->port.ocelot;
>+       rule->ingress_port_mask = BIT(block->priv->chip_port);
>        return rule;
> }
>
>@@ -213,7 +213,7 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
>        int ret;
>
>        rule.prio = f->common.prio;
>-       rule.port = &port_block->priv->port;
>+       rule.ocelot = port_block->priv->port.ocelot;
>        rule.id = f->cookie;
>
>        ret = ocelot_ace_rule_offload_del(&rule);
>@@ -231,7 +231,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
>        int ret;
>
>        rule.prio = f->common.prio;
>-       rule.port = &port_block->priv->port;
>+       rule.ocelot = port_block->priv->port.ocelot;
>        rule.id = f->cookie;
>        ret = ocelot_ace_rule_stats_update(&rule);
>        if (ret)
>--
>2.17.1
>

Reviewed-by: Allan W. Nielsen <allan.nielsen@microchip.com>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 02/10] net: mscc: ocelot: simplify tc-flower offload structures
  2020-02-24 13:08 ` [PATCH net-next 02/10] net: mscc: ocelot: simplify tc-flower offload structures Vladimir Oltean
@ 2020-02-27  8:08   ` Allan W. Nielsen
  0 siblings, 0 replies; 22+ messages in thread
From: Allan W. Nielsen @ 2020-02-27  8:08 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, claudiu.manoil, netdev,
	UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1, yangbo.lu,
	po.liu, jiri, idosch, kuba

On 24.02.2020 15:08, Vladimir Oltean wrote:
>EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
>From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
>The ocelot tc-flower offload binds a second flow block callback (apart
>from the one for matchall) just because it uses a different block
>private structure (ocelot_port_private for matchall, ocelot_port_block
>for flower).
>
>But ocelot_port_block just appears to be boilerplate, and doesn't help
>with anything in particular at all, it's just useless glue between the
>(global!) struct ocelot_acl_block *block pointer, and a per-netdevice
>struct ocelot_port_private *priv.
>
>So let's just simplify that, and make struct ocelot_port_private be the
>private structure for the block offload. This makes us able to use the
>same flow callback as in the case of matchall.
>
>This also reveals that the struct ocelot_acl_block *block is used rather
>strangely, as mentioned above: it is defined globally, allocated at
>probe time, and freed at unbind time. So just move the structure to the
>main ocelot structure, which gives further opportunity for
>simplification.
>
>Also get rid of backpointers from struct ocelot_acl_block and struct
>ocelot_ace_rule back to struct ocelot, by reworking the function
>prototypes, where necessary, to use a more DSA-friendly "struct ocelot
>*ocelot, int port" format.
>
>And finally, remove the debugging prints that were added during
>development, since they provide no useful information at this point.
>
>Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
>---
> drivers/net/ethernet/mscc/ocelot.c        |   1 -
> drivers/net/ethernet/mscc/ocelot_ace.c    |  81 +++++------
> drivers/net/ethernet/mscc/ocelot_ace.h    |  24 ++--
> drivers/net/ethernet/mscc/ocelot_flower.c | 155 ++++------------------
> drivers/net/ethernet/mscc/ocelot_tc.c     |  22 +--
> include/soc/mscc/ocelot.h                 |   7 +
> 6 files changed, 75 insertions(+), 215 deletions(-)
>
>diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
>index b85e4fe9466d..3de8267180e2 100644
>--- a/drivers/net/ethernet/mscc/ocelot.c
>+++ b/drivers/net/ethernet/mscc/ocelot.c
>@@ -2502,7 +2502,6 @@ void ocelot_deinit(struct ocelot *ocelot)
>        cancel_delayed_work(&ocelot->stats_work);
>        destroy_workqueue(ocelot->stats_queue);
>        mutex_destroy(&ocelot->stats_lock);
>-       ocelot_ace_deinit();
>        if (ocelot->ptp_clock)
>                ptp_clock_unregister(ocelot->ptp_clock);
>
>diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
>index 18670645d47f..375c7c6aa7d5 100644
>--- a/drivers/net/ethernet/mscc/ocelot_ace.c
>+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
>@@ -12,8 +12,6 @@
>
> #define OCELOT_POLICER_DISCARD 0x17f
>
>-static struct ocelot_acl_block *acl_block;
>-
> struct vcap_props {
>        const char *name; /* Symbolic name */
>        u16 tg_width; /* Type-group width (in bits) */
>@@ -574,15 +572,15 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
>        vcap_row_cmd(ocelot, row, VCAP_CMD_WRITE, VCAP_SEL_ALL);
> }
>
>-static void is2_entry_get(struct ocelot_ace_rule *rule, int ix)
>+static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
>+                         int ix)
> {
>-       struct ocelot *op = rule->ocelot;
>        struct vcap_data data;
>        int row = (ix / 2);
>        u32 cnt;
>
>-       vcap_row_cmd(op, row, VCAP_CMD_READ, VCAP_SEL_COUNTER);
>-       vcap_cache2action(op, &data);
>+       vcap_row_cmd(ocelot, row, VCAP_CMD_READ, VCAP_SEL_COUNTER);
>+       vcap_cache2action(ocelot, &data);
>        data.tg_sw = VCAP_TG_HALF;
>        is2_data_get(&data, ix);
>        cnt = vcap_data_get(data.counter, data.counter_offset,
>@@ -641,25 +639,27 @@ ocelot_ace_rule_get_rule_index(struct ocelot_acl_block *block, int index)
>        return NULL;
> }
>
>-int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule)
>+int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
>+                               struct ocelot_ace_rule *rule)
> {
>+       struct ocelot_acl_block *block = &ocelot->acl_block;
>        struct ocelot_ace_rule *ace;
>        int i, index;
>
>        /* Add rule to the linked list */
>-       ocelot_ace_rule_add(acl_block, rule);
>+       ocelot_ace_rule_add(block, rule);
>
>        /* Get the index of the inserted rule */
>-       index = ocelot_ace_rule_get_index_id(acl_block, rule);
>+       index = ocelot_ace_rule_get_index_id(block, rule);
>
>        /* Move down the rules to make place for the new rule */
>-       for (i = acl_block->count - 1; i > index; i--) {
>-               ace = ocelot_ace_rule_get_rule_index(acl_block, i);
>-               is2_entry_set(rule->ocelot, i, ace);
>+       for (i = block->count - 1; i > index; i--) {
>+               ace = ocelot_ace_rule_get_rule_index(block, i);
>+               is2_entry_set(ocelot, i, ace);
>        }
>
>        /* Now insert the new rule */
>-       is2_entry_set(rule->ocelot, index, rule);
>+       is2_entry_set(ocelot, index, rule);
>        return 0;
> }
>
>@@ -680,8 +680,10 @@ static void ocelot_ace_rule_del(struct ocelot_acl_block *block,
>        block->count--;
> }
>
>-int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule)
>+int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
>+                               struct ocelot_ace_rule *rule)
> {
>+       struct ocelot_acl_block *block = &ocelot->acl_block;
>        struct ocelot_ace_rule del_ace;
>        struct ocelot_ace_rule *ace;
>        int i, index;
>@@ -689,59 +691,41 @@ int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule)
>        memset(&del_ace, 0, sizeof(del_ace));
>
>        /* Gets index of the rule */
>-       index = ocelot_ace_rule_get_index_id(acl_block, rule);
>+       index = ocelot_ace_rule_get_index_id(block, rule);
>
>        /* Delete rule */
>-       ocelot_ace_rule_del(acl_block, rule);
>+       ocelot_ace_rule_del(block, rule);
>
>        /* Move up all the blocks over the deleted rule */
>-       for (i = index; i < acl_block->count; i++) {
>-               ace = ocelot_ace_rule_get_rule_index(acl_block, i);
>-               is2_entry_set(rule->ocelot, i, ace);
>+       for (i = index; i < block->count; i++) {
>+               ace = ocelot_ace_rule_get_rule_index(block, i);
>+               is2_entry_set(ocelot, i, ace);
>        }
>
>        /* Now delete the last rule, because it is duplicated */
>-       is2_entry_set(rule->ocelot, acl_block->count, &del_ace);
>+       is2_entry_set(ocelot, block->count, &del_ace);
>
>        return 0;
> }
>
>-int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule)
>+int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
>+                                struct ocelot_ace_rule *rule)
> {
>+       struct ocelot_acl_block *block = &ocelot->acl_block;
>        struct ocelot_ace_rule *tmp;
>        int index;
>
>-       index = ocelot_ace_rule_get_index_id(acl_block, rule);
>-       is2_entry_get(rule, index);
>+       index = ocelot_ace_rule_get_index_id(block, rule);
>+       is2_entry_get(ocelot, rule, index);
>
>        /* After we get the result we need to clear the counters */
>-       tmp = ocelot_ace_rule_get_rule_index(acl_block, index);
>+       tmp = ocelot_ace_rule_get_rule_index(block, index);
>        tmp->stats.pkts = 0;
>-       is2_entry_set(rule->ocelot, index, tmp);
>+       is2_entry_set(ocelot, index, tmp);
>
>        return 0;
> }
>
>-static struct ocelot_acl_block *ocelot_acl_block_create(struct ocelot *ocelot)
>-{
>-       struct ocelot_acl_block *block;
>-
>-       block = kzalloc(sizeof(*block), GFP_KERNEL);
>-       if (!block)
>-               return NULL;
>-
>-       INIT_LIST_HEAD(&block->rules);
>-       block->count = 0;
>-       block->ocelot = ocelot;
>-
>-       return block;
>-}
>-
>-static void ocelot_acl_block_destroy(struct ocelot_acl_block *block)
>-{
>-       kfree(block);
>-}
>-
> int ocelot_ace_init(struct ocelot *ocelot)
> {
>        struct vcap_data data;
>@@ -771,12 +755,7 @@ int ocelot_ace_init(struct ocelot *ocelot)
>        ocelot_write_gix(ocelot, 0x3fffff, ANA_POL_CIR_STATE,
>                         OCELOT_POLICER_DISCARD);
>
>-       acl_block = ocelot_acl_block_create(ocelot);
>+       INIT_LIST_HEAD(&ocelot->acl_block.rules);
>
>        return 0;
> }
>-
>-void ocelot_ace_deinit(void)
>-{
>-       ocelot_acl_block_destroy(acl_block);
>-}
>diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h
>index 2927ac83741b..b9a5868e3f15 100644
>--- a/drivers/net/ethernet/mscc/ocelot_ace.h
>+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
>@@ -186,7 +186,6 @@ struct ocelot_ace_stats {
>
> struct ocelot_ace_rule {
>        struct list_head list;
>-       struct ocelot *ocelot;
>
>        u16 prio;
>        u32 id;
>@@ -211,22 +210,17 @@ struct ocelot_ace_rule {
>        } frame;
> };
>
>-struct ocelot_acl_block {
>-       struct list_head rules;
>-       struct ocelot *ocelot;
>-       int count;
>-};
>-
>-int ocelot_ace_rule_offload_add(struct ocelot_ace_rule *rule);
>-int ocelot_ace_rule_offload_del(struct ocelot_ace_rule *rule);
>-int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule);
>+int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
>+                               struct ocelot_ace_rule *rule);
>+int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
>+                               struct ocelot_ace_rule *rule);
>+int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
>+                                struct ocelot_ace_rule *rule);
>
> int ocelot_ace_init(struct ocelot *ocelot);
>-void ocelot_ace_deinit(void);
>
>-int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
>-                                     struct flow_block_offload *f);
>-void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
>-                                        struct flow_block_offload *f);
>+int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv,
>+                              struct flow_cls_offload *f,
>+                              bool ingress);
>
> #endif /* _MSCC_OCELOT_ACE_H_ */
>diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
>index ffd2bb50cfc3..b9673df6dbc5 100644
>--- a/drivers/net/ethernet/mscc/ocelot_flower.c
>+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
>@@ -8,11 +8,6 @@
>
> #include "ocelot_ace.h"
>
>-struct ocelot_port_block {
>-       struct ocelot_acl_block *block;
>-       struct ocelot_port_private *priv;
>-};
>-
> static int ocelot_flower_parse_action(struct flow_cls_offload *f,
>                                      struct ocelot_ace_rule *rule)
> {
>@@ -168,8 +163,8 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
> }
>
> static
>-struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
>-                                              struct ocelot_port_block *block)
>+struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port,
>+                                              struct flow_cls_offload *f)
> {
>        struct ocelot_ace_rule *rule;
>
>@@ -177,18 +172,17 @@ struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
>        if (!rule)
>                return NULL;
>
>-       rule->ocelot = block->priv->port.ocelot;
>-       rule->ingress_port_mask = BIT(block->priv->chip_port);
>+       rule->ingress_port_mask = BIT(port);
>        return rule;
> }
>
>-static int ocelot_flower_replace(struct flow_cls_offload *f,
>-                                struct ocelot_port_block *port_block)
>+int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
>+                             struct flow_cls_offload *f, bool ingress)
> {
>        struct ocelot_ace_rule *rule;
>        int ret;
>
>-       rule = ocelot_ace_rule_create(f, port_block);
>+       rule = ocelot_ace_rule_create(ocelot, port, f);
>        if (!rule)
>                return -ENOMEM;
>
>@@ -198,159 +192,66 @@ static int ocelot_flower_replace(struct flow_cls_offload *f,
>                return ret;
>        }
>
>-       ret = ocelot_ace_rule_offload_add(rule);
>+       ret = ocelot_ace_rule_offload_add(ocelot, rule);
>        if (ret)
>                return ret;
>
>-       port_block->priv->tc.offload_cnt++;
>        return 0;
> }
>+EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
>
>-static int ocelot_flower_destroy(struct flow_cls_offload *f,
>-                                struct ocelot_port_block *port_block)
>+int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
>+                             struct flow_cls_offload *f, bool ingress)
> {
>        struct ocelot_ace_rule rule;
>        int ret;
>
>        rule.prio = f->common.prio;
>-       rule.ocelot = port_block->priv->port.ocelot;
>        rule.id = f->cookie;
>
>-       ret = ocelot_ace_rule_offload_del(&rule);
>+       ret = ocelot_ace_rule_offload_del(ocelot, &rule);
>        if (ret)
>                return ret;
>
>-       port_block->priv->tc.offload_cnt--;
>        return 0;
> }
>+EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
>
>-static int ocelot_flower_stats_update(struct flow_cls_offload *f,
>-                                     struct ocelot_port_block *port_block)
>+int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
>+                           struct flow_cls_offload *f, bool ingress)
> {
>        struct ocelot_ace_rule rule;
>        int ret;
>
>        rule.prio = f->common.prio;
>-       rule.ocelot = port_block->priv->port.ocelot;
>        rule.id = f->cookie;
>-       ret = ocelot_ace_rule_stats_update(&rule);
>+       ret = ocelot_ace_rule_stats_update(ocelot, &rule);
>        if (ret)
>                return ret;
>
>        flow_stats_update(&f->stats, 0x0, rule.stats.pkts, 0x0);
>        return 0;
> }
>+EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
>
>-static int ocelot_setup_tc_cls_flower(struct flow_cls_offload *f,
>-                                     struct ocelot_port_block *port_block)
>+int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv,
>+                              struct flow_cls_offload *f,
>+                              bool ingress)
> {
>+       struct ocelot *ocelot = priv->port.ocelot;
>+       int port = priv->chip_port;
>+
>+       if (!ingress)
>+               return -EOPNOTSUPP;
>+
>        switch (f->command) {
>        case FLOW_CLS_REPLACE:
>-               return ocelot_flower_replace(f, port_block);
>+               return ocelot_cls_flower_replace(ocelot, port, f, ingress);
>        case FLOW_CLS_DESTROY:
>-               return ocelot_flower_destroy(f, port_block);
>+               return ocelot_cls_flower_destroy(ocelot, port, f, ingress);
>        case FLOW_CLS_STATS:
>-               return ocelot_flower_stats_update(f, port_block);
>+               return ocelot_cls_flower_stats(ocelot, port, f, ingress);
>        default:
>                return -EOPNOTSUPP;
>        }
> }
>-
>-static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type,
>-                                          void *type_data, void *cb_priv)
>-{
>-       struct ocelot_port_block *port_block = cb_priv;
>-
>-       if (!tc_cls_can_offload_and_chain0(port_block->priv->dev, type_data))
>-               return -EOPNOTSUPP;
>-
>-       switch (type) {
>-       case TC_SETUP_CLSFLOWER:
>-               return ocelot_setup_tc_cls_flower(type_data, cb_priv);
>-       case TC_SETUP_CLSMATCHALL:
>-               return 0;
>-       default:
>-               return -EOPNOTSUPP;
>-       }
>-}
>-
>-static struct ocelot_port_block*
>-ocelot_port_block_create(struct ocelot_port_private *priv)
>-{
>-       struct ocelot_port_block *port_block;
>-
>-       port_block = kzalloc(sizeof(*port_block), GFP_KERNEL);
>-       if (!port_block)
>-               return NULL;
>-
>-       port_block->priv = priv;
>-
>-       return port_block;
>-}
>-
>-static void ocelot_port_block_destroy(struct ocelot_port_block *block)
>-{
>-       kfree(block);
>-}
>-
>-static void ocelot_tc_block_unbind(void *cb_priv)
>-{
>-       struct ocelot_port_block *port_block = cb_priv;
>-
>-       ocelot_port_block_destroy(port_block);
>-}
>-
>-int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
>-                                     struct flow_block_offload *f)
>-{
>-       struct ocelot_port_block *port_block;
>-       struct flow_block_cb *block_cb;
>-       int ret;
>-
>-       if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
>-               return -EOPNOTSUPP;
>-
>-       block_cb = flow_block_cb_lookup(f->block,
>-                                       ocelot_setup_tc_block_cb_flower, priv);
>-       if (!block_cb) {
>-               port_block = ocelot_port_block_create(priv);
>-               if (!port_block)
>-                       return -ENOMEM;
>-
>-               block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower,
>-                                              priv, port_block,
>-                                              ocelot_tc_block_unbind);
>-               if (IS_ERR(block_cb)) {
>-                       ret = PTR_ERR(block_cb);
>-                       goto err_cb_register;
>-               }
>-               flow_block_cb_add(block_cb, f);
>-               list_add_tail(&block_cb->driver_list, f->driver_block_list);
>-       } else {
>-               port_block = flow_block_cb_priv(block_cb);
>-       }
>-
>-       flow_block_cb_incref(block_cb);
>-       return 0;
>-
>-err_cb_register:
>-       ocelot_port_block_destroy(port_block);
>-
>-       return ret;
>-}
>-
>-void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
>-                                        struct flow_block_offload *f)
>-{
>-       struct flow_block_cb *block_cb;
>-
>-       block_cb = flow_block_cb_lookup(f->block,
>-                                       ocelot_setup_tc_block_cb_flower, priv);
>-       if (!block_cb)
>-               return;
>-
>-       if (!flow_block_cb_decref(block_cb)) {
>-               flow_block_cb_remove(block_cb, f);
>-               list_del(&block_cb->driver_list);
>-       }
>-}
>diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
>index a4f7fbd76507..3ff5ef41eccf 100644
>--- a/drivers/net/ethernet/mscc/ocelot_tc.c
>+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
>@@ -20,9 +20,6 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port_private *priv,
>        int port = priv->chip_port;
>        int err;
>
>-       netdev_dbg(priv->dev, "%s: port %u command %d cookie %lu\n",
>-                  __func__, port, f->command, f->cookie);
>-
>        if (!ingress) {
>                NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported");
>                return -EOPNOTSUPP;
>@@ -99,17 +96,10 @@ static int ocelot_setup_tc_block_cb(enum tc_setup_type type,
>
>        switch (type) {
>        case TC_SETUP_CLSMATCHALL:
>-               netdev_dbg(priv->dev, "tc_block_cb: TC_SETUP_CLSMATCHALL %s\n",
>-                          ingress ? "ingress" : "egress");
>-
>                return ocelot_setup_tc_cls_matchall(priv, type_data, ingress);
>        case TC_SETUP_CLSFLOWER:
>-               return 0;
>+               return ocelot_setup_tc_cls_flower(priv, type_data, ingress);
>        default:
>-               netdev_dbg(priv->dev, "tc_block_cb: type %d %s\n",
>-                          type,
>-                          ingress ? "ingress" : "egress");
>-
>                return -EOPNOTSUPP;
>        }
> }
>@@ -137,10 +127,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
> {
>        struct flow_block_cb *block_cb;
>        flow_setup_cb_t *cb;
>-       int err;
>-
>-       netdev_dbg(priv->dev, "tc_block command %d, binder_type %d\n",
>-                  f->command, f->binder_type);
>
>        if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
>                cb = ocelot_setup_tc_block_cb_ig;
>@@ -162,11 +148,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
>                if (IS_ERR(block_cb))
>                        return PTR_ERR(block_cb);
>
>-               err = ocelot_setup_tc_block_flower_bind(priv, f);
>-               if (err < 0) {
>-                       flow_block_cb_free(block_cb);
>-                       return err;
>-               }
>                flow_block_cb_add(block_cb, f);
>                list_add_tail(&block_cb->driver_list, f->driver_block_list);
>                return 0;
>@@ -175,7 +156,6 @@ static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
>                if (!block_cb)
>                        return -ENOENT;
>
>-               ocelot_setup_tc_block_flower_unbind(priv, f);
>                flow_block_cb_remove(block_cb, f);
>                list_del(&block_cb->driver_list);
>                return 0;
>diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
>index 068f96b1a83e..74e7c63adad4 100644
>--- a/include/soc/mscc/ocelot.h
>+++ b/include/soc/mscc/ocelot.h
>@@ -406,6 +406,11 @@ struct ocelot_ops {
>        int (*reset)(struct ocelot *ocelot);
> };
>
>+struct ocelot_acl_block {
>+       struct list_head rules;
>+       int count;
>+};
>+
> struct ocelot_port {
>        struct ocelot                   *ocelot;
>
>@@ -455,6 +460,8 @@ struct ocelot {
>
>        struct list_head                multicast;
>
>+       struct ocelot_acl_block         acl_block;
>+
>        /* Workqueue to check statistics for overflow with its lock */
>        struct mutex                    stats_lock;
>        u64                             *stats;
>--
>2.17.1
>

Reviewed-by: Allan W. Nielsen <allan.nielsen@microchip.com>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 03/10] net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names with "ace"
  2020-02-24 13:08 ` [PATCH net-next 03/10] net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names with "ace" Vladimir Oltean
@ 2020-02-27  8:09   ` Allan W. Nielsen
  0 siblings, 0 replies; 22+ messages in thread
From: Allan W. Nielsen @ 2020-02-27  8:09 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, claudiu.manoil, netdev,
	UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1, yangbo.lu,
	po.liu, jiri, idosch, kuba

On 24.02.2020 15:08, Vladimir Oltean wrote:
>EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
>From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
>The "ocelot_rule" variable name is both annoyingly long trying to
>distinguish itself from struct flow_rule *rule =
>flow_cls_offload_flow_rule(f), as well as actually different from the
>"ace" variable name which is used all over the place in ocelot_ace.c and
>is referring to the same structure.
>
>And the "rule" variable name is, confusingly, different from f->rule,
>but sometimes one has to look up to the beginning of the function to get
>an understanding of what structure type is actually being handled.
>
>So let's use the "ace" name wherever possible ("Access Control Entry").
>
>Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
>---
> drivers/net/ethernet/mscc/ocelot_flower.c | 102 +++++++++++-----------
> 1 file changed, 51 insertions(+), 51 deletions(-)
>
>diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
>index b9673df6dbc5..698e9fee6b1a 100644
>--- a/drivers/net/ethernet/mscc/ocelot_flower.c
>+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
>@@ -9,7 +9,7 @@
> #include "ocelot_ace.h"
>
> static int ocelot_flower_parse_action(struct flow_cls_offload *f,
>-                                     struct ocelot_ace_rule *rule)
>+                                     struct ocelot_ace_rule *ace)
> {
>        const struct flow_action_entry *a;
>        int i;
>@@ -20,10 +20,10 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
>        flow_action_for_each(i, a, &f->rule->action) {
>                switch (a->id) {
>                case FLOW_ACTION_DROP:
>-                       rule->action = OCELOT_ACL_ACTION_DROP;
>+                       ace->action = OCELOT_ACL_ACTION_DROP;
>                        break;
>                case FLOW_ACTION_TRAP:
>-                       rule->action = OCELOT_ACL_ACTION_TRAP;
>+                       ace->action = OCELOT_ACL_ACTION_TRAP;
>                        break;
>                default:
>                        return -EOPNOTSUPP;
>@@ -34,7 +34,7 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
> }
>
> static int ocelot_flower_parse(struct flow_cls_offload *f,
>-                              struct ocelot_ace_rule *ocelot_rule)
>+                              struct ocelot_ace_rule *ace)
> {
>        struct flow_rule *rule = flow_cls_offload_flow_rule(f);
>        struct flow_dissector *dissector = rule->match.dissector;
>@@ -79,14 +79,14 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
>                        return -EOPNOTSUPP;
>
>                flow_rule_match_eth_addrs(rule, &match);
>-               ocelot_rule->type = OCELOT_ACE_TYPE_ETYPE;
>-               ether_addr_copy(ocelot_rule->frame.etype.dmac.value,
>+               ace->type = OCELOT_ACE_TYPE_ETYPE;
>+               ether_addr_copy(ace->frame.etype.dmac.value,
>                                match.key->dst);
>-               ether_addr_copy(ocelot_rule->frame.etype.smac.value,
>+               ether_addr_copy(ace->frame.etype.smac.value,
>                                match.key->src);
>-               ether_addr_copy(ocelot_rule->frame.etype.dmac.mask,
>+               ether_addr_copy(ace->frame.etype.dmac.mask,
>                                match.mask->dst);
>-               ether_addr_copy(ocelot_rule->frame.etype.smac.mask,
>+               ether_addr_copy(ace->frame.etype.smac.mask,
>                                match.mask->src);
>                goto finished_key_parsing;
>        }
>@@ -96,17 +96,17 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
>
>                flow_rule_match_basic(rule, &match);
>                if (ntohs(match.key->n_proto) == ETH_P_IP) {
>-                       ocelot_rule->type = OCELOT_ACE_TYPE_IPV4;
>-                       ocelot_rule->frame.ipv4.proto.value[0] =
>+                       ace->type = OCELOT_ACE_TYPE_IPV4;
>+                       ace->frame.ipv4.proto.value[0] =
>                                match.key->ip_proto;
>-                       ocelot_rule->frame.ipv4.proto.mask[0] =
>+                       ace->frame.ipv4.proto.mask[0] =
>                                match.mask->ip_proto;
>                }
>                if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
>-                       ocelot_rule->type = OCELOT_ACE_TYPE_IPV6;
>-                       ocelot_rule->frame.ipv6.proto.value[0] =
>+                       ace->type = OCELOT_ACE_TYPE_IPV6;
>+                       ace->frame.ipv6.proto.value[0] =
>                                match.key->ip_proto;
>-                       ocelot_rule->frame.ipv6.proto.mask[0] =
>+                       ace->frame.ipv6.proto.mask[0] =
>                                match.mask->ip_proto;
>                }
>        }
>@@ -117,16 +117,16 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
>                u8 *tmp;
>
>                flow_rule_match_ipv4_addrs(rule, &match);
>-               tmp = &ocelot_rule->frame.ipv4.sip.value.addr[0];
>+               tmp = &ace->frame.ipv4.sip.value.addr[0];
>                memcpy(tmp, &match.key->src, 4);
>
>-               tmp = &ocelot_rule->frame.ipv4.sip.mask.addr[0];
>+               tmp = &ace->frame.ipv4.sip.mask.addr[0];
>                memcpy(tmp, &match.mask->src, 4);
>
>-               tmp = &ocelot_rule->frame.ipv4.dip.value.addr[0];
>+               tmp = &ace->frame.ipv4.dip.value.addr[0];
>                memcpy(tmp, &match.key->dst, 4);
>
>-               tmp = &ocelot_rule->frame.ipv4.dip.mask.addr[0];
>+               tmp = &ace->frame.ipv4.dip.mask.addr[0];
>                memcpy(tmp, &match.mask->dst, 4);
>        }
>
>@@ -139,60 +139,60 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
>                struct flow_match_ports match;
>
>                flow_rule_match_ports(rule, &match);
>-               ocelot_rule->frame.ipv4.sport.value = ntohs(match.key->src);
>-               ocelot_rule->frame.ipv4.sport.mask = ntohs(match.mask->src);
>-               ocelot_rule->frame.ipv4.dport.value = ntohs(match.key->dst);
>-               ocelot_rule->frame.ipv4.dport.mask = ntohs(match.mask->dst);
>+               ace->frame.ipv4.sport.value = ntohs(match.key->src);
>+               ace->frame.ipv4.sport.mask = ntohs(match.mask->src);
>+               ace->frame.ipv4.dport.value = ntohs(match.key->dst);
>+               ace->frame.ipv4.dport.mask = ntohs(match.mask->dst);
>        }
>
>        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
>                struct flow_match_vlan match;
>
>                flow_rule_match_vlan(rule, &match);
>-               ocelot_rule->type = OCELOT_ACE_TYPE_ANY;
>-               ocelot_rule->vlan.vid.value = match.key->vlan_id;
>-               ocelot_rule->vlan.vid.mask = match.mask->vlan_id;
>-               ocelot_rule->vlan.pcp.value[0] = match.key->vlan_priority;
>-               ocelot_rule->vlan.pcp.mask[0] = match.mask->vlan_priority;
>+               ace->type = OCELOT_ACE_TYPE_ANY;
>+               ace->vlan.vid.value = match.key->vlan_id;
>+               ace->vlan.vid.mask = match.mask->vlan_id;
>+               ace->vlan.pcp.value[0] = match.key->vlan_priority;
>+               ace->vlan.pcp.mask[0] = match.mask->vlan_priority;
>        }
>
> finished_key_parsing:
>-       ocelot_rule->prio = f->common.prio;
>-       ocelot_rule->id = f->cookie;
>-       return ocelot_flower_parse_action(f, ocelot_rule);
>+       ace->prio = f->common.prio;
>+       ace->id = f->cookie;
>+       return ocelot_flower_parse_action(f, ace);
> }
>
> static
> struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port,
>                                               struct flow_cls_offload *f)
> {
>-       struct ocelot_ace_rule *rule;
>+       struct ocelot_ace_rule *ace;
>
>-       rule = kzalloc(sizeof(*rule), GFP_KERNEL);
>-       if (!rule)
>+       ace = kzalloc(sizeof(*ace), GFP_KERNEL);
>+       if (!ace)
>                return NULL;
>
>-       rule->ingress_port_mask = BIT(port);
>-       return rule;
>+       ace->ingress_port_mask = BIT(port);
>+       return ace;
> }
>
> int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
>                              struct flow_cls_offload *f, bool ingress)
> {
>-       struct ocelot_ace_rule *rule;
>+       struct ocelot_ace_rule *ace;
>        int ret;
>
>-       rule = ocelot_ace_rule_create(ocelot, port, f);
>-       if (!rule)
>+       ace = ocelot_ace_rule_create(ocelot, port, f);
>+       if (!ace)
>                return -ENOMEM;
>
>-       ret = ocelot_flower_parse(f, rule);
>+       ret = ocelot_flower_parse(f, ace);
>        if (ret) {
>-               kfree(rule);
>+               kfree(ace);
>                return ret;
>        }
>
>-       ret = ocelot_ace_rule_offload_add(ocelot, rule);
>+       ret = ocelot_ace_rule_offload_add(ocelot, ace);
>        if (ret)
>                return ret;
>
>@@ -203,13 +203,13 @@ EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
> int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
>                              struct flow_cls_offload *f, bool ingress)
> {
>-       struct ocelot_ace_rule rule;
>+       struct ocelot_ace_rule ace;
>        int ret;
>
>-       rule.prio = f->common.prio;
>-       rule.id = f->cookie;
>+       ace.prio = f->common.prio;
>+       ace.id = f->cookie;
>
>-       ret = ocelot_ace_rule_offload_del(ocelot, &rule);
>+       ret = ocelot_ace_rule_offload_del(ocelot, &ace);
>        if (ret)
>                return ret;
>
>@@ -220,16 +220,16 @@ EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
> int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
>                            struct flow_cls_offload *f, bool ingress)
> {
>-       struct ocelot_ace_rule rule;
>+       struct ocelot_ace_rule ace;
>        int ret;
>
>-       rule.prio = f->common.prio;
>-       rule.id = f->cookie;
>-       ret = ocelot_ace_rule_stats_update(ocelot, &rule);
>+       ace.prio = f->common.prio;
>+       ace.id = f->cookie;
>+       ret = ocelot_ace_rule_stats_update(ocelot, &ace);
>        if (ret)
>                return ret;
>
>-       flow_stats_update(&f->stats, 0x0, rule.stats.pkts, 0x0);
>+       flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0x0);
>        return 0;
> }
> EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
>--
>2.17.1
>

Reviewed-by: Allan W. Nielsen <allan.nielsen@microchip.com>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 04/10] net: mscc: ocelot: return directly in ocelot_cls_flower_{replace,destroy}
  2020-02-24 13:08 ` [PATCH net-next 04/10] net: mscc: ocelot: return directly in ocelot_cls_flower_{replace,destroy} Vladimir Oltean
@ 2020-02-27  8:10   ` Allan W. Nielsen
  0 siblings, 0 replies; 22+ messages in thread
From: Allan W. Nielsen @ 2020-02-27  8:10 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, claudiu.manoil, netdev,
	UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1, yangbo.lu,
	po.liu, jiri, idosch, kuba

On 24.02.2020 15:08, Vladimir Oltean wrote:
>EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
>From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
>There is no need to check the "ret" variable, one can just return the
>function result back to the caller.
>
>Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
>---
> drivers/net/ethernet/mscc/ocelot_flower.c | 13 ++-----------
> 1 file changed, 2 insertions(+), 11 deletions(-)
>
>diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
>index 698e9fee6b1a..8993dadf063c 100644
>--- a/drivers/net/ethernet/mscc/ocelot_flower.c
>+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
>@@ -192,11 +192,7 @@ int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
>                return ret;
>        }
>
>-       ret = ocelot_ace_rule_offload_add(ocelot, ace);
>-       if (ret)
>-               return ret;
>-
>-       return 0;
>+       return ocelot_ace_rule_offload_add(ocelot, ace);
> }
> EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
>
>@@ -204,16 +200,11 @@ int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
>                              struct flow_cls_offload *f, bool ingress)
> {
>        struct ocelot_ace_rule ace;
>-       int ret;
>
>        ace.prio = f->common.prio;
>        ace.id = f->cookie;
>
>-       ret = ocelot_ace_rule_offload_del(ocelot, &ace);
>-       if (ret)
>-               return ret;
>-
>-       return 0;
>+       return ocelot_ace_rule_offload_del(ocelot, &ace);
> }
> EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
>
>--
>2.17.1
>

Reviewed-by: Allan W. Nielsen <allan.nielsen@microchip.com>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 06/10] net: mscc: ocelot: remove port_pcs_init indirection for VSC7514
  2020-02-24 13:08 ` [PATCH net-next 06/10] net: mscc: ocelot: remove port_pcs_init indirection for VSC7514 Vladimir Oltean
@ 2020-02-27  8:13   ` Allan W. Nielsen
  0 siblings, 0 replies; 22+ messages in thread
From: Allan W. Nielsen @ 2020-02-27  8:13 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, claudiu.manoil, netdev,
	UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1, yangbo.lu,
	po.liu, jiri, idosch, kuba

On 24.02.2020 15:08, Vladimir Oltean wrote:
>EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
>From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
>The Felix driver is now using its own PHYLINK instance, not calling into
>ocelot_adjust_link. So the port_pcs_init function pointer is an
>unnecessary indirection. Remove it.
>
>Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
>---
> drivers/net/ethernet/mscc/ocelot.c       | 19 +++++++++++++++++--
> drivers/net/ethernet/mscc/ocelot_board.c | 24 ------------------------
> include/soc/mscc/ocelot.h                |  3 ---
> 3 files changed, 17 insertions(+), 29 deletions(-)
>
>diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
>index 3de8267180e2..2fc10b89bbcb 100644
>--- a/drivers/net/ethernet/mscc/ocelot.c
>+++ b/drivers/net/ethernet/mscc/ocelot.c
>@@ -442,8 +442,23 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port,
>        ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
>                           mode, DEV_MAC_MODE_CFG);
>
>-       if (ocelot->ops->pcs_init)
>-               ocelot->ops->pcs_init(ocelot, port);
>+       /* Disable HDX fast control */
>+       ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
>+                          DEV_PORT_MISC);
>+
>+       /* SGMII only for now */
>+       ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
>+                          PCS1G_MODE_CFG);
>+       ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
>+
>+       /* Enable PCS */
>+       ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
>+
>+       /* No aneg on SGMII */
>+       ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
>+
>+       /* No loopback */
>+       ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
>
>        /* Enable MAC module */
>        ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
>diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
>index 8b83a10083e2..5e21d0cc8335 100644
>--- a/drivers/net/ethernet/mscc/ocelot_board.c
>+++ b/drivers/net/ethernet/mscc/ocelot_board.c
>@@ -212,29 +212,6 @@ static const struct of_device_id mscc_ocelot_match[] = {
> };
> MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
>
>-static void ocelot_port_pcs_init(struct ocelot *ocelot, int port)
>-{
>-       struct ocelot_port *ocelot_port = ocelot->ports[port];
>-
>-       /* Disable HDX fast control */
>-       ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
>-                          DEV_PORT_MISC);
>-
>-       /* SGMII only for now */
>-       ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
>-                          PCS1G_MODE_CFG);
>-       ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
>-
>-       /* Enable PCS */
>-       ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
>-
>-       /* No aneg on SGMII */
>-       ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
>-
>-       /* No loopback */
>-       ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
>-}
>-
> static int ocelot_reset(struct ocelot *ocelot)
> {
>        int retries = 100;
>@@ -259,7 +236,6 @@ static int ocelot_reset(struct ocelot *ocelot)
> }
>
> static const struct ocelot_ops ocelot_ops = {
>-       .pcs_init               = ocelot_port_pcs_init,
>        .reset                  = ocelot_reset,
> };
>
>diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
>index f63266a4ca70..31bcbc1ab2f9 100644
>--- a/include/soc/mscc/ocelot.h
>+++ b/include/soc/mscc/ocelot.h
>@@ -402,7 +402,6 @@ enum ocelot_tag_prefix {
> struct ocelot;
>
> struct ocelot_ops {
>-       void (*pcs_init)(struct ocelot *ocelot, int port);
>        int (*reset)(struct ocelot *ocelot);
> };
>
>@@ -479,8 +478,6 @@ struct ocelot {
>        struct mutex                    ptp_lock;
>        /* Protects the PTP clock */
>        spinlock_t                      ptp_clock_lock;
>-
>-       void (*port_pcs_init)(struct ocelot_port *port);
> };
>
> #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
>--
>2.17.1
>

Reviewed-by: Allan W. Nielsen <allan.nielsen@microchip.com>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 07/10] net: mscc: ocelot: parameterize the vcap_is2 properties
  2020-02-24 13:08 ` [PATCH net-next 07/10] net: mscc: ocelot: parameterize the vcap_is2 properties Vladimir Oltean
@ 2020-02-27  8:47   ` Allan W. Nielsen
  0 siblings, 0 replies; 22+ messages in thread
From: Allan W. Nielsen @ 2020-02-27  8:47 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: davem, horatiu.vultur, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, claudiu.manoil, netdev,
	UNGLinuxDriver, alexandru.marginean, xiaoliang.yang_1, yangbo.lu,
	po.liu, jiri, idosch, kuba

On 24.02.2020 15:08, Vladimir Oltean wrote:
>EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
>From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
>Remove the definitions for the VCAP IS2 table from ocelot_ace.c, since
>it is specific to VSC7514.
>
>The VSC9959 VCAP IS2 table supports more rules (1024 instead of 64) and
>has a different width for the action (89 bits instead of 99).
>
>Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
>---
> drivers/net/ethernet/mscc/ocelot_ace.c   | 108 ++++++++---------------
> drivers/net/ethernet/mscc/ocelot_board.c |  25 ++++++
> include/soc/mscc/ocelot.h                |   1 +
> include/soc/mscc/ocelot_vcap.h           |  37 ++++++--
> 4 files changed, 94 insertions(+), 77 deletions(-)
>
>diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
>index c838e681963f..76809ffd5d99 100644
>--- a/drivers/net/ethernet/mscc/ocelot_ace.c
>+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
>@@ -11,53 +11,7 @@
> #include "ocelot_s2.h"
>
> #define OCELOT_POLICER_DISCARD 0x17f
>-
>-struct vcap_props {
>-       const char *name; /* Symbolic name */
>-       u16 tg_width; /* Type-group width (in bits) */
>-       u16 sw_count; /* Sub word count */
>-       u16 entry_count; /* Entry count */
>-       u16 entry_words; /* Number of entry words */
>-       u16 entry_width; /* Entry width (in bits) */
>-       u16 action_count; /* Action count */
>-       u16 action_words; /* Number of action words */
>-       u16 action_width; /* Action width (in bits) */
>-       u16 action_type_width; /* Action type width (in bits) */
>-       struct {
>-               u16 width; /* Action type width (in bits) */
>-               u16 count; /* Action type sub word count */
>-       } action_table[2];
>-       u16 counter_words; /* Number of counter words */
>-       u16 counter_width; /* Counter width (in bits) */
>-};
>-
> #define ENTRY_WIDTH 32
>-#define BITS_TO_32BIT(x) (1 + (((x) - 1) / ENTRY_WIDTH))
>-
>-static const struct vcap_props vcap_is2 = {
>-       .name = "IS2",
>-       .tg_width = 2,
>-       .sw_count = 4,
>-       .entry_count = VCAP_IS2_CNT,
>-       .entry_words = BITS_TO_32BIT(VCAP_IS2_ENTRY_WIDTH),
>-       .entry_width = VCAP_IS2_ENTRY_WIDTH,
>-       .action_count = (VCAP_IS2_CNT + VCAP_PORT_CNT + 2),
>-       .action_words = BITS_TO_32BIT(VCAP_IS2_ACTION_WIDTH),
>-       .action_width = (VCAP_IS2_ACTION_WIDTH),
>-       .action_type_width = 1,
>-       .action_table = {
>-               {
>-                       .width = 49,
>-                       .count = 2
>-               },
>-               {
>-                       .width = 6,
>-                       .count = 4
>-               },
>-       },
>-       .counter_words = BITS_TO_32BIT(4 * ENTRY_WIDTH),
>-       .counter_width = ENTRY_WIDTH,
>-};
>
> enum vcap_sel {
>        VCAP_SEL_ENTRY = 0x1,
>@@ -101,11 +55,13 @@ static u32 vcap_s2_read_update_ctrl(struct ocelot *oc)
>
> static void vcap_cmd(struct ocelot *oc, u16 ix, int cmd, int sel)
> {
>+       const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
>+
>        u32 value = (S2_CORE_UPDATE_CTRL_UPDATE_CMD(cmd) |
>                     S2_CORE_UPDATE_CTRL_UPDATE_ADDR(ix) |
>                     S2_CORE_UPDATE_CTRL_UPDATE_SHOT);
>
>-       if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2.entry_count)
>+       if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2->entry_count)
>                return;
>
>        if (!(sel & VCAP_SEL_ENTRY))
>@@ -126,14 +82,18 @@ static void vcap_cmd(struct ocelot *oc, u16 ix, int cmd, int sel)
> /* Convert from 0-based row to VCAP entry row and run command */
> static void vcap_row_cmd(struct ocelot *oc, u32 row, int cmd, int sel)
> {
>-       vcap_cmd(oc, vcap_is2.entry_count - row - 1, cmd, sel);
>+       const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
>+
>+       vcap_cmd(oc, vcap_is2->entry_count - row - 1, cmd, sel);
> }
>
> static void vcap_entry2cache(struct ocelot *oc, struct vcap_data *data)
> {
>+       const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
>+       u32 entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH);
>        u32 i;
>
>-       for (i = 0; i < vcap_is2.entry_words; i++) {
>+       for (i = 0; i < entry_words; i++) {
>                ocelot_write_rix(oc, data->entry[i], S2_CACHE_ENTRY_DAT, i);
>                ocelot_write_rix(oc, ~data->mask[i], S2_CACHE_MASK_DAT, i);
>        }
>@@ -142,9 +102,11 @@ static void vcap_entry2cache(struct ocelot *oc, struct vcap_data *data)
>
> static void vcap_cache2entry(struct ocelot *oc, struct vcap_data *data)
> {
>+       const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
>+       u32 entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH);
>        u32 i;
>
>-       for (i = 0; i < vcap_is2.entry_words; i++) {
>+       for (i = 0; i < entry_words; i++) {
>                data->entry[i] = ocelot_read_rix(oc, S2_CACHE_ENTRY_DAT, i);
>                // Invert mask
>                data->mask[i] = ~ocelot_read_rix(oc, S2_CACHE_MASK_DAT, i);
>@@ -154,46 +116,51 @@ static void vcap_cache2entry(struct ocelot *oc, struct vcap_data *data)
>
> static void vcap_action2cache(struct ocelot *oc, struct vcap_data *data)
> {
>+       const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
>+       u32 action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH);
>        u32 i, width, mask;
>
>        /* Encode action type */
>-       width = vcap_is2.action_type_width;
>+       width = vcap_is2->action_type_width;
>        if (width) {
>                mask = GENMASK(width, 0);
>                data->action[0] = ((data->action[0] & ~mask) | data->type);
>        }
>
>-       for (i = 0; i < vcap_is2.action_words; i++)
>+       for (i = 0; i < action_words; i++)
>                ocelot_write_rix(oc, data->action[i], S2_CACHE_ACTION_DAT, i);
>
>-       for (i = 0; i < vcap_is2.counter_words; i++)
>+       for (i = 0; i < vcap_is2->counter_words; i++)
>                ocelot_write_rix(oc, data->counter[i], S2_CACHE_CNT_DAT, i);
> }
>
> static void vcap_cache2action(struct ocelot *oc, struct vcap_data *data)
> {
>+       const struct vcap_props *vcap_is2 = &oc->vcap[VCAP_IS2];
>+       u32 action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH);
>        u32 i, width;
>
>-       for (i = 0; i < vcap_is2.action_words; i++)
>+       for (i = 0; i < action_words; i++)
>                data->action[i] = ocelot_read_rix(oc, S2_CACHE_ACTION_DAT, i);
>
>-       for (i = 0; i < vcap_is2.counter_words; i++)
>+       for (i = 0; i < vcap_is2->counter_words; i++)
>                data->counter[i] = ocelot_read_rix(oc, S2_CACHE_CNT_DAT, i);
>
>        /* Extract action type */
>-       width = vcap_is2.action_type_width;
>+       width = vcap_is2->action_type_width;
>        data->type = (width ? (data->action[0] & GENMASK(width, 0)) : 0);
> }
>
> /* Calculate offsets for entry */
> static void is2_data_get(struct vcap_data *data, int ix)
> {
>-       u32 i, col, offset, count, cnt, base, width = vcap_is2.tg_width;
>+       const struct vcap_props *vcap_is2 = &data->ocelot->vcap[VCAP_IS2];
>+       u32 i, col, offset, count, cnt, base, width = vcap_is2->tg_width;
>
>        count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4);
>        col = (ix % 2);
>-       cnt = (vcap_is2.sw_count / count);
>-       base = (vcap_is2.sw_count - col * cnt - cnt);
>+       cnt = (vcap_is2->sw_count / count);
>+       base = (vcap_is2->sw_count - col * cnt - cnt);
>        data->tg_value = 0;
>        data->tg_mask = 0;
>        for (i = 0; i < cnt; i++) {
>@@ -204,13 +171,13 @@ static void is2_data_get(struct vcap_data *data, int ix)
>
>        /* Calculate key/action/counter offsets */
>        col = (count - col - 1);
>-       data->key_offset = (base * vcap_is2.entry_width) / vcap_is2.sw_count;
>-       data->counter_offset = (cnt * col * vcap_is2.counter_width);
>+       data->key_offset = (base * vcap_is2->entry_width) / vcap_is2->sw_count;
>+       data->counter_offset = (cnt * col * vcap_is2->counter_width);
>        i = data->type;
>-       width = vcap_is2.action_table[i].width;
>-       cnt = vcap_is2.action_table[i].count;
>+       width = vcap_is2->action_table[i].width;
>+       cnt = vcap_is2->action_table[i].count;
>        data->action_offset =
>-               (((cnt * col * width) / count) + vcap_is2.action_type_width);
>+               (((cnt * col * width) / count) + vcap_is2->action_type_width);
> }
>
> static void vcap_data_set(u32 *data, u32 offset, u32 len, u32 value)
>@@ -357,6 +324,7 @@ static void is2_action_set(struct vcap_data *data,
> static void is2_entry_set(struct ocelot *ocelot, int ix,
>                          struct ocelot_ace_rule *ace)
> {
>+       const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];
>        u32 val, msk, type, type_mask = 0xf, i, count;
>        struct ocelot_ace_vlan *tag = &ace->vlan;
>        struct ocelot_vcap_u64 payload;
>@@ -602,7 +570,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
>        default:
>                type = 0;
>                type_mask = 0;
>-               count = (vcap_is2.entry_width / 2);
>+               count = vcap_is2->entry_width / 2;
>                /* Iterate over the non-common part of the key and
>                 * clear entry data
>                 */
>@@ -615,7 +583,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
>
>        vcap_key_set(&data, VCAP_IS2_TYPE, type, type_mask);
>        is2_action_set(&data, ace->action);
>-       vcap_data_set(data.counter, data.counter_offset, vcap_is2.counter_width,
>+       vcap_data_set(data.counter, data.counter_offset, vcap_is2->counter_width,
>                      ace->stats.pkts);
>
>        /* Write row */
>@@ -627,6 +595,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
> static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
>                          int ix)
> {
>+       const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];
>        struct vcap_data data;
>        int row = (ix / 2);
>        u32 cnt;
>@@ -638,7 +607,7 @@ static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
>        data.tg_sw = VCAP_TG_HALF;
>        is2_data_get(&data, ix);
>        cnt = vcap_data_get(data.counter, data.counter_offset,
>-                           vcap_is2.counter_width);
>+                           vcap_is2->counter_width);
>
>        rule->stats.pkts = cnt;
> }
>@@ -782,6 +751,7 @@ int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
>
> int ocelot_ace_init(struct ocelot *ocelot)
> {
>+       const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2];
>        struct vcap_data data;
>
>        memset(&data, 0, sizeof(data));
>@@ -789,11 +759,11 @@ int ocelot_ace_init(struct ocelot *ocelot)
>        data.ocelot = ocelot;
>
>        vcap_entry2cache(ocelot, &data);
>-       ocelot_write(ocelot, vcap_is2.entry_count, S2_CORE_MV_CFG);
>+       ocelot_write(ocelot, vcap_is2->entry_count, S2_CORE_MV_CFG);
>        vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY);
>
>        vcap_action2cache(ocelot, &data);
>-       ocelot_write(ocelot, vcap_is2.action_count, S2_CORE_MV_CFG);
>+       ocelot_write(ocelot, vcap_is2->action_count, S2_CORE_MV_CFG);
>        vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE,
>                 VCAP_SEL_ACTION | VCAP_SEL_COUNTER);
>
>diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
>index 5e21d0cc8335..1d6d2b48a92f 100644
>--- a/drivers/net/ethernet/mscc/ocelot_board.c
>+++ b/drivers/net/ethernet/mscc/ocelot_board.c
>@@ -337,6 +337,30 @@ struct vcap_field vsc7514_vcap_is2_actions[] = {
>        [VCAP_IS2_ACT_HIT_CNT]                  = { 49, 32},
> };
>
>+static const struct vcap_props vsc7514_vcap_props[] = {
>+       [VCAP_IS2] = {
>+               .tg_width = 2,
>+               .sw_count = 4,
>+               .entry_count = 64,
>+               .entry_width = 376,
>+               .action_count = 64 + 11 + 2,
>+               .action_width = 99,
Can you please use the defines here. We will need to rename them to
avoid confusion: VCAP_IS2_CNT -> VSC7514_IS2_CNT or something like that.

>+               .action_type_width = 1,
>+               .action_table = {
>+                       [IS2_ACTION_TYPE_NORMAL] = {
>+                               .width = 49,
>+                               .count = 2
>+                       },
>+                       [IS2_ACTION_TYPE_SMAC_SIP] = {
>+                               .width = 6,
>+                               .count = 4
>+                       },
>+               },
>+               .counter_words = 4,
>+               .counter_width = 32,
>+       },
>+};
>+
> static int mscc_ocelot_probe(struct platform_device *pdev)
> {
>        struct device_node *np = pdev->dev.of_node;
>@@ -439,6 +463,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
>
>        ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
>        ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
>+       ocelot->vcap = vsc7514_vcap_props;
>
>        ocelot_init(ocelot);
>        ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports,
>diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
>index 31bcbc1ab2f9..0cbd61d1c30c 100644
>--- a/include/soc/mscc/ocelot.h
>+++ b/include/soc/mscc/ocelot.h
>@@ -463,6 +463,7 @@ struct ocelot {
>
>        struct vcap_field               *vcap_is2_keys;
>        struct vcap_field               *vcap_is2_actions;
>+       const struct vcap_props         *vcap;
>
>        /* Workqueue to check statistics for overflow with its lock */
>        struct mutex                    stats_lock;
>diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h
>index 0783f0ffc813..5748373ab4d3 100644
>--- a/include/soc/mscc/ocelot_vcap.h
>+++ b/include/soc/mscc/ocelot_vcap.h
>@@ -11,6 +11,30 @@
>  * =================================================================
>  */
>
>+enum {
>+       /* VCAP_IS1, */
>+       VCAP_IS2,
>+       /* VCAP_ES0, */
>+};
>+
>+struct vcap_props {
>+       u16 tg_width; /* Type-group width (in bits) */
>+       u16 sw_count; /* Sub word count */
>+       u16 entry_count; /* Entry count */
>+       u16 entry_words; /* Number of entry words */
>+       u16 entry_width; /* Entry width (in bits) */
>+       u16 action_count; /* Action count */
>+       u16 action_words; /* Number of action words */
>+       u16 action_width; /* Action width (in bits) */
>+       u16 action_type_width; /* Action type width (in bits) */
>+       struct {
>+               u16 width; /* Action type width (in bits) */
>+               u16 count; /* Action type sub word count */
>+       } action_table[2];
>+       u16 counter_words; /* Number of counter words */
>+       u16 counter_width; /* Counter width (in bits) */
>+};
>+
> /* VCAP Type-Group values */
> #define VCAP_TG_NONE 0 /* Entry is invalid */
> #define VCAP_TG_FULL 1 /* Full entry */
>@@ -22,11 +46,6 @@
>  * =================================================================
>  */
>
>-#define VCAP_IS2_CNT 64
>-#define VCAP_IS2_ENTRY_WIDTH 376
>-#define VCAP_IS2_ACTION_WIDTH 99
>-#define VCAP_PORT_CNT 11
>-
> /* IS2 half key types */
> #define IS2_TYPE_ETYPE 0
> #define IS2_TYPE_LLC 1
>@@ -42,9 +61,11 @@
> /* IS2 half key type mask for matching any IP */
> #define IS2_TYPE_MASK_IP_ANY 0xe
>
>-/* IS2 action types */
>-#define IS2_ACTION_TYPE_NORMAL 0
>-#define IS2_ACTION_TYPE_SMAC_SIP 1
>+enum {
>+       IS2_ACTION_TYPE_NORMAL,
>+       IS2_ACTION_TYPE_SMAC_SIP,
>+       IS2_ACTION_TYPE_MAX,
>+};
>
> /* IS2 MASK_MODE values */
> #define IS2_ACT_MASK_MODE_NONE 0
>--
>2.17.1
>
/Allan

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2020-02-27  8:47 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-24 13:08 [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Vladimir Oltean
2020-02-24 13:08 ` [PATCH net-next 01/10] net: mscc: ocelot: make ocelot_ace_rule support multiple ports Vladimir Oltean
2020-02-27  8:02   ` Allan W. Nielsen
2020-02-24 13:08 ` [PATCH net-next 02/10] net: mscc: ocelot: simplify tc-flower offload structures Vladimir Oltean
2020-02-27  8:08   ` Allan W. Nielsen
2020-02-24 13:08 ` [PATCH net-next 03/10] net: mscc: ocelot: replace "rule" and "ocelot_rule" variable names with "ace" Vladimir Oltean
2020-02-27  8:09   ` Allan W. Nielsen
2020-02-24 13:08 ` [PATCH net-next 04/10] net: mscc: ocelot: return directly in ocelot_cls_flower_{replace,destroy} Vladimir Oltean
2020-02-27  8:10   ` Allan W. Nielsen
2020-02-24 13:08 ` [PATCH net-next 05/10] net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing Vladimir Oltean
2020-02-24 23:21   ` David Miller
2020-02-25  4:58   ` kbuild test robot
2020-02-25  4:58   ` [RFC PATCH] net: mscc: ocelot: vsc7514_vcap_is2_keys[] can be static kbuild test robot
2020-02-24 13:08 ` [PATCH net-next 06/10] net: mscc: ocelot: remove port_pcs_init indirection for VSC7514 Vladimir Oltean
2020-02-27  8:13   ` Allan W. Nielsen
2020-02-24 13:08 ` [PATCH net-next 07/10] net: mscc: ocelot: parameterize the vcap_is2 properties Vladimir Oltean
2020-02-27  8:47   ` Allan W. Nielsen
2020-02-24 13:08 ` [PATCH net-next 08/10] net: dsa: Refactor matchall mirred action to separate function Vladimir Oltean
2020-02-24 13:08 ` [PATCH net-next 09/10] net: dsa: Add bypass operations for the flower classifier-action filter Vladimir Oltean
2020-02-24 13:08 ` [PATCH net-next 10/10] net: dsa: felix: Wire up the ocelot cls_flower methods Vladimir Oltean
2020-02-25 14:45 ` [PATCH net-next 00/10] Wire up Ocelot tc-flower to Felix DSA Horatiu Vultur
2020-02-25 16:06   ` Vladimir Oltean

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).