en_rep.c (38516B)
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 <linux/mlx5/fs.h> 34#include <net/switchdev.h> 35#include <net/pkt_cls.h> 36#include <net/act_api.h> 37#include <net/devlink.h> 38#include <net/ipv6_stubs.h> 39 40#include "eswitch.h" 41#include "en.h" 42#include "en_rep.h" 43#include "en/params.h" 44#include "en/txrx.h" 45#include "en_tc.h" 46#include "en/rep/tc.h" 47#include "en/rep/neigh.h" 48#include "en/rep/bridge.h" 49#include "en/devlink.h" 50#include "fs_core.h" 51#include "lib/mlx5.h" 52#include "lib/devcom.h" 53#include "lib/vxlan.h" 54#define CREATE_TRACE_POINTS 55#include "diag/en_rep_tracepoint.h" 56#include "en_accel/ipsec.h" 57#include "en/tc/int_port.h" 58#include "en/ptp.h" 59 60#define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \ 61 max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE) 62#define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1 63 64static const char mlx5e_rep_driver_name[] = "mlx5e_rep"; 65 66static void mlx5e_rep_get_drvinfo(struct net_device *dev, 67 struct ethtool_drvinfo *drvinfo) 68{ 69 struct mlx5e_priv *priv = netdev_priv(dev); 70 struct mlx5_core_dev *mdev = priv->mdev; 71 72 strlcpy(drvinfo->driver, mlx5e_rep_driver_name, 73 sizeof(drvinfo->driver)); 74 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 75 "%d.%d.%04d (%.16s)", 76 fw_rev_maj(mdev), fw_rev_min(mdev), 77 fw_rev_sub(mdev), mdev->board_id); 78} 79 80static const struct counter_desc sw_rep_stats_desc[] = { 81 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) }, 82 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) }, 83 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_packets) }, 84 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_bytes) }, 85}; 86 87struct vport_stats { 88 u64 vport_rx_packets; 89 u64 vport_tx_packets; 90 u64 vport_rx_bytes; 91 u64 vport_tx_bytes; 92}; 93 94static const struct counter_desc vport_rep_stats_desc[] = { 95 { MLX5E_DECLARE_STAT(struct vport_stats, vport_rx_packets) }, 96 { MLX5E_DECLARE_STAT(struct vport_stats, vport_rx_bytes) }, 97 { MLX5E_DECLARE_STAT(struct vport_stats, vport_tx_packets) }, 98 { MLX5E_DECLARE_STAT(struct vport_stats, vport_tx_bytes) }, 99}; 100 101#define NUM_VPORT_REP_SW_COUNTERS ARRAY_SIZE(sw_rep_stats_desc) 102#define NUM_VPORT_REP_HW_COUNTERS ARRAY_SIZE(vport_rep_stats_desc) 103 104static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(sw_rep) 105{ 106 return NUM_VPORT_REP_SW_COUNTERS; 107} 108 109static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(sw_rep) 110{ 111 int i; 112 113 for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++) 114 strcpy(data + (idx++) * ETH_GSTRING_LEN, 115 sw_rep_stats_desc[i].format); 116 return idx; 117} 118 119static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(sw_rep) 120{ 121 int i; 122 123 for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++) 124 data[idx++] = MLX5E_READ_CTR64_CPU(&priv->stats.sw, 125 sw_rep_stats_desc, i); 126 return idx; 127} 128 129static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(sw_rep) 130{ 131 struct mlx5e_sw_stats *s = &priv->stats.sw; 132 struct rtnl_link_stats64 stats64 = {}; 133 134 memset(s, 0, sizeof(*s)); 135 mlx5e_fold_sw_stats64(priv, &stats64); 136 137 s->rx_packets = stats64.rx_packets; 138 s->rx_bytes = stats64.rx_bytes; 139 s->tx_packets = stats64.tx_packets; 140 s->tx_bytes = stats64.tx_bytes; 141 s->tx_queue_dropped = stats64.tx_dropped; 142} 143 144static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(vport_rep) 145{ 146 return NUM_VPORT_REP_HW_COUNTERS; 147} 148 149static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport_rep) 150{ 151 int i; 152 153 for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++) 154 strcpy(data + (idx++) * ETH_GSTRING_LEN, vport_rep_stats_desc[i].format); 155 return idx; 156} 157 158static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(vport_rep) 159{ 160 int i; 161 162 for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++) 163 data[idx++] = MLX5E_READ_CTR64_CPU(&priv->stats.vf_vport, 164 vport_rep_stats_desc, i); 165 return idx; 166} 167 168static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(vport_rep) 169{ 170 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 171 struct mlx5e_rep_priv *rpriv = priv->ppriv; 172 struct mlx5_eswitch_rep *rep = rpriv->rep; 173 struct rtnl_link_stats64 *vport_stats; 174 struct ifla_vf_stats vf_stats; 175 int err; 176 177 err = mlx5_eswitch_get_vport_stats(esw, rep->vport, &vf_stats); 178 if (err) { 179 netdev_warn(priv->netdev, "vport %d error %d reading stats\n", 180 rep->vport, err); 181 return; 182 } 183 184 vport_stats = &priv->stats.vf_vport; 185 /* flip tx/rx as we are reporting the counters for the switch vport */ 186 vport_stats->rx_packets = vf_stats.tx_packets; 187 vport_stats->rx_bytes = vf_stats.tx_bytes; 188 vport_stats->tx_packets = vf_stats.rx_packets; 189 vport_stats->tx_bytes = vf_stats.rx_bytes; 190} 191 192static void mlx5e_rep_get_strings(struct net_device *dev, 193 u32 stringset, uint8_t *data) 194{ 195 struct mlx5e_priv *priv = netdev_priv(dev); 196 197 switch (stringset) { 198 case ETH_SS_STATS: 199 mlx5e_stats_fill_strings(priv, data); 200 break; 201 } 202} 203 204static void mlx5e_rep_get_ethtool_stats(struct net_device *dev, 205 struct ethtool_stats *stats, u64 *data) 206{ 207 struct mlx5e_priv *priv = netdev_priv(dev); 208 209 mlx5e_ethtool_get_ethtool_stats(priv, stats, data); 210} 211 212static int mlx5e_rep_get_sset_count(struct net_device *dev, int sset) 213{ 214 struct mlx5e_priv *priv = netdev_priv(dev); 215 216 switch (sset) { 217 case ETH_SS_STATS: 218 return mlx5e_stats_total_num(priv); 219 default: 220 return -EOPNOTSUPP; 221 } 222} 223 224static void 225mlx5e_rep_get_ringparam(struct net_device *dev, 226 struct ethtool_ringparam *param, 227 struct kernel_ethtool_ringparam *kernel_param, 228 struct netlink_ext_ack *extack) 229{ 230 struct mlx5e_priv *priv = netdev_priv(dev); 231 232 mlx5e_ethtool_get_ringparam(priv, param); 233} 234 235static int 236mlx5e_rep_set_ringparam(struct net_device *dev, 237 struct ethtool_ringparam *param, 238 struct kernel_ethtool_ringparam *kernel_param, 239 struct netlink_ext_ack *extack) 240{ 241 struct mlx5e_priv *priv = netdev_priv(dev); 242 243 return mlx5e_ethtool_set_ringparam(priv, param); 244} 245 246static void mlx5e_rep_get_channels(struct net_device *dev, 247 struct ethtool_channels *ch) 248{ 249 struct mlx5e_priv *priv = netdev_priv(dev); 250 251 mlx5e_ethtool_get_channels(priv, ch); 252} 253 254static int mlx5e_rep_set_channels(struct net_device *dev, 255 struct ethtool_channels *ch) 256{ 257 struct mlx5e_priv *priv = netdev_priv(dev); 258 259 return mlx5e_ethtool_set_channels(priv, ch); 260} 261 262static int mlx5e_rep_get_coalesce(struct net_device *netdev, 263 struct ethtool_coalesce *coal, 264 struct kernel_ethtool_coalesce *kernel_coal, 265 struct netlink_ext_ack *extack) 266{ 267 struct mlx5e_priv *priv = netdev_priv(netdev); 268 269 return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal); 270} 271 272static int mlx5e_rep_set_coalesce(struct net_device *netdev, 273 struct ethtool_coalesce *coal, 274 struct kernel_ethtool_coalesce *kernel_coal, 275 struct netlink_ext_ack *extack) 276{ 277 struct mlx5e_priv *priv = netdev_priv(netdev); 278 279 return mlx5e_ethtool_set_coalesce(priv, coal, kernel_coal, extack); 280} 281 282static u32 mlx5e_rep_get_rxfh_key_size(struct net_device *netdev) 283{ 284 struct mlx5e_priv *priv = netdev_priv(netdev); 285 286 return mlx5e_ethtool_get_rxfh_key_size(priv); 287} 288 289static u32 mlx5e_rep_get_rxfh_indir_size(struct net_device *netdev) 290{ 291 struct mlx5e_priv *priv = netdev_priv(netdev); 292 293 return mlx5e_ethtool_get_rxfh_indir_size(priv); 294} 295 296static const struct ethtool_ops mlx5e_rep_ethtool_ops = { 297 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 298 ETHTOOL_COALESCE_MAX_FRAMES | 299 ETHTOOL_COALESCE_USE_ADAPTIVE, 300 .get_drvinfo = mlx5e_rep_get_drvinfo, 301 .get_link = ethtool_op_get_link, 302 .get_strings = mlx5e_rep_get_strings, 303 .get_sset_count = mlx5e_rep_get_sset_count, 304 .get_ethtool_stats = mlx5e_rep_get_ethtool_stats, 305 .get_ringparam = mlx5e_rep_get_ringparam, 306 .set_ringparam = mlx5e_rep_set_ringparam, 307 .get_channels = mlx5e_rep_get_channels, 308 .set_channels = mlx5e_rep_set_channels, 309 .get_coalesce = mlx5e_rep_get_coalesce, 310 .set_coalesce = mlx5e_rep_set_coalesce, 311 .get_rxfh_key_size = mlx5e_rep_get_rxfh_key_size, 312 .get_rxfh_indir_size = mlx5e_rep_get_rxfh_indir_size, 313}; 314 315static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, 316 struct mlx5_eswitch_rep *rep) 317{ 318 struct mlx5e_rep_sq *rep_sq, *tmp; 319 struct mlx5e_rep_priv *rpriv; 320 321 if (esw->mode != MLX5_ESWITCH_OFFLOADS) 322 return; 323 324 rpriv = mlx5e_rep_to_rep_priv(rep); 325 list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) { 326 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); 327 if (rep_sq->send_to_vport_rule_peer) 328 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); 329 list_del(&rep_sq->list); 330 kfree(rep_sq); 331 } 332} 333 334static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, 335 struct mlx5_eswitch_rep *rep, 336 u32 *sqns_array, int sqns_num) 337{ 338 struct mlx5_eswitch *peer_esw = NULL; 339 struct mlx5_flow_handle *flow_rule; 340 struct mlx5e_rep_priv *rpriv; 341 struct mlx5e_rep_sq *rep_sq; 342 int err; 343 int i; 344 345 if (esw->mode != MLX5_ESWITCH_OFFLOADS) 346 return 0; 347 348 rpriv = mlx5e_rep_to_rep_priv(rep); 349 if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS)) 350 peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom, 351 MLX5_DEVCOM_ESW_OFFLOADS); 352 353 for (i = 0; i < sqns_num; i++) { 354 rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL); 355 if (!rep_sq) { 356 err = -ENOMEM; 357 goto out_err; 358 } 359 360 /* Add re-inject rule to the PF/representor sqs */ 361 flow_rule = mlx5_eswitch_add_send_to_vport_rule(esw, esw, rep, 362 sqns_array[i]); 363 if (IS_ERR(flow_rule)) { 364 err = PTR_ERR(flow_rule); 365 kfree(rep_sq); 366 goto out_err; 367 } 368 rep_sq->send_to_vport_rule = flow_rule; 369 rep_sq->sqn = sqns_array[i]; 370 371 if (peer_esw) { 372 flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, 373 rep, sqns_array[i]); 374 if (IS_ERR(flow_rule)) { 375 err = PTR_ERR(flow_rule); 376 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); 377 kfree(rep_sq); 378 goto out_err; 379 } 380 rep_sq->send_to_vport_rule_peer = flow_rule; 381 } 382 383 list_add(&rep_sq->list, &rpriv->vport_sqs_list); 384 } 385 386 if (peer_esw) 387 mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); 388 389 return 0; 390 391out_err: 392 mlx5e_sqs2vport_stop(esw, rep); 393 394 if (peer_esw) 395 mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); 396 397 return err; 398} 399 400int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv) 401{ 402 int sqs_per_channel = mlx5e_get_dcb_num_tc(&priv->channels.params); 403 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 404 bool is_uplink_rep = mlx5e_is_uplink_rep(priv); 405 struct mlx5e_rep_priv *rpriv = priv->ppriv; 406 struct mlx5_eswitch_rep *rep = rpriv->rep; 407 int n, tc, nch, num_sqs = 0; 408 struct mlx5e_channel *c; 409 int err = -ENOMEM; 410 bool ptp_sq; 411 u32 *sqs; 412 413 ptp_sq = !!(priv->channels.ptp && 414 MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS)); 415 nch = priv->channels.num + ptp_sq; 416 /* +2 for xdpsqs, they don't exist on the ptp channel but will not be 417 * counted for by num_sqs. 418 */ 419 if (is_uplink_rep) 420 sqs_per_channel += 2; 421 422 sqs = kvcalloc(nch * sqs_per_channel, sizeof(*sqs), GFP_KERNEL); 423 if (!sqs) 424 goto out; 425 426 for (n = 0; n < priv->channels.num; n++) { 427 c = priv->channels.c[n]; 428 for (tc = 0; tc < c->num_tc; tc++) 429 sqs[num_sqs++] = c->sq[tc].sqn; 430 431 if (is_uplink_rep) { 432 if (c->xdp) 433 sqs[num_sqs++] = c->rq_xdpsq.sqn; 434 435 sqs[num_sqs++] = c->xdpsq.sqn; 436 } 437 } 438 if (ptp_sq) { 439 struct mlx5e_ptp *ptp_ch = priv->channels.ptp; 440 441 for (tc = 0; tc < ptp_ch->num_tc; tc++) 442 sqs[num_sqs++] = ptp_ch->ptpsq[tc].txqsq.sqn; 443 } 444 445 err = mlx5e_sqs2vport_start(esw, rep, sqs, num_sqs); 446 kvfree(sqs); 447 448out: 449 if (err) 450 netdev_warn(priv->netdev, "Failed to add SQs FWD rules %d\n", err); 451 return err; 452} 453 454void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv) 455{ 456 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 457 struct mlx5e_rep_priv *rpriv = priv->ppriv; 458 struct mlx5_eswitch_rep *rep = rpriv->rep; 459 460 mlx5e_sqs2vport_stop(esw, rep); 461} 462 463static int mlx5e_rep_open(struct net_device *dev) 464{ 465 struct mlx5e_priv *priv = netdev_priv(dev); 466 struct mlx5e_rep_priv *rpriv = priv->ppriv; 467 struct mlx5_eswitch_rep *rep = rpriv->rep; 468 int err; 469 470 mutex_lock(&priv->state_lock); 471 err = mlx5e_open_locked(dev); 472 if (err) 473 goto unlock; 474 475 if (!mlx5_modify_vport_admin_state(priv->mdev, 476 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 477 rep->vport, 1, 478 MLX5_VPORT_ADMIN_STATE_UP)) 479 netif_carrier_on(dev); 480 481unlock: 482 mutex_unlock(&priv->state_lock); 483 return err; 484} 485 486static int mlx5e_rep_close(struct net_device *dev) 487{ 488 struct mlx5e_priv *priv = netdev_priv(dev); 489 struct mlx5e_rep_priv *rpriv = priv->ppriv; 490 struct mlx5_eswitch_rep *rep = rpriv->rep; 491 int ret; 492 493 mutex_lock(&priv->state_lock); 494 mlx5_modify_vport_admin_state(priv->mdev, 495 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 496 rep->vport, 1, 497 MLX5_VPORT_ADMIN_STATE_DOWN); 498 ret = mlx5e_close_locked(dev); 499 mutex_unlock(&priv->state_lock); 500 return ret; 501} 502 503bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) 504{ 505 struct mlx5e_rep_priv *rpriv = priv->ppriv; 506 struct mlx5_eswitch_rep *rep; 507 508 if (!MLX5_ESWITCH_MANAGER(priv->mdev)) 509 return false; 510 511 if (!rpriv) /* non vport rep mlx5e instances don't use this field */ 512 return false; 513 514 rep = rpriv->rep; 515 return (rep->vport == MLX5_VPORT_UPLINK); 516} 517 518bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id) 519{ 520 switch (attr_id) { 521 case IFLA_OFFLOAD_XSTATS_CPU_HIT: 522 return true; 523 } 524 525 return false; 526} 527 528static int 529mlx5e_get_sw_stats64(const struct net_device *dev, 530 struct rtnl_link_stats64 *stats) 531{ 532 struct mlx5e_priv *priv = netdev_priv(dev); 533 534 mlx5e_fold_sw_stats64(priv, stats); 535 return 0; 536} 537 538int mlx5e_rep_get_offload_stats(int attr_id, const struct net_device *dev, 539 void *sp) 540{ 541 switch (attr_id) { 542 case IFLA_OFFLOAD_XSTATS_CPU_HIT: 543 return mlx5e_get_sw_stats64(dev, sp); 544 } 545 546 return -EINVAL; 547} 548 549static void 550mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) 551{ 552 struct mlx5e_priv *priv = netdev_priv(dev); 553 554 /* update HW stats in background for next time */ 555 mlx5e_queue_update_stats(priv); 556 memcpy(stats, &priv->stats.vf_vport, sizeof(*stats)); 557} 558 559static int mlx5e_rep_change_mtu(struct net_device *netdev, int new_mtu) 560{ 561 return mlx5e_change_mtu(netdev, new_mtu, NULL); 562} 563 564static struct devlink_port *mlx5e_rep_get_devlink_port(struct net_device *netdev) 565{ 566 struct mlx5e_priv *priv = netdev_priv(netdev); 567 struct mlx5e_rep_priv *rpriv = priv->ppriv; 568 struct mlx5_core_dev *dev = priv->mdev; 569 570 return mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport); 571} 572 573static int mlx5e_rep_change_carrier(struct net_device *dev, bool new_carrier) 574{ 575 struct mlx5e_priv *priv = netdev_priv(dev); 576 struct mlx5e_rep_priv *rpriv = priv->ppriv; 577 struct mlx5_eswitch_rep *rep = rpriv->rep; 578 int err; 579 580 if (new_carrier) { 581 err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 582 rep->vport, 1, MLX5_VPORT_ADMIN_STATE_UP); 583 if (err) 584 return err; 585 netif_carrier_on(dev); 586 } else { 587 err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, 588 rep->vport, 1, MLX5_VPORT_ADMIN_STATE_DOWN); 589 if (err) 590 return err; 591 netif_carrier_off(dev); 592 } 593 return 0; 594} 595 596static const struct net_device_ops mlx5e_netdev_ops_rep = { 597 .ndo_open = mlx5e_rep_open, 598 .ndo_stop = mlx5e_rep_close, 599 .ndo_start_xmit = mlx5e_xmit, 600 .ndo_setup_tc = mlx5e_rep_setup_tc, 601 .ndo_get_devlink_port = mlx5e_rep_get_devlink_port, 602 .ndo_get_stats64 = mlx5e_rep_get_stats, 603 .ndo_has_offload_stats = mlx5e_rep_has_offload_stats, 604 .ndo_get_offload_stats = mlx5e_rep_get_offload_stats, 605 .ndo_change_mtu = mlx5e_rep_change_mtu, 606 .ndo_change_carrier = mlx5e_rep_change_carrier, 607}; 608 609bool mlx5e_eswitch_uplink_rep(const struct net_device *netdev) 610{ 611 return netdev->netdev_ops == &mlx5e_netdev_ops && 612 mlx5e_is_uplink_rep(netdev_priv(netdev)); 613} 614 615bool mlx5e_eswitch_vf_rep(const struct net_device *netdev) 616{ 617 return netdev->netdev_ops == &mlx5e_netdev_ops_rep; 618} 619 620/* One indirect TIR set for outer. Inner not supported in reps. */ 621#define REP_NUM_INDIR_TIRS MLX5E_NUM_INDIR_TIRS 622 623static int mlx5e_rep_max_nch_limit(struct mlx5_core_dev *mdev) 624{ 625 int max_tir_num = 1 << MLX5_CAP_GEN(mdev, log_max_tir); 626 int num_vports = mlx5_eswitch_get_total_vports(mdev); 627 628 return (max_tir_num - mlx5e_get_pf_num_tirs(mdev) 629 - (num_vports * REP_NUM_INDIR_TIRS)) / num_vports; 630} 631 632static void mlx5e_build_rep_params(struct net_device *netdev) 633{ 634 struct mlx5e_priv *priv = netdev_priv(netdev); 635 struct mlx5e_rep_priv *rpriv = priv->ppriv; 636 struct mlx5_eswitch_rep *rep = rpriv->rep; 637 struct mlx5_core_dev *mdev = priv->mdev; 638 struct mlx5e_params *params; 639 640 u8 cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ? 641 MLX5_CQ_PERIOD_MODE_START_FROM_CQE : 642 MLX5_CQ_PERIOD_MODE_START_FROM_EQE; 643 644 params = &priv->channels.params; 645 646 params->num_channels = MLX5E_REP_PARAMS_DEF_NUM_CHANNELS; 647 params->hard_mtu = MLX5E_ETH_HARD_MTU; 648 params->sw_mtu = netdev->mtu; 649 650 /* SQ */ 651 if (rep->vport == MLX5_VPORT_UPLINK) 652 params->log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE; 653 else 654 params->log_sq_size = MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE; 655 656 /* RQ */ 657 mlx5e_build_rq_params(mdev, params); 658 659 /* CQ moderation params */ 660 params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation); 661 mlx5e_set_rx_cq_mode_params(params, cq_period_mode); 662 663 params->mqprio.num_tc = 1; 664 params->tunneled_offload_en = false; 665 666 mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode); 667} 668 669static void mlx5e_build_rep_netdev(struct net_device *netdev, 670 struct mlx5_core_dev *mdev) 671{ 672 SET_NETDEV_DEV(netdev, mdev->device); 673 netdev->netdev_ops = &mlx5e_netdev_ops_rep; 674 eth_hw_addr_random(netdev); 675 netdev->ethtool_ops = &mlx5e_rep_ethtool_ops; 676 677 netdev->watchdog_timeo = 15 * HZ; 678 679#if IS_ENABLED(CONFIG_MLX5_CLS_ACT) 680 netdev->hw_features |= NETIF_F_HW_TC; 681#endif 682 netdev->hw_features |= NETIF_F_SG; 683 netdev->hw_features |= NETIF_F_IP_CSUM; 684 netdev->hw_features |= NETIF_F_IPV6_CSUM; 685 netdev->hw_features |= NETIF_F_GRO; 686 netdev->hw_features |= NETIF_F_TSO; 687 netdev->hw_features |= NETIF_F_TSO6; 688 netdev->hw_features |= NETIF_F_RXCSUM; 689 690 netdev->features |= netdev->hw_features; 691 netdev->features |= NETIF_F_NETNS_LOCAL; 692} 693 694static int mlx5e_init_rep(struct mlx5_core_dev *mdev, 695 struct net_device *netdev) 696{ 697 struct mlx5e_priv *priv = netdev_priv(netdev); 698 699 mlx5e_build_rep_params(netdev); 700 mlx5e_timestamp_init(priv); 701 702 return 0; 703} 704 705static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev, 706 struct net_device *netdev) 707{ 708 struct mlx5e_priv *priv = netdev_priv(netdev); 709 int err; 710 711 err = mlx5e_ipsec_init(priv); 712 if (err) 713 mlx5_core_err(mdev, "Uplink rep IPsec initialization failed, %d\n", err); 714 715 mlx5e_vxlan_set_netdev_info(priv); 716 return mlx5e_init_rep(mdev, netdev); 717} 718 719static void mlx5e_cleanup_rep(struct mlx5e_priv *priv) 720{ 721 mlx5e_ipsec_cleanup(priv); 722} 723 724static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv) 725{ 726 struct mlx5e_rep_priv *rpriv = priv->ppriv; 727 struct mlx5_eswitch_rep *rep = rpriv->rep; 728 struct ttc_params ttc_params = {}; 729 int err; 730 731 priv->fs.ns = mlx5_get_flow_namespace(priv->mdev, 732 MLX5_FLOW_NAMESPACE_KERNEL); 733 734 /* The inner_ttc in the ttc params is intentionally not set */ 735 mlx5e_set_ttc_params(priv, &ttc_params, false); 736 737 if (rep->vport != MLX5_VPORT_UPLINK) 738 /* To give uplik rep TTC a lower level for chaining from root ft */ 739 ttc_params.ft_attr.level = MLX5E_TTC_FT_LEVEL + 1; 740 741 priv->fs.ttc = mlx5_create_ttc_table(priv->mdev, &ttc_params); 742 if (IS_ERR(priv->fs.ttc)) { 743 err = PTR_ERR(priv->fs.ttc); 744 netdev_err(priv->netdev, "Failed to create rep ttc table, err=%d\n", 745 err); 746 return err; 747 } 748 return 0; 749} 750 751static int mlx5e_create_rep_root_ft(struct mlx5e_priv *priv) 752{ 753 struct mlx5e_rep_priv *rpriv = priv->ppriv; 754 struct mlx5_eswitch_rep *rep = rpriv->rep; 755 struct mlx5_flow_table_attr ft_attr = {}; 756 struct mlx5_flow_namespace *ns; 757 int err = 0; 758 759 if (rep->vport != MLX5_VPORT_UPLINK) { 760 /* non uplik reps will skip any bypass tables and go directly to 761 * their own ttc 762 */ 763 rpriv->root_ft = mlx5_get_ttc_flow_table(priv->fs.ttc); 764 return 0; 765 } 766 767 /* uplink root ft will be used to auto chain, to ethtool or ttc tables */ 768 ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_OFFLOADS); 769 if (!ns) { 770 netdev_err(priv->netdev, "Failed to get reps offloads namespace\n"); 771 return -EOPNOTSUPP; 772 } 773 774 ft_attr.max_fte = 0; /* Empty table, miss rule will always point to next table */ 775 ft_attr.prio = 1; 776 ft_attr.level = 1; 777 778 rpriv->root_ft = mlx5_create_flow_table(ns, &ft_attr); 779 if (IS_ERR(rpriv->root_ft)) { 780 err = PTR_ERR(rpriv->root_ft); 781 rpriv->root_ft = NULL; 782 } 783 784 return err; 785} 786 787static void mlx5e_destroy_rep_root_ft(struct mlx5e_priv *priv) 788{ 789 struct mlx5e_rep_priv *rpriv = priv->ppriv; 790 struct mlx5_eswitch_rep *rep = rpriv->rep; 791 792 if (rep->vport != MLX5_VPORT_UPLINK) 793 return; 794 mlx5_destroy_flow_table(rpriv->root_ft); 795} 796 797static int mlx5e_create_rep_vport_rx_rule(struct mlx5e_priv *priv) 798{ 799 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 800 struct mlx5e_rep_priv *rpriv = priv->ppriv; 801 struct mlx5_eswitch_rep *rep = rpriv->rep; 802 struct mlx5_flow_handle *flow_rule; 803 struct mlx5_flow_destination dest; 804 805 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 806 dest.ft = rpriv->root_ft; 807 808 flow_rule = mlx5_eswitch_create_vport_rx_rule(esw, rep->vport, &dest); 809 if (IS_ERR(flow_rule)) 810 return PTR_ERR(flow_rule); 811 rpriv->vport_rx_rule = flow_rule; 812 return 0; 813} 814 815static void rep_vport_rx_rule_destroy(struct mlx5e_priv *priv) 816{ 817 struct mlx5e_rep_priv *rpriv = priv->ppriv; 818 819 if (!rpriv->vport_rx_rule) 820 return; 821 822 mlx5_del_flow_rules(rpriv->vport_rx_rule); 823 rpriv->vport_rx_rule = NULL; 824} 825 826int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup) 827{ 828 rep_vport_rx_rule_destroy(priv); 829 830 return cleanup ? 0 : mlx5e_create_rep_vport_rx_rule(priv); 831} 832 833static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) 834{ 835 struct mlx5_core_dev *mdev = priv->mdev; 836 int err; 837 838 priv->rx_res = mlx5e_rx_res_alloc(); 839 if (!priv->rx_res) 840 return -ENOMEM; 841 842 mlx5e_init_l2_addr(priv); 843 844 err = mlx5e_open_drop_rq(priv, &priv->drop_rq); 845 if (err) { 846 mlx5_core_err(mdev, "open drop rq failed, %d\n", err); 847 return err; 848 } 849 850 err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, 851 priv->max_nch, priv->drop_rq.rqn, 852 &priv->channels.params.packet_merge, 853 priv->channels.params.num_channels); 854 if (err) 855 goto err_close_drop_rq; 856 857 err = mlx5e_create_rep_ttc_table(priv); 858 if (err) 859 goto err_destroy_rx_res; 860 861 err = mlx5e_create_rep_root_ft(priv); 862 if (err) 863 goto err_destroy_ttc_table; 864 865 err = mlx5e_create_rep_vport_rx_rule(priv); 866 if (err) 867 goto err_destroy_root_ft; 868 869 mlx5e_ethtool_init_steering(priv); 870 871 return 0; 872 873err_destroy_root_ft: 874 mlx5e_destroy_rep_root_ft(priv); 875err_destroy_ttc_table: 876 mlx5_destroy_ttc_table(priv->fs.ttc); 877err_destroy_rx_res: 878 mlx5e_rx_res_destroy(priv->rx_res); 879err_close_drop_rq: 880 mlx5e_close_drop_rq(&priv->drop_rq); 881 mlx5e_rx_res_free(priv->rx_res); 882 priv->rx_res = NULL; 883 return err; 884} 885 886static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv) 887{ 888 mlx5e_ethtool_cleanup_steering(priv); 889 rep_vport_rx_rule_destroy(priv); 890 mlx5e_destroy_rep_root_ft(priv); 891 mlx5_destroy_ttc_table(priv->fs.ttc); 892 mlx5e_rx_res_destroy(priv->rx_res); 893 mlx5e_close_drop_rq(&priv->drop_rq); 894 mlx5e_rx_res_free(priv->rx_res); 895 priv->rx_res = NULL; 896} 897 898static int mlx5e_init_ul_rep_rx(struct mlx5e_priv *priv) 899{ 900 int err; 901 902 mlx5e_create_q_counters(priv); 903 err = mlx5e_init_rep_rx(priv); 904 if (err) 905 goto out; 906 907 mlx5e_tc_int_port_init_rep_rx(priv); 908 909out: 910 return err; 911} 912 913static void mlx5e_cleanup_ul_rep_rx(struct mlx5e_priv *priv) 914{ 915 mlx5e_tc_int_port_cleanup_rep_rx(priv); 916 mlx5e_cleanup_rep_rx(priv); 917 mlx5e_destroy_q_counters(priv); 918} 919 920static int mlx5e_init_uplink_rep_tx(struct mlx5e_rep_priv *rpriv) 921{ 922 struct mlx5_rep_uplink_priv *uplink_priv; 923 struct net_device *netdev; 924 struct mlx5e_priv *priv; 925 int err; 926 927 netdev = rpriv->netdev; 928 priv = netdev_priv(netdev); 929 uplink_priv = &rpriv->uplink_priv; 930 931 err = mlx5e_rep_tc_init(rpriv); 932 if (err) 933 return err; 934 935 mlx5_init_port_tun_entropy(&uplink_priv->tun_entropy, priv->mdev); 936 937 mlx5e_rep_bond_init(rpriv); 938 err = mlx5e_rep_tc_netdevice_event_register(rpriv); 939 if (err) { 940 mlx5_core_err(priv->mdev, "Failed to register netdev notifier, err: %d\n", 941 err); 942 goto err_event_reg; 943 } 944 945 return 0; 946 947err_event_reg: 948 mlx5e_rep_bond_cleanup(rpriv); 949 mlx5e_rep_tc_cleanup(rpriv); 950 return err; 951} 952 953static void mlx5e_cleanup_uplink_rep_tx(struct mlx5e_rep_priv *rpriv) 954{ 955 mlx5e_rep_tc_netdevice_event_unregister(rpriv); 956 mlx5e_rep_bond_cleanup(rpriv); 957 mlx5e_rep_tc_cleanup(rpriv); 958} 959 960static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) 961{ 962 struct mlx5e_rep_priv *rpriv = priv->ppriv; 963 int err; 964 965 err = mlx5e_create_tises(priv); 966 if (err) { 967 mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err); 968 return err; 969 } 970 971 if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { 972 err = mlx5e_init_uplink_rep_tx(rpriv); 973 if (err) 974 goto err_init_tx; 975 } 976 977 err = mlx5e_tc_ht_init(&rpriv->tc_ht); 978 if (err) 979 goto err_ht_init; 980 981 return 0; 982 983err_ht_init: 984 if (rpriv->rep->vport == MLX5_VPORT_UPLINK) 985 mlx5e_cleanup_uplink_rep_tx(rpriv); 986err_init_tx: 987 mlx5e_destroy_tises(priv); 988 return err; 989} 990 991static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv) 992{ 993 struct mlx5e_rep_priv *rpriv = priv->ppriv; 994 995 mlx5e_tc_ht_cleanup(&rpriv->tc_ht); 996 997 if (rpriv->rep->vport == MLX5_VPORT_UPLINK) 998 mlx5e_cleanup_uplink_rep_tx(rpriv); 999 1000 mlx5e_destroy_tises(priv); 1001} 1002 1003static void mlx5e_rep_enable(struct mlx5e_priv *priv) 1004{ 1005 struct mlx5e_rep_priv *rpriv = priv->ppriv; 1006 1007 mlx5e_set_netdev_mtu_boundaries(priv); 1008 mlx5e_rep_neigh_init(rpriv); 1009} 1010 1011static void mlx5e_rep_disable(struct mlx5e_priv *priv) 1012{ 1013 struct mlx5e_rep_priv *rpriv = priv->ppriv; 1014 1015 mlx5e_rep_neigh_cleanup(rpriv); 1016} 1017 1018static int mlx5e_update_rep_rx(struct mlx5e_priv *priv) 1019{ 1020 return 0; 1021} 1022 1023static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data) 1024{ 1025 struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb); 1026 1027 if (event == MLX5_EVENT_TYPE_PORT_CHANGE) { 1028 struct mlx5_eqe *eqe = data; 1029 1030 switch (eqe->sub_type) { 1031 case MLX5_PORT_CHANGE_SUBTYPE_DOWN: 1032 case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: 1033 queue_work(priv->wq, &priv->update_carrier_work); 1034 break; 1035 default: 1036 return NOTIFY_DONE; 1037 } 1038 1039 return NOTIFY_OK; 1040 } 1041 1042 if (event == MLX5_DEV_EVENT_PORT_AFFINITY) 1043 return mlx5e_rep_tc_event_port_affinity(priv); 1044 1045 return NOTIFY_DONE; 1046} 1047 1048static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) 1049{ 1050 struct mlx5e_rep_priv *rpriv = priv->ppriv; 1051 struct net_device *netdev = priv->netdev; 1052 struct mlx5_core_dev *mdev = priv->mdev; 1053 u16 max_mtu; 1054 1055 netdev->min_mtu = ETH_MIN_MTU; 1056 mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1); 1057 netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu); 1058 mlx5e_set_dev_port_mtu(priv); 1059 1060 mlx5e_rep_tc_enable(priv); 1061 1062 if (MLX5_CAP_GEN(mdev, uplink_follow)) 1063 mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK, 1064 0, 0, MLX5_VPORT_ADMIN_STATE_AUTO); 1065 mlx5_lag_add_netdev(mdev, netdev); 1066 priv->events_nb.notifier_call = uplink_rep_async_event; 1067 mlx5_notifier_register(mdev, &priv->events_nb); 1068 mlx5e_dcbnl_initialize(priv); 1069 mlx5e_dcbnl_init_app(priv); 1070 mlx5e_rep_neigh_init(rpriv); 1071 mlx5e_rep_bridge_init(priv); 1072 1073 netdev->wanted_features |= NETIF_F_HW_TC; 1074 1075 rtnl_lock(); 1076 if (netif_running(netdev)) 1077 mlx5e_open(netdev); 1078 udp_tunnel_nic_reset_ntf(priv->netdev); 1079 netif_device_attach(netdev); 1080 rtnl_unlock(); 1081} 1082 1083static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) 1084{ 1085 struct mlx5e_rep_priv *rpriv = priv->ppriv; 1086 struct mlx5_core_dev *mdev = priv->mdev; 1087 1088 rtnl_lock(); 1089 if (netif_running(priv->netdev)) 1090 mlx5e_close(priv->netdev); 1091 netif_device_detach(priv->netdev); 1092 rtnl_unlock(); 1093 1094 mlx5e_rep_bridge_cleanup(priv); 1095 mlx5e_rep_neigh_cleanup(rpriv); 1096 mlx5e_dcbnl_delete_app(priv); 1097 mlx5_notifier_unregister(mdev, &priv->events_nb); 1098 mlx5e_rep_tc_disable(priv); 1099 mlx5_lag_remove_netdev(mdev, priv->netdev); 1100 mlx5_vxlan_reset_to_default(mdev->vxlan); 1101} 1102 1103static MLX5E_DEFINE_STATS_GRP(sw_rep, 0); 1104static MLX5E_DEFINE_STATS_GRP(vport_rep, MLX5E_NDO_UPDATE_STATS); 1105 1106/* The stats groups order is opposite to the update_stats() order calls */ 1107static mlx5e_stats_grp_t mlx5e_rep_stats_grps[] = { 1108 &MLX5E_STATS_GRP(sw_rep), 1109 &MLX5E_STATS_GRP(vport_rep), 1110}; 1111 1112static unsigned int mlx5e_rep_stats_grps_num(struct mlx5e_priv *priv) 1113{ 1114 return ARRAY_SIZE(mlx5e_rep_stats_grps); 1115} 1116 1117/* The stats groups order is opposite to the update_stats() order calls */ 1118static mlx5e_stats_grp_t mlx5e_ul_rep_stats_grps[] = { 1119 &MLX5E_STATS_GRP(sw), 1120 &MLX5E_STATS_GRP(qcnt), 1121 &MLX5E_STATS_GRP(vnic_env), 1122 &MLX5E_STATS_GRP(vport), 1123 &MLX5E_STATS_GRP(802_3), 1124 &MLX5E_STATS_GRP(2863), 1125 &MLX5E_STATS_GRP(2819), 1126 &MLX5E_STATS_GRP(phy), 1127 &MLX5E_STATS_GRP(eth_ext), 1128 &MLX5E_STATS_GRP(pcie), 1129 &MLX5E_STATS_GRP(per_prio), 1130 &MLX5E_STATS_GRP(pme), 1131 &MLX5E_STATS_GRP(channels), 1132 &MLX5E_STATS_GRP(per_port_buff_congest), 1133#ifdef CONFIG_MLX5_EN_IPSEC 1134 &MLX5E_STATS_GRP(ipsec_sw), 1135#endif 1136 &MLX5E_STATS_GRP(ptp), 1137}; 1138 1139static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv) 1140{ 1141 return ARRAY_SIZE(mlx5e_ul_rep_stats_grps); 1142} 1143 1144static const struct mlx5e_profile mlx5e_rep_profile = { 1145 .init = mlx5e_init_rep, 1146 .cleanup = mlx5e_cleanup_rep, 1147 .init_rx = mlx5e_init_rep_rx, 1148 .cleanup_rx = mlx5e_cleanup_rep_rx, 1149 .init_tx = mlx5e_init_rep_tx, 1150 .cleanup_tx = mlx5e_cleanup_rep_tx, 1151 .enable = mlx5e_rep_enable, 1152 .disable = mlx5e_rep_disable, 1153 .update_rx = mlx5e_update_rep_rx, 1154 .update_stats = mlx5e_stats_update_ndo_stats, 1155 .rx_handlers = &mlx5e_rx_handlers_rep, 1156 .max_tc = 1, 1157 .rq_groups = MLX5E_NUM_RQ_GROUPS(REGULAR), 1158 .stats_grps = mlx5e_rep_stats_grps, 1159 .stats_grps_num = mlx5e_rep_stats_grps_num, 1160 .max_nch_limit = mlx5e_rep_max_nch_limit, 1161}; 1162 1163static const struct mlx5e_profile mlx5e_uplink_rep_profile = { 1164 .init = mlx5e_init_ul_rep, 1165 .cleanup = mlx5e_cleanup_rep, 1166 .init_rx = mlx5e_init_ul_rep_rx, 1167 .cleanup_rx = mlx5e_cleanup_ul_rep_rx, 1168 .init_tx = mlx5e_init_rep_tx, 1169 .cleanup_tx = mlx5e_cleanup_rep_tx, 1170 .enable = mlx5e_uplink_rep_enable, 1171 .disable = mlx5e_uplink_rep_disable, 1172 .update_rx = mlx5e_update_rep_rx, 1173 .update_stats = mlx5e_stats_update_ndo_stats, 1174 .update_carrier = mlx5e_update_carrier, 1175 .rx_handlers = &mlx5e_rx_handlers_rep, 1176 .max_tc = MLX5E_MAX_NUM_TC, 1177 /* XSK is needed so we can replace profile with NIC netdev */ 1178 .rq_groups = MLX5E_NUM_RQ_GROUPS(XSK), 1179 .stats_grps = mlx5e_ul_rep_stats_grps, 1180 .stats_grps_num = mlx5e_ul_rep_stats_grps_num, 1181}; 1182 1183/* e-Switch vport representors */ 1184static int 1185mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) 1186{ 1187 struct mlx5e_priv *priv = netdev_priv(mlx5_uplink_netdev_get(dev)); 1188 struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); 1189 struct devlink_port *dl_port; 1190 int err; 1191 1192 rpriv->netdev = priv->netdev; 1193 1194 err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile, 1195 rpriv); 1196 if (err) 1197 return err; 1198 1199 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport); 1200 if (dl_port) 1201 devlink_port_type_eth_set(dl_port, rpriv->netdev); 1202 1203 return 0; 1204} 1205 1206static void 1207mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv) 1208{ 1209 struct net_device *netdev = rpriv->netdev; 1210 struct devlink_port *dl_port; 1211 struct mlx5_core_dev *dev; 1212 struct mlx5e_priv *priv; 1213 1214 priv = netdev_priv(netdev); 1215 dev = priv->mdev; 1216 1217 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport); 1218 if (dl_port) 1219 devlink_port_type_clear(dl_port); 1220 mlx5e_netdev_attach_nic_profile(priv); 1221} 1222 1223static int 1224mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) 1225{ 1226 struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); 1227 const struct mlx5e_profile *profile; 1228 struct devlink_port *dl_port; 1229 struct net_device *netdev; 1230 struct mlx5e_priv *priv; 1231 int err; 1232 1233 profile = &mlx5e_rep_profile; 1234 netdev = mlx5e_create_netdev(dev, profile); 1235 if (!netdev) { 1236 mlx5_core_warn(dev, 1237 "Failed to create representor netdev for vport %d\n", 1238 rep->vport); 1239 return -EINVAL; 1240 } 1241 1242 mlx5e_build_rep_netdev(netdev, dev); 1243 rpriv->netdev = netdev; 1244 1245 priv = netdev_priv(netdev); 1246 priv->profile = profile; 1247 priv->ppriv = rpriv; 1248 err = profile->init(dev, netdev); 1249 if (err) { 1250 netdev_warn(netdev, "rep profile init failed, %d\n", err); 1251 goto err_destroy_netdev; 1252 } 1253 1254 err = mlx5e_attach_netdev(netdev_priv(netdev)); 1255 if (err) { 1256 netdev_warn(netdev, 1257 "Failed to attach representor netdev for vport %d\n", 1258 rep->vport); 1259 goto err_cleanup_profile; 1260 } 1261 1262 err = register_netdev(netdev); 1263 if (err) { 1264 netdev_warn(netdev, 1265 "Failed to register representor netdev for vport %d\n", 1266 rep->vport); 1267 goto err_detach_netdev; 1268 } 1269 1270 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport); 1271 if (dl_port) 1272 devlink_port_type_eth_set(dl_port, netdev); 1273 return 0; 1274 1275err_detach_netdev: 1276 mlx5e_detach_netdev(netdev_priv(netdev)); 1277 1278err_cleanup_profile: 1279 priv->profile->cleanup(priv); 1280 1281err_destroy_netdev: 1282 mlx5e_destroy_netdev(netdev_priv(netdev)); 1283 return err; 1284} 1285 1286static int 1287mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) 1288{ 1289 struct mlx5e_rep_priv *rpriv; 1290 int err; 1291 1292 rpriv = kvzalloc(sizeof(*rpriv), GFP_KERNEL); 1293 if (!rpriv) 1294 return -ENOMEM; 1295 1296 /* rpriv->rep to be looked up when profile->init() is called */ 1297 rpriv->rep = rep; 1298 rep->rep_data[REP_ETH].priv = rpriv; 1299 INIT_LIST_HEAD(&rpriv->vport_sqs_list); 1300 1301 if (rep->vport == MLX5_VPORT_UPLINK) 1302 err = mlx5e_vport_uplink_rep_load(dev, rep); 1303 else 1304 err = mlx5e_vport_vf_rep_load(dev, rep); 1305 1306 if (err) 1307 kvfree(rpriv); 1308 1309 return err; 1310} 1311 1312static void 1313mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep) 1314{ 1315 struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); 1316 struct net_device *netdev = rpriv->netdev; 1317 struct mlx5e_priv *priv = netdev_priv(netdev); 1318 struct mlx5_core_dev *dev = priv->mdev; 1319 struct devlink_port *dl_port; 1320 void *ppriv = priv->ppriv; 1321 1322 if (rep->vport == MLX5_VPORT_UPLINK) { 1323 mlx5e_vport_uplink_rep_unload(rpriv); 1324 goto free_ppriv; 1325 } 1326 1327 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport); 1328 if (dl_port) 1329 devlink_port_type_clear(dl_port); 1330 unregister_netdev(netdev); 1331 mlx5e_detach_netdev(priv); 1332 priv->profile->cleanup(priv); 1333 mlx5e_destroy_netdev(priv); 1334free_ppriv: 1335 kvfree(ppriv); /* mlx5e_rep_priv */ 1336} 1337 1338static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep) 1339{ 1340 struct mlx5e_rep_priv *rpriv; 1341 1342 rpriv = mlx5e_rep_to_rep_priv(rep); 1343 1344 return rpriv->netdev; 1345} 1346 1347static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep) 1348{ 1349 struct mlx5e_rep_priv *rpriv; 1350 struct mlx5e_rep_sq *rep_sq; 1351 1352 rpriv = mlx5e_rep_to_rep_priv(rep); 1353 list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { 1354 if (!rep_sq->send_to_vport_rule_peer) 1355 continue; 1356 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); 1357 rep_sq->send_to_vport_rule_peer = NULL; 1358 } 1359} 1360 1361static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw, 1362 struct mlx5_eswitch_rep *rep, 1363 struct mlx5_eswitch *peer_esw) 1364{ 1365 struct mlx5_flow_handle *flow_rule; 1366 struct mlx5e_rep_priv *rpriv; 1367 struct mlx5e_rep_sq *rep_sq; 1368 1369 rpriv = mlx5e_rep_to_rep_priv(rep); 1370 list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { 1371 if (rep_sq->send_to_vport_rule_peer) 1372 continue; 1373 flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn); 1374 if (IS_ERR(flow_rule)) 1375 goto err_out; 1376 rep_sq->send_to_vport_rule_peer = flow_rule; 1377 } 1378 1379 return 0; 1380err_out: 1381 mlx5e_vport_rep_event_unpair(rep); 1382 return PTR_ERR(flow_rule); 1383} 1384 1385static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw, 1386 struct mlx5_eswitch_rep *rep, 1387 enum mlx5_switchdev_event event, 1388 void *data) 1389{ 1390 int err = 0; 1391 1392 if (event == MLX5_SWITCHDEV_EVENT_PAIR) 1393 err = mlx5e_vport_rep_event_pair(esw, rep, data); 1394 else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR) 1395 mlx5e_vport_rep_event_unpair(rep); 1396 1397 return err; 1398} 1399 1400static const struct mlx5_eswitch_rep_ops rep_ops = { 1401 .load = mlx5e_vport_rep_load, 1402 .unload = mlx5e_vport_rep_unload, 1403 .get_proto_dev = mlx5e_vport_rep_get_proto_dev, 1404 .event = mlx5e_vport_rep_event, 1405}; 1406 1407static int mlx5e_rep_probe(struct auxiliary_device *adev, 1408 const struct auxiliary_device_id *id) 1409{ 1410 struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 1411 struct mlx5_core_dev *mdev = edev->mdev; 1412 struct mlx5_eswitch *esw; 1413 1414 esw = mdev->priv.eswitch; 1415 mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_ETH); 1416 return 0; 1417} 1418 1419static void mlx5e_rep_remove(struct auxiliary_device *adev) 1420{ 1421 struct mlx5_adev *vdev = container_of(adev, struct mlx5_adev, adev); 1422 struct mlx5_core_dev *mdev = vdev->mdev; 1423 struct mlx5_eswitch *esw; 1424 1425 esw = mdev->priv.eswitch; 1426 mlx5_eswitch_unregister_vport_reps(esw, REP_ETH); 1427} 1428 1429static const struct auxiliary_device_id mlx5e_rep_id_table[] = { 1430 { .name = MLX5_ADEV_NAME ".eth-rep", }, 1431 {}, 1432}; 1433 1434MODULE_DEVICE_TABLE(auxiliary, mlx5e_rep_id_table); 1435 1436static struct auxiliary_driver mlx5e_rep_driver = { 1437 .name = "eth-rep", 1438 .probe = mlx5e_rep_probe, 1439 .remove = mlx5e_rep_remove, 1440 .id_table = mlx5e_rep_id_table, 1441}; 1442 1443int mlx5e_rep_init(void) 1444{ 1445 return auxiliary_driver_register(&mlx5e_rep_driver); 1446} 1447 1448void mlx5e_rep_cleanup(void) 1449{ 1450 auxiliary_driver_unregister(&mlx5e_rep_driver); 1451}