Commit a2efb1b8 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'net-dsa-mv88e6xxx-add-partial-support-for-tcam-entries'



Cedric Jehasse says:

====================
net: dsa: mv88e6xxx: Add partial support for TCAM entries

This series adds partial Ternary Content Addressable Memory (TCAM) for
the mv88e6390 and mv88e6393 family of switches. TCAM entries allow the
switch to match the first 48 or 96 bytes of a frame and take actions on
matched frames.

This patch introduces a subset of the available TCAM functionality.
Matching on ip addresses/protocol and trapping to the cpu.

Eg. to trap traffic with destination ip 224.0.1.129 to the cpu:

tc qdisc add dev p1 clsact
tc filter add dev p1 ingress protocol ip flower skip_sw \
    dst_ip 224.0.1.129 action trap

Review of the mv88e6xxx changes have brought to light something in
cls_flower:
When adding a classifier with an ipv4 address both
FLOW_DISSECTOR_KEY_IPV4_ADDRS and FLOW_DISSECTOR_KEY_IPV6_ADDRS bits are
set in dissector->used_keys.
A change was made to address this.

Signed-off-by: default avatarCedric Jehasse <cedric.jehasse@luminex.be>
====================

Link: https://patch.msgid.link/20260311-net-next-mv88e6xxx-tcam-v8-0-32dd5ba30002@luminex.be


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 348baefb 639f1dcf
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ mv88e6xxx-objs += serdes.o
mv88e6xxx-objs += smi.o
mv88e6xxx-objs += switchdev.o
mv88e6xxx-objs += trace.o
mv88e6xxx-objs += tcflower.o
mv88e6xxx-objs += tcam.o

# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
+35 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@
#include "ptp.h"
#include "serdes.h"
#include "smi.h"
#include "tcam.h"
#include "tcflower.h"

static void assert_reg_lock(struct mv88e6xxx_chip *chip)
{
@@ -3560,6 +3562,11 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
		if (err)
			return err;
	}
	if (chip->info->ops->port_enable_tcam) {
		err = chip->info->ops->port_enable_tcam(chip, port);
		if (err)
			return err;
	}

	if (chip->info->ops->port_tag_remap) {
		err = chip->info->ops->port_tag_remap(chip, port);
@@ -3938,6 +3945,14 @@ static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip)
	return 0;
}

static int mv88e6xxx_tcam_setup(struct mv88e6xxx_chip *chip)
{
	if (!mv88e6xxx_has_tcam(chip))
		return 0;

	return chip->info->ops->tcam_ops->flush_tcam(chip);
}

static void mv88e6xxx_teardown(struct dsa_switch *ds)
{
	struct mv88e6xxx_chip *chip = ds->priv;
@@ -3947,6 +3962,7 @@ static void mv88e6xxx_teardown(struct dsa_switch *ds)
	mv88e6xxx_teardown_devlink_regions_global(ds);
	mv88e6xxx_hwtstamp_free(chip);
	mv88e6xxx_ptp_free(chip);
	mv88e6xxx_flower_teardown(chip);
	mv88e6xxx_mdios_unregister(chip);
}

@@ -4083,6 +4099,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
	if (err)
		goto unlock;

	err = mv88e6xxx_tcam_setup(chip);
	if (err)
		goto unlock;

unlock:
	mv88e6xxx_reg_unlock(chip);

@@ -5134,6 +5154,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
	.ptp_ops = &mv88e6390_ptp_ops,
	.phylink_get_caps = mv88e6390_phylink_get_caps,
	.pcs_ops = &mv88e6390_pcs_ops,
	.tcam_ops = &mv88e6390_tcam_ops,
};

static const struct mv88e6xxx_ops mv88e6320_ops = {
@@ -5525,6 +5546,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
	.serdes_get_regs = mv88e6390_serdes_get_regs,
	.phylink_get_caps = mv88e6390_phylink_get_caps,
	.pcs_ops = &mv88e6390_pcs_ops,
	.tcam_ops = &mv88e6390_tcam_ops,
};

static const struct mv88e6xxx_ops mv88e6390x_ops = {
@@ -5621,6 +5643,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
	.port_set_cmode = mv88e6393x_port_set_cmode,
	.port_setup_message_port = mv88e6xxx_setup_message_port,
	.port_set_upstream_port = mv88e6393x_port_set_upstream_port,
	.port_enable_tcam = mv88e6xxx_port_enable_tcam,
	.stats_snapshot = mv88e6390_g1_stats_snapshot,
	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -5652,6 +5675,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
	.ptp_ops = &mv88e6352_ptp_ops,
	.phylink_get_caps = mv88e6393x_phylink_get_caps,
	.pcs_ops = &mv88e6393x_pcs_ops,
	.tcam_ops = &mv88e6393_tcam_ops,
};

static const struct mv88e6xxx_info mv88e6xxx_table[] = {
@@ -6125,6 +6149,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
		.num_internal_phys = 8,
		.num_tcam_entries = 256,
		.internal_phys_offset = 1,
		.max_vid = 8191,
		.max_sid = 63,
@@ -6132,6 +6157,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
		.phy_base_addr = 0x0,
		.global1_addr = 0x1b,
		.global2_addr = 0x1c,
		.tcam_addr = 0x1f,
		.age_time_coeff = 3750,
		.g1_irqs = 10,
		.g2_irqs = 14,
@@ -6227,12 +6253,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
		.num_ports = 11,	/* 10 + Z80 */
		.num_internal_phys = 9,
		.num_gpio = 16,
		.num_tcam_entries = 256,
		.max_vid = 8191,
		.max_sid = 63,
		.port_base_addr = 0x0,
		.phy_base_addr = 0x0,
		.global1_addr = 0x1b,
		.global2_addr = 0x1c,
		.tcam_addr = 0x1f,
		.age_time_coeff = 3750,
		.g1_irqs = 9,
		.g2_irqs = 14,
@@ -6439,12 +6467,14 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
		.num_ports = 11,	/* 10 + Z80 */
		.num_internal_phys = 9,
		.num_gpio = 16,
		.num_tcam_entries = 256,
		.max_vid = 8191,
		.max_sid = 63,
		.port_base_addr = 0x0,
		.phy_base_addr = 0x0,
		.global1_addr = 0x1b,
		.global2_addr = 0x1c,
		.tcam_addr = 0x1f,
		.age_time_coeff = 3750,
		.g1_irqs = 9,
		.g2_irqs = 14,
@@ -6490,6 +6520,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
		.num_databases = 4096,
		.num_ports = 11,	/* 10 + Z80 */
		.num_internal_phys = 8,
		.num_tcam_entries = 256,
		.internal_phys_offset = 1,
		.max_vid = 8191,
		.max_sid = 63,
@@ -6497,6 +6528,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
		.phy_base_addr = 0x0,
		.global1_addr = 0x1b,
		.global2_addr = 0x1c,
		.tcam_addr = 0x1f,
		.age_time_coeff = 3750,
		.g1_irqs = 10,
		.g2_irqs = 14,
@@ -6589,6 +6621,7 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(struct device *dev)
	INIT_LIST_HEAD(&chip->mdios);
	idr_init(&chip->policies);
	INIT_LIST_HEAD(&chip->msts);
	INIT_LIST_HEAD(&chip->tcam.entries);

	return chip;
}
@@ -7184,6 +7217,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
	.port_hwtstamp_get	= mv88e6xxx_port_hwtstamp_get,
	.port_txtstamp		= mv88e6xxx_port_txtstamp,
	.port_rxtstamp		= mv88e6xxx_port_rxtstamp,
	.cls_flower_add		= mv88e6xxx_cls_flower_add,
	.cls_flower_del         = mv88e6xxx_cls_flower_del,
	.get_ts_info		= mv88e6xxx_get_ts_info,
	.devlink_param_get	= mv88e6xxx_devlink_param_get,
	.devlink_param_set	= mv88e6xxx_devlink_param_set,
+52 −0
Original line number Diff line number Diff line
@@ -135,12 +135,14 @@ struct mv88e6xxx_info {
	unsigned int num_ports;
	unsigned int num_internal_phys;
	unsigned int num_gpio;
	unsigned int num_tcam_entries;
	unsigned int max_vid;
	unsigned int max_sid;
	unsigned int port_base_addr;
	unsigned int phy_base_addr;
	unsigned int global1_addr;
	unsigned int global2_addr;
	unsigned int tcam_addr;
	unsigned int age_time_coeff;
	unsigned int g1_irqs;
	unsigned int g2_irqs;
@@ -210,6 +212,7 @@ struct mv88e6xxx_avb_ops;
struct mv88e6xxx_ptp_ops;
struct mv88e6xxx_pcs_ops;
struct mv88e6xxx_cc_coeffs;
struct mv88e6xxx_tcam_ops;

struct mv88e6xxx_irq {
	u16 masked;
@@ -339,6 +342,10 @@ struct mv88e6xxx_hw_stat {
	int type;
};

struct mv88e6xxx_tcam {
	struct list_head entries;
};

struct mv88e6xxx_chip {
	const struct mv88e6xxx_info *info;

@@ -444,6 +451,35 @@ struct mv88e6xxx_chip {

	/* FID map */
	DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);

	/* TCAM entries */
	struct mv88e6xxx_tcam tcam;
};

#define TCAM_MATCH_SIZE 96

struct mv88e6xxx_tcam_key {
	u16 spv;
	u16 spv_mask;

	u8 frame_data[TCAM_MATCH_SIZE];
	u8 frame_mask[TCAM_MATCH_SIZE];
};

struct mv88e6xxx_tcam_action {
	u8 dpv_mode;
	u16 dpv;
};

struct mv88e6xxx_tcam_entry {
	struct list_head list;
	unsigned long cookie;
	u32 prio;
	u8 hw_idx;

	struct mv88e6xxx_tcam_key key;
	struct mv88e6xxx_tcam_action action;

};

struct mv88e6xxx_bus_ops {
@@ -678,6 +714,11 @@ struct mv88e6xxx_ops {

	/* Max Frame Size */
	int (*set_max_frame_size)(struct mv88e6xxx_chip *chip, int mtu);

	int (*port_enable_tcam)(struct mv88e6xxx_chip *chip, int port);

	/* Ternary Content Addressable Memory operations */
	const struct mv88e6xxx_tcam_ops *tcam_ops;
};

struct mv88e6xxx_irq_ops {
@@ -752,6 +793,12 @@ struct mv88e6xxx_pcs_ops {

};

struct mv88e6xxx_tcam_ops {
	int (*entry_add)(struct mv88e6xxx_chip *chip,
			 struct mv88e6xxx_tcam_entry *entry, u8 idx);
	int (*flush_tcam)(struct mv88e6xxx_chip *chip);
};

static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip)
{
	return chip->info->max_sid > 0 &&
@@ -769,6 +816,11 @@ static inline bool mv88e6xxx_has_lag(struct mv88e6xxx_chip *chip)
	return !!chip->info->global2_addr;
}

static inline bool mv88e6xxx_has_tcam(struct mv88e6xxx_chip *chip)
{
	return !!chip->info->tcam_addr;
}

static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip)
{
	return chip->info->num_databases;
+27 −1
Original line number Diff line number Diff line
@@ -1380,7 +1380,33 @@ int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)

int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
{
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
	u16 reg;
	int err;

	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE,
				  &reg);
	if (err)
		return err;

	reg &= MV88E6XXX_PORT_PRI_OVERRIDE_TCAM_MODE_MASK;
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE,
				    reg);
}

int mv88e6xxx_port_enable_tcam(struct mv88e6xxx_chip *chip, int port)
{
	u16 reg;
	int err;

	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE,
				  &reg);
	if (err)
		return err;

	reg &= ~MV88E6XXX_PORT_PRI_OVERRIDE_TCAM_MODE_MASK;
	reg |= MV88E6XXX_PORT_PRI_OVERRIDE_TCAM_MODE_96_BYTE;
	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE,
				    reg);
}

/* Offset 0x0E: Policy & MGMT Control Register for FAMILY 6191X 6193X 6393X */
+6 −1
Original line number Diff line number Diff line
@@ -255,6 +255,9 @@

/* Offset 0x0D: Priority Override Register */
#define MV88E6XXX_PORT_PRI_OVERRIDE			0x0d
#define MV88E6XXX_PORT_PRI_OVERRIDE_TCAM_MODE_MASK	0x0003
#define MV88E6XXX_PORT_PRI_OVERRIDE_TCAM_MODE_48_BYTE	0x0001
#define MV88E6XXX_PORT_PRI_OVERRIDE_TCAM_MODE_96_BYTE	0x0002

/* Offset 0x0E: Policy Control Register */
#define MV88E6XXX_PORT_POLICY_CTL		0x0e
@@ -608,4 +611,6 @@ int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip);
int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
			       int reg, u16 *val);

int mv88e6xxx_port_enable_tcam(struct mv88e6xxx_chip *chip, int port);

#endif /* _MV88E6XXX_PORT_H */
Loading