All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
To: xiaoliang.yang_1@nxp.com, po.liu@nxp.com, claudiu.manoil@nxp.com,
	alexandru.marginean@nxp.com, vladimir.oltean@nxp.com,
	leoyang.li@nxp.com, mingkai.hu@nxp.com, andrew@lunn.ch,
	f.fainelli@gmail.com, vivien.didelot@gmail.com,
	davem@davemloft.net, jiri@resnulli.us, idosch@idosch.org,
	kuba@kernel.org, vinicius.gomes@intel.com,
	nikolay@cumulusnetworks.com, roopa@cumulusnetworks.com,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	horatiu.vultur@microchip.com, alexandre.belloni@bootlin.com,
	allan.nielsen@microchip.com, joergen.andreasen@microchip.com,
	UNGLinuxDriver@microchip.com, linux-devel@linux.nxdi.nxp.com
Subject: [PATCH v2 net-next 03/10] net: mscc: ocelot: allocated rules to different hardware VCAP TCAMs by chain index
Date: Tue,  2 Jun 2020 13:18:21 +0800	[thread overview]
Message-ID: <20200602051828.5734-4-xiaoliang.yang_1@nxp.com> (raw)
In-Reply-To: <20200602051828.5734-1-xiaoliang.yang_1@nxp.com>

There are three hardware TCAMs for ocelot chips: IS1, IS2 and ES0. Each
one supports different actions. The hardware flow order is: IS1->IS2->ES0.

This patch add three blocks to store rules according to chain index.
chain 0 is offloaded to IS1, chain 1 is offloaded to IS2, and egress chain
0 is offloaded to ES0.

Using action goto chain to express flow order as follows:
	tc filter add dev swp0 chain 0 parent ffff: flower skip_sw \
	action goto chain 1

Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot_ace.c    | 51 +++++++++++++++--------
 drivers/net/ethernet/mscc/ocelot_ace.h    |  7 ++--
 drivers/net/ethernet/mscc/ocelot_flower.c | 46 +++++++++++++++++---
 include/soc/mscc/ocelot.h                 |  2 +-
 include/soc/mscc/ocelot_vcap.h            |  4 +-
 5 files changed, 81 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c
index 748c618db7d8..b76593b40097 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.c
+++ b/drivers/net/ethernet/mscc/ocelot_ace.c
@@ -341,6 +341,8 @@ static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data,
 		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
 		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
 		break;
+	default:
+		break;
 	}
 }
 
@@ -644,9 +646,9 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
 }
 
 static void vcap_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
-			   int ix)
+			   int ix, int block_id)
 {
-	const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];
+	const struct vcap_props *vcap = &ocelot->vcap[block_id];
 	struct vcap_data data;
 	int row, count;
 	u32 cnt;
@@ -663,6 +665,19 @@ static void vcap_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
 	rule->stats.pkts = cnt;
 }
 
+static void vcap_entry_set(struct ocelot *ocelot, int ix,
+			   struct ocelot_ace_rule *ace,
+			   int block_id)
+{
+	switch (block_id) {
+	case VCAP_IS2:
+		is2_entry_set(ocelot, ix, ace);
+		break;
+	default:
+		break;
+	}
+}
+
 static void ocelot_ace_rule_add(struct ocelot *ocelot,
 				struct ocelot_acl_block *block,
 				struct ocelot_ace_rule *rule)
@@ -790,7 +805,7 @@ static bool ocelot_ace_is_problematic_non_mac_etype(struct ocelot_ace_rule *ace)
 static bool ocelot_exclusive_mac_etype_ace_rules(struct ocelot *ocelot,
 						 struct ocelot_ace_rule *ace)
 {
-	struct ocelot_acl_block *block = &ocelot->acl_block;
+	struct ocelot_acl_block *block = &ocelot->acl_block[VCAP_IS2];
 	struct ocelot_ace_rule *tmp;
 	unsigned long port;
 	int i;
@@ -824,15 +839,16 @@ static bool ocelot_exclusive_mac_etype_ace_rules(struct ocelot *ocelot,
 	return true;
 }
 
-int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
+int ocelot_ace_rule_offload_add(struct ocelot *ocelot, int block_id,
 				struct ocelot_ace_rule *rule,
 				struct netlink_ext_ack *extack)
 {
-	struct ocelot_acl_block *block = &ocelot->acl_block;
+	struct ocelot_acl_block *block = &ocelot->acl_block[block_id];
 	struct ocelot_ace_rule *ace;
 	int i, index;
 
-	if (!ocelot_exclusive_mac_etype_ace_rules(ocelot, rule)) {
+	if (block_id == VCAP_IS2 &&
+	    !ocelot_exclusive_mac_etype_ace_rules(ocelot, rule)) {
 		NL_SET_ERR_MSG_MOD(extack,
 				   "Cannot mix MAC_ETYPE with non-MAC_ETYPE rules");
 		return -EBUSY;
@@ -847,11 +863,11 @@ int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
 	/* Move down the rules to make place for the new rule */
 	for (i = block->count - 1; i > index; i--) {
 		ace = ocelot_ace_rule_get_rule_index(block, i);
-		is2_entry_set(ocelot, i, ace);
+		vcap_entry_set(ocelot, i, ace, block_id);
 	}
 
 	/* Now insert the new rule */
-	is2_entry_set(ocelot, index, rule);
+	vcap_entry_set(ocelot, index, rule, block_id);
 	return 0;
 }
 
@@ -902,10 +918,10 @@ static void ocelot_ace_rule_del(struct ocelot *ocelot,
 	block->count--;
 }
 
-int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
+int ocelot_ace_rule_offload_del(struct ocelot *ocelot, int block_id,
 				struct ocelot_ace_rule *rule)
 {
-	struct ocelot_acl_block *block = &ocelot->acl_block;
+	struct ocelot_acl_block *block = &ocelot->acl_block[block_id];
 	struct ocelot_ace_rule del_ace;
 	struct ocelot_ace_rule *ace;
 	int i, index;
@@ -921,29 +937,29 @@ int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
 	/* Move up all the blocks over the deleted rule */
 	for (i = index; i < block->count; i++) {
 		ace = ocelot_ace_rule_get_rule_index(block, i);
-		is2_entry_set(ocelot, i, ace);
+		vcap_entry_set(ocelot, i, ace, block_id);
 	}
 
 	/* Now delete the last rule, because it is duplicated */
-	is2_entry_set(ocelot, block->count, &del_ace);
+	vcap_entry_set(ocelot, block->count, &del_ace, block_id);
 
 	return 0;
 }
 
-int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
+int ocelot_ace_rule_stats_update(struct ocelot *ocelot, int block_id,
 				 struct ocelot_ace_rule *rule)
 {
-	struct ocelot_acl_block *block = &ocelot->acl_block;
+	struct ocelot_acl_block *block = &ocelot->acl_block[block_id];
 	struct ocelot_ace_rule *tmp;
 	int index;
 
 	index = ocelot_ace_rule_get_index_id(block, rule);
-	vcap_entry_get(ocelot, rule, index);
+	vcap_entry_get(ocelot, rule, index, block_id);
 
 	/* After we get the result we need to clear the counters */
 	tmp = ocelot_ace_rule_get_rule_index(block, index);
 	tmp->stats.pkts = 0;
-	is2_entry_set(ocelot, index, tmp);
+	vcap_entry_set(ocelot, index, tmp, block_id);
 
 	return 0;
 }
@@ -968,7 +984,7 @@ static void vcap_init(struct ocelot *ocelot, const struct vcap_props *vcap)
 
 int ocelot_ace_init(struct ocelot *ocelot)
 {
-	struct ocelot_acl_block *block = &ocelot->acl_block;
+	struct ocelot_acl_block *block;
 
 	vcap_init(ocelot, &ocelot->vcap[VCAP_IS2]);
 
@@ -987,6 +1003,7 @@ int ocelot_ace_init(struct ocelot *ocelot)
 	ocelot_write_gix(ocelot, 0x3fffff, ANA_POL_CIR_STATE,
 			 OCELOT_POLICER_DISCARD);
 
+	block = &ocelot->acl_block[VCAP_IS2];
 	block->pol_lpr = OCELOT_POLICER_DISCARD - 1;
 	INIT_LIST_HEAD(&block->rules);
 
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h
index 099e177f2617..a9fd99401a65 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.h
+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
@@ -175,6 +175,7 @@ struct ocelot_ace_frame_ipv6 {
 };
 
 enum ocelot_ace_action {
+	OCELOT_ACL_ACTION_NULL,
 	OCELOT_ACL_ACTION_DROP,
 	OCELOT_ACL_ACTION_TRAP,
 	OCELOT_ACL_ACTION_POLICE,
@@ -214,12 +215,12 @@ struct ocelot_ace_rule {
 	u32 pol_ix;
 };
 
-int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
+int ocelot_ace_rule_offload_add(struct ocelot *ocelot, int block_id,
 				struct ocelot_ace_rule *rule,
 				struct netlink_ext_ack *extack);
-int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
+int ocelot_ace_rule_offload_del(struct ocelot *ocelot, int block_id,
 				struct ocelot_ace_rule *rule);
-int ocelot_ace_rule_stats_update(struct ocelot *ocelot,
+int ocelot_ace_rule_stats_update(struct ocelot *ocelot, int block_id,
 				 struct ocelot_ace_rule *rule);
 
 int ocelot_ace_init(struct ocelot *ocelot);
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 891925f73cbc..a1f7b6b28170 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -9,13 +9,26 @@
 
 #include "ocelot_ace.h"
 
+static int ocelot_block_id_get(int chain, bool ingress)
+{
+	/* Select TCAM blocks by using chain index. Rules in chain 0 are
+	 * implemented on IS1, chain 1 are implemented on IS2, and egress
+	 * chain corresponds to ES0 block.
+	 */
+	if (ingress)
+		return chain ? VCAP_IS2 : VCAP_IS1;
+	else
+		return VCAP_ES0;
+}
+
 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
 				      struct ocelot_ace_rule *ace)
 {
+	struct netlink_ext_ack *extack = f->common.extack;
 	const struct flow_action_entry *a;
+	int i, allowed_chain = 0;
 	s64 burst;
 	u64 rate;
-	int i;
 
 	if (!flow_offload_has_one_action(&f->rule->action))
 		return -EOPNOTSUPP;
@@ -28,9 +41,11 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
 		switch (a->id) {
 		case FLOW_ACTION_DROP:
 			ace->action = OCELOT_ACL_ACTION_DROP;
+			allowed_chain = 1;
 			break;
 		case FLOW_ACTION_TRAP:
 			ace->action = OCELOT_ACL_ACTION_TRAP;
+			allowed_chain = 1;
 			break;
 		case FLOW_ACTION_POLICE:
 			ace->action = OCELOT_ACL_ACTION_POLICE;
@@ -38,10 +53,23 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
 			ace->pol.rate = div_u64(rate, 1000) * 8;
 			burst = rate * PSCHED_NS2TICKS(a->police.burst);
 			ace->pol.burst = div_u64(burst, PSCHED_TICKS_PER_SEC);
+			allowed_chain = 1;
+			break;
+		case FLOW_ACTION_GOTO:
+			if (a->chain_index != f->common.chain_index + 1) {
+				NL_SET_ERR_MSG_MOD(extack, "HW only support goto next chain\n");
+				return -EOPNOTSUPP;
+			}
+			ace->action = OCELOT_ACL_ACTION_NULL;
+			allowed_chain = f->common.chain_index;
 			break;
 		default:
 			return -EOPNOTSUPP;
 		}
+		if (f->common.chain_index != allowed_chain) {
+			NL_SET_ERR_MSG_MOD(extack, "Action is not supported on this chain\n");
+			return -EOPNOTSUPP;
+		}
 	}
 
 	return 0;
@@ -205,7 +233,7 @@ int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
 			      struct flow_cls_offload *f, bool ingress)
 {
 	struct ocelot_ace_rule *ace;
-	int ret;
+	int ret, block_id;
 
 	ace = ocelot_ace_rule_create(ocelot, port, f);
 	if (!ace)
@@ -216,8 +244,10 @@ int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
 		kfree(ace);
 		return ret;
 	}
+	block_id = ocelot_block_id_get(f->common.chain_index, ingress);
 
-	return ocelot_ace_rule_offload_add(ocelot, ace, f->common.extack);
+	return ocelot_ace_rule_offload_add(ocelot, block_id, ace,
+					   f->common.extack);
 }
 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
 
@@ -225,11 +255,13 @@ int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
 			      struct flow_cls_offload *f, bool ingress)
 {
 	struct ocelot_ace_rule ace;
+	int block_id;
 
 	ace.prio = f->common.prio;
 	ace.id = f->cookie;
+	block_id = ocelot_block_id_get(f->common.chain_index, ingress);
 
-	return ocelot_ace_rule_offload_del(ocelot, &ace);
+	return ocelot_ace_rule_offload_del(ocelot, block_id, &ace);
 }
 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
 
@@ -237,11 +269,13 @@ int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
 			    struct flow_cls_offload *f, bool ingress)
 {
 	struct ocelot_ace_rule ace;
-	int ret;
+	int ret, block_id;
 
 	ace.prio = f->common.prio;
 	ace.id = f->cookie;
-	ret = ocelot_ace_rule_stats_update(ocelot, &ace);
+	block_id = ocelot_block_id_get(f->common.chain_index, ingress);
+
+	ret = ocelot_ace_rule_stats_update(ocelot, block_id, &ace);
 	if (ret)
 		return ret;
 
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 91357b1c8f31..4b2320bdc036 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -540,7 +540,7 @@ struct ocelot {
 
 	struct list_head		multicast;
 
-	struct ocelot_acl_block		acl_block;
+	struct ocelot_acl_block		acl_block[3];
 
 	const struct vcap_props		*vcap;
 
diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h
index 26d9384b3657..495847a40490 100644
--- a/include/soc/mscc/ocelot_vcap.h
+++ b/include/soc/mscc/ocelot_vcap.h
@@ -14,9 +14,9 @@
  */
 
 enum {
-	/* VCAP_IS1, */
+	VCAP_IS1,
 	VCAP_IS2,
-	/* VCAP_ES0, */
+	VCAP_ES0,
 };
 
 struct vcap_props {
-- 
2.17.1


  parent reply	other threads:[~2020-06-02  5:24 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-02  5:18 [PATCH v2 net-next 00/10] net: ocelot: VCAP IS1 and ES0 support Xiaoliang Yang
2020-06-02  5:18 ` [PATCH v2 net-next 01/10] net: mscc: ocelot: introduce a new ocelot_target_{read,write} API Xiaoliang Yang
2020-06-02  5:18 ` [PATCH v2 net-next 02/10] net: mscc: ocelot: generalize existing code for VCAP Xiaoliang Yang
2020-06-02  5:18 ` Xiaoliang Yang [this message]
2020-06-02  8:36   ` [PATCH v2 net-next 03/10] net: mscc: ocelot: allocated rules to different hardware VCAP TCAMs by chain index Allan W. Nielsen
2020-06-03 10:04     ` Vladimir Oltean
2020-06-08 13:56       ` Allan W. Nielsen
2020-06-09 12:55         ` Vladimir Oltean
2020-06-10 18:18           ` Allan W. Nielsen
2020-07-16  6:49             ` [EXT] " Xiaoliang Yang
2020-07-16  8:50               ` Joergen Andreasen
2020-07-16 10:37                 ` Xiaoliang Yang
2020-07-16 14:45                   ` Vladimir Oltean
2020-07-17  7:34                     ` Joergen Andreasen
2020-07-17  9:08                       ` Vladimir Oltean
2020-07-17 19:10                         ` Allan W. Nielsen
2020-07-20 11:04                           ` Xiaoliang Yang
2020-06-02  5:18 ` [PATCH v2 net-next 04/10] net: mscc: ocelot: change vcap to be compatible with full and quad entry Xiaoliang Yang
2020-06-02  5:18 ` [PATCH v2 net-next 05/10] net: mscc: ocelot: VCAP IS1 support Xiaoliang Yang
2020-06-02 11:46   ` kbuild test robot
2020-06-02 16:16   ` Jakub Kicinski
2020-06-02  5:18 ` [PATCH v2 net-next 06/10] net: mscc: ocelot: VCAP ES0 support Xiaoliang Yang
2020-06-02 16:17   ` Jakub Kicinski
2020-06-02  5:18 ` [PATCH v2 net-next 07/10] net: mscc: ocelot: multiple actions support Xiaoliang Yang
2020-06-02  5:18 ` [PATCH v2 net-next 08/10] net: ocelot: return error if rule is not found Xiaoliang Yang
2020-06-02  5:18 ` [PATCH v2 net-next 09/10] net: dsa: felix: correct VCAP IS2 keys offset Xiaoliang Yang
2020-06-02  5:18 ` [PATCH v2 net-next 10/10] net: dsa: tag_ocelot: use VLAN information from tagging header when available Xiaoliang Yang
2020-06-02  8:03 ` [PATCH v2 net-next 00/10] net: ocelot: VCAP IS1 and ES0 support Vladimir Oltean
2020-06-02  8:49   ` [EXT] " Xiaoliang Yang
2020-06-09 11:35     ` Vladimir Oltean

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200602051828.5734-4-xiaoliang.yang_1@nxp.com \
    --to=xiaoliang.yang_1@nxp.com \
    --cc=UNGLinuxDriver@microchip.com \
    --cc=alexandre.belloni@bootlin.com \
    --cc=alexandru.marginean@nxp.com \
    --cc=allan.nielsen@microchip.com \
    --cc=andrew@lunn.ch \
    --cc=claudiu.manoil@nxp.com \
    --cc=davem@davemloft.net \
    --cc=f.fainelli@gmail.com \
    --cc=horatiu.vultur@microchip.com \
    --cc=idosch@idosch.org \
    --cc=jiri@resnulli.us \
    --cc=joergen.andreasen@microchip.com \
    --cc=kuba@kernel.org \
    --cc=leoyang.li@nxp.com \
    --cc=linux-devel@linux.nxdi.nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingkai.hu@nxp.com \
    --cc=netdev@vger.kernel.org \
    --cc=nikolay@cumulusnetworks.com \
    --cc=po.liu@nxp.com \
    --cc=roopa@cumulusnetworks.com \
    --cc=vinicius.gomes@intel.com \
    --cc=vivien.didelot@gmail.com \
    --cc=vladimir.oltean@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.