2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
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:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
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.
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
33 #include <linux/netdevice.h>
34 #include <net/bonding.h>
35 #include <linux/mlx5/driver.h>
36 #include <linux/mlx5/eswitch.h>
37 #include <linux/mlx5/vport.h>
38 #include "lib/devcom.h"
39 #include "mlx5_core.h"
41 #include "esw/acl/ofld.h"
47 MLX5_LAG_EGRESS_PORT_1 = 1,
48 MLX5_LAG_EGRESS_PORT_2,
51 /* General purpose, use for short periods of time.
52 * Beware of lock dependencies (preferably, no locks should be acquired
55 static DEFINE_SPINLOCK(lag_lock);
57 static int get_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
59 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
60 return MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT;
62 if (mode == MLX5_LAG_MODE_MPESW)
63 return MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_MPESW;
65 return MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY;
68 static u8 lag_active_port_bits(struct mlx5_lag *ldev)
70 u8 enabled_ports[MLX5_MAX_PORTS] = {};
75 mlx5_infer_tx_enabled(&ldev->tracker, ldev->ports, enabled_ports,
77 for (idx = 0; idx < num_enabled; idx++)
78 active_port |= BIT_MASK(enabled_ports[idx]);
83 static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, int mode,
86 bool fdb_sel_mode = test_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE,
88 int port_sel_mode = get_port_sel_mode(mode, flags);
89 u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};
92 lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);
93 MLX5_SET(create_lag_in, in, opcode, MLX5_CMD_OP_CREATE_LAG);
94 MLX5_SET(lagc, lag_ctx, fdb_selection_mode, fdb_sel_mode);
96 switch (port_sel_mode) {
97 case MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY:
98 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
99 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
101 case MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT:
102 if (!MLX5_CAP_PORT_SELECTION(dev, port_select_flow_table_bypass))
105 MLX5_SET(lagc, lag_ctx, active_port,
106 lag_active_port_bits(mlx5_lag_dev(dev)));
111 MLX5_SET(lagc, lag_ctx, port_select_mode, port_sel_mode);
113 return mlx5_cmd_exec_in(dev, create_lag, in);
116 static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 num_ports,
119 u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};
120 void *lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);
122 MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
123 MLX5_SET(modify_lag_in, in, field_select, 0x1);
125 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
126 MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
128 return mlx5_cmd_exec_in(dev, modify_lag, in);
131 int mlx5_cmd_create_vport_lag(struct mlx5_core_dev *dev)
133 u32 in[MLX5_ST_SZ_DW(create_vport_lag_in)] = {};
135 MLX5_SET(create_vport_lag_in, in, opcode, MLX5_CMD_OP_CREATE_VPORT_LAG);
137 return mlx5_cmd_exec_in(dev, create_vport_lag, in);
139 EXPORT_SYMBOL(mlx5_cmd_create_vport_lag);
141 int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev)
143 u32 in[MLX5_ST_SZ_DW(destroy_vport_lag_in)] = {};
145 MLX5_SET(destroy_vport_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_VPORT_LAG);
147 return mlx5_cmd_exec_in(dev, destroy_vport_lag, in);
149 EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag);
151 static void mlx5_infer_tx_disabled(struct lag_tracker *tracker, u8 num_ports,
152 u8 *ports, int *num_disabled)
157 for (i = 0; i < num_ports; i++) {
158 if (!tracker->netdev_state[i].tx_enabled ||
159 !tracker->netdev_state[i].link_up)
160 ports[(*num_disabled)++] = i;
164 void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
165 u8 *ports, int *num_enabled)
170 for (i = 0; i < num_ports; i++) {
171 if (tracker->netdev_state[i].tx_enabled &&
172 tracker->netdev_state[i].link_up)
173 ports[(*num_enabled)++] = i;
176 if (*num_enabled == 0)
177 mlx5_infer_tx_disabled(tracker, num_ports, ports, num_enabled);
180 static void mlx5_lag_print_mapping(struct mlx5_core_dev *dev,
181 struct mlx5_lag *ldev,
182 struct lag_tracker *tracker,
185 char buf[MLX5_MAX_PORTS * 10 + 1] = {};
186 u8 enabled_ports[MLX5_MAX_PORTS] = {};
194 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
195 mlx5_infer_tx_enabled(tracker, ldev->ports, enabled_ports,
197 for (i = 0; i < num_enabled; i++) {
198 err = scnprintf(buf + written, 4, "%d, ", enabled_ports[i] + 1);
203 buf[written - 2] = 0;
204 mlx5_core_info(dev, "lag map active ports: %s\n", buf);
206 for (i = 0; i < ldev->ports; i++) {
207 for (j = 0; j < ldev->buckets; j++) {
208 idx = i * ldev->buckets + j;
209 err = scnprintf(buf + written, 10,
210 " port %d:%d", i + 1, ldev->v2p_map[idx]);
216 mlx5_core_info(dev, "lag map:%s\n", buf);
220 static int mlx5_lag_netdev_event(struct notifier_block *this,
221 unsigned long event, void *ptr);
222 static void mlx5_do_bond_work(struct work_struct *work);
224 static void mlx5_ldev_free(struct kref *ref)
226 struct mlx5_lag *ldev = container_of(ref, struct mlx5_lag, ref);
228 if (ldev->nb.notifier_call)
229 unregister_netdevice_notifier_net(&init_net, &ldev->nb);
230 mlx5_lag_mp_cleanup(ldev);
231 cancel_delayed_work_sync(&ldev->bond_work);
232 destroy_workqueue(ldev->wq);
233 mutex_destroy(&ldev->lock);
237 static void mlx5_ldev_put(struct mlx5_lag *ldev)
239 kref_put(&ldev->ref, mlx5_ldev_free);
242 static void mlx5_ldev_get(struct mlx5_lag *ldev)
244 kref_get(&ldev->ref);
247 static struct mlx5_lag *mlx5_lag_dev_alloc(struct mlx5_core_dev *dev)
249 struct mlx5_lag *ldev;
252 ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
256 ldev->wq = create_singlethread_workqueue("mlx5_lag");
262 kref_init(&ldev->ref);
263 mutex_init(&ldev->lock);
264 INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
266 ldev->nb.notifier_call = mlx5_lag_netdev_event;
267 if (register_netdevice_notifier_net(&init_net, &ldev->nb)) {
268 ldev->nb.notifier_call = NULL;
269 mlx5_core_err(dev, "Failed to register LAG netdev notifier\n");
271 ldev->mode = MLX5_LAG_MODE_NONE;
273 err = mlx5_lag_mp_init(ldev);
275 mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
278 ldev->ports = MLX5_CAP_GEN(dev, num_lag_ports);
284 int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
285 struct net_device *ndev)
289 for (i = 0; i < ldev->ports; i++)
290 if (ldev->pf[i].netdev == ndev)
296 static bool __mlx5_lag_is_roce(struct mlx5_lag *ldev)
298 return ldev->mode == MLX5_LAG_MODE_ROCE;
301 static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev)
303 return ldev->mode == MLX5_LAG_MODE_SRIOV;
306 /* Create a mapping between steering slots and active ports.
307 * As we have ldev->buckets slots per port first assume the native
308 * mapping should be used.
309 * If there are ports that are disabled fill the relevant slots
310 * with mapping that points to active ports.
312 static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
317 int disabled[MLX5_MAX_PORTS] = {};
318 int enabled[MLX5_MAX_PORTS] = {};
319 int disabled_ports_num = 0;
320 int enabled_ports_num = 0;
326 for (i = 0; i < num_ports; i++) {
327 if (tracker->netdev_state[i].tx_enabled &&
328 tracker->netdev_state[i].link_up)
329 enabled[enabled_ports_num++] = i;
331 disabled[disabled_ports_num++] = i;
334 /* Use native mapping by default where each port's buckets
335 * point the native port: 1 1 1 .. 1 2 2 2 ... 2 3 3 3 ... 3 etc
337 for (i = 0; i < num_ports; i++)
338 for (j = 0; j < buckets; j++) {
339 idx = i * buckets + j;
340 ports[idx] = MLX5_LAG_EGRESS_PORT_1 + i;
343 /* If all ports are disabled/enabled keep native mapping */
344 if (enabled_ports_num == num_ports ||
345 disabled_ports_num == num_ports)
348 /* Go over the disabled ports and for each assign a random active port */
349 for (i = 0; i < disabled_ports_num; i++) {
350 for (j = 0; j < buckets; j++) {
351 get_random_bytes(&rand, 4);
352 ports[disabled[i] * buckets + j] = enabled[rand % enabled_ports_num] + 1;
357 static bool mlx5_lag_has_drop_rule(struct mlx5_lag *ldev)
361 for (i = 0; i < ldev->ports; i++)
362 if (ldev->pf[i].has_drop)
367 static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev)
371 for (i = 0; i < ldev->ports; i++) {
372 if (!ldev->pf[i].has_drop)
375 mlx5_esw_acl_ingress_vport_drop_rule_destroy(ldev->pf[i].dev->priv.eswitch,
377 ldev->pf[i].has_drop = false;
381 static void mlx5_lag_drop_rule_setup(struct mlx5_lag *ldev,
382 struct lag_tracker *tracker)
384 u8 disabled_ports[MLX5_MAX_PORTS] = {};
385 struct mlx5_core_dev *dev;
391 /* First delete the current drop rule so there won't be any dropped
394 mlx5_lag_drop_rule_cleanup(ldev);
396 if (!ldev->tracker.has_inactive)
399 mlx5_infer_tx_disabled(tracker, ldev->ports, disabled_ports, &num_disabled);
401 for (i = 0; i < num_disabled; i++) {
402 disabled_index = disabled_ports[i];
403 dev = ldev->pf[disabled_index].dev;
404 err = mlx5_esw_acl_ingress_vport_drop_rule_create(dev->priv.eswitch,
407 ldev->pf[disabled_index].has_drop = true;
410 "Failed to create lag drop rule, error: %d", err);
414 static int mlx5_cmd_modify_active_port(struct mlx5_core_dev *dev, u8 ports)
416 u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};
419 lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);
421 MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
422 MLX5_SET(modify_lag_in, in, field_select, 0x2);
424 MLX5_SET(lagc, lag_ctx, active_port, ports);
426 return mlx5_cmd_exec_in(dev, modify_lag, in);
429 static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
431 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
435 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) {
436 ret = mlx5_lag_port_sel_modify(ldev, ports);
438 !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table_bypass))
441 active_ports = lag_active_port_bits(ldev);
443 return mlx5_cmd_modify_active_port(dev0, active_ports);
445 return mlx5_cmd_modify_lag(dev0, ldev->ports, ports);
448 void mlx5_modify_lag(struct mlx5_lag *ldev,
449 struct lag_tracker *tracker)
451 u8 ports[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS] = {};
452 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
458 mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ports);
460 for (i = 0; i < ldev->ports; i++) {
461 for (j = 0; j < ldev->buckets; j++) {
462 idx = i * ldev->buckets + j;
463 if (ports[idx] == ldev->v2p_map[idx])
465 err = _mlx5_modify_lag(ldev, ports);
468 "Failed to modify LAG (%d)\n",
472 memcpy(ldev->v2p_map, ports, sizeof(ports));
474 mlx5_lag_print_mapping(dev0, ldev, tracker,
480 if (tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
481 !(ldev->mode == MLX5_LAG_MODE_ROCE))
482 mlx5_lag_drop_rule_setup(ldev, tracker);
485 static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
486 unsigned long *flags)
488 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
490 if (!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table)) {
497 ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS;
499 set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags);
504 static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
505 struct lag_tracker *tracker,
506 enum mlx5_lag_mode mode,
507 unsigned long *flags)
509 struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
511 if (mode == MLX5_LAG_MODE_MPESW)
514 if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
515 tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) {
517 ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS;
518 set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags);
522 static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode,
523 struct lag_tracker *tracker, bool shared_fdb,
524 unsigned long *flags)
526 bool roce_lag = mode == MLX5_LAG_MODE_ROCE;
530 set_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, flags);
531 set_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE, flags);
534 if (mode == MLX5_LAG_MODE_MPESW)
535 set_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE, flags);
538 return mlx5_lag_set_port_sel_mode_roce(ldev, flags);
540 mlx5_lag_set_port_sel_mode_offloads(ldev, tracker, mode, flags);
544 char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
546 int port_sel_mode = get_port_sel_mode(mode, flags);
548 switch (port_sel_mode) {
549 case MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY: return "queue_affinity";
550 case MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT: return "hash";
551 case MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_MPESW: return "mpesw";
552 default: return "invalid";
556 static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev)
558 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
559 struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
563 for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
564 struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch;
566 err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw,
567 slave_esw, ldev->ports);
573 for (; i > MLX5_LAG_P1; i--)
574 mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
575 ldev->pf[i].dev->priv.eswitch);
579 static int mlx5_create_lag(struct mlx5_lag *ldev,
580 struct lag_tracker *tracker,
581 enum mlx5_lag_mode mode,
584 bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
585 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
586 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
590 mlx5_lag_print_mapping(dev0, ldev, tracker, flags);
591 mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
592 shared_fdb, mlx5_get_str_port_sel_mode(mode, flags));
594 err = mlx5_cmd_create_lag(dev0, ldev->v2p_map, mode, flags);
597 "Failed to create LAG (%d)\n",
603 err = mlx5_lag_create_single_fdb(ldev);
605 mlx5_core_err(dev0, "Can't enable single FDB mode\n");
607 mlx5_core_info(dev0, "Operation mode is single FDB\n");
611 MLX5_SET(destroy_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_LAG);
612 if (mlx5_cmd_exec_in(dev0, destroy_lag, in))
614 "Failed to deactivate RoCE LAG; driver restart required\n");
620 int mlx5_activate_lag(struct mlx5_lag *ldev,
621 struct lag_tracker *tracker,
622 enum mlx5_lag_mode mode,
625 bool roce_lag = mode == MLX5_LAG_MODE_ROCE;
626 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
627 unsigned long flags = 0;
630 err = mlx5_lag_set_flags(ldev, mode, tracker, shared_fdb, &flags);
634 if (mode != MLX5_LAG_MODE_MPESW) {
635 mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ldev->v2p_map);
636 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
637 err = mlx5_lag_port_sel_create(ldev, tracker->hash_type,
641 "Failed to create LAG port selection(%d)\n",
648 err = mlx5_create_lag(ldev, tracker, mode, flags);
650 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
651 mlx5_lag_port_sel_destroy(ldev);
654 "Failed to activate RoCE LAG\n");
657 "Failed to activate VF LAG\n"
658 "Make sure all VFs are unbound prior to VF LAG activation or deactivation\n");
662 if (tracker && tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
664 mlx5_lag_drop_rule_setup(ldev, tracker);
667 ldev->mode_flags = flags;
671 int mlx5_deactivate_lag(struct mlx5_lag *ldev)
673 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
674 struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
675 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
676 bool roce_lag = __mlx5_lag_is_roce(ldev);
677 unsigned long flags = ldev->mode_flags;
681 ldev->mode = MLX5_LAG_MODE_NONE;
682 ldev->mode_flags = 0;
683 mlx5_lag_mp_reset(ldev);
685 if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) {
686 for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++)
687 mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
688 ldev->pf[i].dev->priv.eswitch);
689 clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
692 MLX5_SET(destroy_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_LAG);
693 err = mlx5_cmd_exec_in(dev0, destroy_lag, in);
697 "Failed to deactivate RoCE LAG; driver restart required\n");
700 "Failed to deactivate VF LAG; driver restart required\n"
701 "Make sure all VFs are unbound prior to VF LAG activation or deactivation\n");
706 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
707 mlx5_lag_port_sel_destroy(ldev);
710 if (mlx5_lag_has_drop_rule(ldev))
711 mlx5_lag_drop_rule_cleanup(ldev);
716 #define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 4
717 bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
719 #ifdef CONFIG_MLX5_ESWITCH
720 struct mlx5_core_dev *dev;
725 for (i = 0; i < ldev->ports; i++)
726 if (!ldev->pf[i].dev)
729 #ifdef CONFIG_MLX5_ESWITCH
730 for (i = 0; i < ldev->ports; i++) {
731 dev = ldev->pf[i].dev;
732 if (mlx5_eswitch_num_vfs(dev->priv.eswitch) && !is_mdev_switchdev_mode(dev))
736 dev = ldev->pf[MLX5_LAG_P1].dev;
737 mode = mlx5_eswitch_mode(dev);
738 for (i = 0; i < ldev->ports; i++)
739 if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode)
742 if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports > MLX5_LAG_OFFLOADS_SUPPORTED_PORTS)
745 for (i = 0; i < ldev->ports; i++)
746 if (mlx5_sriov_is_enabled(ldev->pf[i].dev))
752 void mlx5_lag_add_devices(struct mlx5_lag *ldev)
756 for (i = 0; i < ldev->ports; i++) {
757 if (!ldev->pf[i].dev)
760 if (ldev->pf[i].dev->priv.flags &
761 MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)
764 ldev->pf[i].dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
765 mlx5_rescan_drivers_locked(ldev->pf[i].dev);
769 void mlx5_lag_remove_devices(struct mlx5_lag *ldev)
773 for (i = 0; i < ldev->ports; i++) {
774 if (!ldev->pf[i].dev)
777 if (ldev->pf[i].dev->priv.flags &
778 MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)
781 ldev->pf[i].dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
782 mlx5_rescan_drivers_locked(ldev->pf[i].dev);
786 void mlx5_disable_lag(struct mlx5_lag *ldev)
788 bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
789 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
794 roce_lag = __mlx5_lag_is_roce(ldev);
797 mlx5_lag_remove_devices(ldev);
798 } else if (roce_lag) {
799 if (!(dev0->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) {
800 dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
801 mlx5_rescan_drivers_locked(dev0);
803 for (i = 1; i < ldev->ports; i++)
804 mlx5_nic_vport_disable_roce(ldev->pf[i].dev);
807 err = mlx5_deactivate_lag(ldev);
811 if (shared_fdb || roce_lag)
812 mlx5_lag_add_devices(ldev);
815 for (i = 0; i < ldev->ports; i++)
816 if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
817 mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
820 static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
822 struct mlx5_core_dev *dev;
825 for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
826 dev = ldev->pf[i].dev;
827 if (is_mdev_switchdev_mode(dev) &&
828 mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
829 MLX5_CAP_GEN(dev, lag_native_fdb_selection) &&
830 MLX5_CAP_ESW(dev, root_ft_on_other_esw) &&
831 mlx5_eswitch_get_npeers(dev->priv.eswitch) ==
832 MLX5_CAP_GEN(dev, num_lag_ports) - 1)
837 dev = ldev->pf[MLX5_LAG_P1].dev;
838 if (is_mdev_switchdev_mode(dev) &&
839 mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
840 mlx5_esw_offloads_devcom_is_ready(dev->priv.eswitch) &&
841 MLX5_CAP_ESW(dev, esw_shared_ingress_acl) &&
842 mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1)
848 static bool mlx5_lag_is_roce_lag(struct mlx5_lag *ldev)
850 bool roce_lag = true;
853 for (i = 0; i < ldev->ports; i++)
854 roce_lag = roce_lag && !mlx5_sriov_is_enabled(ldev->pf[i].dev);
856 #ifdef CONFIG_MLX5_ESWITCH
857 for (i = 0; i < ldev->ports; i++)
858 roce_lag = roce_lag && is_mdev_legacy_mode(ldev->pf[i].dev);
864 static bool mlx5_lag_should_modify_lag(struct mlx5_lag *ldev, bool do_bond)
866 return do_bond && __mlx5_lag_is_active(ldev) &&
867 ldev->mode != MLX5_LAG_MODE_MPESW;
870 static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
872 return !do_bond && __mlx5_lag_is_active(ldev) &&
873 ldev->mode != MLX5_LAG_MODE_MPESW;
876 static void mlx5_do_bond(struct mlx5_lag *ldev)
878 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
879 struct lag_tracker tracker = { };
880 bool do_bond, roce_lag;
884 if (!mlx5_lag_is_ready(ldev)) {
887 /* VF LAG is in multipath mode, ignore bond change requests */
888 if (mlx5_lag_is_multipath(dev0))
891 tracker = ldev->tracker;
893 do_bond = tracker.is_bonded && mlx5_lag_check_prereq(ldev);
896 if (do_bond && !__mlx5_lag_is_active(ldev)) {
897 bool shared_fdb = mlx5_shared_fdb_supported(ldev);
899 roce_lag = mlx5_lag_is_roce_lag(ldev);
901 if (shared_fdb || roce_lag)
902 mlx5_lag_remove_devices(ldev);
904 err = mlx5_activate_lag(ldev, &tracker,
905 roce_lag ? MLX5_LAG_MODE_ROCE :
909 if (shared_fdb || roce_lag)
910 mlx5_lag_add_devices(ldev);
913 } else if (roce_lag) {
914 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
915 mlx5_rescan_drivers_locked(dev0);
916 for (i = 1; i < ldev->ports; i++)
917 mlx5_nic_vport_enable_roce(ldev->pf[i].dev);
918 } else if (shared_fdb) {
921 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
922 mlx5_rescan_drivers_locked(dev0);
924 for (i = 0; i < ldev->ports; i++) {
925 err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
931 dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
932 mlx5_rescan_drivers_locked(dev0);
933 mlx5_deactivate_lag(ldev);
934 mlx5_lag_add_devices(ldev);
935 for (i = 0; i < ldev->ports; i++)
936 mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
937 mlx5_core_err(dev0, "Failed to enable lag\n");
941 } else if (mlx5_lag_should_modify_lag(ldev, do_bond)) {
942 mlx5_modify_lag(ldev, &tracker);
943 } else if (mlx5_lag_should_disable_lag(ldev, do_bond)) {
944 mlx5_disable_lag(ldev);
948 /* The last mdev to unregister will destroy the workqueue before removing the
949 * devcom component, and as all the mdevs use the same devcom component we are
950 * guaranteed that the devcom is valid while the calling work is running.
952 struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev)
954 struct mlx5_devcom_comp_dev *devcom = NULL;
957 mutex_lock(&ldev->lock);
958 for (i = 0; i < ldev->ports; i++) {
959 if (ldev->pf[i].dev) {
960 devcom = ldev->pf[i].dev->priv.hca_devcom_comp;
964 mutex_unlock(&ldev->lock);
968 static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay)
970 queue_delayed_work(ldev->wq, &ldev->bond_work, delay);
973 static void mlx5_do_bond_work(struct work_struct *work)
975 struct delayed_work *delayed_work = to_delayed_work(work);
976 struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag,
978 struct mlx5_devcom_comp_dev *devcom;
981 devcom = mlx5_lag_get_devcom_comp(ldev);
985 status = mlx5_devcom_comp_trylock(devcom);
987 mlx5_queue_bond_work(ldev, HZ);
991 mutex_lock(&ldev->lock);
992 if (ldev->mode_changes_in_progress) {
993 mutex_unlock(&ldev->lock);
994 mlx5_devcom_comp_unlock(devcom);
995 mlx5_queue_bond_work(ldev, HZ);
1000 mutex_unlock(&ldev->lock);
1001 mlx5_devcom_comp_unlock(devcom);
1004 static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
1005 struct lag_tracker *tracker,
1006 struct netdev_notifier_changeupper_info *info)
1008 struct net_device *upper = info->upper_dev, *ndev_tmp;
1009 struct netdev_lag_upper_info *lag_upper_info = NULL;
1010 bool is_bonded, is_in_lag, mode_supported;
1011 bool has_inactive = 0;
1012 struct slave *slave;
1018 if (!netif_is_lag_master(upper))
1022 lag_upper_info = info->upper_info;
1024 /* The event may still be of interest if the slave does not belong to
1025 * us, but is enslaved to a master which has one or more of our netdevs
1026 * as slaves (e.g., if a new slave is added to a master that bonds two
1027 * of our netdevs, we should unbond).
1030 for_each_netdev_in_bond_rcu(upper, ndev_tmp) {
1031 idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev_tmp);
1033 slave = bond_slave_get_rcu(ndev_tmp);
1035 has_inactive |= bond_is_slave_inactive(slave);
1036 bond_status |= (1 << idx);
1043 /* None of this lagdev's netdevs are slaves of this master. */
1044 if (!(bond_status & GENMASK(ldev->ports - 1, 0)))
1047 if (lag_upper_info) {
1048 tracker->tx_type = lag_upper_info->tx_type;
1049 tracker->hash_type = lag_upper_info->hash_type;
1052 tracker->has_inactive = has_inactive;
1053 /* Determine bonding status:
1054 * A device is considered bonded if both its physical ports are slaves
1055 * of the same lag master, and only them.
1057 is_in_lag = num_slaves == ldev->ports &&
1058 bond_status == GENMASK(ldev->ports - 1, 0);
1060 /* Lag mode must be activebackup or hash. */
1061 mode_supported = tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP ||
1062 tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH;
1064 is_bonded = is_in_lag && mode_supported;
1065 if (tracker->is_bonded != is_bonded) {
1066 tracker->is_bonded = is_bonded;
1073 if (!mlx5_lag_is_ready(ldev))
1074 NL_SET_ERR_MSG_MOD(info->info.extack,
1075 "Can't activate LAG offload, PF is configured with more than 64 VFs");
1076 else if (!mode_supported)
1077 NL_SET_ERR_MSG_MOD(info->info.extack,
1078 "Can't activate LAG offload, TX type isn't supported");
1083 static int mlx5_handle_changelowerstate_event(struct mlx5_lag *ldev,
1084 struct lag_tracker *tracker,
1085 struct net_device *ndev,
1086 struct netdev_notifier_changelowerstate_info *info)
1088 struct netdev_lag_lower_state_info *lag_lower_info;
1091 if (!netif_is_lag_port(ndev))
1094 idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev);
1098 /* This information is used to determine virtual to physical
1101 lag_lower_info = info->lower_state_info;
1102 if (!lag_lower_info)
1105 tracker->netdev_state[idx] = *lag_lower_info;
1110 static int mlx5_handle_changeinfodata_event(struct mlx5_lag *ldev,
1111 struct lag_tracker *tracker,
1112 struct net_device *ndev)
1114 struct net_device *ndev_tmp;
1115 struct slave *slave;
1116 bool has_inactive = 0;
1119 if (!netif_is_lag_master(ndev))
1123 for_each_netdev_in_bond_rcu(ndev, ndev_tmp) {
1124 idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev_tmp);
1128 slave = bond_slave_get_rcu(ndev_tmp);
1130 has_inactive |= bond_is_slave_inactive(slave);
1134 if (tracker->has_inactive == has_inactive)
1137 tracker->has_inactive = has_inactive;
1142 /* this handler is always registered to netdev events */
1143 static int mlx5_lag_netdev_event(struct notifier_block *this,
1144 unsigned long event, void *ptr)
1146 struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
1147 struct lag_tracker tracker;
1148 struct mlx5_lag *ldev;
1151 if (event != NETDEV_CHANGEUPPER &&
1152 event != NETDEV_CHANGELOWERSTATE &&
1153 event != NETDEV_CHANGEINFODATA)
1156 ldev = container_of(this, struct mlx5_lag, nb);
1158 tracker = ldev->tracker;
1161 case NETDEV_CHANGEUPPER:
1162 changed = mlx5_handle_changeupper_event(ldev, &tracker, ptr);
1164 case NETDEV_CHANGELOWERSTATE:
1165 changed = mlx5_handle_changelowerstate_event(ldev, &tracker,
1168 case NETDEV_CHANGEINFODATA:
1169 changed = mlx5_handle_changeinfodata_event(ldev, &tracker, ndev);
1173 ldev->tracker = tracker;
1176 mlx5_queue_bond_work(ldev, 0);
1181 static void mlx5_ldev_add_netdev(struct mlx5_lag *ldev,
1182 struct mlx5_core_dev *dev,
1183 struct net_device *netdev)
1185 unsigned int fn = mlx5_get_dev_index(dev);
1186 unsigned long flags;
1188 if (fn >= ldev->ports)
1191 spin_lock_irqsave(&lag_lock, flags);
1192 ldev->pf[fn].netdev = netdev;
1193 ldev->tracker.netdev_state[fn].link_up = 0;
1194 ldev->tracker.netdev_state[fn].tx_enabled = 0;
1195 spin_unlock_irqrestore(&lag_lock, flags);
1198 static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev,
1199 struct net_device *netdev)
1201 unsigned long flags;
1204 spin_lock_irqsave(&lag_lock, flags);
1205 for (i = 0; i < ldev->ports; i++) {
1206 if (ldev->pf[i].netdev == netdev) {
1207 ldev->pf[i].netdev = NULL;
1211 spin_unlock_irqrestore(&lag_lock, flags);
1214 static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev,
1215 struct mlx5_core_dev *dev)
1217 unsigned int fn = mlx5_get_dev_index(dev);
1219 if (fn >= ldev->ports)
1222 ldev->pf[fn].dev = dev;
1223 dev->priv.lag = ldev;
1226 static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev,
1227 struct mlx5_core_dev *dev)
1231 for (i = 0; i < ldev->ports; i++)
1232 if (ldev->pf[i].dev == dev)
1235 if (i == ldev->ports)
1238 ldev->pf[i].dev = NULL;
1239 dev->priv.lag = NULL;
1242 /* Must be called with HCA devcom component lock held */
1243 static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev)
1245 struct mlx5_devcom_comp_dev *pos = NULL;
1246 struct mlx5_lag *ldev = NULL;
1247 struct mlx5_core_dev *tmp_dev;
1249 tmp_dev = mlx5_devcom_get_next_peer_data(dev->priv.hca_devcom_comp, &pos);
1251 ldev = mlx5_lag_dev(tmp_dev);
1254 ldev = mlx5_lag_dev_alloc(dev);
1256 mlx5_core_err(dev, "Failed to alloc lag dev\n");
1259 mlx5_ldev_add_mdev(ldev, dev);
1263 mutex_lock(&ldev->lock);
1264 if (ldev->mode_changes_in_progress) {
1265 mutex_unlock(&ldev->lock);
1268 mlx5_ldev_get(ldev);
1269 mlx5_ldev_add_mdev(ldev, dev);
1270 mutex_unlock(&ldev->lock);
1275 void mlx5_lag_remove_mdev(struct mlx5_core_dev *dev)
1277 struct mlx5_lag *ldev;
1279 ldev = mlx5_lag_dev(dev);
1283 /* mdev is being removed, might as well remove debugfs
1284 * as early as possible.
1286 mlx5_ldev_remove_debugfs(dev->priv.dbg.lag_debugfs);
1288 mutex_lock(&ldev->lock);
1289 if (ldev->mode_changes_in_progress) {
1290 mutex_unlock(&ldev->lock);
1294 mlx5_ldev_remove_mdev(ldev, dev);
1295 mutex_unlock(&ldev->lock);
1296 mlx5_ldev_put(ldev);
1299 void mlx5_lag_add_mdev(struct mlx5_core_dev *dev)
1303 if (!mlx5_lag_is_supported(dev))
1306 if (IS_ERR_OR_NULL(dev->priv.hca_devcom_comp))
1310 mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp);
1311 err = __mlx5_lag_dev_add_mdev(dev);
1312 mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp);
1318 mlx5_ldev_add_debugfs(dev);
1321 void mlx5_lag_remove_netdev(struct mlx5_core_dev *dev,
1322 struct net_device *netdev)
1324 struct mlx5_lag *ldev;
1327 ldev = mlx5_lag_dev(dev);
1331 mutex_lock(&ldev->lock);
1332 mlx5_ldev_remove_netdev(ldev, netdev);
1333 clear_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
1335 lag_is_active = __mlx5_lag_is_active(ldev);
1336 mutex_unlock(&ldev->lock);
1339 mlx5_queue_bond_work(ldev, 0);
1342 void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
1343 struct net_device *netdev)
1345 struct mlx5_lag *ldev;
1348 ldev = mlx5_lag_dev(dev);
1352 mutex_lock(&ldev->lock);
1353 mlx5_ldev_add_netdev(ldev, dev, netdev);
1355 for (i = 0; i < ldev->ports; i++)
1356 if (!ldev->pf[i].netdev)
1359 if (i >= ldev->ports)
1360 set_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
1361 mutex_unlock(&ldev->lock);
1362 mlx5_queue_bond_work(ldev, 0);
1365 bool mlx5_lag_is_roce(struct mlx5_core_dev *dev)
1367 struct mlx5_lag *ldev;
1368 unsigned long flags;
1371 spin_lock_irqsave(&lag_lock, flags);
1372 ldev = mlx5_lag_dev(dev);
1373 res = ldev && __mlx5_lag_is_roce(ldev);
1374 spin_unlock_irqrestore(&lag_lock, flags);
1378 EXPORT_SYMBOL(mlx5_lag_is_roce);
1380 bool mlx5_lag_is_active(struct mlx5_core_dev *dev)
1382 struct mlx5_lag *ldev;
1383 unsigned long flags;
1386 spin_lock_irqsave(&lag_lock, flags);
1387 ldev = mlx5_lag_dev(dev);
1388 res = ldev && __mlx5_lag_is_active(ldev);
1389 spin_unlock_irqrestore(&lag_lock, flags);
1393 EXPORT_SYMBOL(mlx5_lag_is_active);
1395 bool mlx5_lag_mode_is_hash(struct mlx5_core_dev *dev)
1397 struct mlx5_lag *ldev;
1398 unsigned long flags;
1401 spin_lock_irqsave(&lag_lock, flags);
1402 ldev = mlx5_lag_dev(dev);
1404 res = test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags);
1405 spin_unlock_irqrestore(&lag_lock, flags);
1409 EXPORT_SYMBOL(mlx5_lag_mode_is_hash);
1411 bool mlx5_lag_is_master(struct mlx5_core_dev *dev)
1413 struct mlx5_lag *ldev;
1414 unsigned long flags;
1417 spin_lock_irqsave(&lag_lock, flags);
1418 ldev = mlx5_lag_dev(dev);
1419 res = ldev && __mlx5_lag_is_active(ldev) &&
1420 dev == ldev->pf[MLX5_LAG_P1].dev;
1421 spin_unlock_irqrestore(&lag_lock, flags);
1425 EXPORT_SYMBOL(mlx5_lag_is_master);
1427 bool mlx5_lag_is_sriov(struct mlx5_core_dev *dev)
1429 struct mlx5_lag *ldev;
1430 unsigned long flags;
1433 spin_lock_irqsave(&lag_lock, flags);
1434 ldev = mlx5_lag_dev(dev);
1435 res = ldev && __mlx5_lag_is_sriov(ldev);
1436 spin_unlock_irqrestore(&lag_lock, flags);
1440 EXPORT_SYMBOL(mlx5_lag_is_sriov);
1442 bool mlx5_lag_is_shared_fdb(struct mlx5_core_dev *dev)
1444 struct mlx5_lag *ldev;
1445 unsigned long flags;
1448 spin_lock_irqsave(&lag_lock, flags);
1449 ldev = mlx5_lag_dev(dev);
1450 res = ldev && test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
1451 spin_unlock_irqrestore(&lag_lock, flags);
1455 EXPORT_SYMBOL(mlx5_lag_is_shared_fdb);
1457 void mlx5_lag_disable_change(struct mlx5_core_dev *dev)
1459 struct mlx5_lag *ldev;
1461 ldev = mlx5_lag_dev(dev);
1465 mlx5_devcom_comp_lock(dev->priv.hca_devcom_comp);
1466 mutex_lock(&ldev->lock);
1468 ldev->mode_changes_in_progress++;
1469 if (__mlx5_lag_is_active(ldev))
1470 mlx5_disable_lag(ldev);
1472 mutex_unlock(&ldev->lock);
1473 mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp);
1476 void mlx5_lag_enable_change(struct mlx5_core_dev *dev)
1478 struct mlx5_lag *ldev;
1480 ldev = mlx5_lag_dev(dev);
1484 mutex_lock(&ldev->lock);
1485 ldev->mode_changes_in_progress--;
1486 mutex_unlock(&ldev->lock);
1487 mlx5_queue_bond_work(ldev, 0);
1490 struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev)
1492 struct net_device *ndev = NULL;
1493 struct mlx5_lag *ldev;
1494 unsigned long flags;
1497 spin_lock_irqsave(&lag_lock, flags);
1498 ldev = mlx5_lag_dev(dev);
1500 if (!(ldev && __mlx5_lag_is_roce(ldev)))
1503 if (ldev->tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
1504 for (i = 0; i < ldev->ports; i++)
1505 if (ldev->tracker.netdev_state[i].tx_enabled)
1506 ndev = ldev->pf[i].netdev;
1508 ndev = ldev->pf[ldev->ports - 1].netdev;
1510 ndev = ldev->pf[MLX5_LAG_P1].netdev;
1516 spin_unlock_irqrestore(&lag_lock, flags);
1520 EXPORT_SYMBOL(mlx5_lag_get_roce_netdev);
1522 u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev,
1523 struct net_device *slave)
1525 struct mlx5_lag *ldev;
1526 unsigned long flags;
1530 spin_lock_irqsave(&lag_lock, flags);
1531 ldev = mlx5_lag_dev(dev);
1532 if (!(ldev && __mlx5_lag_is_roce(ldev)))
1535 for (i = 0; i < ldev->ports; i++) {
1536 if (ldev->pf[MLX5_LAG_P1].netdev == slave) {
1542 port = ldev->v2p_map[port * ldev->buckets];
1545 spin_unlock_irqrestore(&lag_lock, flags);
1548 EXPORT_SYMBOL(mlx5_lag_get_slave_port);
1550 u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev)
1552 struct mlx5_lag *ldev;
1554 ldev = mlx5_lag_dev(dev);
1560 EXPORT_SYMBOL(mlx5_lag_get_num_ports);
1562 struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i)
1564 struct mlx5_core_dev *peer_dev = NULL;
1565 struct mlx5_lag *ldev;
1566 unsigned long flags;
1569 spin_lock_irqsave(&lag_lock, flags);
1570 ldev = mlx5_lag_dev(dev);
1574 if (*i == ldev->ports)
1576 for (idx = *i; idx < ldev->ports; idx++)
1577 if (ldev->pf[idx].dev != dev)
1580 if (idx == ldev->ports) {
1586 peer_dev = ldev->pf[idx].dev;
1589 spin_unlock_irqrestore(&lag_lock, flags);
1592 EXPORT_SYMBOL(mlx5_lag_get_next_peer_mdev);
1594 int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
1599 int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out);
1600 struct mlx5_core_dev **mdev;
1601 struct mlx5_lag *ldev;
1602 unsigned long flags;
1607 out = kvzalloc(outlen, GFP_KERNEL);
1611 mdev = kvzalloc(sizeof(mdev[0]) * MLX5_MAX_PORTS, GFP_KERNEL);
1617 memset(values, 0, sizeof(*values) * num_counters);
1619 spin_lock_irqsave(&lag_lock, flags);
1620 ldev = mlx5_lag_dev(dev);
1621 if (ldev && __mlx5_lag_is_active(ldev)) {
1622 num_ports = ldev->ports;
1623 for (i = 0; i < ldev->ports; i++)
1624 mdev[i] = ldev->pf[i].dev;
1627 mdev[MLX5_LAG_P1] = dev;
1629 spin_unlock_irqrestore(&lag_lock, flags);
1631 for (i = 0; i < num_ports; ++i) {
1632 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {};
1634 MLX5_SET(query_cong_statistics_in, in, opcode,
1635 MLX5_CMD_OP_QUERY_CONG_STATISTICS);
1636 ret = mlx5_cmd_exec_inout(mdev[i], query_cong_statistics, in,
1641 for (j = 0; j < num_counters; ++j)
1642 values[j] += be64_to_cpup((__be64 *)(out + offsets[j]));
1651 EXPORT_SYMBOL(mlx5_lag_query_cong_counters);