FILE
en_common.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en_common.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.