Commit b0be25c5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-mvpp2-Classifier-updates-and-cleanups'



Maxime Chevallier says:

====================
net: mvpp2: Classifier updates and cleanups

In preparation for the future addition of classification offload
support, this series cleans-up the current code dealing with the
classification engines.

As of today, the classification code only deals with RSS, which is a
very narrow use-case when considering all of the classifier's features.

This lead to design and naming decisions that don't really stand when
considering using more classification features.

This series therefore includes quite a lot a renaming of functions and
macros, and tries to make the naming schemes more consistent and the
code more readable.

The debugfs interface that allows reading the various Parsing and
Classification engines has been cleaned-up and made more generic,
allowing to read the Flow Table and C2 engine hit counters on a
per-entry basis.

The Classifier itself has been made more robust by introducing the
lu_type field in classification lookups, that prevents false-positive
matches in the future. We also initialise the various engine in a more
extensive and less error-prone way by assining default values to all
entries in the C2 and Flow table.

This is a pretty big series considering it's mostly cleanup, but my goal
is to make the future series that will contain new big features easier
to review, focusing on the real logic.

Besides the debugfs interface, this series doesn't intend to introduce any
new features or change in behaviours.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5133a4a8 c2d3d8ee
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@
#define MVPP2_CLS_FLOW_TBL1_REG			0x1828
#define     MVPP2_CLS_FLOW_TBL1_N_FIELDS_MASK	0x7
#define     MVPP2_CLS_FLOW_TBL1_N_FIELDS(x)	(x)
#define     MVPP2_CLS_FLOW_TBL1_LU_TYPE(lu)	(((lu) & 0x3f) << 3)
#define     MVPP2_CLS_FLOW_TBL1_PRIO_MASK	0x3f
#define     MVPP2_CLS_FLOW_TBL1_PRIO(x)		((x) << 9)
#define     MVPP2_CLS_FLOW_TBL1_SEQ_MASK	0x7
@@ -123,7 +124,10 @@
#define MVPP22_CLS_C2_TCAM_DATA2		0x1b18
#define MVPP22_CLS_C2_TCAM_DATA3		0x1b1c
#define MVPP22_CLS_C2_TCAM_DATA4		0x1b20
#define     MVPP22_CLS_C2_LU_TYPE(lu)		((lu) & 0x3f)
#define     MVPP22_CLS_C2_PORT_ID(port)		((port) << 8)
#define MVPP22_CLS_C2_TCAM_INV			0x1b24
#define     MVPP22_CLS_C2_TCAM_INV_BIT		BIT(31)
#define MVPP22_CLS_C2_HIT_CTR			0x1b50
#define MVPP22_CLS_C2_ACT			0x1b60
#define     MVPP22_CLS_C2_ACT_RSS_EN(act)	(((act) & 0x3) << 19)
@@ -610,6 +614,8 @@
#define MVPP2_BIT_TO_WORD(bit)		((bit) / 32)
#define MVPP2_BIT_IN_WORD(bit)		((bit) % 32)

#define MVPP2_N_PRS_FLOWS		52

/* RSS constants */
#define MVPP22_RSS_TABLE_ENTRIES	32

@@ -710,6 +716,7 @@ enum mvpp2_prs_l3_cast {
#define MVPP2_DESC_DMA_MASK	DMA_BIT_MASK(40)

/* Definitions */
struct mvpp2_dbgfs_entries;

/* Shared Packet Processor resources */
struct mvpp2 {
@@ -771,6 +778,9 @@ struct mvpp2 {

	/* Debugfs root entry */
	struct dentry *dbgfs_dir;

	/* Debugfs entries private data */
	struct mvpp2_dbgfs_entries *dbgfs_entries;
};

struct mvpp2_pcpu_stats {
+122 −90
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@
	}							\
}

static struct mvpp2_cls_flow cls_flows[MVPP2_N_FLOWS] = {
static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = {
	/* TCP over IPv4 flows, Not fragmented, no vlan tag */
	MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_NF_UNTAG,
		       MVPP22_CLS_HEK_IP4_5T,
@@ -429,12 +429,6 @@ static void mvpp2_cls_flow_port_id_sel(struct mvpp2_cls_flow_entry *fe,
		fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_PORT_ID_SEL;
}

static void mvpp2_cls_flow_seq_set(struct mvpp2_cls_flow_entry *fe, u32 seq)
{
	fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_SEQ(MVPP2_CLS_FLOW_TBL1_SEQ_MASK);
	fe->data[1] |= MVPP2_CLS_FLOW_TBL1_SEQ(seq);
}

static void mvpp2_cls_flow_last_set(struct mvpp2_cls_flow_entry *fe,
				    bool is_last)
{
@@ -454,9 +448,16 @@ static void mvpp2_cls_flow_port_add(struct mvpp2_cls_flow_entry *fe,
	fe->data[0] |= MVPP2_CLS_FLOW_TBL0_PORT_ID(port);
}

static void mvpp2_cls_flow_lu_type_set(struct mvpp2_cls_flow_entry *fe,
				       u8 lu_type)
{
	fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK);
	fe->data[1] |= MVPP2_CLS_FLOW_TBL1_LU_TYPE(lu_type);
}

/* Initialize the parser entry for the given flow */
static void mvpp2_cls_flow_prs_init(struct mvpp2 *priv,
				    struct mvpp2_cls_flow *flow)
				    const struct mvpp2_cls_flow *flow)
{
	mvpp2_prs_add_flow(priv, flow->flow_id, flow->prs_ri.ri,
			   flow->prs_ri.ri_mask);
@@ -464,7 +465,7 @@ static void mvpp2_cls_flow_prs_init(struct mvpp2 *priv,

/* Initialize the Lookup Id table entry for the given flow */
static void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv,
				    struct mvpp2_cls_flow *flow)
				    const struct mvpp2_cls_flow *flow)
{
	struct mvpp2_cls_lookup_entry le;

@@ -477,7 +478,7 @@ static void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv,
	/* We point on the first lookup in the sequence for the flow, that is
	 * the C2 lookup.
	 */
	le.data |= MVPP2_CLS_LKP_FLOW_PTR(MVPP2_FLOW_C2_ENTRY(flow->flow_id));
	le.data |= MVPP2_CLS_LKP_FLOW_PTR(MVPP2_CLS_FLT_FIRST(flow->flow_id));

	/* CLS is always enabled, RSS is enabled/disabled in C2 lookup */
	le.data |= MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
@@ -485,21 +486,86 @@ static void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv,
	mvpp2_cls_lookup_write(priv, &le);
}

static void mvpp2_cls_c2_write(struct mvpp2 *priv,
			       struct mvpp2_cls_c2_entry *c2)
{
	u32 val;
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2->index);

	val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV);
	if (c2->valid)
		val &= ~MVPP22_CLS_C2_TCAM_INV_BIT;
	else
		val |= MVPP22_CLS_C2_TCAM_INV_BIT;
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_INV, val);

	mvpp2_write(priv, MVPP22_CLS_C2_ACT, c2->act);

	mvpp2_write(priv, MVPP22_CLS_C2_ATTR0, c2->attr[0]);
	mvpp2_write(priv, MVPP22_CLS_C2_ATTR1, c2->attr[1]);
	mvpp2_write(priv, MVPP22_CLS_C2_ATTR2, c2->attr[2]);
	mvpp2_write(priv, MVPP22_CLS_C2_ATTR3, c2->attr[3]);

	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA0, c2->tcam[0]);
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA1, c2->tcam[1]);
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA2, c2->tcam[2]);
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA3, c2->tcam[3]);
	/* Writing TCAM_DATA4 flushes writes to TCAM_DATA0-4 and INV to HW */
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA4, c2->tcam[4]);
}

void mvpp2_cls_c2_read(struct mvpp2 *priv, int index,
		       struct mvpp2_cls_c2_entry *c2)
{
	u32 val;
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, index);

	c2->index = index;

	c2->tcam[0] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA0);
	c2->tcam[1] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA1);
	c2->tcam[2] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA2);
	c2->tcam[3] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA3);
	c2->tcam[4] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA4);

	c2->act = mvpp2_read(priv, MVPP22_CLS_C2_ACT);

	c2->attr[0] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR0);
	c2->attr[1] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR1);
	c2->attr[2] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR2);
	c2->attr[3] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR3);

	val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV);
	c2->valid = !(val & MVPP22_CLS_C2_TCAM_INV_BIT);
}

/* Initialize the flow table entries for the given flow */
static void mvpp2_cls_flow_init(struct mvpp2 *priv, struct mvpp2_cls_flow *flow)
static void mvpp2_cls_flow_init(struct mvpp2 *priv,
				const struct mvpp2_cls_flow *flow)
{
	struct mvpp2_cls_flow_entry fe;
	int i;
	int i, pri = 0;

	/* C2 lookup */
	/* Assign default values to all entries in the flow */
	for (i = MVPP2_CLS_FLT_FIRST(flow->flow_id);
	     i <= MVPP2_CLS_FLT_LAST(flow->flow_id); i++) {
		memset(&fe, 0, sizeof(fe));
	fe.index = MVPP2_FLOW_C2_ENTRY(flow->flow_id);
		fe.index = i;
		mvpp2_cls_flow_pri_set(&fe, pri++);

		if (i == MVPP2_CLS_FLT_LAST(flow->flow_id))
			mvpp2_cls_flow_last_set(&fe, 1);

		mvpp2_cls_flow_write(priv, &fe);
	}

	/* RSS config C2 lookup */
	mvpp2_cls_flow_read(priv, MVPP2_CLS_FLT_C2_RSS_ENTRY(flow->flow_id),
			    &fe);

	mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C2);
	mvpp2_cls_flow_port_id_sel(&fe, true);
	mvpp2_cls_flow_last_set(&fe, 0);
	mvpp2_cls_flow_pri_set(&fe, 0);
	mvpp2_cls_flow_seq_set(&fe, MVPP2_CLS_FLOW_SEQ_FIRST1);
	mvpp2_cls_flow_lu_type_set(&fe, MVPP2_CLS_LU_ALL);

	/* Add all ports */
	for (i = 0; i < MVPP2_MAX_PORTS; i++)
@@ -509,22 +575,19 @@ static void mvpp2_cls_flow_init(struct mvpp2 *priv, struct mvpp2_cls_flow *flow)

	/* C3Hx lookups */
	for (i = 0; i < MVPP2_MAX_PORTS; i++) {
		memset(&fe, 0, sizeof(fe));
		fe.index = MVPP2_PORT_FLOW_HASH_ENTRY(i, flow->flow_id);
		mvpp2_cls_flow_read(priv,
				    MVPP2_CLS_FLT_HASH_ENTRY(i, flow->flow_id),
				    &fe);

		/* Set a default engine. Will be overwritten when setting the
		 * real HEK parameters
		 */
		mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C3HA);
		mvpp2_cls_flow_port_id_sel(&fe, true);
		mvpp2_cls_flow_pri_set(&fe, i + 1);
		mvpp2_cls_flow_seq_set(&fe, MVPP2_CLS_FLOW_SEQ_MIDDLE);
		mvpp2_cls_flow_port_add(&fe, BIT(i));

		mvpp2_cls_flow_write(priv, &fe);
	}

	/* Update the last entry */
	mvpp2_cls_flow_last_set(&fe, 1);
	mvpp2_cls_flow_seq_set(&fe, MVPP2_CLS_FLOW_SEQ_LAST);

	mvpp2_cls_flow_write(priv, &fe);
}

/* Adds a field to the Header Extracted Key generation parameters*/
@@ -555,6 +618,9 @@ static int mvpp2_flow_set_hek_fields(struct mvpp2_cls_flow_entry *fe,

	for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) {
		switch (BIT(i)) {
		case MVPP22_CLS_HEK_OPT_MAC_DA:
			field_id = MVPP22_CLS_FIELD_MAC_DA;
			break;
		case MVPP22_CLS_HEK_OPT_VLAN:
			field_id = MVPP22_CLS_FIELD_VLAN;
			break;
@@ -586,9 +652,9 @@ static int mvpp2_flow_set_hek_fields(struct mvpp2_cls_flow_entry *fe,
	return 0;
}

struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow)
const struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow)
{
	if (flow >= MVPP2_N_FLOWS)
	if (flow >= MVPP2_N_PRS_FLOWS)
		return NULL;

	return &cls_flows[flow];
@@ -608,21 +674,17 @@ struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow)
static int mvpp2_port_rss_hash_opts_set(struct mvpp2_port *port, int flow_type,
					u16 requested_opts)
{
	const struct mvpp2_cls_flow *flow;
	struct mvpp2_cls_flow_entry fe;
	struct mvpp2_cls_flow *flow;
	int i, engine, flow_index;
	u16 hash_opts;

	for (i = 0; i < MVPP2_N_FLOWS; i++) {
	for_each_cls_flow_id_with_type(i, flow_type) {
		flow = mvpp2_cls_flow_get(i);
		if (!flow)
			return -EINVAL;

		if (flow->flow_type != flow_type)
			continue;

		flow_index = MVPP2_PORT_FLOW_HASH_ENTRY(port->id,
							flow->flow_id);
		flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id);

		mvpp2_cls_flow_read(port->priv, flow_index, &fe);

@@ -697,21 +759,17 @@ u16 mvpp2_flow_get_hek_fields(struct mvpp2_cls_flow_entry *fe)
 */
static u16 mvpp2_port_rss_hash_opts_get(struct mvpp2_port *port, int flow_type)
{
	const struct mvpp2_cls_flow *flow;
	struct mvpp2_cls_flow_entry fe;
	struct mvpp2_cls_flow *flow;
	int i, flow_index;
	u16 hash_opts = 0;

	for (i = 0; i < MVPP2_N_FLOWS; i++) {
	for_each_cls_flow_id_with_type(i, flow_type) {
		flow = mvpp2_cls_flow_get(i);
		if (!flow)
			return 0;

		if (flow->flow_type != flow_type)
			continue;

		flow_index = MVPP2_PORT_FLOW_HASH_ENTRY(port->id,
							flow->flow_id);
		flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id);

		mvpp2_cls_flow_read(port->priv, flow_index, &fe);

@@ -723,10 +781,10 @@ static u16 mvpp2_port_rss_hash_opts_get(struct mvpp2_port *port, int flow_type)

static void mvpp2_cls_port_init_flows(struct mvpp2 *priv)
{
	struct mvpp2_cls_flow *flow;
	const struct mvpp2_cls_flow *flow;
	int i;

	for (i = 0; i < MVPP2_N_FLOWS; i++) {
	for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) {
		flow = mvpp2_cls_flow_get(i);
		if (!flow)
			break;
@@ -737,47 +795,6 @@ static void mvpp2_cls_port_init_flows(struct mvpp2 *priv)
	}
}

static void mvpp2_cls_c2_write(struct mvpp2 *priv,
			       struct mvpp2_cls_c2_entry *c2)
{
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2->index);

	/* Write TCAM */
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA0, c2->tcam[0]);
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA1, c2->tcam[1]);
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA2, c2->tcam[2]);
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA3, c2->tcam[3]);
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA4, c2->tcam[4]);

	mvpp2_write(priv, MVPP22_CLS_C2_ACT, c2->act);

	mvpp2_write(priv, MVPP22_CLS_C2_ATTR0, c2->attr[0]);
	mvpp2_write(priv, MVPP22_CLS_C2_ATTR1, c2->attr[1]);
	mvpp2_write(priv, MVPP22_CLS_C2_ATTR2, c2->attr[2]);
	mvpp2_write(priv, MVPP22_CLS_C2_ATTR3, c2->attr[3]);
}

void mvpp2_cls_c2_read(struct mvpp2 *priv, int index,
		       struct mvpp2_cls_c2_entry *c2)
{
	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, index);

	c2->index = index;

	c2->tcam[0] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA0);
	c2->tcam[1] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA1);
	c2->tcam[2] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA2);
	c2->tcam[3] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA3);
	c2->tcam[4] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA4);

	c2->act = mvpp2_read(priv, MVPP22_CLS_C2_ACT);

	c2->attr[0] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR0);
	c2->attr[1] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR1);
	c2->attr[2] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR2);
	c2->attr[3] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR3);
}

static void mvpp2_port_c2_cls_init(struct mvpp2_port *port)
{
	struct mvpp2_cls_c2_entry c2;
@@ -791,6 +808,10 @@ static void mvpp2_port_c2_cls_init(struct mvpp2_port *port)
	c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap);
	c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap));

	/* Match on Lookup Type */
	c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK));
	c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_ALL);

	/* Update RSS status after matching this entry */
	c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK);

@@ -809,6 +830,8 @@ static void mvpp2_port_c2_cls_init(struct mvpp2_port *port)
	c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
		      MVPP22_CLS_C2_ATTR0_QLOW(ql);

	c2.valid = true;

	mvpp2_cls_c2_write(port->priv, &c2);
}

@@ -817,6 +840,7 @@ void mvpp2_cls_init(struct mvpp2 *priv)
{
	struct mvpp2_cls_lookup_entry le;
	struct mvpp2_cls_flow_entry fe;
	struct mvpp2_cls_c2_entry c2;
	int index;

	/* Enable classifier */
@@ -840,6 +864,14 @@ void mvpp2_cls_init(struct mvpp2 *priv)
		mvpp2_cls_lookup_write(priv, &le);
	}

	/* Clear C2 TCAM engine table */
	memset(&c2, 0, sizeof(c2));
	c2.valid = false;
	for (index = 0; index < MVPP22_CLS_C2_N_ENTRIES; index++) {
		c2.index = index;
		mvpp2_cls_c2_write(priv, &c2);
	}

	mvpp2_cls_port_init_flows(priv);
}

@@ -902,12 +934,12 @@ static void mvpp2_rss_port_c2_disable(struct mvpp2_port *port)
	mvpp2_cls_c2_write(port->priv, &c2);
}

void mvpp22_rss_enable(struct mvpp2_port *port)
void mvpp22_port_rss_enable(struct mvpp2_port *port)
{
	mvpp2_rss_port_c2_enable(port);
}

void mvpp22_rss_disable(struct mvpp2_port *port)
void mvpp22_port_rss_disable(struct mvpp2_port *port)
{
	mvpp2_rss_port_c2_disable(port);
}
@@ -1037,7 +1069,7 @@ int mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info)
	return 0;
}

void mvpp22_rss_port_init(struct mvpp2_port *port)
void mvpp22_port_rss_init(struct mvpp2_port *port)
{
	struct mvpp2 *priv = port->priv;
	int i;
+54 −38
Original line number Diff line number Diff line
@@ -71,14 +71,6 @@ enum mvpp2_cls_field_id {
	MVPP22_CLS_FIELD_L4DIP = 0x1e,
};

enum mvpp2_cls_flow_seq {
	MVPP2_CLS_FLOW_SEQ_NORMAL = 0,
	MVPP2_CLS_FLOW_SEQ_FIRST1,
	MVPP2_CLS_FLOW_SEQ_FIRST2,
	MVPP2_CLS_FLOW_SEQ_LAST,
	MVPP2_CLS_FLOW_SEQ_MIDDLE
};

/* Classifier C2 engine constants */
#define MVPP22_CLS_C2_TCAM_EN(data)		((data) << 16)

@@ -105,34 +97,25 @@ enum mvpp22_cls_c2_fwd_action {

struct mvpp2_cls_c2_entry {
	u32 index;
	/* TCAM lookup key */
	u32 tcam[MVPP2_CLS_C2_TCAM_WORDS];
	/* Actions to perform upon TCAM match */
	u32 act;
	/* Attributes relative to the actions to perform */
	u32 attr[MVPP2_CLS_C2_ATTR_WORDS];
	/* Entry validity */
	u8 valid;
};

/* Classifier C2 engine entries */
#define MVPP22_CLS_C2_RSS_ENTRY(port)	(port)
#define MVPP22_CLS_C2_N_ENTRIES		MVPP2_MAX_PORTS
#define MVPP22_CLS_C2_N_ENTRIES		256

/* RSS flow entries in the flow table. We have 2 entries per port for RSS.
 *
 * The first performs a lookup using the C2 TCAM engine, to tag the
 * packet for software forwarding (needed for RSS), enable or disable RSS, and
 * assign the default rx queue.
 *
 * The second configures the hash generation, by specifying which fields of the
 * packet header are used to generate the hash, and specifies the relevant hash
 * engine to use.
 */
#define MVPP22_RSS_FLOW_C2_OFFS		0
#define MVPP22_RSS_FLOW_HASH_OFFS	1
#define MVPP22_RSS_FLOW_SIZE		(MVPP22_RSS_FLOW_HASH_OFFS + 1)
/* Number of per-port dedicated entries in the C2 TCAM */
#define MVPP22_CLS_C2_PORT_RANGE	8

#define MVPP22_RSS_FLOW_C2(port)	((port) * MVPP22_RSS_FLOW_SIZE + \
					 MVPP22_RSS_FLOW_C2_OFFS)
#define MVPP22_RSS_FLOW_HASH(port)	((port) * MVPP22_RSS_FLOW_SIZE + \
					 MVPP22_RSS_FLOW_HASH_OFFS)
#define MVPP22_RSS_FLOW_FIRST(port)	MVPP22_RSS_FLOW_C2(port)
#define MVPP22_CLS_C2_PORT_FIRST(p)	(MVPP22_CLS_C2_N_ENTRIES - \
					((p) * MVPP22_CLS_C2_PORT_RANGE))
#define MVPP22_CLS_C2_RSS_ENTRY(p)	(MVPP22_CLS_C2_PORT_FIRST(p) - 1)

/* Packet flow ID */
enum mvpp2_prs_flow {
@@ -162,6 +145,15 @@ enum mvpp2_prs_flow {
	MVPP2_FL_LAST,
};

enum mvpp2_cls_lu_type {
	MVPP2_CLS_LU_ALL = 0,
};

/* LU Type defined for all engines, and specified in the flow table */
#define MVPP2_CLS_LU_TYPE_MASK			0x3f

#define MVPP2_N_FLOWS		(MVPP2_FL_LAST - MVPP2_FL_START)

struct mvpp2_cls_flow {
	/* The L2-L4 traffic flow type */
	int flow_type;
@@ -176,12 +168,37 @@ struct mvpp2_cls_flow {
	struct mvpp2_prs_result_info prs_ri;
};

#define MVPP2_N_FLOWS	52
#define MVPP2_CLS_FLT_ENTRIES_PER_FLOW		(MVPP2_MAX_PORTS + 1)
#define MVPP2_CLS_FLT_FIRST(id)			(((id) - MVPP2_FL_START) * \
						 MVPP2_CLS_FLT_ENTRIES_PER_FLOW)
#define MVPP2_CLS_FLT_C2_RSS_ENTRY(id)		(MVPP2_CLS_FLT_FIRST(id))
#define MVPP2_CLS_FLT_HASH_ENTRY(port, id)	(MVPP2_CLS_FLT_C2_RSS_ENTRY(id) + (port) + 1)
#define MVPP2_CLS_FLT_LAST(id)			(MVPP2_CLS_FLT_FIRST(id) + \
						 MVPP2_CLS_FLT_ENTRIES_PER_FLOW - 1)

/* Iterate on each classifier flow id. Sets 'i' to be the index of the first
 * entry in the cls_flows table for each different flow_id.
 * This relies on entries having the same flow_id in the cls_flows table being
 * contiguous.
 */
#define for_each_cls_flow_id(i)						      \
	for ((i) = 0; (i) < MVPP2_N_PRS_FLOWS; (i)++)			      \
		if ((i) > 0 &&						      \
		    cls_flows[(i)].flow_id == cls_flows[(i) - 1].flow_id)       \
			continue;					      \
		else

/* Iterate on each classifier flow that has a given flow_type. Sets 'i' to be
 * the index of the first entry in the cls_flow table for each different flow_id
 * that has the given flow_type. This allows to operate on all flows that
 * matches a given ethtool flow type.
 */
#define for_each_cls_flow_id_with_type(i, type)				      \
	for_each_cls_flow_id((i))					      \
		if (cls_flows[(i)].flow_type != (type))			      \
			continue;					      \
		else

#define MVPP2_ENTRIES_PER_FLOW			(MVPP2_MAX_PORTS + 1)
#define MVPP2_FLOW_C2_ENTRY(id)			((id) * MVPP2_ENTRIES_PER_FLOW)
#define MVPP2_PORT_FLOW_HASH_ENTRY(port, id)	((id) * MVPP2_ENTRIES_PER_FLOW + \
						(port) + 1)
struct mvpp2_cls_flow_entry {
	u32 index;
	u32 data[MVPP2_CLS_FLOWS_TBL_DATA_WORDS];
@@ -194,11 +211,10 @@ struct mvpp2_cls_lookup_entry {
};

void mvpp22_rss_fill_table(struct mvpp2_port *port, u32 table);
void mvpp22_port_rss_init(struct mvpp2_port *port);

void mvpp22_rss_port_init(struct mvpp2_port *port);

void mvpp22_rss_enable(struct mvpp2_port *port);
void mvpp22_rss_disable(struct mvpp2_port *port);
void mvpp22_port_rss_enable(struct mvpp2_port *port);
void mvpp22_port_rss_disable(struct mvpp2_port *port);

int mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info);
int mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info);
@@ -213,7 +229,7 @@ int mvpp2_cls_flow_eng_get(struct mvpp2_cls_flow_entry *fe);

u16 mvpp2_flow_get_hek_fields(struct mvpp2_cls_flow_entry *fe);

struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow);
const struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow);

u32 mvpp2_cls_flow_hits(struct mvpp2 *priv, int index);

+151 −102

File changed.

Preview size limit exceeded, changes collapsed.

+4 −4
Original line number Diff line number Diff line
@@ -3741,9 +3741,9 @@ static int mvpp2_set_features(struct net_device *dev,

	if (changed & NETIF_F_RXHASH) {
		if (features & NETIF_F_RXHASH)
			mvpp22_rss_enable(port);
			mvpp22_port_rss_enable(port);
		else
			mvpp22_rss_disable(port);
			mvpp22_port_rss_disable(port);
	}

	return 0;
@@ -4301,7 +4301,7 @@ static int mvpp2_port_init(struct mvpp2_port *port)
	mvpp2_cls_port_config(port);

	if (mvpp22_rss_is_supported())
		mvpp22_rss_port_init(port);
		mvpp22_port_rss_init(port);

	/* Provide an initial Rx packet size */
	port->pkt_size = MVPP2_RX_PKT_SIZE(port->dev->mtu);
@@ -4848,6 +4848,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
	struct mvpp2_port *port;
	struct mvpp2_port_pcpu *port_pcpu;
	struct device_node *port_node = to_of_node(port_fwnode);
	netdev_features_t features;
	struct net_device *dev;
	struct resource *res;
	struct phylink *phylink;
@@ -4856,7 +4857,6 @@ static int mvpp2_port_probe(struct platform_device *pdev,
	unsigned long flags = 0;
	bool has_tx_irqs;
	u32 id;
	int features;
	int phy_mode;
	int err, i;