summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mscc/ocelot_vcap.c
diff options
context:
space:
mode:
authorVladimir Oltean <vladimir.oltean@nxp.com>2020-10-02 15:02:20 +0300
committerDavid S. Miller <davem@davemloft.net>2020-10-02 15:40:29 -0700
commitea9d1f30b128c2bc5f429b3bd822b45ac9bf5114 (patch)
treea10872bda9d630a668aed69468adcf46a4248cb9 /drivers/net/ethernet/mscc/ocelot_vcap.c
parent26d0a8edca2886ed82838510bf44b6b68613641c (diff)
net: mscc: ocelot: offload multiple tc-flower actions in same rule
At this stage, the tc-flower offload of mscc_ocelot can only delegate rules to the VCAP IS2 security enforcement block. These rules have, in hardware, separate bits for policing and for overriding the destination port mask and/or copying to the CPU. So it makes sense that we attempt to expose some more of that low-level complexity instead of simply choosing between a single type of action. Something similar happens with the VCAP IS1 block, where the same action can contain enable bits for VLAN classification and for QoS classification at the same time. So model the action structure after the hardware description, and let the high-level ocelot_flower.c construct an action vector from multiple tc actions. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mscc/ocelot_vcap.c')
-rw-r--r--drivers/net/ethernet/mscc/ocelot_vcap.c59
1 files changed, 19 insertions, 40 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c
index 75eca3457e6e..1d880045786c 100644
--- a/drivers/net/ethernet/mscc/ocelot_vcap.c
+++ b/drivers/net/ethernet/mscc/ocelot_vcap.c
@@ -10,7 +10,6 @@
#include "ocelot_police.h"
#include "ocelot_vcap.h"
-#define OCELOT_POLICER_DISCARD 0x17f
#define ENTRY_WIDTH 32
enum vcap_sel {
@@ -332,35 +331,14 @@ static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data,
struct ocelot_vcap_filter *filter)
{
const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];
-
- switch (filter->action) {
- case OCELOT_VCAP_ACTION_DROP:
- vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX,
- OCELOT_POLICER_DISCARD);
- 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;
- case OCELOT_VCAP_ACTION_TRAP:
- vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 1);
- break;
- case OCELOT_VCAP_ACTION_POLICE:
- vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 0);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 1);
- vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX,
- filter->pol_ix);
- 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;
- }
+ struct ocelot_vcap_action *a = &filter->action;
+
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, a->mask_mode);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, a->port_mask);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, a->police_ena);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX, a->pol_ix);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, a->cpu_qu_num);
+ vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, a->cpu_copy_ena);
}
static void is2_entry_set(struct ocelot *ocelot, int ix,
@@ -710,11 +688,11 @@ static void ocelot_vcap_policer_del(struct ocelot *ocelot,
list_for_each_entry(filter, &block->rules, list) {
index++;
- if (filter->action == OCELOT_VCAP_ACTION_POLICE &&
- filter->pol_ix < pol_ix) {
- filter->pol_ix += 1;
- ocelot_vcap_policer_add(ocelot, filter->pol_ix,
- &filter->pol);
+ if (filter->action.police_ena &&
+ filter->action.pol_ix < pol_ix) {
+ filter->action.pol_ix += 1;
+ ocelot_vcap_policer_add(ocelot, filter->action.pol_ix,
+ &filter->action.pol);
is2_entry_set(ocelot, index, filter);
}
}
@@ -732,10 +710,11 @@ static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot,
struct ocelot_vcap_filter *tmp;
struct list_head *pos, *n;
- if (filter->action == OCELOT_VCAP_ACTION_POLICE) {
+ if (filter->action.police_ena) {
block->pol_lpr--;
- filter->pol_ix = block->pol_lpr;
- ocelot_vcap_policer_add(ocelot, filter->pol_ix, &filter->pol);
+ filter->action.pol_ix = block->pol_lpr;
+ ocelot_vcap_policer_add(ocelot, filter->action.pol_ix,
+ &filter->action.pol);
}
block->count++;
@@ -947,9 +926,9 @@ static void ocelot_vcap_block_remove_filter(struct ocelot *ocelot,
list_for_each_safe(pos, q, &block->rules) {
tmp = list_entry(pos, struct ocelot_vcap_filter, list);
if (tmp->id == filter->id) {
- if (tmp->action == OCELOT_VCAP_ACTION_POLICE)
+ if (tmp->action.police_ena)
ocelot_vcap_policer_del(ocelot, block,
- tmp->pol_ix);
+ tmp->action.pol_ix);
list_del(pos);
kfree(tmp);