File Index
Files and directories
Sign in
FILE

en_common.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en_common.c C
  1/*
  2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
  3 *
  4 * This software is available to you under a choice of one of two
  5 * licenses.  You may choose to be licensed under the terms of the GNU
  6 * General Public License (GPL) Version 2, available from the file
  7 * COPYING in the main directory of this source tree, or the
  8 * OpenIB.org BSD license below:
  9 *
 10 *     Redistribution and use in source and binary forms, with or
 11 *     without modification, are permitted provided that the following
 12 *     conditions are met:
 13 *
 14 *      - Redistributions of source code must retain the above
 15 *        copyright notice, this list of conditions and the following
 16 *        disclaimer.
 17 *
 18 *      - Redistributions in binary form must reproduce the above
 19 *        copyright notice, this list of conditions and the following
 20 *        disclaimer in the documentation and/or other materials
 21 *        provided with the distribution.
 22 *
 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 30 * SOFTWARE.
 31 */
 32
 33#include "devlink.h"
 34#include "en.h"
 35#include "lib/crypto.h"
 36
 37/* mlx5e global resources should be placed in this file.
 38 * Global resources are common to all the netdevices created on the same nic.
 39 */
 40
 41void mlx5e_mkey_set_relaxed_ordering(struct mlx5_core_dev *mdev, void *mkc)
 42{
 43	bool ro_write = MLX5_CAP_GEN(mdev, relaxed_ordering_write);
 44	bool ro_read = MLX5_CAP_GEN(mdev, relaxed_ordering_read) ||
 45		       (pcie_relaxed_ordering_enabled(mdev->pdev) &&
 46			MLX5_CAP_GEN(mdev, relaxed_ordering_read_pci_enabled));
 47
 48	MLX5_SET(mkc, mkc, relaxed_ordering_read, ro_read);
 49	MLX5_SET(mkc, mkc, relaxed_ordering_write, ro_write);
 50}
 51
 52int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, u32 *mkey)
 53{
 54	int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
 55	void *mkc;
 56	u32 *in;
 57	int err;
 58
 59	in = kvzalloc(inlen, GFP_KERNEL);
 60	if (!in)
 61		return -ENOMEM;
 62
 63	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
 64	MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_PA);
 65	MLX5_SET(mkc, mkc, lw, 1);
 66	MLX5_SET(mkc, mkc, lr, 1);
 67	mlx5e_mkey_set_relaxed_ordering(mdev, mkc);
 68	MLX5_SET(mkc, mkc, pd, pdn);
 69	MLX5_SET(mkc, mkc, length64, 1);
 70	MLX5_SET(mkc, mkc, qpn, 0xffffff);
 71
 72	err = mlx5_core_create_mkey(mdev, mkey, in, inlen);
 73
 74	kvfree(in);
 75	return err;
 76}
 77
 78int mlx5e_create_tis(struct mlx5_core_dev *mdev, void *in, u32 *tisn)
 79{
 80	void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
 81
 82	MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.hw_objs.td.tdn);
 83
 84	if (mlx5_lag_is_lacp_owner(mdev))
 85		MLX5_SET(tisc, tisc, strict_lag_tx_port_affinity, 1);
 86
 87	return mlx5_core_create_tis(mdev, in, tisn);
 88}
 89
 90void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn)
 91{
 92	mlx5_core_destroy_tis(mdev, tisn);
 93}
 94
 95static void mlx5e_destroy_tises(struct mlx5_core_dev *mdev, u32 tisn[MLX5_MAX_PORTS][MLX5_MAX_NUM_TC])
 96{
 97	int tc, i;
 98
 99	for (i = 0; i < mlx5e_get_num_lag_ports(mdev); i++)
100		for (tc = 0; tc < MLX5_MAX_NUM_TC; tc++)
101			mlx5e_destroy_tis(mdev, tisn[i][tc]);
102}
103
104static bool mlx5_lag_should_assign_affinity(struct mlx5_core_dev *mdev)
105{
106	return MLX5_CAP_GEN(mdev, lag_tx_port_affinity) && mlx5e_get_num_lag_ports(mdev) > 1;
107}
108
109static int mlx5e_create_tises(struct mlx5_core_dev *mdev, u32 tisn[MLX5_MAX_PORTS][MLX5_MAX_NUM_TC])
110{
111	int tc, i;
112	int err;
113
114	for (i = 0; i < mlx5e_get_num_lag_ports(mdev); i++) {
115		for (tc = 0; tc < MLX5_MAX_NUM_TC; tc++) {
116			u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {};
117			void *tisc;
118
119			tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
120
121			MLX5_SET(tisc, tisc, prio, tc << 1);
122
123			if (mlx5_lag_should_assign_affinity(mdev))
124				MLX5_SET(tisc, tisc, lag_tx_port_affinity, i + 1);
125
126			err = mlx5e_create_tis(mdev, in, &tisn[i][tc]);
127			if (err)
128				goto err_close_tises;
129		}
130	}
131
132	return 0;
133
134err_close_tises:
135	for (; i >= 0; i--) {
136		for (tc--; tc >= 0; tc--)
137			mlx5e_destroy_tis(mdev, tisn[i][tc]);
138		tc = MLX5_MAX_NUM_TC;
139	}
140
141	return err;
142}
143
144static unsigned int
145mlx5e_get_devlink_param_num_doorbells(struct mlx5_core_dev *dev)
146{
147	const u32 param_id = DEVLINK_PARAM_GENERIC_ID_NUM_DOORBELLS;
148	struct devlink *devlink = priv_to_devlink(dev);
149	union devlink_param_value val;
150	int err;
151
152	err = devl_param_driverinit_value_get(devlink, param_id, &val);
153	return err ? MLX5_DEFAULT_NUM_DOORBELLS : val.vu32;
154}
155
156int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev, bool create_tises)
157{
158	struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs;
159	unsigned int num_doorbells, i;
160	int err;
161
162	err = mlx5_core_alloc_pd(mdev, &res->pdn);
163	if (err) {
164		mlx5_core_err(mdev, "alloc pd failed, %d\n", err);
165		return err;
166	}
167
168	err = mlx5_core_alloc_transport_domain(mdev, &res->td.tdn);
169	if (err) {
170		mlx5_core_err(mdev, "alloc td failed, %d\n", err);
171		goto err_dealloc_pd;
172	}
173
174	err = mlx5e_create_mkey(mdev, res->pdn, &res->mkey);
175	if (err) {
176		mlx5_core_err(mdev, "create mkey failed, %d\n", err);
177		goto err_dealloc_transport_domain;
178	}
179
180	num_doorbells = min(mlx5e_get_devlink_param_num_doorbells(mdev),
181			    mlx5e_get_max_num_channels(mdev));
182	res->bfregs = kcalloc(num_doorbells, sizeof(*res->bfregs), GFP_KERNEL);
183	if (!res->bfregs) {
184		err = -ENOMEM;
185		goto err_destroy_mkey;
186	}
187
188	for (i = 0; i < num_doorbells; i++) {
189		err = mlx5_alloc_bfreg(mdev, res->bfregs + i, false, false);
190		if (err) {
191			mlx5_core_warn(mdev,
192				       "could only allocate %d/%d doorbells, err %d.\n",
193				       i, num_doorbells, err);
194			break;
195		}
196	}
197	res->num_bfregs = i;
198
199	if (create_tises) {
200		err = mlx5e_create_tises(mdev, res->tisn);
201		if (err) {
202			mlx5_core_err(mdev, "alloc tises failed, %d\n", err);
203			goto err_destroy_bfregs;
204		}
205		res->tisn_valid = true;
206	}
207
208	INIT_LIST_HEAD(&res->td.tirs_list);
209	mutex_init(&res->td.list_lock);
210
211	mdev->mlx5e_res.dek_priv = mlx5_crypto_dek_init(mdev);
212	if (IS_ERR(mdev->mlx5e_res.dek_priv)) {
213		mlx5_core_err(mdev, "crypto dek init failed, %pe\n",
214			      mdev->mlx5e_res.dek_priv);
215		mdev->mlx5e_res.dek_priv = NULL;
216	}
217
218	return 0;
219
220err_destroy_bfregs:
221	for (i = 0; i < res->num_bfregs; i++)
222		mlx5_free_bfreg(mdev, res->bfregs + i);
223	kfree(res->bfregs);
224err_destroy_mkey:
225	mlx5_core_destroy_mkey(mdev, res->mkey);
226err_dealloc_transport_domain:
227	mlx5_core_dealloc_transport_domain(mdev, res->td.tdn);
228err_dealloc_pd:
229	mlx5_core_dealloc_pd(mdev, res->pdn);
230	return err;
231}
232
233void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev)
234{
235	struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs;
236
237	mlx5_crypto_dek_cleanup(mdev->mlx5e_res.dek_priv);
238	mdev->mlx5e_res.dek_priv = NULL;
239	if (res->tisn_valid)
240		mlx5e_destroy_tises(mdev, res->tisn);
241	for (unsigned int i = 0; i < res->num_bfregs; i++)
242		mlx5_free_bfreg(mdev, res->bfregs + i);
243	kfree(res->bfregs);
244	mlx5_core_destroy_mkey(mdev, res->mkey);
245	mlx5_core_dealloc_transport_domain(mdev, res->td.tdn);
246	mlx5_core_dealloc_pd(mdev, res->pdn);
247	memset(res, 0, sizeof(*res));
248}
249
250int mlx5e_modify_tirs_lb(struct mlx5_core_dev *mdev, bool enable_uc_lb,
251			 bool enable_mc_lb)
252{
253	struct mlx5e_tir_builder *builder;
254	struct mlx5e_tir *tir;
255	int err = 0;
256
257	builder = mlx5e_tir_builder_alloc(true);
258	if (!builder)
259		return -ENOMEM;
260
261	mlx5e_tir_builder_build_self_lb_block(builder, enable_uc_lb,
262					      enable_mc_lb);
263
264	mutex_lock(&mdev->mlx5e_res.hw_objs.td.list_lock);
265	list_for_each_entry(tir, &mdev->mlx5e_res.hw_objs.td.tirs_list, list) {
266		err = mlx5e_tir_modify(tir, builder);
267		if (err) {
268			mlx5_core_err(mdev,
269				      "modify tir(0x%x) enable_lb uc(%d) mc(%d) failed, %d\n",
270				      mlx5e_tir_get_tirn(tir),
271				      enable_uc_lb, enable_mc_lb, err);
272			break;
273		}
274	}
275	mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock);
276
277	mlx5e_tir_builder_free(builder);
278
279	return err;
280}
281
282int mlx5e_refresh_tirs(struct mlx5_core_dev *mdev, bool enable_uc_lb,
283		       bool enable_mc_lb)
284{
285	if (MLX5_CAP_GEN(mdev, tis_tir_td_order))
286		return 0; /* refresh not needed */
287
288	return mlx5e_modify_tirs_lb(mdev, enable_uc_lb, enable_mc_lb);
289}
~/ Read-only file preview.