Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mlx5-updates-2023-05-31' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2023-05-31

net/mlx5: Support 4 ports VF LAG, part 1/2

This series continues the series[1] "Support 4 ports HCAs LAG mode"
by Mark Bloch. This series adds support for 4 ports VF LAG (single FDB
E-Switch).

This series of patches focuses on refactoring different sections of the
code that make assumptions about VF LAG supporting only two ports. For
instance, it assumes that each device can only have one peer.

Patches 1-5:
- Refactor ETH handling of TC rules of eswitches with peers.
Patch 6:
- Refactors peer miss group table.
Patches 7-9:
- Refactor single FDB E-Switch creation.
Patch 10:
- Refactor the DR layer.
Patches 11-14:
- Refactors devcom layer.

Next series will refactor LAG layer and enable 4 ports VF LAG.
This series specifically allows HCAs with 4 ports to create a VF LAG
with only 4 ports. It is not possible to create a VF LAG with 2 or 3
ports using HCAs that have 4 ports.

Currently, the Merged E-Switch feature only supports HCAs with 2 ports.
However, upcoming patches will introduce support for HCAs with 4 ports.

In order to activate VF LAG a user can execute:

devlink dev eswitch set pci/0000:08:00.0 mode switchdev
devlink dev eswitch set pci/0000:08:00.1 mode switchdev
devlink dev eswitch set pci/0000:08:00.2 mode switchdev
devlink dev eswitch set pci/0000:08:00.3 mode switchdev
ip link add name bond0 type bond
ip link set dev bond0 type bond mode 802.3ad
ip link set dev eth2 master bond0
ip link set dev eth3 master bond0
ip link set dev eth4 master bond0
ip link set dev eth5 master bond0

Where eth2, eth3, eth4 and eth5 are net-interfaces of pci/0000:08:00.0
pci/0000:08:00.1 pci/0000:08:00.2 pci/0000:08:00.3 respectively.

User can verify LAG state and type via debugfs:
/sys/kernel/debug/mlx5/0000\:08\:00.0/lag/state
/sys/kernel/debug/mlx5/0000\:08\:00.0/lag/type

[1]
https://lore.kernel.org/netdev/20220510055743.118828-1-saeedm@nvidia.com/

* tag 'mlx5-updates-2023-05-31' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux:
net/mlx5: Devcom, extend mlx5_devcom_send_event to work with more than two devices
net/mlx5: Devcom, introduce devcom_for_each_peer_entry
net/mlx5: E-switch, mark devcom as not ready when all eswitches are unpaired
net/mlx5: Devcom, Rename paired to ready
net/mlx5: DR, handle more than one peer domain
net/mlx5: E-switch, generalize shared FDB creation
net/mlx5: E-switch, Handle multiple master egress rules
net/mlx5: E-switch, refactor FDB miss rule add/remove
net/mlx5: E-switch, enlarge peer miss group table
net/mlx5e: Handle offloads flows per peer
net/mlx5e: en_tc, re-factor query route port
net/mlx5e: rep, store send to vport rules per peer
net/mlx5e: tc, Refactor peer add/del flow
net/mlx5e: en_tc, Extend peer flows to a list
====================

Link: https://lore.kernel.org/r/20230602191301.47004-1-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+612 -280
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
··· 94 94 * destinations. 95 95 */ 96 96 struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS]; 97 - struct mlx5e_tc_flow *peer_flow; 98 97 struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */ 99 98 struct list_head hairpin; /* flows sharing the same hairpin */ 100 - struct list_head peer; /* flows with peer flow */ 99 + struct list_head peer[MLX5_MAX_PORTS]; /* flows with peer flow */ 101 100 struct list_head unready; /* flows not ready to be offloaded (e.g 102 101 * due to missing route) 103 102 */ 103 + struct list_head peer_flows; /* flows on peer */ 104 104 struct net_device *orig_dev; /* netdev adding flow first */ 105 105 int tmp_entry_index; 106 106 struct list_head tmp_list; /* temporary flow list used by neigh update */
+110 -27
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
··· 374 374 struct mlx5_eswitch_rep *rep) 375 375 { 376 376 struct mlx5e_rep_sq *rep_sq, *tmp; 377 + struct mlx5e_rep_sq_peer *sq_peer; 377 378 struct mlx5e_rep_priv *rpriv; 379 + unsigned long i; 378 380 379 381 if (esw->mode != MLX5_ESWITCH_OFFLOADS) 380 382 return; ··· 384 382 rpriv = mlx5e_rep_to_rep_priv(rep); 385 383 list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) { 386 384 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); 387 - if (rep_sq->send_to_vport_rule_peer) 388 - mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); 385 + xa_for_each(&rep_sq->sq_peer, i, sq_peer) { 386 + if (sq_peer->rule) 387 + mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule); 388 + 389 + xa_erase(&rep_sq->sq_peer, i); 390 + kfree(sq_peer); 391 + } 392 + 393 + xa_destroy(&rep_sq->sq_peer); 389 394 list_del(&rep_sq->list); 390 395 kfree(rep_sq); 391 396 } 397 + } 398 + 399 + static int mlx5e_sqs2vport_add_peers_rules(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, 400 + struct mlx5_devcom *devcom, 401 + struct mlx5e_rep_sq *rep_sq, int i) 402 + { 403 + struct mlx5_eswitch *peer_esw = NULL; 404 + struct mlx5_flow_handle *flow_rule; 405 + int tmp; 406 + 407 + mlx5_devcom_for_each_peer_entry(devcom, MLX5_DEVCOM_ESW_OFFLOADS, 408 + peer_esw, tmp) { 409 + int peer_rule_idx = mlx5_get_dev_index(peer_esw->dev); 410 + struct mlx5e_rep_sq_peer *sq_peer; 411 + int err; 412 + 413 + sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL); 414 + if (!sq_peer) 415 + return -ENOMEM; 416 + 417 + flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, 418 + rep, rep_sq->sqn); 419 + if (IS_ERR(flow_rule)) { 420 + kfree(sq_peer); 421 + return PTR_ERR(flow_rule); 422 + } 423 + 424 + sq_peer->rule = flow_rule; 425 + sq_peer->peer = peer_esw; 426 + err = xa_insert(&rep_sq->sq_peer, peer_rule_idx, sq_peer, GFP_KERNEL); 427 + if (err) { 428 + kfree(sq_peer); 429 + mlx5_eswitch_del_send_to_vport_rule(flow_rule); 430 + return err; 431 + } 432 + } 433 + 434 + return 0; 392 435 } 393 436 394 437 static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, 395 438 struct mlx5_eswitch_rep *rep, 396 439 u32 *sqns_array, int sqns_num) 397 440 { 398 - struct mlx5_eswitch *peer_esw = NULL; 399 441 struct mlx5_flow_handle *flow_rule; 400 442 struct mlx5e_rep_priv *rpriv; 401 443 struct mlx5e_rep_sq *rep_sq; 444 + struct mlx5_devcom *devcom; 445 + bool devcom_locked = false; 402 446 int err; 403 447 int i; 404 448 405 449 if (esw->mode != MLX5_ESWITCH_OFFLOADS) 406 450 return 0; 407 451 452 + devcom = esw->dev->priv.devcom; 408 453 rpriv = mlx5e_rep_to_rep_priv(rep); 409 - if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS)) 410 - peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom, 411 - MLX5_DEVCOM_ESW_OFFLOADS); 454 + if (mlx5_devcom_comp_is_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS) && 455 + mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) 456 + devcom_locked = true; 412 457 413 458 for (i = 0; i < sqns_num; i++) { 414 459 rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL); ··· 475 426 rep_sq->send_to_vport_rule = flow_rule; 476 427 rep_sq->sqn = sqns_array[i]; 477 428 478 - if (peer_esw) { 479 - flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, 480 - rep, sqns_array[i]); 481 - if (IS_ERR(flow_rule)) { 482 - err = PTR_ERR(flow_rule); 429 + xa_init(&rep_sq->sq_peer); 430 + if (devcom_locked) { 431 + err = mlx5e_sqs2vport_add_peers_rules(esw, rep, devcom, rep_sq, i); 432 + if (err) { 483 433 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); 434 + xa_destroy(&rep_sq->sq_peer); 484 435 kfree(rep_sq); 485 436 goto out_err; 486 437 } 487 - rep_sq->send_to_vport_rule_peer = flow_rule; 488 438 } 489 439 490 440 list_add(&rep_sq->list, &rpriv->vport_sqs_list); 491 441 } 492 442 493 - if (peer_esw) 494 - mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); 443 + if (devcom_locked) 444 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 495 445 496 446 return 0; 497 447 498 448 out_err: 499 449 mlx5e_sqs2vport_stop(esw, rep); 500 450 501 - if (peer_esw) 502 - mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); 451 + if (devcom_locked) 452 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 503 453 504 454 return err; 505 455 } ··· 1578 1530 return rpriv->netdev; 1579 1531 } 1580 1532 1581 - static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep) 1533 + static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep, 1534 + struct mlx5_eswitch *peer_esw) 1582 1535 { 1536 + int i = mlx5_get_dev_index(peer_esw->dev); 1583 1537 struct mlx5e_rep_priv *rpriv; 1584 1538 struct mlx5e_rep_sq *rep_sq; 1585 1539 1540 + WARN_ON_ONCE(!peer_esw); 1586 1541 rpriv = mlx5e_rep_to_rep_priv(rep); 1587 1542 list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { 1588 - if (!rep_sq->send_to_vport_rule_peer) 1543 + struct mlx5e_rep_sq_peer *sq_peer = xa_load(&rep_sq->sq_peer, i); 1544 + 1545 + if (!sq_peer || sq_peer->peer != peer_esw) 1589 1546 continue; 1590 - mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); 1591 - rep_sq->send_to_vport_rule_peer = NULL; 1547 + 1548 + mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule); 1549 + xa_erase(&rep_sq->sq_peer, i); 1550 + kfree(sq_peer); 1592 1551 } 1593 1552 } 1594 1553 ··· 1603 1548 struct mlx5_eswitch_rep *rep, 1604 1549 struct mlx5_eswitch *peer_esw) 1605 1550 { 1551 + int i = mlx5_get_dev_index(peer_esw->dev); 1606 1552 struct mlx5_flow_handle *flow_rule; 1553 + struct mlx5e_rep_sq_peer *sq_peer; 1607 1554 struct mlx5e_rep_priv *rpriv; 1608 1555 struct mlx5e_rep_sq *rep_sq; 1556 + int err; 1609 1557 1610 1558 rpriv = mlx5e_rep_to_rep_priv(rep); 1611 1559 list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { 1612 - if (rep_sq->send_to_vport_rule_peer) 1560 + sq_peer = xa_load(&rep_sq->sq_peer, i); 1561 + 1562 + if (sq_peer && sq_peer->peer) 1613 1563 continue; 1614 - flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn); 1615 - if (IS_ERR(flow_rule)) 1564 + 1565 + flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, 1566 + rep_sq->sqn); 1567 + if (IS_ERR(flow_rule)) { 1568 + err = PTR_ERR(flow_rule); 1616 1569 goto err_out; 1617 - rep_sq->send_to_vport_rule_peer = flow_rule; 1570 + } 1571 + 1572 + if (sq_peer) { 1573 + sq_peer->rule = flow_rule; 1574 + sq_peer->peer = peer_esw; 1575 + continue; 1576 + } 1577 + sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL); 1578 + if (!sq_peer) { 1579 + err = -ENOMEM; 1580 + goto err_sq_alloc; 1581 + } 1582 + err = xa_insert(&rep_sq->sq_peer, i, sq_peer, GFP_KERNEL); 1583 + if (err) 1584 + goto err_xa; 1585 + sq_peer->rule = flow_rule; 1586 + sq_peer->peer = peer_esw; 1618 1587 } 1619 1588 1620 1589 return 0; 1590 + err_xa: 1591 + kfree(sq_peer); 1592 + err_sq_alloc: 1593 + mlx5_eswitch_del_send_to_vport_rule(flow_rule); 1621 1594 err_out: 1622 - mlx5e_vport_rep_event_unpair(rep); 1623 - return PTR_ERR(flow_rule); 1595 + mlx5e_vport_rep_event_unpair(rep, peer_esw); 1596 + return err; 1624 1597 } 1625 1598 1626 1599 static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw, ··· 1661 1578 if (event == MLX5_SWITCHDEV_EVENT_PAIR) 1662 1579 err = mlx5e_vport_rep_event_pair(esw, rep, data); 1663 1580 else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR) 1664 - mlx5e_vport_rep_event_unpair(rep); 1581 + mlx5e_vport_rep_event_unpair(rep, data); 1665 1582 1666 1583 return err; 1667 1584 }
+6 -1
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
··· 225 225 struct rcu_head rcu; 226 226 }; 227 227 228 + struct mlx5e_rep_sq_peer { 229 + struct mlx5_flow_handle *rule; 230 + void *peer; 231 + }; 232 + 228 233 struct mlx5e_rep_sq { 229 234 struct mlx5_flow_handle *send_to_vport_rule; 230 - struct mlx5_flow_handle *send_to_vport_rule_peer; 235 + struct xarray sq_peer; 231 236 u32 sqn; 232 237 struct list_head list; 233 238 };
+112 -75
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 1666 1666 { 1667 1667 struct mlx5e_priv *out_priv, *route_priv; 1668 1668 struct mlx5_core_dev *route_mdev; 1669 + struct mlx5_devcom *devcom; 1669 1670 struct mlx5_eswitch *esw; 1670 1671 u16 vhca_id; 1672 + int err; 1673 + int i; 1671 1674 1672 1675 out_priv = netdev_priv(out_dev); 1673 1676 esw = out_priv->mdev->priv.eswitch; ··· 1678 1675 route_mdev = route_priv->mdev; 1679 1676 1680 1677 vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id); 1681 - if (mlx5_lag_is_active(out_priv->mdev)) { 1682 - struct mlx5_devcom *devcom; 1683 - int err; 1684 - 1685 - /* In lag case we may get devices from different eswitch instances. 1686 - * If we failed to get vport num, it means, mostly, that we on the wrong 1687 - * eswitch. 1688 - */ 1689 - err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); 1690 - if (err != -ENOENT) 1691 - return err; 1692 - 1693 - rcu_read_lock(); 1694 - devcom = out_priv->mdev->priv.devcom; 1695 - esw = mlx5_devcom_get_peer_data_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 1696 - err = esw ? mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport) : -ENODEV; 1697 - rcu_read_unlock(); 1698 - 1678 + err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); 1679 + if (!err) 1699 1680 return err; 1700 - } 1701 1681 1702 - return mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); 1682 + if (!mlx5_lag_is_active(out_priv->mdev)) 1683 + return err; 1684 + 1685 + rcu_read_lock(); 1686 + devcom = out_priv->mdev->priv.devcom; 1687 + err = -ENODEV; 1688 + mlx5_devcom_for_each_peer_entry_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS, 1689 + esw, i) { 1690 + err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); 1691 + if (!err) 1692 + break; 1693 + } 1694 + rcu_read_unlock(); 1695 + 1696 + return err; 1703 1697 } 1704 1698 1705 1699 static int ··· 1986 1986 mlx5e_flow_put(priv, flow); 1987 1987 } 1988 1988 1989 - static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) 1989 + static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow, 1990 + int peer_index) 1990 1991 { 1991 1992 struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch; 1993 + struct mlx5e_tc_flow *peer_flow; 1994 + struct mlx5e_tc_flow *tmp; 1992 1995 1993 1996 if (!flow_flag_test(flow, ESWITCH) || 1994 1997 !flow_flag_test(flow, DUP)) 1995 1998 return; 1996 1999 1997 2000 mutex_lock(&esw->offloads.peer_mutex); 1998 - list_del(&flow->peer); 2001 + list_del(&flow->peer[peer_index]); 1999 2002 mutex_unlock(&esw->offloads.peer_mutex); 2000 2003 2001 - flow_flag_clear(flow, DUP); 2002 - 2003 - if (refcount_dec_and_test(&flow->peer_flow->refcnt)) { 2004 - mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow); 2005 - kfree(flow->peer_flow); 2004 + list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) { 2005 + if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev)) 2006 + continue; 2007 + if (refcount_dec_and_test(&peer_flow->refcnt)) { 2008 + mlx5e_tc_del_fdb_flow(peer_flow->priv, peer_flow); 2009 + list_del(&peer_flow->peer_flows); 2010 + kfree(peer_flow); 2011 + } 2006 2012 } 2007 2013 2008 - flow->peer_flow = NULL; 2014 + if (list_empty(&flow->peer_flows)) 2015 + flow_flag_clear(flow, DUP); 2009 2016 } 2010 2017 2011 - static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) 2018 + static void mlx5e_tc_del_fdb_peers_flow(struct mlx5e_tc_flow *flow) 2012 2019 { 2013 - struct mlx5_core_dev *dev = flow->priv->mdev; 2014 - struct mlx5_devcom *devcom = dev->priv.devcom; 2015 - struct mlx5_eswitch *peer_esw; 2020 + int i; 2016 2021 2017 - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 2018 - if (!peer_esw) 2019 - return; 2020 - 2021 - __mlx5e_tc_del_fdb_peer_flow(flow); 2022 - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 2022 + for (i = 0; i < MLX5_MAX_PORTS; i++) { 2023 + if (i == mlx5_get_dev_index(flow->priv->mdev)) 2024 + continue; 2025 + mlx5e_tc_del_fdb_peer_flow(flow, i); 2026 + } 2023 2027 } 2024 2028 2025 2029 static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, 2026 2030 struct mlx5e_tc_flow *flow) 2027 2031 { 2028 2032 if (mlx5e_is_eswitch_flow(flow)) { 2029 - mlx5e_tc_del_fdb_peer_flow(flow); 2033 + struct mlx5_devcom *devcom = flow->priv->mdev->priv.devcom; 2034 + 2035 + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { 2036 + mlx5e_tc_del_fdb_flow(priv, flow); 2037 + return; 2038 + } 2039 + 2040 + mlx5e_tc_del_fdb_peers_flow(flow); 2041 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 2030 2042 mlx5e_tc_del_fdb_flow(priv, flow); 2031 2043 } else { 2032 2044 mlx5e_tc_del_nic_flow(priv, flow); ··· 4215 4203 flow_flag_test(flow, INGRESS); 4216 4204 bool act_is_encap = !!(attr->action & 4217 4205 MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT); 4218 - bool esw_paired = mlx5_devcom_is_paired(esw_attr->in_mdev->priv.devcom, 4219 - MLX5_DEVCOM_ESW_OFFLOADS); 4206 + bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.devcom, 4207 + MLX5_DEVCOM_ESW_OFFLOADS); 4220 4208 4221 4209 if (!esw_paired) 4222 4210 return false; ··· 4307 4295 INIT_LIST_HEAD(&flow->hairpin); 4308 4296 INIT_LIST_HEAD(&flow->l3_to_l2_reformat); 4309 4297 INIT_LIST_HEAD(&flow->attrs); 4298 + INIT_LIST_HEAD(&flow->peer_flows); 4310 4299 refcount_set(&flow->refcnt, 1); 4311 4300 init_completion(&flow->init_done); 4312 4301 init_completion(&flow->del_hw_done); ··· 4416 4403 4417 4404 static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, 4418 4405 struct mlx5e_tc_flow *flow, 4419 - unsigned long flow_flags) 4406 + unsigned long flow_flags, 4407 + struct mlx5_eswitch *peer_esw) 4420 4408 { 4421 4409 struct mlx5e_priv *priv = flow->priv, *peer_priv; 4422 - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw; 4410 + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 4423 4411 struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr; 4424 - struct mlx5_devcom *devcom = priv->mdev->priv.devcom; 4425 4412 struct mlx5e_tc_flow_parse_attr *parse_attr; 4413 + int i = mlx5_get_dev_index(peer_esw->dev); 4426 4414 struct mlx5e_rep_priv *peer_urpriv; 4427 4415 struct mlx5e_tc_flow *peer_flow; 4428 4416 struct mlx5_core_dev *in_mdev; 4429 4417 int err = 0; 4430 - 4431 - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 4432 - if (!peer_esw) 4433 - return -ENODEV; 4434 4418 4435 4419 peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH); 4436 4420 peer_priv = netdev_priv(peer_urpriv->netdev); ··· 4453 4443 goto out; 4454 4444 } 4455 4445 4456 - flow->peer_flow = peer_flow; 4446 + list_add_tail(&peer_flow->peer_flows, &flow->peer_flows); 4457 4447 flow_flag_set(flow, DUP); 4458 4448 mutex_lock(&esw->offloads.peer_mutex); 4459 - list_add_tail(&flow->peer, &esw->offloads.peer_flows); 4449 + list_add_tail(&flow->peer[i], &esw->offloads.peer_flows[i]); 4460 4450 mutex_unlock(&esw->offloads.peer_mutex); 4461 4451 4462 4452 out: 4463 - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 4464 4453 return err; 4465 4454 } 4466 4455 ··· 4470 4461 struct net_device *filter_dev, 4471 4462 struct mlx5e_tc_flow **__flow) 4472 4463 { 4464 + struct mlx5_devcom *devcom = priv->mdev->priv.devcom; 4473 4465 struct mlx5e_rep_priv *rpriv = priv->ppriv; 4474 4466 struct mlx5_eswitch_rep *in_rep = rpriv->rep; 4475 4467 struct mlx5_core_dev *in_mdev = priv->mdev; 4468 + struct mlx5_eswitch *peer_esw; 4476 4469 struct mlx5e_tc_flow *flow; 4477 4470 int err; 4471 + int i; 4478 4472 4479 4473 flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep, 4480 4474 in_mdev); 4481 4475 if (IS_ERR(flow)) 4482 4476 return PTR_ERR(flow); 4483 4477 4484 - if (is_peer_flow_needed(flow)) { 4485 - err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags); 4486 - if (err) { 4487 - mlx5e_tc_del_fdb_flow(priv, flow); 4488 - goto out; 4489 - } 4478 + if (!is_peer_flow_needed(flow)) { 4479 + *__flow = flow; 4480 + return 0; 4490 4481 } 4491 4482 4492 - *__flow = flow; 4483 + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { 4484 + err = -ENODEV; 4485 + goto clean_flow; 4486 + } 4493 4487 4488 + mlx5_devcom_for_each_peer_entry(devcom, 4489 + MLX5_DEVCOM_ESW_OFFLOADS, 4490 + peer_esw, i) { 4491 + err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags, peer_esw); 4492 + if (err) 4493 + goto peer_clean; 4494 + } 4495 + 4496 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 4497 + 4498 + *__flow = flow; 4494 4499 return 0; 4495 4500 4496 - out: 4501 + peer_clean: 4502 + mlx5e_tc_del_fdb_peers_flow(flow); 4503 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 4504 + clean_flow: 4505 + mlx5e_tc_del_fdb_flow(priv, flow); 4497 4506 return err; 4498 4507 } 4499 4508 ··· 4729 4702 { 4730 4703 struct mlx5_devcom *devcom = priv->mdev->priv.devcom; 4731 4704 struct rhashtable *tc_ht = get_tc_ht(priv, flags); 4732 - struct mlx5_eswitch *peer_esw; 4733 4705 struct mlx5e_tc_flow *flow; 4734 4706 struct mlx5_fc *counter; 4735 4707 u64 lastuse = 0; ··· 4763 4737 /* Under multipath it's possible for one rule to be currently 4764 4738 * un-offloaded while the other rule is offloaded. 4765 4739 */ 4766 - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 4767 - if (!peer_esw) 4740 + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) 4768 4741 goto out; 4769 4742 4770 - if (flow_flag_test(flow, DUP) && 4771 - flow_flag_test(flow->peer_flow, OFFLOADED)) { 4772 - u64 bytes2; 4773 - u64 packets2; 4774 - u64 lastuse2; 4743 + if (flow_flag_test(flow, DUP)) { 4744 + struct mlx5e_tc_flow *peer_flow; 4775 4745 4776 - if (flow_flag_test(flow, USE_ACT_STATS)) { 4777 - f->use_act_stats = true; 4778 - } else { 4779 - counter = mlx5e_tc_get_counter(flow->peer_flow); 4746 + list_for_each_entry(peer_flow, &flow->peer_flows, peer_flows) { 4747 + u64 packets2; 4748 + u64 lastuse2; 4749 + u64 bytes2; 4750 + 4751 + if (!flow_flag_test(peer_flow, OFFLOADED)) 4752 + continue; 4753 + if (flow_flag_test(flow, USE_ACT_STATS)) { 4754 + f->use_act_stats = true; 4755 + break; 4756 + } 4757 + 4758 + counter = mlx5e_tc_get_counter(peer_flow); 4780 4759 if (!counter) 4781 4760 goto no_peer_counter; 4782 - mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2); 4761 + mlx5_fc_query_cached(counter, &bytes2, &packets2, 4762 + &lastuse2); 4783 4763 4784 4764 bytes += bytes2; 4785 4765 packets += packets2; ··· 4794 4762 } 4795 4763 4796 4764 no_peer_counter: 4797 - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 4765 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 4798 4766 out: 4799 4767 flow_stats_update(&f->stats, bytes, packets, 0, lastuse, 4800 4768 FLOW_ACTION_HW_STATS_DELAYED); ··· 5312 5280 void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw) 5313 5281 { 5314 5282 struct mlx5e_tc_flow *flow, *tmp; 5283 + int i; 5315 5284 5316 - list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer) 5317 - __mlx5e_tc_del_fdb_peer_flow(flow); 5285 + for (i = 0; i < MLX5_MAX_PORTS; i++) { 5286 + if (i == mlx5_get_dev_index(esw->dev)) 5287 + continue; 5288 + list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i]) 5289 + mlx5e_tc_del_fdb_peers_flow(flow); 5290 + } 5318 5291 } 5319 5292 5320 5293 void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
+20 -5
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c
··· 15 15 vport->egress.offloads.fwd_rule = NULL; 16 16 } 17 17 18 - static void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport) 18 + void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index) 19 19 { 20 - if (!vport->egress.offloads.bounce_rule) 20 + struct mlx5_flow_handle *bounce_rule = 21 + xa_load(&vport->egress.offloads.bounce_rules, rule_index); 22 + 23 + if (!bounce_rule) 21 24 return; 22 25 23 - mlx5_del_flow_rules(vport->egress.offloads.bounce_rule); 24 - vport->egress.offloads.bounce_rule = NULL; 26 + mlx5_del_flow_rules(bounce_rule); 27 + xa_erase(&vport->egress.offloads.bounce_rules, rule_index); 28 + } 29 + 30 + static void esw_acl_egress_ofld_bounce_rules_destroy(struct mlx5_vport *vport) 31 + { 32 + struct mlx5_flow_handle *bounce_rule; 33 + unsigned long i; 34 + 35 + xa_for_each(&vport->egress.offloads.bounce_rules, i, bounce_rule) { 36 + mlx5_del_flow_rules(bounce_rule); 37 + xa_erase(&vport->egress.offloads.bounce_rules, i); 38 + } 25 39 } 26 40 27 41 static int esw_acl_egress_ofld_fwd2vport_create(struct mlx5_eswitch *esw, ··· 110 96 { 111 97 esw_acl_egress_vlan_destroy(vport); 112 98 esw_acl_egress_ofld_fwd2vport_destroy(vport); 113 - esw_acl_egress_ofld_bounce_rule_destroy(vport); 99 + esw_acl_egress_ofld_bounce_rules_destroy(vport); 114 100 } 115 101 116 102 static int esw_acl_egress_ofld_groups_create(struct mlx5_eswitch *esw, ··· 208 194 vport->egress.acl = NULL; 209 195 return err; 210 196 } 197 + vport->egress.type = VPORT_EGRESS_ACL_TYPE_DEFAULT; 211 198 212 199 err = esw_acl_egress_ofld_groups_create(esw, vport); 213 200 if (err)
+1
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h
··· 10 10 /* Eswitch acl egress external APIs */ 11 11 int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport); 12 12 void esw_acl_egress_ofld_cleanup(struct mlx5_vport *vport); 13 + void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index); 13 14 int mlx5_esw_acl_egress_vport_bond(struct mlx5_eswitch *esw, u16 active_vport_num, 14 15 u16 passive_vport_num); 15 16 int mlx5_esw_acl_egress_vport_unbond(struct mlx5_eswitch *esw, u16 vport_num);
+22 -8
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
··· 647 647 } 648 648 649 649 static struct mlx5_flow_handle * 650 - mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, const unsigned char *addr, 650 + mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id, 651 + const unsigned char *addr, 651 652 struct mlx5_esw_bridge_vlan *vlan, u32 counter_id, 652 653 struct mlx5_esw_bridge *bridge) 653 654 { 654 655 struct mlx5_devcom *devcom = bridge->br_offloads->esw->dev->priv.devcom; 656 + struct mlx5_eswitch *tmp, *peer_esw = NULL; 655 657 static struct mlx5_flow_handle *handle; 656 - struct mlx5_eswitch *peer_esw; 658 + int i; 657 659 658 - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 659 - if (!peer_esw) 660 + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) 660 661 return ERR_PTR(-ENODEV); 662 + 663 + mlx5_devcom_for_each_peer_entry(devcom, 664 + MLX5_DEVCOM_ESW_OFFLOADS, 665 + tmp, i) { 666 + if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) { 667 + peer_esw = tmp; 668 + break; 669 + } 670 + } 671 + if (!peer_esw) { 672 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 673 + return ERR_PTR(-ENODEV); 674 + } 661 675 662 676 handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id, 663 677 bridge, peer_esw); 664 - 665 - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 678 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 666 679 return handle; 667 680 } 668 681 ··· 1382 1369 entry->ingress_counter = counter; 1383 1370 1384 1371 handle = peer ? 1385 - mlx5_esw_bridge_ingress_flow_peer_create(vport_num, addr, vlan, 1386 - mlx5_fc_id(counter), bridge) : 1372 + mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id, 1373 + addr, vlan, mlx5_fc_id(counter), 1374 + bridge) : 1387 1375 mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan, 1388 1376 mlx5_fc_id(counter), bridge); 1389 1377 if (IS_ERR(handle)) {
+17 -4
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
··· 540 540 mlx5_esw_bridge_mcast_filter_flow_peer_create(struct mlx5_esw_bridge_port *port) 541 541 { 542 542 struct mlx5_devcom *devcom = port->bridge->br_offloads->esw->dev->priv.devcom; 543 + struct mlx5_eswitch *tmp, *peer_esw = NULL; 543 544 static struct mlx5_flow_handle *handle; 544 - struct mlx5_eswitch *peer_esw; 545 + int i; 545 546 546 - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 547 - if (!peer_esw) 547 + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) 548 548 return ERR_PTR(-ENODEV); 549 + 550 + mlx5_devcom_for_each_peer_entry(devcom, 551 + MLX5_DEVCOM_ESW_OFFLOADS, 552 + tmp, i) { 553 + if (mlx5_esw_is_owner(tmp, port->vport_num, port->esw_owner_vhca_id)) { 554 + peer_esw = tmp; 555 + break; 556 + } 557 + } 558 + if (!peer_esw) { 559 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 560 + return ERR_PTR(-ENODEV); 561 + } 549 562 550 563 handle = mlx5_esw_bridge_mcast_flow_with_esw_create(port, peer_esw); 551 564 552 - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 565 + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); 553 566 return handle; 554 567 } 555 568
+23 -9
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 123 123 } offloads; 124 124 }; 125 125 126 + enum vport_egress_acl_type { 127 + VPORT_EGRESS_ACL_TYPE_DEFAULT, 128 + VPORT_EGRESS_ACL_TYPE_SHARED_FDB, 129 + }; 130 + 126 131 struct vport_egress { 127 132 struct mlx5_flow_table *acl; 133 + enum vport_egress_acl_type type; 128 134 struct mlx5_flow_handle *allowed_vlan; 129 135 struct mlx5_flow_group *vlan_grp; 130 136 union { ··· 142 136 struct { 143 137 struct mlx5_flow_group *fwd_grp; 144 138 struct mlx5_flow_handle *fwd_rule; 145 - struct mlx5_flow_handle *bounce_rule; 139 + struct xarray bounce_rules; 146 140 struct mlx5_flow_group *bounce_grp; 147 141 } offloads; 148 142 }; ··· 224 218 struct mlx5_flow_group *send_to_vport_grp; 225 219 struct mlx5_flow_group *send_to_vport_meta_grp; 226 220 struct mlx5_flow_group *peer_miss_grp; 227 - struct mlx5_flow_handle **peer_miss_rules; 221 + struct mlx5_flow_handle **peer_miss_rules[MLX5_MAX_PORTS]; 228 222 struct mlx5_flow_group *miss_grp; 229 223 struct mlx5_flow_handle **send_to_vport_meta_rules; 230 224 struct mlx5_flow_handle *miss_rule_uni; ··· 255 249 struct mlx5_flow_group *vport_rx_drop_group; 256 250 struct mlx5_flow_handle *vport_rx_drop_rule; 257 251 struct xarray vport_reps; 258 - struct list_head peer_flows; 252 + struct list_head peer_flows[MLX5_MAX_PORTS]; 259 253 struct mutex peer_mutex; 260 254 struct mutex encap_tbl_lock; /* protects encap_tbl */ 261 255 DECLARE_HASHTABLE(encap_tbl, 8); ··· 343 337 int mode; 344 338 u16 manager_vport; 345 339 u16 first_host_vport; 340 + u8 num_peers; 346 341 struct mlx5_esw_functions esw_funcs; 347 342 struct { 348 343 u32 large_group_num; ··· 585 578 return esw->manager_vport == vport_num; 586 579 } 587 580 581 + static inline bool mlx5_esw_is_owner(struct mlx5_eswitch *esw, u16 vport_num, 582 + u16 esw_owner_vhca_id) 583 + { 584 + return esw_owner_vhca_id == MLX5_CAP_GEN(esw->dev, vhca_id) || 585 + (vport_num == MLX5_VPORT_UPLINK && mlx5_lag_is_master(esw->dev)); 586 + } 587 + 588 588 static inline u16 mlx5_eswitch_first_host_vport_num(struct mlx5_core_dev *dev) 589 589 { 590 590 return mlx5_core_is_ecpf_esw_manager(dev) ? ··· 762 748 763 749 bool mlx5_esw_offloads_controller_valid(const struct mlx5_eswitch *esw, u32 controller); 764 750 765 - int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, 766 - struct mlx5_eswitch *slave_esw); 767 - void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, 751 + int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, 752 + struct mlx5_eswitch *slave_esw, int max_slaves); 753 + void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, 768 754 struct mlx5_eswitch *slave_esw); 769 755 int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw); 770 756 ··· 816 802 } 817 803 818 804 static inline int 819 - mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, 820 - struct mlx5_eswitch *slave_esw) 805 + mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, 806 + struct mlx5_eswitch *slave_esw, int max_slaves) 821 807 { 822 808 return 0; 823 809 } 824 810 825 811 static inline void 826 - mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, 812 + mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, 827 813 struct mlx5_eswitch *slave_esw) {} 828 814 829 815 static inline int
+115 -61
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 1132 1132 flows[vport->index] = flow; 1133 1133 } 1134 1134 1135 - esw->fdb_table.offloads.peer_miss_rules = flows; 1135 + esw->fdb_table.offloads.peer_miss_rules[mlx5_get_dev_index(peer_dev)] = flows; 1136 1136 1137 1137 kvfree(spec); 1138 1138 return 0; ··· 1160 1160 return err; 1161 1161 } 1162 1162 1163 - static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw) 1163 + static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw, 1164 + struct mlx5_core_dev *peer_dev) 1164 1165 { 1165 1166 struct mlx5_flow_handle **flows; 1166 1167 struct mlx5_vport *vport; 1167 1168 unsigned long i; 1168 1169 1169 - flows = esw->fdb_table.offloads.peer_miss_rules; 1170 + flows = esw->fdb_table.offloads.peer_miss_rules[mlx5_get_dev_index(peer_dev)]; 1170 1171 1171 1172 mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) 1172 1173 mlx5_del_flow_rules(flows[vport->index]); ··· 1574 1573 u32 *flow_group_in, 1575 1574 int *ix) 1576 1575 { 1576 + int max_peer_ports = (esw->total_vports - 1) * (MLX5_MAX_PORTS - 1); 1577 1577 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 1578 1578 struct mlx5_flow_group *g; 1579 1579 void *match_criteria; ··· 1601 1599 1602 1600 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix); 1603 1601 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1604 - *ix + esw->total_vports - 1); 1605 - *ix += esw->total_vports; 1602 + *ix + max_peer_ports); 1603 + *ix += max_peer_ports + 1; 1606 1604 1607 1605 g = mlx5_create_flow_group(fdb, flow_group_in); 1608 1606 if (IS_ERR(g)) { ··· 1704 1702 * total vports of the peer (currently is also uses esw->total_vports). 1705 1703 */ 1706 1704 table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) + 1707 - esw->total_vports * 2 + MLX5_ESW_MISS_FLOWS; 1705 + esw->total_vports * MLX5_MAX_PORTS + MLX5_ESW_MISS_FLOWS; 1708 1706 1709 1707 /* create the slow path fdb with encap set, so further table instances 1710 1708 * can be created at run time while VFs are probed if the FW allows that. ··· 2512 2510 struct mlx5_vport *vport, 2513 2511 struct mlx5_flow_table *acl) 2514 2512 { 2513 + u16 slave_index = MLX5_CAP_GEN(slave, vhca_id); 2515 2514 struct mlx5_flow_handle *flow_rule = NULL; 2516 2515 struct mlx5_flow_destination dest = {}; 2517 2516 struct mlx5_flow_act flow_act = {}; ··· 2528 2525 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, 2529 2526 misc_parameters); 2530 2527 MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK); 2531 - MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, 2532 - MLX5_CAP_GEN(slave, vhca_id)); 2528 + MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, slave_index); 2533 2529 2534 2530 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); 2535 2531 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); ··· 2543 2541 2544 2542 flow_rule = mlx5_add_flow_rules(acl, spec, &flow_act, 2545 2543 &dest, 1); 2546 - if (IS_ERR(flow_rule)) 2544 + if (IS_ERR(flow_rule)) { 2547 2545 err = PTR_ERR(flow_rule); 2548 - else 2549 - vport->egress.offloads.bounce_rule = flow_rule; 2546 + } else { 2547 + err = xa_insert(&vport->egress.offloads.bounce_rules, 2548 + slave_index, flow_rule, GFP_KERNEL); 2549 + if (err) 2550 + mlx5_del_flow_rules(flow_rule); 2551 + } 2550 2552 2551 2553 kvfree(spec); 2552 2554 return err; 2553 2555 } 2554 2556 2555 - static int esw_set_master_egress_rule(struct mlx5_core_dev *master, 2556 - struct mlx5_core_dev *slave) 2557 + static int esw_master_egress_create_resources(struct mlx5_flow_namespace *egress_ns, 2558 + struct mlx5_vport *vport, size_t count) 2557 2559 { 2558 2560 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 2559 - struct mlx5_eswitch *esw = master->priv.eswitch; 2560 2561 struct mlx5_flow_table_attr ft_attr = { 2561 - .max_fte = 1, .prio = 0, .level = 0, 2562 + .max_fte = count, .prio = 0, .level = 0, 2562 2563 .flags = MLX5_FLOW_TABLE_OTHER_VPORT, 2563 2564 }; 2564 - struct mlx5_flow_namespace *egress_ns; 2565 2565 struct mlx5_flow_table *acl; 2566 2566 struct mlx5_flow_group *g; 2567 - struct mlx5_vport *vport; 2568 2567 void *match_criteria; 2569 2568 u32 *flow_group_in; 2570 2569 int err; 2571 2570 2572 - vport = mlx5_eswitch_get_vport(esw, esw->manager_vport); 2573 - if (IS_ERR(vport)) 2574 - return PTR_ERR(vport); 2575 - 2576 - egress_ns = mlx5_get_flow_vport_acl_namespace(master, 2577 - MLX5_FLOW_NAMESPACE_ESW_EGRESS, 2578 - vport->index); 2579 - if (!egress_ns) 2580 - return -EINVAL; 2581 - 2582 2571 if (vport->egress.acl) 2583 - return -EINVAL; 2572 + return 0; 2584 2573 2585 2574 flow_group_in = kvzalloc(inlen, GFP_KERNEL); 2586 2575 if (!flow_group_in) ··· 2595 2602 MLX5_SET(create_flow_group_in, flow_group_in, 2596 2603 source_eswitch_owner_vhca_id_valid, 1); 2597 2604 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); 2598 - MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0); 2605 + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, count); 2599 2606 2600 2607 g = mlx5_create_flow_group(acl, flow_group_in); 2601 2608 if (IS_ERR(g)) { ··· 2603 2610 goto err_group; 2604 2611 } 2605 2612 2606 - err = __esw_set_master_egress_rule(master, slave, vport, acl); 2607 - if (err) 2608 - goto err_rule; 2609 - 2610 2613 vport->egress.acl = acl; 2611 2614 vport->egress.offloads.bounce_grp = g; 2615 + vport->egress.type = VPORT_EGRESS_ACL_TYPE_SHARED_FDB; 2616 + xa_init_flags(&vport->egress.offloads.bounce_rules, XA_FLAGS_ALLOC); 2612 2617 2613 2618 kvfree(flow_group_in); 2614 2619 2615 2620 return 0; 2616 2621 2617 - err_rule: 2618 - mlx5_destroy_flow_group(g); 2619 2622 err_group: 2620 2623 mlx5_destroy_flow_table(acl); 2621 2624 out: ··· 2619 2630 return err; 2620 2631 } 2621 2632 2622 - static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev) 2633 + static void esw_master_egress_destroy_resources(struct mlx5_vport *vport) 2634 + { 2635 + mlx5_destroy_flow_group(vport->egress.offloads.bounce_grp); 2636 + mlx5_destroy_flow_table(vport->egress.acl); 2637 + } 2638 + 2639 + static int esw_set_master_egress_rule(struct mlx5_core_dev *master, 2640 + struct mlx5_core_dev *slave, size_t count) 2641 + { 2642 + struct mlx5_eswitch *esw = master->priv.eswitch; 2643 + u16 slave_index = MLX5_CAP_GEN(slave, vhca_id); 2644 + struct mlx5_flow_namespace *egress_ns; 2645 + struct mlx5_vport *vport; 2646 + int err; 2647 + 2648 + vport = mlx5_eswitch_get_vport(esw, esw->manager_vport); 2649 + if (IS_ERR(vport)) 2650 + return PTR_ERR(vport); 2651 + 2652 + egress_ns = mlx5_get_flow_vport_acl_namespace(master, 2653 + MLX5_FLOW_NAMESPACE_ESW_EGRESS, 2654 + vport->index); 2655 + if (!egress_ns) 2656 + return -EINVAL; 2657 + 2658 + if (vport->egress.acl && vport->egress.type != VPORT_EGRESS_ACL_TYPE_SHARED_FDB) 2659 + return 0; 2660 + 2661 + err = esw_master_egress_create_resources(egress_ns, vport, count); 2662 + if (err) 2663 + return err; 2664 + 2665 + if (xa_load(&vport->egress.offloads.bounce_rules, slave_index)) 2666 + return -EINVAL; 2667 + 2668 + err = __esw_set_master_egress_rule(master, slave, vport, vport->egress.acl); 2669 + if (err) 2670 + goto err_rule; 2671 + 2672 + return 0; 2673 + 2674 + err_rule: 2675 + esw_master_egress_destroy_resources(vport); 2676 + return err; 2677 + } 2678 + 2679 + static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev, 2680 + struct mlx5_core_dev *slave_dev) 2623 2681 { 2624 2682 struct mlx5_vport *vport; 2625 2683 2626 2684 vport = mlx5_eswitch_get_vport(dev->priv.eswitch, 2627 2685 dev->priv.eswitch->manager_vport); 2628 2686 2629 - esw_acl_egress_ofld_cleanup(vport); 2687 + esw_acl_egress_ofld_bounce_rule_destroy(vport, MLX5_CAP_GEN(slave_dev, vhca_id)); 2688 + 2689 + if (xa_empty(&vport->egress.offloads.bounce_rules)) { 2690 + esw_acl_egress_ofld_cleanup(vport); 2691 + xa_destroy(&vport->egress.offloads.bounce_rules); 2692 + } 2630 2693 } 2631 2694 2632 - int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, 2633 - struct mlx5_eswitch *slave_esw) 2695 + int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, 2696 + struct mlx5_eswitch *slave_esw, int max_slaves) 2634 2697 { 2635 2698 int err; 2636 2699 ··· 2692 2651 return err; 2693 2652 2694 2653 err = esw_set_master_egress_rule(master_esw->dev, 2695 - slave_esw->dev); 2654 + slave_esw->dev, max_slaves); 2696 2655 if (err) 2697 2656 goto err_acl; 2698 2657 ··· 2700 2659 2701 2660 err_acl: 2702 2661 esw_set_slave_root_fdb(NULL, slave_esw->dev); 2703 - 2704 2662 return err; 2705 2663 } 2706 2664 2707 - void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, 2665 + void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, 2708 2666 struct mlx5_eswitch *slave_esw) 2709 2667 { 2710 - esw_unset_master_egress_rule(master_esw->dev); 2711 2668 esw_set_slave_root_fdb(NULL, slave_esw->dev); 2669 + esw_unset_master_egress_rule(master_esw->dev, slave_esw->dev); 2712 2670 } 2713 2671 2714 2672 #define ESW_OFFLOADS_DEVCOM_PAIR (0) 2715 2673 #define ESW_OFFLOADS_DEVCOM_UNPAIR (1) 2716 2674 2717 - static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw) 2675 + static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw, 2676 + struct mlx5_eswitch *peer_esw) 2718 2677 { 2719 2678 const struct mlx5_eswitch_rep_ops *ops; 2720 2679 struct mlx5_eswitch_rep *rep; ··· 2727 2686 ops = esw->offloads.rep_ops[rep_type]; 2728 2687 if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED && 2729 2688 ops->event) 2730 - ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, NULL); 2689 + ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, peer_esw); 2731 2690 } 2732 2691 } 2733 2692 } 2734 2693 2735 - static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw) 2694 + static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw, 2695 + struct mlx5_eswitch *peer_esw) 2736 2696 { 2737 2697 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) 2738 2698 mlx5e_tc_clean_fdb_peer_flows(esw); 2739 2699 #endif 2740 - mlx5_esw_offloads_rep_event_unpair(esw); 2741 - esw_del_fdb_peer_miss_rules(esw); 2700 + mlx5_esw_offloads_rep_event_unpair(esw, peer_esw); 2701 + esw_del_fdb_peer_miss_rules(esw, peer_esw->dev); 2742 2702 } 2743 2703 2744 2704 static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw, ··· 2770 2728 return 0; 2771 2729 2772 2730 err_out: 2773 - mlx5_esw_offloads_unpair(esw); 2731 + mlx5_esw_offloads_unpair(esw, peer_esw); 2774 2732 return err; 2775 2733 } 2776 2734 ··· 2778 2736 struct mlx5_eswitch *peer_esw, 2779 2737 bool pair) 2780 2738 { 2739 + u8 peer_idx = mlx5_get_dev_index(peer_esw->dev); 2781 2740 struct mlx5_flow_root_namespace *peer_ns; 2741 + u8 idx = mlx5_get_dev_index(esw->dev); 2782 2742 struct mlx5_flow_root_namespace *ns; 2783 2743 int err; 2784 2744 ··· 2788 2744 ns = esw->dev->priv.steering->fdb_root_ns; 2789 2745 2790 2746 if (pair) { 2791 - err = mlx5_flow_namespace_set_peer(ns, peer_ns); 2747 + err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_idx); 2792 2748 if (err) 2793 2749 return err; 2794 2750 2795 - err = mlx5_flow_namespace_set_peer(peer_ns, ns); 2751 + err = mlx5_flow_namespace_set_peer(peer_ns, ns, idx); 2796 2752 if (err) { 2797 - mlx5_flow_namespace_set_peer(ns, NULL); 2753 + mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); 2798 2754 return err; 2799 2755 } 2800 2756 } else { 2801 - mlx5_flow_namespace_set_peer(ns, NULL); 2802 - mlx5_flow_namespace_set_peer(peer_ns, NULL); 2757 + mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); 2758 + mlx5_flow_namespace_set_peer(peer_ns, NULL, idx); 2803 2759 } 2804 2760 2805 2761 return 0; ··· 2836 2792 2837 2793 esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true; 2838 2794 peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true; 2839 - mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); 2795 + esw->num_peers++; 2796 + peer_esw->num_peers++; 2797 + mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); 2840 2798 break; 2841 2799 2842 2800 case ESW_OFFLOADS_DEVCOM_UNPAIR: 2843 2801 if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)]) 2844 2802 break; 2845 2803 2846 - mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); 2804 + peer_esw->num_peers--; 2805 + esw->num_peers--; 2806 + if (!esw->num_peers && !peer_esw->num_peers) 2807 + mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); 2847 2808 esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false; 2848 2809 peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false; 2849 - mlx5_esw_offloads_unpair(peer_esw); 2850 - mlx5_esw_offloads_unpair(esw); 2810 + mlx5_esw_offloads_unpair(peer_esw, esw); 2811 + mlx5_esw_offloads_unpair(esw, peer_esw); 2851 2812 mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false); 2852 2813 break; 2853 2814 } ··· 2860 2811 return 0; 2861 2812 2862 2813 err_pair: 2863 - mlx5_esw_offloads_unpair(esw); 2814 + mlx5_esw_offloads_unpair(esw, peer_esw); 2864 2815 err_peer: 2865 2816 mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false); 2866 2817 err_out: ··· 2872 2823 void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) 2873 2824 { 2874 2825 struct mlx5_devcom *devcom = esw->dev->priv.devcom; 2826 + int i; 2875 2827 2876 - INIT_LIST_HEAD(&esw->offloads.peer_flows); 2828 + for (i = 0; i < MLX5_MAX_PORTS; i++) 2829 + INIT_LIST_HEAD(&esw->offloads.peer_flows[i]); 2877 2830 mutex_init(&esw->offloads.peer_mutex); 2878 2831 2879 2832 if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) ··· 2889 2838 mlx5_esw_offloads_devcom_event, 2890 2839 esw); 2891 2840 2841 + esw->num_peers = 0; 2892 2842 mlx5_devcom_send_event(devcom, 2893 2843 MLX5_DEVCOM_ESW_OFFLOADS, 2894 - ESW_OFFLOADS_DEVCOM_PAIR, esw); 2844 + ESW_OFFLOADS_DEVCOM_PAIR, 2845 + ESW_OFFLOADS_DEVCOM_UNPAIR, esw); 2895 2846 } 2896 2847 2897 2848 void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) ··· 2907 2854 return; 2908 2855 2909 2856 mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS, 2857 + ESW_OFFLOADS_DEVCOM_UNPAIR, 2910 2858 ESW_OFFLOADS_DEVCOM_UNPAIR, esw); 2911 2859 2912 2860 mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
··· 139 139 } 140 140 141 141 static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, 142 - struct mlx5_flow_root_namespace *peer_ns) 142 + struct mlx5_flow_root_namespace *peer_ns, 143 + u8 peer_idx) 143 144 { 144 145 return 0; 145 146 }
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
··· 93 93 struct mlx5_modify_hdr *modify_hdr); 94 94 95 95 int (*set_peer)(struct mlx5_flow_root_namespace *ns, 96 - struct mlx5_flow_root_namespace *peer_ns); 96 + struct mlx5_flow_root_namespace *peer_ns, 97 + u8 peer_idx); 97 98 98 99 int (*create_ns)(struct mlx5_flow_root_namespace *ns); 99 100 int (*destroy_ns)(struct mlx5_flow_root_namespace *ns);
+3 -2
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 3620 3620 } 3621 3621 3622 3622 int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, 3623 - struct mlx5_flow_root_namespace *peer_ns) 3623 + struct mlx5_flow_root_namespace *peer_ns, 3624 + u8 peer_idx) 3624 3625 { 3625 3626 if (peer_ns && ns->mode != peer_ns->mode) { 3626 3627 mlx5_core_err(ns->dev, ··· 3629 3628 return -EINVAL; 3630 3629 } 3631 3630 3632 - return ns->cmds->set_peer(ns, peer_ns); 3631 + return ns->cmds->set_peer(ns, peer_ns, peer_idx); 3633 3632 } 3634 3633 3635 3634 /* This function should be called only at init stage of the namespace.
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
··· 295 295 const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void); 296 296 297 297 int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, 298 - struct mlx5_flow_root_namespace *peer_ns); 298 + struct mlx5_flow_root_namespace *peer_ns, 299 + u8 peer_idx); 299 300 300 301 int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns, 301 302 enum mlx5_flow_steering_mode mode);
+31 -8
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
··· 550 550 } 551 551 } 552 552 553 + static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev) 554 + { 555 + struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; 556 + struct mlx5_eswitch *master_esw = dev0->priv.eswitch; 557 + int err; 558 + int i; 559 + 560 + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) { 561 + struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch; 562 + 563 + err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw, 564 + slave_esw, ldev->ports); 565 + if (err) 566 + goto err; 567 + } 568 + return 0; 569 + err: 570 + for (; i > MLX5_LAG_P1; i--) 571 + mlx5_eswitch_offloads_single_fdb_del_one(master_esw, 572 + ldev->pf[i].dev->priv.eswitch); 573 + return err; 574 + } 575 + 553 576 static int mlx5_create_lag(struct mlx5_lag *ldev, 554 577 struct lag_tracker *tracker, 555 578 enum mlx5_lag_mode mode, ··· 580 557 { 581 558 bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); 582 559 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; 583 - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; 584 560 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; 585 561 int err; 586 562 ··· 597 575 } 598 576 599 577 if (shared_fdb) { 600 - err = mlx5_eswitch_offloads_config_single_fdb(dev0->priv.eswitch, 601 - dev1->priv.eswitch); 578 + err = mlx5_lag_create_single_fdb(ldev); 602 579 if (err) 603 580 mlx5_core_err(dev0, "Can't enable single FDB mode\n"); 604 581 else ··· 668 647 int mlx5_deactivate_lag(struct mlx5_lag *ldev) 669 648 { 670 649 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; 671 - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; 650 + struct mlx5_eswitch *master_esw = dev0->priv.eswitch; 672 651 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; 673 652 bool roce_lag = __mlx5_lag_is_roce(ldev); 674 653 unsigned long flags = ldev->mode_flags; 675 654 int err; 655 + int i; 676 656 677 657 ldev->mode = MLX5_LAG_MODE_NONE; 678 658 ldev->mode_flags = 0; 679 659 mlx5_lag_mp_reset(ldev); 680 660 681 661 if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) { 682 - mlx5_eswitch_offloads_destroy_single_fdb(dev0->priv.eswitch, 683 - dev1->priv.eswitch); 662 + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) 663 + mlx5_eswitch_offloads_single_fdb_del_one(master_esw, 664 + ldev->pf[i].dev->priv.eswitch); 684 665 clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); 685 666 } 686 667 ··· 824 801 is_mdev_switchdev_mode(dev1) && 825 802 mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) && 826 803 mlx5_eswitch_vport_match_metadata_enabled(dev1->priv.eswitch) && 827 - mlx5_devcom_is_paired(dev0->priv.devcom, 828 - MLX5_DEVCOM_ESW_OFFLOADS) && 804 + mlx5_devcom_comp_is_ready(dev0->priv.devcom, 805 + MLX5_DEVCOM_ESW_OFFLOADS) && 829 806 MLX5_CAP_GEN(dev1, lag_native_fdb_selection) && 830 807 MLX5_CAP_ESW(dev1, root_ft_on_other_esw) && 831 808 MLX5_CAP_ESW(dev0, esw_shared_ingress_acl))
+94 -44
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
··· 19 19 20 20 mlx5_devcom_event_handler_t handler; 21 21 struct rw_semaphore sem; 22 - bool paired; 22 + bool ready; 23 23 }; 24 24 25 25 struct mlx5_devcom_list { ··· 193 193 194 194 int mlx5_devcom_send_event(struct mlx5_devcom *devcom, 195 195 enum mlx5_devcom_components id, 196 - int event, 196 + int event, int rollback_event, 197 197 void *event_data) 198 198 { 199 199 struct mlx5_devcom_component *comp; ··· 210 210 211 211 if (i != devcom->idx && data) { 212 212 err = comp->handler(event, data, event_data); 213 - break; 213 + if (err) 214 + goto rollback; 214 215 } 216 + } 217 + 218 + up_write(&comp->sem); 219 + return 0; 220 + 221 + rollback: 222 + while (i--) { 223 + void *data = rcu_dereference_protected(comp->device[i].data, 224 + lockdep_is_held(&comp->sem)); 225 + 226 + if (i != devcom->idx && data) 227 + comp->handler(rollback_event, data, event_data); 215 228 } 216 229 217 230 up_write(&comp->sem); 218 231 return err; 219 232 } 220 233 221 - void mlx5_devcom_set_paired(struct mlx5_devcom *devcom, 222 - enum mlx5_devcom_components id, 223 - bool paired) 234 + void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, 235 + enum mlx5_devcom_components id, 236 + bool ready) 224 237 { 225 238 struct mlx5_devcom_component *comp; 226 239 227 240 comp = &devcom->priv->components[id]; 228 241 WARN_ON(!rwsem_is_locked(&comp->sem)); 229 242 230 - WRITE_ONCE(comp->paired, paired); 243 + WRITE_ONCE(comp->ready, ready); 231 244 } 232 245 233 - bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom, 234 - enum mlx5_devcom_components id) 246 + bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, 247 + enum mlx5_devcom_components id) 235 248 { 236 249 if (IS_ERR_OR_NULL(devcom)) 237 250 return false; 238 251 239 - return READ_ONCE(devcom->priv->components[id].paired); 252 + return READ_ONCE(devcom->priv->components[id].ready); 240 253 } 241 254 242 - void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, 243 - enum mlx5_devcom_components id) 255 + bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, 256 + enum mlx5_devcom_components id) 244 257 { 245 258 struct mlx5_devcom_component *comp; 246 - int i; 247 259 248 260 if (IS_ERR_OR_NULL(devcom)) 249 - return NULL; 261 + return false; 250 262 251 263 comp = &devcom->priv->components[id]; 252 264 down_read(&comp->sem); 253 - if (!READ_ONCE(comp->paired)) { 265 + if (!READ_ONCE(comp->ready)) { 254 266 up_read(&comp->sem); 255 - return NULL; 267 + return false; 256 268 } 257 269 258 - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) 259 - if (i != devcom->idx) 260 - break; 261 - 262 - return rcu_dereference_protected(comp->device[i].data, lockdep_is_held(&comp->sem)); 270 + return true; 263 271 } 264 272 265 - void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id) 266 - { 267 - struct mlx5_devcom_component *comp; 268 - int i; 269 - 270 - if (IS_ERR_OR_NULL(devcom)) 271 - return NULL; 272 - 273 - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) 274 - if (i != devcom->idx) 275 - break; 276 - 277 - comp = &devcom->priv->components[id]; 278 - /* This can change concurrently, however 'data' pointer will remain 279 - * valid for the duration of RCU read section. 280 - */ 281 - if (!READ_ONCE(comp->paired)) 282 - return NULL; 283 - 284 - return rcu_dereference(comp->device[i].data); 285 - } 286 - 287 - void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom, 273 + void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, 288 274 enum mlx5_devcom_components id) 289 275 { 290 276 struct mlx5_devcom_component *comp = &devcom->priv->components[id]; 291 277 292 278 up_read(&comp->sem); 279 + } 280 + 281 + void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, 282 + enum mlx5_devcom_components id, 283 + int *i) 284 + { 285 + struct mlx5_devcom_component *comp; 286 + void *ret; 287 + int idx; 288 + 289 + comp = &devcom->priv->components[id]; 290 + 291 + if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) 292 + return NULL; 293 + for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { 294 + if (idx != devcom->idx) { 295 + ret = rcu_dereference_protected(comp->device[idx].data, 296 + lockdep_is_held(&comp->sem)); 297 + if (ret) 298 + break; 299 + } 300 + } 301 + 302 + if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { 303 + *i = idx; 304 + return NULL; 305 + } 306 + *i = idx + 1; 307 + 308 + return ret; 309 + } 310 + 311 + void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, 312 + enum mlx5_devcom_components id, 313 + int *i) 314 + { 315 + struct mlx5_devcom_component *comp; 316 + void *ret; 317 + int idx; 318 + 319 + comp = &devcom->priv->components[id]; 320 + 321 + if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) 322 + return NULL; 323 + for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { 324 + if (idx != devcom->idx) { 325 + /* This can change concurrently, however 'data' pointer will remain 326 + * valid for the duration of RCU read section. 327 + */ 328 + if (!READ_ONCE(comp->ready)) 329 + return NULL; 330 + ret = rcu_dereference(comp->device[idx].data); 331 + if (ret) 332 + break; 333 + } 334 + } 335 + 336 + if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { 337 + *i = idx; 338 + return NULL; 339 + } 340 + *i = idx + 1; 341 + 342 + return ret; 293 343 }
+24 -11
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
··· 30 30 31 31 int mlx5_devcom_send_event(struct mlx5_devcom *devcom, 32 32 enum mlx5_devcom_components id, 33 - int event, 33 + int event, int rollback_event, 34 34 void *event_data); 35 35 36 - void mlx5_devcom_set_paired(struct mlx5_devcom *devcom, 37 - enum mlx5_devcom_components id, 38 - bool paired); 39 - bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom, 40 - enum mlx5_devcom_components id); 36 + void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, 37 + enum mlx5_devcom_components id, 38 + bool ready); 39 + bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, 40 + enum mlx5_devcom_components id); 41 41 42 - void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, 43 - enum mlx5_devcom_components id); 44 - void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id); 45 - void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom, 42 + bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, 43 + enum mlx5_devcom_components id); 44 + void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, 46 45 enum mlx5_devcom_components id); 46 + void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, 47 + enum mlx5_devcom_components id, int *i); 48 + 49 + #define mlx5_devcom_for_each_peer_entry(devcom, id, data, i) \ 50 + for (i = 0, data = mlx5_devcom_get_next_peer_data(devcom, id, &i); \ 51 + data; \ 52 + data = mlx5_devcom_get_next_peer_data(devcom, id, &i)) 53 + 54 + void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, 55 + enum mlx5_devcom_components id, int *i); 56 + 57 + #define mlx5_devcom_for_each_peer_entry_rcu(devcom, id, data, i) \ 58 + for (i = 0, data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i); \ 59 + data; \ 60 + data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i)) 47 61 48 62 #endif 49 -
+3 -2
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
··· 2071 2071 struct mlx5dr_action *action; 2072 2072 u8 peer_vport; 2073 2073 2074 - peer_vport = vhca_id_valid && (vhca_id != dmn->info.caps.gvmi); 2075 - vport_dmn = peer_vport ? dmn->peer_dmn : dmn; 2074 + peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) && 2075 + (vhca_id != dmn->info.caps.gvmi); 2076 + vport_dmn = peer_vport ? dmn->peer_dmn[vhca_id] : dmn; 2076 2077 if (!vport_dmn) { 2077 2078 mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n"); 2078 2079 return NULL;
+7 -6
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
··· 555 555 } 556 556 557 557 void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, 558 - struct mlx5dr_domain *peer_dmn) 558 + struct mlx5dr_domain *peer_dmn, 559 + u8 peer_idx) 559 560 { 560 561 mlx5dr_domain_lock(dmn); 561 562 562 - if (dmn->peer_dmn) 563 - refcount_dec(&dmn->peer_dmn->refcount); 563 + if (dmn->peer_dmn[peer_idx]) 564 + refcount_dec(&dmn->peer_dmn[peer_idx]->refcount); 564 565 565 - dmn->peer_dmn = peer_dmn; 566 + dmn->peer_dmn[peer_idx] = peer_dmn; 566 567 567 - if (dmn->peer_dmn) 568 - refcount_inc(&dmn->peer_dmn->refcount); 568 + if (dmn->peer_dmn[peer_idx]) 569 + refcount_inc(&dmn->peer_dmn[peer_idx]->refcount); 569 570 570 571 mlx5dr_domain_unlock(dmn); 571 572 }
+5 -4
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
··· 1647 1647 u8 *tag) 1648 1648 { 1649 1649 struct mlx5dr_match_misc *misc = &value->misc; 1650 + int id = misc->source_eswitch_owner_vhca_id; 1650 1651 struct mlx5dr_cmd_vport_cap *vport_cap; 1651 1652 struct mlx5dr_domain *dmn = sb->dmn; 1652 1653 struct mlx5dr_domain *vport_dmn; ··· 1658 1657 1659 1658 if (sb->vhca_id_valid) { 1660 1659 /* Find port GVMI based on the eswitch_owner_vhca_id */ 1661 - if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi) 1660 + if (id == dmn->info.caps.gvmi) 1662 1661 vport_dmn = dmn; 1663 - else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id == 1664 - dmn->peer_dmn->info.caps.gvmi)) 1665 - vport_dmn = dmn->peer_dmn; 1662 + else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && 1663 + (id == dmn->peer_dmn[id]->info.caps.gvmi)) 1664 + vport_dmn = dmn->peer_dmn[id]; 1666 1665 else 1667 1666 return -EINVAL; 1668 1667
+5 -4
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
··· 1979 1979 u8 *tag) 1980 1980 { 1981 1981 struct mlx5dr_match_misc *misc = &value->misc; 1982 + int id = misc->source_eswitch_owner_vhca_id; 1982 1983 struct mlx5dr_cmd_vport_cap *vport_cap; 1983 1984 struct mlx5dr_domain *dmn = sb->dmn; 1984 1985 struct mlx5dr_domain *vport_dmn; ··· 1989 1988 1990 1989 if (sb->vhca_id_valid) { 1991 1990 /* Find port GVMI based on the eswitch_owner_vhca_id */ 1992 - if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi) 1991 + if (id == dmn->info.caps.gvmi) 1993 1992 vport_dmn = dmn; 1994 - else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id == 1995 - dmn->peer_dmn->info.caps.gvmi)) 1996 - vport_dmn = dmn->peer_dmn; 1993 + else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && 1994 + (id == dmn->peer_dmn[id]->info.caps.gvmi)) 1995 + vport_dmn = dmn->peer_dmn[id]; 1997 1996 else 1998 1997 return -EINVAL; 1999 1998
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
··· 935 935 }; 936 936 937 937 struct mlx5dr_domain { 938 - struct mlx5dr_domain *peer_dmn; 938 + struct mlx5dr_domain *peer_dmn[MLX5_MAX_PORTS]; 939 939 struct mlx5_core_dev *mdev; 940 940 u32 pdn; 941 941 struct mlx5_uars_page *uar;
+3 -2
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
··· 770 770 } 771 771 772 772 static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns, 773 - struct mlx5_flow_root_namespace *peer_ns) 773 + struct mlx5_flow_root_namespace *peer_ns, 774 + u8 peer_idx) 774 775 { 775 776 struct mlx5dr_domain *peer_domain = NULL; 776 777 777 778 if (peer_ns) 778 779 peer_domain = peer_ns->fs_dr_domain.dr_domain; 779 780 mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain, 780 - peer_domain); 781 + peer_domain, peer_idx); 781 782 return 0; 782 783 } 783 784
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
··· 48 48 int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags); 49 49 50 50 void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, 51 - struct mlx5dr_domain *peer_dmn); 51 + struct mlx5dr_domain *peer_dmn, 52 + u8 peer_idx); 52 53 53 54 struct mlx5dr_table * 54 55 mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags,