drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_table.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_table.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_table.c
Extension
.c
Size
7258 bytes
Lines
320
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2019 Mellanox Technologies. */

#include "dr_types.h"

static int dr_table_set_miss_action_nic(struct mlx5dr_domain *dmn,
					struct mlx5dr_table_rx_tx *nic_tbl,
					struct mlx5dr_action *action)
{
	struct mlx5dr_matcher_rx_tx *last_nic_matcher = NULL;
	struct mlx5dr_htbl_connect_info info;
	struct mlx5dr_ste_htbl *last_htbl;
	struct mlx5dr_icm_chunk *chunk;
	int ret;

	if (!list_empty(&nic_tbl->nic_matcher_list))
		last_nic_matcher = list_last_entry(&nic_tbl->nic_matcher_list,
						   struct mlx5dr_matcher_rx_tx,
						   list_node);

	if (last_nic_matcher)
		last_htbl = last_nic_matcher->e_anchor;
	else
		last_htbl = nic_tbl->s_anchor;

	if (action) {
		chunk = nic_tbl->nic_dmn->type == DR_DOMAIN_NIC_TYPE_RX ?
			action->dest_tbl->tbl->rx.s_anchor->chunk :
			action->dest_tbl->tbl->tx.s_anchor->chunk;
		nic_tbl->default_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(chunk);
	} else {
		nic_tbl->default_icm_addr = nic_tbl->nic_dmn->default_icm_addr;
	}

	info.type = CONNECT_MISS;
	info.miss_icm_addr = nic_tbl->default_icm_addr;

	ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_tbl->nic_dmn,
						last_htbl, &info, true);
	if (ret)
		mlx5dr_dbg(dmn, "Failed to set NIC RX/TX miss action, ret %d\n", ret);

	return ret;
}

int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
				 struct mlx5dr_action *action)
{
	int ret = -EOPNOTSUPP;

	if (action && action->action_type != DR_ACTION_TYP_FT)
		return -EOPNOTSUPP;

	mlx5dr_domain_lock(tbl->dmn);

	if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX ||
	    tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
		ret = dr_table_set_miss_action_nic(tbl->dmn, &tbl->rx, action);
		if (ret)
			goto out;
	}

	if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX ||
	    tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
		ret = dr_table_set_miss_action_nic(tbl->dmn, &tbl->tx, action);
		if (ret)
			goto out;
	}

	if (ret)
		goto out;

	/* Release old action */
	if (tbl->miss_action)
		refcount_dec(&tbl->miss_action->refcount);

	/* Set new miss action */
	tbl->miss_action = action;
	if (tbl->miss_action)
		refcount_inc(&action->refcount);

out:
	mlx5dr_domain_unlock(tbl->dmn);
	return ret;
}

static void dr_table_uninit_nic(struct mlx5dr_table_rx_tx *nic_tbl)
{
	mlx5dr_htbl_put(nic_tbl->s_anchor);
}

Annotation

Implementation Notes