File Index
Files and directories
Sign in
FILE

adj_vport.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2// Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
  3
  4#include "fs_core.h"
  5#include "eswitch.h"
  6
  7int mlx5_esw_adj_vport_modify(struct mlx5_core_dev *dev, u16 vport,
  8			      bool connect)
  9{
 10	u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
 11
 12	MLX5_SET(modify_vport_state_in, in, opcode,
 13		 MLX5_CMD_OP_MODIFY_VPORT_STATE);
 14	MLX5_SET(modify_vport_state_in, in, op_mod,
 15		 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT);
 16	MLX5_SET(modify_vport_state_in, in, other_vport, 1);
 17	MLX5_SET(modify_vport_state_in, in, vport_number, vport);
 18	MLX5_SET(modify_vport_state_in, in, ingress_connect_valid, 1);
 19	MLX5_SET(modify_vport_state_in, in, egress_connect_valid, 1);
 20	MLX5_SET(modify_vport_state_in, in, ingress_connect, connect);
 21	MLX5_SET(modify_vport_state_in, in, egress_connect, connect);
 22	MLX5_SET(modify_vport_state_in, in, admin_state, connect);
 23	return mlx5_cmd_exec_in(dev, modify_vport_state, in);
 24}
 25
 26static void mlx5_esw_destroy_esw_vport(struct mlx5_core_dev *dev, u16 vport)
 27{
 28	u32 in[MLX5_ST_SZ_DW(destroy_esw_vport_in)] = {};
 29
 30	MLX5_SET(destroy_esw_vport_in, in, opcode,
 31		 MLX5_CMD_OPCODE_DESTROY_ESW_VPORT);
 32	MLX5_SET(destroy_esw_vport_in, in, vport_num, vport);
 33
 34	mlx5_cmd_exec_in(dev, destroy_esw_vport, in);
 35}
 36
 37static int mlx5_esw_create_esw_vport(struct mlx5_core_dev *dev, u16 vhca_id,
 38				     u16 *vport_num)
 39{
 40	u32 out[MLX5_ST_SZ_DW(create_esw_vport_out)] = {};
 41	u32 in[MLX5_ST_SZ_DW(create_esw_vport_in)] = {};
 42	int err;
 43
 44	MLX5_SET(create_esw_vport_in, in, opcode,
 45		 MLX5_CMD_OPCODE_CREATE_ESW_VPORT);
 46	MLX5_SET(create_esw_vport_in, in, managed_vhca_id, vhca_id);
 47
 48	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 49	if (!err)
 50		*vport_num = MLX5_GET(create_esw_vport_out, out, vport_num);
 51
 52	return err;
 53}
 54
 55static int mlx5_esw_adj_vport_create(struct mlx5_eswitch *esw, u16 vhca_id,
 56				     const void *rid_info_reg)
 57{
 58	struct mlx5_vport *vport;
 59	u16 vport_num;
 60	int err;
 61
 62	err = mlx5_esw_create_esw_vport(esw->dev, vhca_id, &vport_num);
 63	if (err) {
 64		esw_warn(esw->dev,
 65			 "Failed to create adjacent vport for vhca_id %d, err %d\n",
 66			 vhca_id, err);
 67		return err;
 68	}
 69
 70	esw_debug(esw->dev, "Created adjacent vport[%d] %d for vhca_id 0x%x\n",
 71		  esw->last_vport_idx, vport_num, vhca_id);
 72
 73	err = mlx5_esw_vport_alloc(esw, esw->last_vport_idx++, vport_num);
 74	if (err)
 75		goto destroy_esw_vport;
 76
 77	xa_set_mark(&esw->vports, vport_num, MLX5_ESW_VPT_VF);
 78	vport = mlx5_eswitch_get_vport(esw, vport_num);
 79	vport->adjacent = true;
 80	vport->vhca_id = vhca_id;
 81
 82	vport->adj_info.parent_pci_devfn =
 83		MLX5_GET(function_vhca_rid_info_reg, rid_info_reg,
 84			 parent_pci_device_function);
 85	vport->adj_info.function_id =
 86		MLX5_GET(function_vhca_rid_info_reg, rid_info_reg, function_id);
 87
 88	mlx5_fs_vport_egress_acl_ns_add(esw->dev->priv.steering, vport->index);
 89	mlx5_fs_vport_ingress_acl_ns_add(esw->dev->priv.steering, vport->index);
 90	err = mlx5_esw_offloads_rep_add(esw, vport);
 91	if (err)
 92		goto acl_ns_remove;
 93
 94	return 0;
 95
 96acl_ns_remove:
 97	mlx5_fs_vport_ingress_acl_ns_remove(esw->dev->priv.steering,
 98					    vport->index);
 99	mlx5_fs_vport_egress_acl_ns_remove(esw->dev->priv.steering,
100					   vport->index);
101	mlx5_esw_vport_free(esw, vport);
102destroy_esw_vport:
103	mlx5_esw_destroy_esw_vport(esw->dev, vport_num);
104	return err;
105}
106
107static void mlx5_esw_adj_vport_destroy(struct mlx5_eswitch *esw,
108				       struct mlx5_vport *vport)
109{
110	u16 vport_num = vport->vport;
111
112	esw_debug(esw->dev, "Destroying adjacent vport %d for vhca_id 0x%x\n",
113		  vport_num, vport->vhca_id);
114
115	mlx5_esw_offloads_rep_remove(esw, vport);
116	mlx5_fs_vport_egress_acl_ns_remove(esw->dev->priv.steering,
117					   vport->index);
118	mlx5_fs_vport_ingress_acl_ns_remove(esw->dev->priv.steering,
119					    vport->index);
120	mlx5_esw_vport_free(esw, vport);
121	/* Reset the vport index back so new adj vports can use this index.
122	 * When vport count can incrementally change, this needs to be modified.
123	 */
124	esw->last_vport_idx--;
125	mlx5_esw_destroy_esw_vport(esw->dev, vport_num);
126}
127
128void mlx5_esw_adjacent_vhcas_cleanup(struct mlx5_eswitch *esw)
129{
130	struct mlx5_vport *vport;
131	unsigned long i;
132
133	if (!MLX5_CAP_GEN_2(esw->dev, delegated_vhca_max))
134		return;
135
136	mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) {
137		if (!vport->adjacent)
138			continue;
139		mlx5_esw_adj_vport_destroy(esw, vport);
140	}
141}
142
143void mlx5_esw_adjacent_vhcas_setup(struct mlx5_eswitch *esw)
144{
145	u32 delegated_vhca_max = MLX5_CAP_GEN_2(esw->dev, delegated_vhca_max);
146	u32 in[MLX5_ST_SZ_DW(query_delegated_vhca_in)] = {};
147	int outlen, err, i = 0;
148	u8 *out;
149	u32 count;
150
151	if (!delegated_vhca_max)
152		return;
153
154	outlen = MLX5_ST_SZ_BYTES(query_delegated_vhca_out) +
155		 delegated_vhca_max *
156		 MLX5_ST_SZ_BYTES(delegated_function_vhca_rid_info);
157
158	esw_debug(esw->dev, "delegated_vhca_max=%d\n", delegated_vhca_max);
159
160	out = kvzalloc(outlen, GFP_KERNEL);
161	if (!out)
162		return;
163
164	MLX5_SET(query_delegated_vhca_in, in, opcode,
165		 MLX5_CMD_OPCODE_QUERY_DELEGATED_VHCA);
166
167	err = mlx5_cmd_exec(esw->dev, in, sizeof(in), out, outlen);
168	if (err) {
169		kvfree(out);
170		esw_warn(esw->dev, "Failed to query delegated vhca, err %d\n",
171			 err);
172		return;
173	}
174
175	count = MLX5_GET(query_delegated_vhca_out, out, functions_count);
176	esw_debug(esw->dev, "Delegated vhca functions count %d\n", count);
177
178	for (i = 0; i < count; i++) {
179		const void *rid_info, *rid_info_reg;
180		u16 vhca_id;
181
182		rid_info = MLX5_ADDR_OF(query_delegated_vhca_out, out,
183					delegated_function_vhca_rid_info[i]);
184
185		rid_info_reg = MLX5_ADDR_OF(delegated_function_vhca_rid_info,
186					    rid_info, function_vhca_rid_info);
187
188		vhca_id = MLX5_GET(function_vhca_rid_info_reg, rid_info_reg,
189				   vhca_id);
190		esw_debug(esw->dev, "Delegating vhca_id 0x%x\n", vhca_id);
191
192		err = mlx5_esw_adj_vport_create(esw, vhca_id, rid_info_reg);
193		if (err) {
194			esw_warn(esw->dev,
195				 "Failed to init adjacent vhca 0x%x, err %d\n",
196				 vhca_id, err);
197			break;
198		}
199	}
200
201	kvfree(out);
202}
~/ Read-only file preview.