diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index 0988bc9aaac5..00b02b76164e 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -15,9 +15,6 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f, u64 rate; int i; - if (!flow_offload_has_one_action(&f->rule->action)) - return -EOPNOTSUPP; - if (!flow_action_basic_hw_stats_check(&f->rule->action, f->common.extack)) return -EOPNOTSUPP; @@ -25,16 +22,22 @@ 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: - filter->action = OCELOT_VCAP_ACTION_DROP; + filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; + filter->action.port_mask = 0; + filter->action.police_ena = true; + filter->action.pol_ix = OCELOT_POLICER_DISCARD; break; case FLOW_ACTION_TRAP: - filter->action = OCELOT_VCAP_ACTION_TRAP; + filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; + filter->action.port_mask = 0; + filter->action.cpu_copy_ena = true; + filter->action.cpu_qu_num = 0; break; case FLOW_ACTION_POLICE: - filter->action = OCELOT_VCAP_ACTION_POLICE; + filter->action.police_ena = true; rate = a->police.rate_bytes_ps; - filter->pol.rate = div_u64(rate, 1000) * 8; - filter->pol.burst = a->police.burst; + filter->action.pol.rate = div_u64(rate, 1000) * 8; + filter->action.pol.burst = a->police.burst; break; default: return -EOPNOTSUPP; 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]; + struct ocelot_vcap_action *a = &filter->action; - 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; - } + 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); diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h index 7db6da6e35b9..70d4f7131fde 100644 --- a/drivers/net/ethernet/mscc/ocelot_vcap.h +++ b/drivers/net/ethernet/mscc/ocelot_vcap.h @@ -11,6 +11,8 @@ #include #include +#define OCELOT_POLICER_DISCARD 0x17f + struct ocelot_ipv4 { u8 addr[4]; }; @@ -174,10 +176,26 @@ struct ocelot_vcap_key_ipv6 { enum ocelot_vcap_bit seq_zero; /* TCP sequence number is zero */ }; -enum ocelot_vcap_action { - OCELOT_VCAP_ACTION_DROP, - OCELOT_VCAP_ACTION_TRAP, - OCELOT_VCAP_ACTION_POLICE, +enum ocelot_mask_mode { + OCELOT_MASK_MODE_NONE, + OCELOT_MASK_MODE_PERMIT_DENY, + OCELOT_MASK_MODE_POLICY, + OCELOT_MASK_MODE_REDIRECT, +}; + +struct ocelot_vcap_action { + union { + /* VCAP IS2 */ + struct { + bool cpu_copy_ena; + u8 cpu_qu_num; + enum ocelot_mask_mode mask_mode; + unsigned long port_mask; + bool police_ena; + struct ocelot_policer pol; + u32 pol_ix; + }; + }; }; struct ocelot_vcap_stats { @@ -192,7 +210,7 @@ struct ocelot_vcap_filter { u16 prio; u32 id; - enum ocelot_vcap_action action; + struct ocelot_vcap_action action; struct ocelot_vcap_stats stats; unsigned long ingress_port_mask; @@ -210,8 +228,6 @@ struct ocelot_vcap_filter { struct ocelot_vcap_key_ipv4 ipv4; struct ocelot_vcap_key_ipv6 ipv6; } key; - struct ocelot_policer pol; - u32 pol_ix; }; int ocelot_vcap_filter_add(struct ocelot *ocelot,