Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

Merge branch 'mlxsw-Introduce-initial-Spectrum-2-support'



Ido Schimmel says:

====================
mlxsw: Introduce initial Spectrum-2 support

This patch set adds initial support for the Spectrum-2 ASIC. The first
two patches add Spectrum-2 specific KVD linear (KVDL) manager. Unlike
the Spectrum ASIC, there is no linear memory and instead the type of the
entry (e.g., nexthop) and its index are hashed and the entry is placed
in the computed address in the hash-based KVD memory.

The third patch adds Spectrum-2 stubs in the multicast routing code.
Support for multicast routing will be added later on.

Patches 4-15 add ACL support. The Spectrum-2 ASIC includes an
algorithmic TCAM (A-TCAM) and a regular circuit TCAM (C-TCAM) for rules
that can't be inserted into the A-TCAM. This set does not make use of
the A-TCAM and only places rules in the C-TCAM. This provides equivalent
scale and performance to the Spectrum ASIC. A follow-up patch set will
introduce A-TCAM support.

The last patch extends the main driver file to work with both ASICs.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c0b78038 c3ab4354
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -15,15 +15,17 @@ mlxsw_switchx2-objs := switchx2.o
obj-$(CONFIG_MLXSW_SPECTRUM)	+= mlxsw_spectrum.o
mlxsw_spectrum-objs		:= spectrum.o spectrum_buffers.o \
				   spectrum_switchdev.o spectrum_router.o \
				   spectrum1_kvdl.o spectrum_kvdl.o \
				   spectrum1_kvdl.o spectrum2_kvdl.o \
				   spectrum_kvdl.o \
				   spectrum_acl_tcam.o spectrum_acl_ctcam.o \
				   spectrum1_acl_tcam.o \
				   spectrum_acl_atcam.o \
				   spectrum1_acl_tcam.o spectrum2_acl_tcam.o \
				   spectrum_acl.o \
				   spectrum_flower.o spectrum_cnt.o \
				   spectrum_fid.o spectrum_ipip.o \
				   spectrum_acl_flex_actions.o \
				   spectrum_acl_flex_keys.o \
				   spectrum1_mr_tcam.o \
				   spectrum1_mr_tcam.o spectrum2_mr_tcam.o \
				   spectrum_mr_tcam.o spectrum_mr.o \
				   spectrum_qdisc.o spectrum_span.o
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB)	+= spectrum_dcb.o
+15 −0
Original line number Diff line number Diff line
@@ -430,6 +430,12 @@ char *mlxsw_afa_block_first_set(struct mlxsw_afa_block *block)
}
EXPORT_SYMBOL(mlxsw_afa_block_first_set);

char *mlxsw_afa_block_cur_set(struct mlxsw_afa_block *block)
{
	return block->cur_set->ht_key.enc_actions;
}
EXPORT_SYMBOL(mlxsw_afa_block_cur_set);

u32 mlxsw_afa_block_first_kvdl_index(struct mlxsw_afa_block *block)
{
	/* First set is never in KVD linear. So the first set
@@ -441,6 +447,15 @@ u32 mlxsw_afa_block_first_kvdl_index(struct mlxsw_afa_block *block)
}
EXPORT_SYMBOL(mlxsw_afa_block_first_kvdl_index);

int mlxsw_afa_block_activity_get(struct mlxsw_afa_block *block, bool *activity)
{
	u32 kvdl_index = mlxsw_afa_block_first_kvdl_index(block);

	return block->afa->ops->kvdl_set_activity_get(block->afa->ops_priv,
						      kvdl_index, activity);
}
EXPORT_SYMBOL(mlxsw_afa_block_activity_get);

int mlxsw_afa_block_continue(struct mlxsw_afa_block *block)
{
	if (block->finished)
+4 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ struct mlxsw_afa_ops {
	int (*kvdl_set_add)(void *priv, u32 *p_kvdl_index,
			    char *enc_actions, bool is_first);
	void (*kvdl_set_del)(void *priv, u32 kvdl_index, bool is_first);
	int (*kvdl_set_activity_get)(void *priv, u32 kvdl_index,
				     bool *activity);
	int (*kvdl_fwd_entry_add)(void *priv, u32 *p_kvdl_index, u8 local_port);
	void (*kvdl_fwd_entry_del)(void *priv, u32 kvdl_index);
	int (*counter_index_get)(void *priv, unsigned int *p_counter_index);
@@ -65,7 +67,9 @@ struct mlxsw_afa_block *mlxsw_afa_block_create(struct mlxsw_afa *mlxsw_afa);
void mlxsw_afa_block_destroy(struct mlxsw_afa_block *block);
int mlxsw_afa_block_commit(struct mlxsw_afa_block *block);
char *mlxsw_afa_block_first_set(struct mlxsw_afa_block *block);
char *mlxsw_afa_block_cur_set(struct mlxsw_afa_block *block);
u32 mlxsw_afa_block_first_kvdl_index(struct mlxsw_afa_block *block);
int mlxsw_afa_block_activity_get(struct mlxsw_afa_block *block, bool *activity);
int mlxsw_afa_block_continue(struct mlxsw_afa_block *block);
int mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id);
int mlxsw_afa_block_terminate(struct mlxsw_afa_block *block);
+60 −10
Original line number Diff line number Diff line
@@ -416,24 +416,74 @@ void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values,
}
EXPORT_SYMBOL(mlxsw_afk_values_add_buf);

static void mlxsw_sp_afk_encode_u32(const struct mlxsw_item *storage_item,
				    const struct mlxsw_item *output_item,
				    char *storage, char *output)
{
	u32 value;

	value = __mlxsw_item_get32(storage, storage_item, 0);
	__mlxsw_item_set32(output, output_item, 0, value);
}

static void mlxsw_sp_afk_encode_buf(const struct mlxsw_item *storage_item,
				    const struct mlxsw_item *output_item,
				    char *storage, char *output)
{
	char *storage_data = __mlxsw_item_data(storage, storage_item, 0);
	char *output_data = __mlxsw_item_data(output, output_item, 0);
	size_t len = output_item->size.bytes;

	memcpy(output_data, storage_data, len);
}

static void
mlxsw_sp_afk_encode_one(const struct mlxsw_afk_element_inst *elinst,
			char *output, char *storage)
{
	const struct mlxsw_item *storage_item = &elinst->info->item;
	const struct mlxsw_item *output_item = &elinst->item;

	if (elinst->type == MLXSW_AFK_ELEMENT_TYPE_U32)
		mlxsw_sp_afk_encode_u32(storage_item, output_item,
					storage, output);
	else if (elinst->type == MLXSW_AFK_ELEMENT_TYPE_BUF)
		mlxsw_sp_afk_encode_buf(storage_item, output_item,
					storage, output);
}

#define MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE 16

void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
		      struct mlxsw_afk_key_info *key_info,
		      struct mlxsw_afk_element_values *values,
		      char *key, char *mask)
{
	char block_mask[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE];
	char block_key[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE];
	const struct mlxsw_afk_element_inst *elinst;
	enum mlxsw_afk_element element;
	int block_index;
	int block_index, i;

	for (i = 0; i < key_info->blocks_count; i++) {
		memset(block_key, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE);
		memset(block_mask, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE);

		mlxsw_afk_element_usage_for_each(element, &values->elusage) {
		elinst = mlxsw_afk_key_info_elinst_get(key_info, element,
			elinst = mlxsw_afk_key_info_elinst_get(key_info,
							       element,
							       &block_index);
		if (!elinst)
			if (!elinst || block_index != i)
				continue;
		mlxsw_afk->ops->encode_one(elinst, block_index,
					   values->storage.key, key);
		mlxsw_afk->ops->encode_one(elinst, block_index,
					   values->storage.mask, mask);

			mlxsw_sp_afk_encode_one(elinst, block_key,
						values->storage.key);
			mlxsw_sp_afk_encode_one(elinst, block_mask,
						values->storage.mask);
		}

		mlxsw_afk->ops->encode_block(block_key, i, key);
		mlxsw_afk->ops->encode_block(block_mask, i, mask);
	}
}
EXPORT_SYMBOL(mlxsw_afk_encode);
+1 −2
Original line number Diff line number Diff line
@@ -219,8 +219,7 @@ struct mlxsw_afk;
struct mlxsw_afk_ops {
	const struct mlxsw_afk_block *blocks;
	unsigned int blocks_count;
	void (*encode_one)(const struct mlxsw_afk_element_inst *elinst,
			   int block_index, char *storage, char *output);
	void (*encode_block)(char *block, int block_index, char *output);
};

struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks,
Loading