Commit c9a7fe12 authored by Xiaoliang Yang's avatar Xiaoliang Yang Committed by David S. Miller
Browse files

net: mscc: ocelot: add action of police on vcap_is2



Ocelot has 384 policers that can be allocated to ingress ports,
QoS classes per port, and VCAP IS2 entries. ocelot_police.c
supports to set policers which can be allocated to police action
of VCAP IS2. We allocate policers from maximum pol_id, and
decrease the pol_id when add a new vcap_is2 entry which is
police action.

Signed-off-by: default avatarXiaoliang Yang <xiaoliang.yang_1@nxp.com>
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0d5d6045
Loading
Loading
Loading
Loading
+57 −7
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/proc_fs.h>

#include <soc/mscc/ocelot_vcap.h>
#include "ocelot_police.h"
#include "ocelot_ace.h"
#include "ocelot_s2.h"

@@ -299,9 +300,9 @@ static void vcap_action_set(struct ocelot *ocelot, struct vcap_data *data,
}

static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data,
			   enum ocelot_ace_action action)
			   struct ocelot_ace_rule *ace)
{
	switch (action) {
	switch (ace->action) {
	case OCELOT_ACL_ACTION_DROP:
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_PORT_MASK, 0);
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_MASK_MODE, 1);
@@ -319,6 +320,15 @@ static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data,
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_COPY_ENA, 1);
		break;
	case OCELOT_ACL_ACTION_POLICE:
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_PORT_MASK, 0);
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_MASK_MODE, 0);
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_ENA, 1);
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_IDX,
				ace->pol_ix);
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
		vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
		break;
	}
}

@@ -611,7 +621,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
	}

	vcap_key_set(ocelot, &data, VCAP_IS2_TYPE, type, type_mask);
	is2_action_set(ocelot, &data, ace->action);
	is2_action_set(ocelot, &data, ace);
	vcap_data_set(data.counter, data.counter_offset,
		      vcap_is2->counter_width, ace->stats.pkts);

@@ -639,12 +649,19 @@ static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule,
	rule->stats.pkts = cnt;
}

static void ocelot_ace_rule_add(struct ocelot_acl_block *block,
static void ocelot_ace_rule_add(struct ocelot *ocelot,
				struct ocelot_acl_block *block,
				struct ocelot_ace_rule *rule)
{
	struct ocelot_ace_rule *tmp;
	struct list_head *pos, *n;

	if (rule->action == OCELOT_ACL_ACTION_POLICE) {
		block->pol_lpr--;
		rule->pol_ix = block->pol_lpr;
		ocelot_ace_policer_add(ocelot, rule->pol_ix, &rule->pol);
	}

	block->count++;

	if (list_empty(&block->rules)) {
@@ -697,7 +714,7 @@ int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
	int i, index;

	/* Add rule to the linked list */
	ocelot_ace_rule_add(block, rule);
	ocelot_ace_rule_add(ocelot, block, rule);

	/* Get the index of the inserted rule */
	index = ocelot_ace_rule_get_index_id(block, rule);
@@ -713,7 +730,33 @@ int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
	return 0;
}

static void ocelot_ace_rule_del(struct ocelot_acl_block *block,
static void ocelot_ace_police_del(struct ocelot *ocelot,
				  struct ocelot_acl_block *block,
				  u32 ix)
{
	struct ocelot_ace_rule *ace;
	int index = -1;

	if (ix < block->pol_lpr)
		return;

	list_for_each_entry(ace, &block->rules, list) {
		index++;
		if (ace->action == OCELOT_ACL_ACTION_POLICE &&
		    ace->pol_ix < ix) {
			ace->pol_ix += 1;
			ocelot_ace_policer_add(ocelot, ace->pol_ix,
					       &ace->pol);
			is2_entry_set(ocelot, index, ace);
		}
	}

	ocelot_ace_policer_del(ocelot, block->pol_lpr);
	block->pol_lpr++;
}

static void ocelot_ace_rule_del(struct ocelot *ocelot,
				struct ocelot_acl_block *block,
				struct ocelot_ace_rule *rule)
{
	struct ocelot_ace_rule *tmp;
@@ -722,6 +765,10 @@ static void ocelot_ace_rule_del(struct ocelot_acl_block *block,
	list_for_each_safe(pos, q, &block->rules) {
		tmp = list_entry(pos, struct ocelot_ace_rule, list);
		if (tmp->id == rule->id) {
			if (tmp->action == OCELOT_ACL_ACTION_POLICE)
				ocelot_ace_police_del(ocelot, block,
						      tmp->pol_ix);

			list_del(pos);
			kfree(tmp);
		}
@@ -744,7 +791,7 @@ int ocelot_ace_rule_offload_del(struct ocelot *ocelot,
	index = ocelot_ace_rule_get_index_id(block, rule);

	/* Delete rule */
	ocelot_ace_rule_del(block, rule);
	ocelot_ace_rule_del(ocelot, block, rule);

	/* Move up all the blocks over the deleted rule */
	for (i = index; i < block->count; i++) {
@@ -779,6 +826,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 ocelot_acl_block *block = &ocelot->acl_block;
	struct vcap_data data;

	memset(&data, 0, sizeof(data));
@@ -807,6 +855,8 @@ int ocelot_ace_init(struct ocelot *ocelot)
	ocelot_write_gix(ocelot, 0x3fffff, ANA_POL_CIR_STATE,
			 OCELOT_POLICER_DISCARD);

	block->pol_lpr = OCELOT_POLICER_DISCARD - 1;

	INIT_LIST_HEAD(&ocelot->acl_block.rules);

	return 0;
+4 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#define _MSCC_OCELOT_ACE_H_

#include "ocelot.h"
#include "ocelot_police.h"
#include <net/sch_generic.h>
#include <net/pkt_cls.h>

@@ -176,6 +177,7 @@ struct ocelot_ace_frame_ipv6 {
enum ocelot_ace_action {
	OCELOT_ACL_ACTION_DROP,
	OCELOT_ACL_ACTION_TRAP,
	OCELOT_ACL_ACTION_POLICE,
};

struct ocelot_ace_stats {
@@ -208,6 +210,8 @@ struct ocelot_ace_rule {
		struct ocelot_ace_frame_ipv4 ipv4;
		struct ocelot_ace_frame_ipv6 ipv6;
	} frame;
	struct ocelot_policer pol;
	u32 pol_ix;
};

int ocelot_ace_rule_offload_add(struct ocelot *ocelot,
+9 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
				      struct ocelot_ace_rule *ace)
{
	const struct flow_action_entry *a;
	s64 burst;
	u64 rate;
	int i;

	if (!flow_offload_has_one_action(&f->rule->action))
@@ -29,6 +31,13 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f,
		case FLOW_ACTION_TRAP:
			ace->action = OCELOT_ACL_ACTION_TRAP;
			break;
		case FLOW_ACTION_POLICE:
			ace->action = OCELOT_ACL_ACTION_POLICE;
			rate = a->police.rate_bytes_ps;
			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);
			break;
		default:
			return -EOPNOTSUPP;
		}
+24 −0
Original line number Diff line number Diff line
@@ -225,3 +225,27 @@ int ocelot_port_policer_del(struct ocelot *ocelot, int port)

	return 0;
}

int ocelot_ace_policer_add(struct ocelot *ocelot, u32 pol_ix,
			   struct ocelot_policer *pol)
{
	struct qos_policer_conf pp = { 0 };

	if (!pol)
		return -EINVAL;

	pp.mode = MSCC_QOS_RATE_MODE_DATA;
	pp.pir = pol->rate;
	pp.pbs = pol->burst;

	return qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
}

int ocelot_ace_policer_del(struct ocelot *ocelot, u32 pol_ix)
{
	struct qos_policer_conf pp = { 0 };

	pp.mode = MSCC_QOS_RATE_MODE_DISABLED;

	return qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
}
+5 −0
Original line number Diff line number Diff line
@@ -19,4 +19,9 @@ int ocelot_port_policer_add(struct ocelot *ocelot, int port,

int ocelot_port_policer_del(struct ocelot *ocelot, int port);

int ocelot_ace_policer_add(struct ocelot *ocelot, u32 pol_ix,
			   struct ocelot_policer *pol);

int ocelot_ace_policer_del(struct ocelot *ocelot, u32 pol_ix);

#endif /* _MSCC_OCELOT_POLICE_H_ */
Loading