FILE
ipoib.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
1/* 2 * Copyright (c) 2017, 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 <rdma/ib_verbs.h> 34#include <linux/mlx5/fs.h> 35#include <net/netdev_lock.h> 36#include "en.h" 37#include "en/params.h" 38#include "ipoib.h" 39#include "en/fs_ethtool.h" 40 41#define IB_DEFAULT_Q_KEY 0xb1b 42#define MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE 9 43 44static int mlx5i_open(struct net_device *netdev); 45static int mlx5i_close(struct net_device *netdev); 46static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu); 47 48int mlx5i_hwtstamp_set(struct net_device *dev, 49 struct kernel_hwtstamp_config *config, 50 struct netlink_ext_ack *extack) 51{ 52 struct mlx5e_priv *epriv = mlx5i_epriv(dev); 53 54 return mlx5e_hwtstamp_set(epriv, config, extack); 55} 56 57int mlx5i_hwtstamp_get(struct net_device *dev, 58 struct kernel_hwtstamp_config *config) 59{ 60 struct mlx5e_priv *epriv = mlx5i_epriv(dev); 61 62 return mlx5e_hwtstamp_get(epriv, config); 63} 64 65static const struct net_device_ops mlx5i_netdev_ops = { 66 .ndo_open = mlx5i_open, 67 .ndo_stop = mlx5i_close, 68 .ndo_get_stats64 = mlx5i_get_stats, 69 .ndo_init = mlx5i_dev_init, 70 .ndo_uninit = mlx5i_dev_cleanup, 71 .ndo_change_mtu = mlx5i_change_mtu, 72 .ndo_hwtstamp_get = mlx5i_hwtstamp_get, 73 .ndo_hwtstamp_set = mlx5i_hwtstamp_set, 74}; 75 76/* IPoIB mlx5 netdev profile */ 77static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, 78 struct mlx5e_params *params) 79{ 80 /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */ 81 MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ, false); 82 mlx5e_set_rq_type(mdev, params); 83 mlx5e_init_rq_type_params(mdev, params); 84 85 /* RQ size in ipoib by default is 512 */ 86 params->log_rq_mtu_frames = is_kdump_kernel() ? 87 MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE : 88 MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE; 89 90 params->packet_merge.type = MLX5E_PACKET_MERGE_NONE; 91 params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN; 92 93 /* CQE compression is not supported for IPoIB */ 94 params->rx_cqe_compress_def = false; 95 MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS, params->rx_cqe_compress_def); 96} 97 98/* Called directly after IPoIB netdevice was created to initialize SW structs */ 99int mlx5i_init(struct mlx5_core_dev *mdev, struct net_device *netdev) 100{ 101 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 102 103 netif_carrier_off(netdev); 104 mlx5e_set_netdev_mtu_boundaries(priv); 105 netdev->mtu = netdev->max_mtu; 106 107 mlx5e_build_nic_params(priv, NULL, netdev->mtu); 108 mlx5i_build_nic_params(mdev, &priv->channels.params); 109 110 mlx5e_timestamp_init(priv); 111 112 /* netdev init */ 113 netdev->hw_features |= NETIF_F_SG; 114 netdev->hw_features |= NETIF_F_IP_CSUM; 115 netdev->hw_features |= NETIF_F_IPV6_CSUM; 116 netdev->hw_features |= NETIF_F_GRO; 117 netdev->hw_features |= NETIF_F_TSO; 118 netdev->hw_features |= NETIF_F_TSO6; 119 netdev->hw_features |= NETIF_F_RXCSUM; 120 netdev->hw_features |= NETIF_F_RXHASH; 121 122 netdev->netdev_ops = &mlx5i_netdev_ops; 123 netdev->ethtool_ops = &mlx5i_ethtool_ops; 124 netdev->request_ops_lock = true; 125 netdev_lockdep_set_classes(netdev); 126 127 return 0; 128} 129 130/* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */ 131void mlx5i_cleanup(struct mlx5e_priv *priv) 132{ 133 mlx5e_priv_cleanup(priv); 134} 135 136static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv) 137{ 138 struct rtnl_link_stats64 s = {}; 139 int i, j; 140 141 for (i = 0; i < priv->stats_nch; i++) { 142 struct mlx5e_channel_stats *channel_stats; 143 struct mlx5e_rq_stats *rq_stats; 144 145 channel_stats = priv->channel_stats[i]; 146 rq_stats = &channel_stats->rq; 147 148 s.rx_packets += rq_stats->packets; 149 s.rx_bytes += rq_stats->bytes; 150 151 for (j = 0; j < priv->max_opened_tc; j++) { 152 struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j]; 153 154 s.tx_packets += sq_stats->packets; 155 s.tx_bytes += sq_stats->bytes; 156 s.tx_dropped += sq_stats->dropped; 157 } 158 } 159 160 memset(&priv->stats.sw, 0, sizeof(s)); 161 162 priv->stats.sw.rx_packets = s.rx_packets; 163 priv->stats.sw.rx_bytes = s.rx_bytes; 164 priv->stats.sw.tx_packets = s.tx_packets; 165 priv->stats.sw.tx_bytes = s.tx_bytes; 166 priv->stats.sw.tx_queue_dropped = s.tx_dropped; 167} 168 169void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) 170{ 171 struct mlx5e_priv *priv = mlx5i_epriv(dev); 172 struct mlx5e_sw_stats *sstats = &priv->stats.sw; 173 174 mlx5i_grp_sw_update_stats(priv); 175 176 stats->rx_packets = sstats->rx_packets; 177 stats->rx_bytes = sstats->rx_bytes; 178 stats->tx_packets = sstats->tx_packets; 179 stats->tx_bytes = sstats->tx_bytes; 180 stats->tx_dropped = sstats->tx_queue_dropped; 181} 182 183struct net_device *mlx5i_parent_get(struct net_device *netdev) 184{ 185 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 186 struct mlx5i_priv *ipriv, *parent_ipriv; 187 struct net_device *parent_dev; 188 int parent_ifindex; 189 190 ipriv = priv->ppriv; 191 192 parent_ifindex = netdev->netdev_ops->ndo_get_iflink(netdev); 193 parent_dev = dev_get_by_index(dev_net(netdev), parent_ifindex); 194 if (!parent_dev) 195 return NULL; 196 197 parent_ipriv = netdev_priv(parent_dev); 198 199 ASSERT_RTNL(); 200 parent_ipriv->num_sub_interfaces++; 201 202 ipriv->parent_dev = parent_dev; 203 204 return parent_dev; 205} 206 207void mlx5i_parent_put(struct net_device *netdev) 208{ 209 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 210 struct mlx5i_priv *ipriv, *parent_ipriv; 211 212 ipriv = priv->ppriv; 213 parent_ipriv = netdev_priv(ipriv->parent_dev); 214 215 ASSERT_RTNL(); 216 parent_ipriv->num_sub_interfaces--; 217 218 dev_put(ipriv->parent_dev); 219} 220 221int mlx5i_init_underlay_qp(struct mlx5e_priv *priv) 222{ 223 struct mlx5_core_dev *mdev = priv->mdev; 224 struct mlx5i_priv *ipriv = priv->ppriv; 225 int ret; 226 227 { 228 u32 in[MLX5_ST_SZ_DW(rst2init_qp_in)] = {}; 229 u32 *qpc; 230 231 qpc = MLX5_ADDR_OF(rst2init_qp_in, in, qpc); 232 233 MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); 234 MLX5_SET(qpc, qpc, primary_address_path.pkey_index, 235 ipriv->pkey_index); 236 MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, 1); 237 MLX5_SET(qpc, qpc, q_key, IB_DEFAULT_Q_KEY); 238 239 MLX5_SET(rst2init_qp_in, in, opcode, MLX5_CMD_OP_RST2INIT_QP); 240 MLX5_SET(rst2init_qp_in, in, qpn, ipriv->qpn); 241 ret = mlx5_cmd_exec_in(mdev, rst2init_qp, in); 242 if (ret) 243 goto err_qp_modify_to_err; 244 } 245 { 246 u32 in[MLX5_ST_SZ_DW(init2rtr_qp_in)] = {}; 247 248 MLX5_SET(init2rtr_qp_in, in, opcode, MLX5_CMD_OP_INIT2RTR_QP); 249 MLX5_SET(init2rtr_qp_in, in, qpn, ipriv->qpn); 250 ret = mlx5_cmd_exec_in(mdev, init2rtr_qp, in); 251 if (ret) 252 goto err_qp_modify_to_err; 253 } 254 { 255 u32 in[MLX5_ST_SZ_DW(rtr2rts_qp_in)] = {}; 256 257 MLX5_SET(rtr2rts_qp_in, in, opcode, MLX5_CMD_OP_RTR2RTS_QP); 258 MLX5_SET(rtr2rts_qp_in, in, qpn, ipriv->qpn); 259 ret = mlx5_cmd_exec_in(mdev, rtr2rts_qp, in); 260 if (ret) 261 goto err_qp_modify_to_err; 262 } 263 return 0; 264 265err_qp_modify_to_err: 266 { 267 u32 in[MLX5_ST_SZ_DW(qp_2err_in)] = {}; 268 269 MLX5_SET(qp_2err_in, in, opcode, MLX5_CMD_OP_2ERR_QP); 270 MLX5_SET(qp_2err_in, in, qpn, ipriv->qpn); 271 mlx5_cmd_exec_in(mdev, qp_2err, in); 272 } 273 return ret; 274} 275 276void mlx5i_uninit_underlay_qp(struct mlx5e_priv *priv) 277{ 278 struct mlx5i_priv *ipriv = priv->ppriv; 279 struct mlx5_core_dev *mdev = priv->mdev; 280 u32 in[MLX5_ST_SZ_DW(qp_2rst_in)] = {}; 281 282 MLX5_SET(qp_2rst_in, in, opcode, MLX5_CMD_OP_2RST_QP); 283 MLX5_SET(qp_2rst_in, in, qpn, ipriv->qpn); 284 mlx5_cmd_exec_in(mdev, qp_2rst, in); 285} 286 287#define MLX5_QP_ENHANCED_ULP_STATELESS_MODE 2 288 289int mlx5i_create_underlay_qp(struct mlx5e_priv *priv) 290{ 291 const unsigned char *dev_addr = priv->netdev->dev_addr; 292 u32 out[MLX5_ST_SZ_DW(create_qp_out)] = {}; 293 u32 in[MLX5_ST_SZ_DW(create_qp_in)] = {}; 294 struct mlx5i_priv *ipriv = priv->ppriv; 295 void *addr_path; 296 int qpn = 0; 297 int ret = 0; 298 void *qpc; 299 300 if (MLX5_CAP_GEN(priv->mdev, mkey_by_name)) { 301 qpn = (dev_addr[1] << 16) + (dev_addr[2] << 8) + dev_addr[3]; 302 MLX5_SET(create_qp_in, in, input_qpn, qpn); 303 } 304 305 qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); 306 MLX5_SET(qpc, qpc, ts_format, mlx5_get_qp_default_ts(priv->mdev)); 307 MLX5_SET(qpc, qpc, st, MLX5_QP_ST_UD); 308 MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); 309 MLX5_SET(qpc, qpc, ulp_stateless_offload_mode, 310 MLX5_QP_ENHANCED_ULP_STATELESS_MODE); 311 312 addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path); 313 MLX5_SET(ads, addr_path, vhca_port_num, 1); 314 MLX5_SET(ads, addr_path, grh, 1); 315 316 MLX5_SET(create_qp_in, in, opcode, MLX5_CMD_OP_CREATE_QP); 317 ret = mlx5_cmd_exec_inout(priv->mdev, create_qp, in, out); 318 if (ret) 319 return ret; 320 321 ipriv->qpn = MLX5_GET(create_qp_out, out, qpn); 322 323 return 0; 324} 325 326void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, u32 qpn) 327{ 328 u32 in[MLX5_ST_SZ_DW(destroy_qp_in)] = {}; 329 330 MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP); 331 MLX5_SET(destroy_qp_in, in, qpn, qpn); 332 mlx5_cmd_exec_in(mdev, destroy_qp, in); 333} 334 335int mlx5i_update_nic_rx(struct mlx5e_priv *priv) 336{ 337 return mlx5e_refresh_tirs(priv->mdev, true, true); 338} 339 340int mlx5i_create_tis(struct mlx5_core_dev *mdev, u32 underlay_qpn, u32 *tisn) 341{ 342 u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {}; 343 void *tisc; 344 345 tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); 346 347 MLX5_SET(tisc, tisc, underlay_qpn, underlay_qpn); 348 349 return mlx5e_create_tis(mdev, in, tisn); 350} 351 352static int mlx5i_init_tx(struct mlx5e_priv *priv) 353{ 354 struct mlx5i_priv *ipriv = priv->ppriv; 355 int err; 356 357 err = mlx5i_create_underlay_qp(priv); 358 if (err) { 359 mlx5_core_warn(priv->mdev, "create underlay QP failed, %d\n", err); 360 return err; 361 } 362 363 err = mlx5i_create_tis(priv->mdev, ipriv->qpn, &ipriv->tisn); 364 if (err) { 365 mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err); 366 goto err_destroy_underlay_qp; 367 } 368 369 return 0; 370 371err_destroy_underlay_qp: 372 mlx5i_destroy_underlay_qp(priv->mdev, ipriv->qpn); 373 return err; 374} 375 376static void mlx5i_cleanup_tx(struct mlx5e_priv *priv) 377{ 378 struct mlx5i_priv *ipriv = priv->ppriv; 379 380 mlx5e_destroy_tis(priv->mdev, ipriv->tisn); 381 mlx5i_destroy_underlay_qp(priv->mdev, ipriv->qpn); 382} 383 384static int mlx5i_create_flow_steering(struct mlx5e_priv *priv) 385{ 386 struct mlx5_flow_namespace *ns = 387 mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL); 388 int err; 389 390 391 if (!ns) 392 return -EINVAL; 393 394 mlx5e_fs_set_ns(priv->fs, ns, false); 395 err = mlx5e_arfs_create_tables(priv->fs, priv->rx_res, 396 mlx5e_fs_has_arfs(priv->netdev)); 397 if (err) { 398 netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n", 399 err); 400 priv->netdev->hw_features &= ~NETIF_F_NTUPLE; 401 } 402 403 err = mlx5e_create_ttc_table(priv->fs, priv->rx_res); 404 if (err) { 405 netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n", 406 err); 407 goto err_destroy_arfs_tables; 408 } 409 410 mlx5e_ethtool_init_steering(priv->fs); 411 412 return 0; 413 414err_destroy_arfs_tables: 415 mlx5e_arfs_destroy_tables(priv->fs, mlx5e_fs_has_arfs(priv->netdev)); 416 417 return err; 418} 419 420static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv) 421{ 422 mlx5e_destroy_ttc_table(priv->fs); 423 mlx5e_arfs_destroy_tables(priv->fs, mlx5e_fs_has_arfs(priv->netdev)); 424 mlx5e_ethtool_cleanup_steering(priv->fs); 425} 426 427static int mlx5i_init_rx(struct mlx5e_priv *priv) 428{ 429 struct mlx5_core_dev *mdev = priv->mdev; 430 enum mlx5e_rx_res_features features; 431 int err; 432 433 priv->fs = mlx5e_fs_init(priv->profile, mdev, 434 !test_bit(MLX5E_STATE_DESTROYING, &priv->state), 435 priv->dfs_root); 436 if (!priv->fs) { 437 netdev_err(priv->netdev, "FS allocation failed\n"); 438 return -ENOMEM; 439 } 440 441 mlx5e_create_q_counters(priv); 442 443 err = mlx5e_open_drop_rq(priv, &priv->drop_rq); 444 if (err) { 445 mlx5_core_err(mdev, "open drop rq failed, %d\n", err); 446 goto err_destroy_q_counters; 447 } 448 449 features = MLX5E_RX_RES_FEATURE_SELF_LB_BLOCK; 450 priv->rx_res = mlx5e_rx_res_create(priv->mdev, features, priv->max_nch, 451 priv->drop_rq.rqn, 452 &priv->channels.params.packet_merge, 453 priv->channels.params.num_channels); 454 if (IS_ERR(priv->rx_res)) { 455 err = PTR_ERR(priv->rx_res); 456 goto err_close_drop_rq; 457 } 458 459 err = mlx5i_create_flow_steering(priv); 460 if (err) 461 goto err_destroy_rx_res; 462 463 return 0; 464 465err_destroy_rx_res: 466 mlx5e_rx_res_destroy(priv->rx_res); 467 priv->rx_res = ERR_PTR(-EINVAL); 468err_close_drop_rq: 469 mlx5e_close_drop_rq(&priv->drop_rq); 470err_destroy_q_counters: 471 mlx5e_destroy_q_counters(priv); 472 mlx5e_fs_cleanup(priv->fs); 473 return err; 474} 475 476static void mlx5i_cleanup_rx(struct mlx5e_priv *priv) 477{ 478 mlx5i_destroy_flow_steering(priv); 479 mlx5e_rx_res_destroy(priv->rx_res); 480 priv->rx_res = ERR_PTR(-EINVAL); 481 mlx5e_close_drop_rq(&priv->drop_rq); 482 mlx5e_destroy_q_counters(priv); 483 mlx5e_fs_cleanup(priv->fs); 484} 485 486/* The stats groups order is opposite to the update_stats() order calls */ 487static mlx5e_stats_grp_t mlx5i_stats_grps[] = { 488 &MLX5E_STATS_GRP(sw), 489 &MLX5E_STATS_GRP(qcnt), 490 &MLX5E_STATS_GRP(vnic_env), 491 &MLX5E_STATS_GRP(vport), 492 &MLX5E_STATS_GRP(802_3), 493 &MLX5E_STATS_GRP(2863), 494 &MLX5E_STATS_GRP(2819), 495 &MLX5E_STATS_GRP(phy), 496 &MLX5E_STATS_GRP(pcie), 497 &MLX5E_STATS_GRP(per_prio), 498 &MLX5E_STATS_GRP(pme), 499 &MLX5E_STATS_GRP(channels), 500 &MLX5E_STATS_GRP(per_port_buff_congest), 501}; 502 503static unsigned int mlx5i_stats_grps_num(struct mlx5e_priv *priv) 504{ 505 return ARRAY_SIZE(mlx5i_stats_grps); 506} 507 508u32 mlx5i_get_tisn(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv, u8 lag_port, u8 tc) 509{ 510 struct mlx5i_priv *ipriv = priv->ppriv; 511 512 if (WARN(lag_port || tc, 513 "IPoIB unexpected non-zero value: lag_port (%u), tc (%u)\n", 514 lag_port, tc)) 515 return 0; 516 517 return ipriv->tisn; 518} 519 520static const struct mlx5e_profile mlx5i_nic_profile = { 521 .init = mlx5i_init, 522 .cleanup = mlx5i_cleanup, 523 .init_tx = mlx5i_init_tx, 524 .cleanup_tx = mlx5i_cleanup_tx, 525 .init_rx = mlx5i_init_rx, 526 .cleanup_rx = mlx5i_cleanup_rx, 527 .enable = NULL, /* mlx5i_enable */ 528 .disable = NULL, /* mlx5i_disable */ 529 .update_rx = mlx5i_update_nic_rx, 530 .update_stats = NULL, /* mlx5i_update_stats */ 531 .update_carrier = NULL, /* no HW update in IB link */ 532 .rx_handlers = &mlx5i_rx_handlers, 533 .max_tc = MLX5I_MAX_NUM_TC, 534 .stats_grps = mlx5i_stats_grps, 535 .stats_grps_num = mlx5i_stats_grps_num, 536 .get_tisn = mlx5i_get_tisn, 537}; 538 539/* mlx5i netdev NDos */ 540 541static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu) 542{ 543 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 544 struct mlx5e_params new_params; 545 int err = 0; 546 547 mutex_lock(&priv->state_lock); 548 549 new_params = priv->channels.params; 550 new_params.sw_mtu = new_mtu; 551 552 err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true); 553 if (err) 554 goto out; 555 556 WRITE_ONCE(netdev->mtu, new_params.sw_mtu); 557 558out: 559 mutex_unlock(&priv->state_lock); 560 return err; 561} 562 563int mlx5i_dev_init(struct net_device *dev) 564{ 565 struct mlx5e_priv *priv = mlx5i_epriv(dev); 566 struct mlx5i_priv *ipriv = priv->ppriv; 567 u8 addr_mod[3]; 568 569 /* Set dev address using underlay QP */ 570 addr_mod[0] = (ipriv->qpn >> 16) & 0xff; 571 addr_mod[1] = (ipriv->qpn >> 8) & 0xff; 572 addr_mod[2] = (ipriv->qpn) & 0xff; 573 dev_addr_mod(dev, 1, addr_mod, sizeof(addr_mod)); 574 575 /* Add QPN to net-device mapping to HT */ 576 mlx5i_pkey_add_qpn(dev, ipriv->qpn); 577 578 return 0; 579} 580 581void mlx5i_dev_cleanup(struct net_device *dev) 582{ 583 struct mlx5e_priv *priv = mlx5i_epriv(dev); 584 struct mlx5i_priv *ipriv = priv->ppriv; 585 586 mlx5i_uninit_underlay_qp(priv); 587 588 /* Delete QPN to net-device mapping from HT */ 589 mlx5i_pkey_del_qpn(dev, ipriv->qpn); 590} 591 592static int mlx5i_open(struct net_device *netdev) 593{ 594 struct mlx5e_priv *epriv = mlx5i_epriv(netdev); 595 struct mlx5i_priv *ipriv = epriv->ppriv; 596 struct mlx5_core_dev *mdev = epriv->mdev; 597 int err; 598 599 mutex_lock(&epriv->state_lock); 600 601 set_bit(MLX5E_STATE_OPENED, &epriv->state); 602 603 err = mlx5i_init_underlay_qp(epriv); 604 if (err) { 605 mlx5_core_warn(mdev, "prepare underlay qp state failed, %d\n", err); 606 goto err_clear_state_opened_flag; 607 } 608 609 err = mlx5_fs_add_rx_underlay_qpn(mdev, ipriv->qpn); 610 if (err) { 611 mlx5_core_warn(mdev, "attach underlay qp to ft failed, %d\n", err); 612 goto err_reset_qp; 613 } 614 615 err = mlx5e_open_channels(epriv, &epriv->channels); 616 if (err) 617 goto err_remove_fs_underlay_qp; 618 619 err = epriv->profile->update_rx(epriv); 620 if (err) 621 goto err_close_channels; 622 623 mlx5e_activate_priv_channels(epriv); 624 625 mutex_unlock(&epriv->state_lock); 626 return 0; 627 628err_close_channels: 629 mlx5e_close_channels(&epriv->channels); 630err_remove_fs_underlay_qp: 631 mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qpn); 632err_reset_qp: 633 mlx5i_uninit_underlay_qp(epriv); 634err_clear_state_opened_flag: 635 clear_bit(MLX5E_STATE_OPENED, &epriv->state); 636 mutex_unlock(&epriv->state_lock); 637 return err; 638} 639 640static int mlx5i_close(struct net_device *netdev) 641{ 642 struct mlx5e_priv *epriv = mlx5i_epriv(netdev); 643 struct mlx5i_priv *ipriv = epriv->ppriv; 644 struct mlx5_core_dev *mdev = epriv->mdev; 645 646 /* May already be CLOSED in case a previous configuration operation 647 * (e.g RX/TX queue size change) that involves close&open failed. 648 */ 649 mutex_lock(&epriv->state_lock); 650 651 if (!test_bit(MLX5E_STATE_OPENED, &epriv->state)) 652 goto unlock; 653 654 clear_bit(MLX5E_STATE_OPENED, &epriv->state); 655 656 netif_carrier_off(epriv->netdev); 657 mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qpn); 658 mlx5e_deactivate_priv_channels(epriv); 659 mlx5e_close_channels(&epriv->channels); 660 mlx5i_uninit_underlay_qp(epriv); 661unlock: 662 mutex_unlock(&epriv->state_lock); 663 return 0; 664} 665 666/* IPoIB RDMA netdev callbacks */ 667static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca, 668 union ib_gid *gid, u16 lid, int set_qkey, 669 u32 qkey) 670{ 671 struct mlx5e_priv *epriv = mlx5i_epriv(netdev); 672 struct mlx5_core_dev *mdev = epriv->mdev; 673 struct mlx5i_priv *ipriv = epriv->ppriv; 674 int err; 675 676 mlx5_core_dbg(mdev, "attaching QPN 0x%x, MGID %pI6\n", ipriv->qpn, 677 gid->raw); 678 err = mlx5_core_attach_mcg(mdev, gid, ipriv->qpn); 679 if (err) 680 mlx5_core_warn(mdev, "failed attaching QPN 0x%x, MGID %pI6\n", 681 ipriv->qpn, gid->raw); 682 683 if (set_qkey) { 684 mlx5_core_dbg(mdev, "%s setting qkey 0x%x\n", 685 netdev->name, qkey); 686 ipriv->qkey = qkey; 687 } 688 689 return err; 690} 691 692static int mlx5i_detach_mcast(struct net_device *netdev, struct ib_device *hca, 693 union ib_gid *gid, u16 lid) 694{ 695 struct mlx5e_priv *epriv = mlx5i_epriv(netdev); 696 struct mlx5_core_dev *mdev = epriv->mdev; 697 struct mlx5i_priv *ipriv = epriv->ppriv; 698 int err; 699 700 mlx5_core_dbg(mdev, "detaching QPN 0x%x, MGID %pI6\n", ipriv->qpn, 701 gid->raw); 702 703 err = mlx5_core_detach_mcg(mdev, gid, ipriv->qpn); 704 if (err) 705 mlx5_core_dbg(mdev, "failed detaching QPN 0x%x, MGID %pI6\n", 706 ipriv->qpn, gid->raw); 707 708 return err; 709} 710 711static int mlx5i_xmit(struct net_device *dev, struct sk_buff *skb, 712 struct ib_ah *address, u32 dqpn) 713{ 714 struct mlx5e_priv *epriv = mlx5i_epriv(dev); 715 struct mlx5e_txqsq *sq = epriv->txq2sq[skb_get_queue_mapping(skb)]; 716 struct mlx5_ib_ah *mah = to_mah(address); 717 struct mlx5i_priv *ipriv = epriv->ppriv; 718 719 mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, ipriv->qkey, netdev_xmit_more()); 720 721 return NETDEV_TX_OK; 722} 723 724static void mlx5i_set_pkey_index(struct net_device *netdev, int id) 725{ 726 struct mlx5i_priv *ipriv = netdev_priv(netdev); 727 728 ipriv->pkey_index = (u16)id; 729} 730 731static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev) 732{ 733 if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_IB) 734 return -EOPNOTSUPP; 735 736 if (!MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) { 737 mlx5_core_warn(mdev, "IPoIB enhanced offloads are not supported\n"); 738 return -EOPNOTSUPP; 739 } 740 741 return 0; 742} 743 744static void mlx5_rdma_netdev_free(struct net_device *netdev) 745{ 746 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 747 struct mlx5_core_dev *mdev = priv->mdev; 748 struct mlx5i_priv *ipriv = priv->ppriv; 749 const struct mlx5e_profile *profile = priv->profile; 750 751 mlx5e_detach_netdev(priv); 752 profile->cleanup(priv); 753 754 if (!ipriv->sub_interface) { 755 mlx5i_pkey_qpn_ht_cleanup(netdev); 756 mlx5e_destroy_mdev_resources(mdev); 757 } 758} 759 760static bool mlx5_is_sub_interface(struct mlx5_core_dev *mdev) 761{ 762 return mdev->mlx5e_res.hw_objs.pdn != 0; 763} 764 765static const struct mlx5e_profile *mlx5_get_profile(struct mlx5_core_dev *mdev) 766{ 767 if (mlx5_is_sub_interface(mdev)) 768 return mlx5i_pkey_get_profile(); 769 return &mlx5i_nic_profile; 770} 771 772static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u32 port_num, 773 struct net_device *netdev, void *param) 774{ 775 struct mlx5_core_dev *mdev = (struct mlx5_core_dev *)param; 776 const struct mlx5e_profile *prof = mlx5_get_profile(mdev); 777 struct mlx5i_priv *ipriv; 778 struct mlx5e_priv *epriv; 779 struct rdma_netdev *rn; 780 int err; 781 782 ipriv = netdev_priv(netdev); 783 epriv = mlx5i_epriv(netdev); 784 785 ipriv->sub_interface = mlx5_is_sub_interface(mdev); 786 if (!ipriv->sub_interface) { 787 err = mlx5i_pkey_qpn_ht_init(netdev); 788 if (err) { 789 mlx5_core_warn(mdev, "allocate qpn_to_netdev ht failed\n"); 790 return err; 791 } 792 793 /* This should only be called once per mdev */ 794 err = mlx5e_create_mdev_resources(mdev, false); 795 if (err) 796 goto destroy_ht; 797 } 798 799 err = mlx5e_priv_init(epriv, prof, netdev, mdev); 800 if (err) 801 goto destroy_mdev_resources; 802 803 epriv->profile = prof; 804 epriv->ppriv = ipriv; 805 806 prof->init(mdev, netdev); 807 808 err = mlx5e_attach_netdev(epriv); 809 if (err) 810 goto detach; 811 netif_carrier_off(netdev); 812 813 /* set rdma_netdev func pointers */ 814 rn = &ipriv->rn; 815 rn->hca = ibdev; 816 rn->send = mlx5i_xmit; 817 rn->attach_mcast = mlx5i_attach_mcast; 818 rn->detach_mcast = mlx5i_detach_mcast; 819 rn->set_id = mlx5i_set_pkey_index; 820 821 netdev->priv_destructor = mlx5_rdma_netdev_free; 822 netdev->needs_free_netdev = 1; 823 824 return 0; 825 826detach: 827 prof->cleanup(epriv); 828 if (ipriv->sub_interface) 829 return err; 830destroy_mdev_resources: 831 mlx5e_destroy_mdev_resources(mdev); 832destroy_ht: 833 mlx5i_pkey_qpn_ht_cleanup(netdev); 834 return err; 835} 836 837int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev, 838 struct ib_device *device, 839 struct rdma_netdev_alloc_params *params) 840{ 841 int nch; 842 int rc; 843 844 rc = mlx5i_check_required_hca_cap(mdev); 845 if (rc) 846 return rc; 847 848 nch = mlx5e_get_max_num_channels(mdev); 849 850 *params = (struct rdma_netdev_alloc_params){ 851 .sizeof_priv = sizeof(struct mlx5i_priv) + 852 sizeof(struct mlx5e_priv), 853 .txqs = nch * MLX5_MAX_NUM_TC, 854 .rxqs = nch, 855 .param = mdev, 856 .initialize_rdma_netdev = mlx5_rdma_setup_rn, 857 }; 858 859 return 0; 860} 861EXPORT_SYMBOL(mlx5_rdma_rn_get_params);
~/
Read-only file preview.