e52e2144ab122c94b3c386b6cd4b7a69fe89b5f4
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / lag.c
1 /*
2  * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32
33 #include <linux/netdevice.h>
34 #include <linux/mlx5/driver.h>
35 #include <linux/mlx5/vport.h>
36 #include "mlx5_core.h"
37 #include "eswitch.h"
38 #include "lag.h"
39 #include "lag_mp.h"
40
41 /* General purpose, use for short periods of time.
42  * Beware of lock dependencies (preferably, no locks should be acquired
43  * under it).
44  */
45 static DEFINE_SPINLOCK(lag_lock);
46
47 static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 remap_port1,
48                                u8 remap_port2)
49 {
50         u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};
51         void *lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);
52
53         MLX5_SET(create_lag_in, in, opcode, MLX5_CMD_OP_CREATE_LAG);
54
55         MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);
56         MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);
57
58         return mlx5_cmd_exec_in(dev, create_lag, in);
59 }
60
61 static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 remap_port1,
62                                u8 remap_port2)
63 {
64         u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};
65         void *lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);
66
67         MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
68         MLX5_SET(modify_lag_in, in, field_select, 0x1);
69
70         MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);
71         MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);
72
73         return mlx5_cmd_exec_in(dev, modify_lag, in);
74 }
75
76 int mlx5_cmd_create_vport_lag(struct mlx5_core_dev *dev)
77 {
78         u32 in[MLX5_ST_SZ_DW(create_vport_lag_in)] = {};
79
80         MLX5_SET(create_vport_lag_in, in, opcode, MLX5_CMD_OP_CREATE_VPORT_LAG);
81
82         return mlx5_cmd_exec_in(dev, create_vport_lag, in);
83 }
84 EXPORT_SYMBOL(mlx5_cmd_create_vport_lag);
85
86 int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev)
87 {
88         u32 in[MLX5_ST_SZ_DW(destroy_vport_lag_in)] = {};
89
90         MLX5_SET(destroy_vport_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_VPORT_LAG);
91
92         return mlx5_cmd_exec_in(dev, destroy_vport_lag, in);
93 }
94 EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag);
95
96 int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
97                                 struct net_device *ndev)
98 {
99         int i;
100
101         for (i = 0; i < MLX5_MAX_PORTS; i++)
102                 if (ldev->pf[i].netdev == ndev)
103                         return i;
104
105         return -ENOENT;
106 }
107
108 static bool __mlx5_lag_is_roce(struct mlx5_lag *ldev)
109 {
110         return !!(ldev->flags & MLX5_LAG_FLAG_ROCE);
111 }
112
113 static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev)
114 {
115         return !!(ldev->flags & MLX5_LAG_FLAG_SRIOV);
116 }
117
118 static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
119                                            u8 *port1, u8 *port2)
120 {
121         *port1 = 1;
122         *port2 = 2;
123         if (!tracker->netdev_state[MLX5_LAG_P1].tx_enabled ||
124             !tracker->netdev_state[MLX5_LAG_P1].link_up) {
125                 *port1 = 2;
126                 return;
127         }
128
129         if (!tracker->netdev_state[MLX5_LAG_P2].tx_enabled ||
130             !tracker->netdev_state[MLX5_LAG_P2].link_up)
131                 *port2 = 1;
132 }
133
134 void mlx5_modify_lag(struct mlx5_lag *ldev,
135                      struct lag_tracker *tracker)
136 {
137         struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
138         u8 v2p_port1, v2p_port2;
139         int err;
140
141         mlx5_infer_tx_affinity_mapping(tracker, &v2p_port1,
142                                        &v2p_port2);
143
144         if (v2p_port1 != ldev->v2p_map[MLX5_LAG_P1] ||
145             v2p_port2 != ldev->v2p_map[MLX5_LAG_P2]) {
146                 ldev->v2p_map[MLX5_LAG_P1] = v2p_port1;
147                 ldev->v2p_map[MLX5_LAG_P2] = v2p_port2;
148
149                 mlx5_core_info(dev0, "modify lag map port 1:%d port 2:%d",
150                                ldev->v2p_map[MLX5_LAG_P1],
151                                ldev->v2p_map[MLX5_LAG_P2]);
152
153                 err = mlx5_cmd_modify_lag(dev0, v2p_port1, v2p_port2);
154                 if (err)
155                         mlx5_core_err(dev0,
156                                       "Failed to modify LAG (%d)\n",
157                                       err);
158         }
159 }
160
161 static int mlx5_create_lag(struct mlx5_lag *ldev,
162                            struct lag_tracker *tracker)
163 {
164         struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
165         int err;
166
167         mlx5_infer_tx_affinity_mapping(tracker, &ldev->v2p_map[MLX5_LAG_P1],
168                                        &ldev->v2p_map[MLX5_LAG_P2]);
169
170         mlx5_core_info(dev0, "lag map port 1:%d port 2:%d",
171                        ldev->v2p_map[MLX5_LAG_P1], ldev->v2p_map[MLX5_LAG_P2]);
172
173         err = mlx5_cmd_create_lag(dev0, ldev->v2p_map[MLX5_LAG_P1],
174                                   ldev->v2p_map[MLX5_LAG_P2]);
175         if (err)
176                 mlx5_core_err(dev0,
177                               "Failed to create LAG (%d)\n",
178                               err);
179         return err;
180 }
181
182 int mlx5_activate_lag(struct mlx5_lag *ldev,
183                       struct lag_tracker *tracker,
184                       u8 flags)
185 {
186         bool roce_lag = !!(flags & MLX5_LAG_FLAG_ROCE);
187         struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
188         int err;
189
190         err = mlx5_create_lag(ldev, tracker);
191         if (err) {
192                 if (roce_lag) {
193                         mlx5_core_err(dev0,
194                                       "Failed to activate RoCE LAG\n");
195                 } else {
196                         mlx5_core_err(dev0,
197                                       "Failed to activate VF LAG\n"
198                                       "Make sure all VFs are unbound prior to VF LAG activation or deactivation\n");
199                 }
200                 return err;
201         }
202
203         ldev->flags |= flags;
204         return 0;
205 }
206
207 static int mlx5_deactivate_lag(struct mlx5_lag *ldev)
208 {
209         struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
210         u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
211         bool roce_lag = __mlx5_lag_is_roce(ldev);
212         int err;
213
214         ldev->flags &= ~MLX5_LAG_MODE_FLAGS;
215
216         MLX5_SET(destroy_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_LAG);
217         err = mlx5_cmd_exec_in(dev0, destroy_lag, in);
218         if (err) {
219                 if (roce_lag) {
220                         mlx5_core_err(dev0,
221                                       "Failed to deactivate RoCE LAG; driver restart required\n");
222                 } else {
223                         mlx5_core_err(dev0,
224                                       "Failed to deactivate VF LAG; driver restart required\n"
225                                       "Make sure all VFs are unbound prior to VF LAG activation or deactivation\n");
226                 }
227         }
228
229         return err;
230 }
231
232 static bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
233 {
234         if (!ldev->pf[MLX5_LAG_P1].dev || !ldev->pf[MLX5_LAG_P2].dev)
235                 return false;
236
237 #ifdef CONFIG_MLX5_ESWITCH
238         return mlx5_esw_lag_prereq(ldev->pf[MLX5_LAG_P1].dev,
239                                    ldev->pf[MLX5_LAG_P2].dev);
240 #else
241         return (!mlx5_sriov_is_enabled(ldev->pf[MLX5_LAG_P1].dev) &&
242                 !mlx5_sriov_is_enabled(ldev->pf[MLX5_LAG_P2].dev));
243 #endif
244 }
245
246 static void mlx5_lag_add_devices(struct mlx5_lag *ldev)
247 {
248         int i;
249
250         for (i = 0; i < MLX5_MAX_PORTS; i++) {
251                 if (!ldev->pf[i].dev)
252                         continue;
253
254                 ldev->pf[i].dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
255                 mlx5_rescan_drivers_locked(ldev->pf[i].dev);
256         }
257 }
258
259 static void mlx5_lag_remove_devices(struct mlx5_lag *ldev)
260 {
261         int i;
262
263         for (i = 0; i < MLX5_MAX_PORTS; i++) {
264                 if (!ldev->pf[i].dev)
265                         continue;
266
267                 ldev->pf[i].dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
268                 mlx5_rescan_drivers_locked(ldev->pf[i].dev);
269         }
270 }
271
272 static void mlx5_do_bond(struct mlx5_lag *ldev)
273 {
274         struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
275         struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
276         struct lag_tracker tracker;
277         bool do_bond, roce_lag;
278         int err;
279
280         if (!mlx5_lag_is_ready(ldev))
281                 return;
282
283         tracker = ldev->tracker;
284
285         do_bond = tracker.is_bonded && mlx5_lag_check_prereq(ldev);
286
287         if (do_bond && !__mlx5_lag_is_active(ldev)) {
288                 roce_lag = !mlx5_sriov_is_enabled(dev0) &&
289                            !mlx5_sriov_is_enabled(dev1);
290
291 #ifdef CONFIG_MLX5_ESWITCH
292                 roce_lag = roce_lag &&
293                            dev0->priv.eswitch->mode == MLX5_ESWITCH_NONE &&
294                            dev1->priv.eswitch->mode == MLX5_ESWITCH_NONE;
295 #endif
296
297                 if (roce_lag)
298                         mlx5_lag_remove_devices(ldev);
299
300                 err = mlx5_activate_lag(ldev, &tracker,
301                                         roce_lag ? MLX5_LAG_FLAG_ROCE :
302                                         MLX5_LAG_FLAG_SRIOV);
303                 if (err) {
304                         if (roce_lag)
305                                 mlx5_lag_add_devices(ldev);
306
307                         return;
308                 }
309
310                 if (roce_lag) {
311                         dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
312                         mlx5_rescan_drivers_locked(dev0);
313                         mlx5_nic_vport_enable_roce(dev1);
314                 }
315         } else if (do_bond && __mlx5_lag_is_active(ldev)) {
316                 mlx5_modify_lag(ldev, &tracker);
317         } else if (!do_bond && __mlx5_lag_is_active(ldev)) {
318                 roce_lag = __mlx5_lag_is_roce(ldev);
319
320                 if (roce_lag) {
321                         dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
322                         mlx5_rescan_drivers_locked(dev0);
323                         mlx5_nic_vport_disable_roce(dev1);
324                 }
325
326                 err = mlx5_deactivate_lag(ldev);
327                 if (err)
328                         return;
329
330                 if (roce_lag)
331                         mlx5_lag_add_devices(ldev);
332         }
333 }
334
335 static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay)
336 {
337         queue_delayed_work(ldev->wq, &ldev->bond_work, delay);
338 }
339
340 static void mlx5_do_bond_work(struct work_struct *work)
341 {
342         struct delayed_work *delayed_work = to_delayed_work(work);
343         struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag,
344                                              bond_work);
345         int status;
346
347         status = mlx5_dev_list_trylock();
348         if (!status) {
349                 /* 1 sec delay. */
350                 mlx5_queue_bond_work(ldev, HZ);
351                 return;
352         }
353
354         mlx5_do_bond(ldev);
355         mlx5_dev_list_unlock();
356 }
357
358 static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
359                                          struct lag_tracker *tracker,
360                                          struct net_device *ndev,
361                                          struct netdev_notifier_changeupper_info *info)
362 {
363         struct net_device *upper = info->upper_dev, *ndev_tmp;
364         struct netdev_lag_upper_info *lag_upper_info = NULL;
365         bool is_bonded, is_in_lag, mode_supported;
366         int bond_status = 0;
367         int num_slaves = 0;
368         int idx;
369
370         if (!netif_is_lag_master(upper))
371                 return 0;
372
373         if (info->linking)
374                 lag_upper_info = info->upper_info;
375
376         /* The event may still be of interest if the slave does not belong to
377          * us, but is enslaved to a master which has one or more of our netdevs
378          * as slaves (e.g., if a new slave is added to a master that bonds two
379          * of our netdevs, we should unbond).
380          */
381         rcu_read_lock();
382         for_each_netdev_in_bond_rcu(upper, ndev_tmp) {
383                 idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev_tmp);
384                 if (idx >= 0)
385                         bond_status |= (1 << idx);
386
387                 num_slaves++;
388         }
389         rcu_read_unlock();
390
391         /* None of this lagdev's netdevs are slaves of this master. */
392         if (!(bond_status & 0x3))
393                 return 0;
394
395         if (lag_upper_info)
396                 tracker->tx_type = lag_upper_info->tx_type;
397
398         /* Determine bonding status:
399          * A device is considered bonded if both its physical ports are slaves
400          * of the same lag master, and only them.
401          */
402         is_in_lag = num_slaves == MLX5_MAX_PORTS && bond_status == 0x3;
403
404         if (!mlx5_lag_is_ready(ldev) && is_in_lag) {
405                 NL_SET_ERR_MSG_MOD(info->info.extack,
406                                    "Can't activate LAG offload, PF is configured with more than 64 VFs");
407                 return 0;
408         }
409
410         /* Lag mode must be activebackup or hash. */
411         mode_supported = tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP ||
412                          tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH;
413
414         if (is_in_lag && !mode_supported)
415                 NL_SET_ERR_MSG_MOD(info->info.extack,
416                                    "Can't activate LAG offload, TX type isn't supported");
417
418         is_bonded = is_in_lag && mode_supported;
419         if (tracker->is_bonded != is_bonded) {
420                 tracker->is_bonded = is_bonded;
421                 return 1;
422         }
423
424         return 0;
425 }
426
427 static int mlx5_handle_changelowerstate_event(struct mlx5_lag *ldev,
428                                               struct lag_tracker *tracker,
429                                               struct net_device *ndev,
430                                               struct netdev_notifier_changelowerstate_info *info)
431 {
432         struct netdev_lag_lower_state_info *lag_lower_info;
433         int idx;
434
435         if (!netif_is_lag_port(ndev))
436                 return 0;
437
438         idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev);
439         if (idx < 0)
440                 return 0;
441
442         /* This information is used to determine virtual to physical
443          * port mapping.
444          */
445         lag_lower_info = info->lower_state_info;
446         if (!lag_lower_info)
447                 return 0;
448
449         tracker->netdev_state[idx] = *lag_lower_info;
450
451         return 1;
452 }
453
454 static int mlx5_lag_netdev_event(struct notifier_block *this,
455                                  unsigned long event, void *ptr)
456 {
457         struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
458         struct lag_tracker tracker;
459         struct mlx5_lag *ldev;
460         int changed = 0;
461
462         if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE))
463                 return NOTIFY_DONE;
464
465         ldev    = container_of(this, struct mlx5_lag, nb);
466
467         if (!mlx5_lag_is_ready(ldev) && event == NETDEV_CHANGELOWERSTATE)
468                 return NOTIFY_DONE;
469
470         tracker = ldev->tracker;
471
472         switch (event) {
473         case NETDEV_CHANGEUPPER:
474                 changed = mlx5_handle_changeupper_event(ldev, &tracker, ndev,
475                                                         ptr);
476                 break;
477         case NETDEV_CHANGELOWERSTATE:
478                 changed = mlx5_handle_changelowerstate_event(ldev, &tracker,
479                                                              ndev, ptr);
480                 break;
481         }
482
483         ldev->tracker = tracker;
484
485         if (changed)
486                 mlx5_queue_bond_work(ldev, 0);
487
488         return NOTIFY_DONE;
489 }
490
491 static struct mlx5_lag *mlx5_lag_dev_alloc(void)
492 {
493         struct mlx5_lag *ldev;
494
495         ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
496         if (!ldev)
497                 return NULL;
498
499         ldev->wq = create_singlethread_workqueue("mlx5_lag");
500         if (!ldev->wq) {
501                 kfree(ldev);
502                 return NULL;
503         }
504
505         INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
506
507         return ldev;
508 }
509
510 static void mlx5_lag_dev_free(struct mlx5_lag *ldev)
511 {
512         destroy_workqueue(ldev->wq);
513         kfree(ldev);
514 }
515
516 static int mlx5_lag_dev_add_pf(struct mlx5_lag *ldev,
517                                struct mlx5_core_dev *dev,
518                                struct net_device *netdev)
519 {
520         unsigned int fn = PCI_FUNC(dev->pdev->devfn);
521
522         if (fn >= MLX5_MAX_PORTS)
523                 return -EPERM;
524
525         spin_lock(&lag_lock);
526         ldev->pf[fn].dev    = dev;
527         ldev->pf[fn].netdev = netdev;
528         ldev->tracker.netdev_state[fn].link_up = 0;
529         ldev->tracker.netdev_state[fn].tx_enabled = 0;
530
531         dev->priv.lag = ldev;
532
533         spin_unlock(&lag_lock);
534
535         return fn;
536 }
537
538 static void mlx5_lag_dev_remove_pf(struct mlx5_lag *ldev,
539                                    struct mlx5_core_dev *dev)
540 {
541         int i;
542
543         for (i = 0; i < MLX5_MAX_PORTS; i++)
544                 if (ldev->pf[i].dev == dev)
545                         break;
546
547         if (i == MLX5_MAX_PORTS)
548                 return;
549
550         spin_lock(&lag_lock);
551         memset(&ldev->pf[i], 0, sizeof(*ldev->pf));
552
553         dev->priv.lag = NULL;
554         spin_unlock(&lag_lock);
555 }
556
557 /* Must be called with intf_mutex held */
558 void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
559 {
560         struct mlx5_lag *ldev = NULL;
561         struct mlx5_core_dev *tmp_dev;
562         int i, err;
563
564         if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
565             !MLX5_CAP_GEN(dev, lag_master) ||
566             MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_MAX_PORTS)
567                 return;
568
569         tmp_dev = mlx5_get_next_phys_dev(dev);
570         if (tmp_dev)
571                 ldev = tmp_dev->priv.lag;
572
573         if (!ldev) {
574                 ldev = mlx5_lag_dev_alloc();
575                 if (!ldev) {
576                         mlx5_core_err(dev, "Failed to alloc lag dev\n");
577                         return;
578                 }
579         }
580
581         if (mlx5_lag_dev_add_pf(ldev, dev, netdev) < 0)
582                 return;
583
584         for (i = 0; i < MLX5_MAX_PORTS; i++)
585                 if (!ldev->pf[i].dev)
586                         break;
587
588         if (i >= MLX5_MAX_PORTS)
589                 ldev->flags |= MLX5_LAG_FLAG_READY;
590
591         if (!ldev->nb.notifier_call) {
592                 ldev->nb.notifier_call = mlx5_lag_netdev_event;
593                 if (register_netdevice_notifier_net(&init_net, &ldev->nb)) {
594                         ldev->nb.notifier_call = NULL;
595                         mlx5_core_err(dev, "Failed to register LAG netdev notifier\n");
596                 }
597         }
598
599         err = mlx5_lag_mp_init(ldev);
600         if (err)
601                 mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
602                               err);
603 }
604
605 /* Must be called with intf_mutex held */
606 void mlx5_lag_remove(struct mlx5_core_dev *dev)
607 {
608         struct mlx5_lag *ldev;
609         int i;
610
611         ldev = mlx5_lag_dev_get(dev);
612         if (!ldev)
613                 return;
614
615         if (__mlx5_lag_is_active(ldev))
616                 mlx5_deactivate_lag(ldev);
617
618         mlx5_lag_dev_remove_pf(ldev, dev);
619
620         ldev->flags &= ~MLX5_LAG_FLAG_READY;
621
622         for (i = 0; i < MLX5_MAX_PORTS; i++)
623                 if (ldev->pf[i].dev)
624                         break;
625
626         if (i == MLX5_MAX_PORTS) {
627                 if (ldev->nb.notifier_call) {
628                         unregister_netdevice_notifier_net(&init_net, &ldev->nb);
629                         ldev->nb.notifier_call = NULL;
630                 }
631                 mlx5_lag_mp_cleanup(ldev);
632                 cancel_delayed_work_sync(&ldev->bond_work);
633                 mlx5_lag_dev_free(ldev);
634         }
635 }
636
637 bool mlx5_lag_is_roce(struct mlx5_core_dev *dev)
638 {
639         struct mlx5_lag *ldev;
640         bool res;
641
642         spin_lock(&lag_lock);
643         ldev = mlx5_lag_dev_get(dev);
644         res  = ldev && __mlx5_lag_is_roce(ldev);
645         spin_unlock(&lag_lock);
646
647         return res;
648 }
649 EXPORT_SYMBOL(mlx5_lag_is_roce);
650
651 bool mlx5_lag_is_active(struct mlx5_core_dev *dev)
652 {
653         struct mlx5_lag *ldev;
654         bool res;
655
656         spin_lock(&lag_lock);
657         ldev = mlx5_lag_dev_get(dev);
658         res  = ldev && __mlx5_lag_is_active(ldev);
659         spin_unlock(&lag_lock);
660
661         return res;
662 }
663 EXPORT_SYMBOL(mlx5_lag_is_active);
664
665 bool mlx5_lag_is_sriov(struct mlx5_core_dev *dev)
666 {
667         struct mlx5_lag *ldev;
668         bool res;
669
670         spin_lock(&lag_lock);
671         ldev = mlx5_lag_dev_get(dev);
672         res  = ldev && __mlx5_lag_is_sriov(ldev);
673         spin_unlock(&lag_lock);
674
675         return res;
676 }
677 EXPORT_SYMBOL(mlx5_lag_is_sriov);
678
679 void mlx5_lag_update(struct mlx5_core_dev *dev)
680 {
681         struct mlx5_lag *ldev;
682
683         mlx5_dev_list_lock();
684         ldev = mlx5_lag_dev_get(dev);
685         if (!ldev)
686                 goto unlock;
687
688         mlx5_do_bond(ldev);
689
690 unlock:
691         mlx5_dev_list_unlock();
692 }
693
694 struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev)
695 {
696         struct net_device *ndev = NULL;
697         struct mlx5_lag *ldev;
698
699         spin_lock(&lag_lock);
700         ldev = mlx5_lag_dev_get(dev);
701
702         if (!(ldev && __mlx5_lag_is_roce(ldev)))
703                 goto unlock;
704
705         if (ldev->tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
706                 ndev = ldev->tracker.netdev_state[MLX5_LAG_P1].tx_enabled ?
707                        ldev->pf[MLX5_LAG_P1].netdev :
708                        ldev->pf[MLX5_LAG_P2].netdev;
709         } else {
710                 ndev = ldev->pf[MLX5_LAG_P1].netdev;
711         }
712         if (ndev)
713                 dev_hold(ndev);
714
715 unlock:
716         spin_unlock(&lag_lock);
717
718         return ndev;
719 }
720 EXPORT_SYMBOL(mlx5_lag_get_roce_netdev);
721
722 u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev,
723                            struct net_device *slave)
724 {
725         struct mlx5_lag *ldev;
726         u8 port = 0;
727
728         spin_lock(&lag_lock);
729         ldev = mlx5_lag_dev_get(dev);
730         if (!(ldev && __mlx5_lag_is_roce(ldev)))
731                 goto unlock;
732
733         if (ldev->pf[MLX5_LAG_P1].netdev == slave)
734                 port = MLX5_LAG_P1;
735         else
736                 port = MLX5_LAG_P2;
737
738         port = ldev->v2p_map[port];
739
740 unlock:
741         spin_unlock(&lag_lock);
742         return port;
743 }
744 EXPORT_SYMBOL(mlx5_lag_get_slave_port);
745
746 int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
747                                  u64 *values,
748                                  int num_counters,
749                                  size_t *offsets)
750 {
751         int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out);
752         struct mlx5_core_dev *mdev[MLX5_MAX_PORTS];
753         struct mlx5_lag *ldev;
754         int num_ports;
755         int ret, i, j;
756         void *out;
757
758         out = kvzalloc(outlen, GFP_KERNEL);
759         if (!out)
760                 return -ENOMEM;
761
762         memset(values, 0, sizeof(*values) * num_counters);
763
764         spin_lock(&lag_lock);
765         ldev = mlx5_lag_dev_get(dev);
766         if (ldev && __mlx5_lag_is_active(ldev)) {
767                 num_ports = MLX5_MAX_PORTS;
768                 mdev[MLX5_LAG_P1] = ldev->pf[MLX5_LAG_P1].dev;
769                 mdev[MLX5_LAG_P2] = ldev->pf[MLX5_LAG_P2].dev;
770         } else {
771                 num_ports = 1;
772                 mdev[MLX5_LAG_P1] = dev;
773         }
774         spin_unlock(&lag_lock);
775
776         for (i = 0; i < num_ports; ++i) {
777                 u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {};
778
779                 MLX5_SET(query_cong_statistics_in, in, opcode,
780                          MLX5_CMD_OP_QUERY_CONG_STATISTICS);
781                 ret = mlx5_cmd_exec_inout(mdev[i], query_cong_statistics, in,
782                                           out);
783                 if (ret)
784                         goto free;
785
786                 for (j = 0; j < num_counters; ++j)
787                         values[j] += be64_to_cpup((__be64 *)(out + offsets[j]));
788         }
789
790 free:
791         kvfree(out);
792         return ret;
793 }
794 EXPORT_SYMBOL(mlx5_lag_query_cong_counters);