ACPI: Remove assorted unused declarations of functions
[linux-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / lag / port_sel.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. */
3
4 #include <linux/netdevice.h>
5 #include "lag.h"
6
7 enum {
8         MLX5_LAG_FT_LEVEL_TTC,
9         MLX5_LAG_FT_LEVEL_INNER_TTC,
10         MLX5_LAG_FT_LEVEL_DEFINER,
11 };
12
13 static struct mlx5_flow_group *
14 mlx5_create_hash_flow_group(struct mlx5_flow_table *ft,
15                             struct mlx5_flow_definer *definer,
16                             u8 rules)
17 {
18         int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
19         struct mlx5_flow_group *fg;
20         u32 *in;
21
22         in = kvzalloc(inlen, GFP_KERNEL);
23         if (!in)
24                 return ERR_PTR(-ENOMEM);
25
26         MLX5_SET(create_flow_group_in, in, match_definer_id,
27                  mlx5_get_match_definer_id(definer));
28         MLX5_SET(create_flow_group_in, in, start_flow_index, 0);
29         MLX5_SET(create_flow_group_in, in, end_flow_index, rules - 1);
30         MLX5_SET(create_flow_group_in, in, group_type,
31                  MLX5_CREATE_FLOW_GROUP_IN_GROUP_TYPE_HASH_SPLIT);
32
33         fg = mlx5_create_flow_group(ft, in);
34         kvfree(in);
35         return fg;
36 }
37
38 static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
39                                           struct mlx5_lag_definer *lag_definer,
40                                           u8 *ports)
41 {
42         struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
43         struct mlx5_flow_table_attr ft_attr = {};
44         struct mlx5_flow_destination dest = {};
45         MLX5_DECLARE_FLOW_ACT(flow_act);
46         struct mlx5_flow_namespace *ns;
47         int err, i;
48         int idx;
49         int j;
50
51         ft_attr.max_fte = ldev->ports * ldev->buckets;
52         ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER;
53
54         ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_PORT_SEL);
55         if (!ns) {
56                 mlx5_core_warn(dev, "Failed to get port selection namespace\n");
57                 return -EOPNOTSUPP;
58         }
59
60         lag_definer->ft = mlx5_create_flow_table(ns, &ft_attr);
61         if (IS_ERR(lag_definer->ft)) {
62                 mlx5_core_warn(dev, "Failed to create port selection table\n");
63                 return PTR_ERR(lag_definer->ft);
64         }
65
66         lag_definer->fg = mlx5_create_hash_flow_group(lag_definer->ft,
67                                                       lag_definer->definer,
68                                                       ft_attr.max_fte);
69         if (IS_ERR(lag_definer->fg)) {
70                 err = PTR_ERR(lag_definer->fg);
71                 goto destroy_ft;
72         }
73
74         dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
75         dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
76         flow_act.flags |= FLOW_ACT_NO_APPEND;
77         for (i = 0; i < ldev->ports; i++) {
78                 for (j = 0; j < ldev->buckets; j++) {
79                         u8 affinity;
80
81                         idx = i * ldev->buckets + j;
82                         affinity = ports[idx];
83
84                         dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev,
85                                                           vhca_id);
86                         lag_definer->rules[idx] = mlx5_add_flow_rules(lag_definer->ft,
87                                                                       NULL, &flow_act,
88                                                                       &dest, 1);
89                         if (IS_ERR(lag_definer->rules[idx])) {
90                                 err = PTR_ERR(lag_definer->rules[idx]);
91                                 while (i--)
92                                         while (j--)
93                                                 mlx5_del_flow_rules(lag_definer->rules[idx]);
94                                 goto destroy_fg;
95                         }
96                 }
97         }
98
99         return 0;
100
101 destroy_fg:
102         mlx5_destroy_flow_group(lag_definer->fg);
103 destroy_ft:
104         mlx5_destroy_flow_table(lag_definer->ft);
105         return err;
106 }
107
108 static int mlx5_lag_set_definer_inner(u32 *match_definer_mask,
109                                       enum mlx5_traffic_types tt)
110 {
111         int format_id;
112         u8 *ipv6;
113
114         switch (tt) {
115         case MLX5_TT_IPV4_UDP:
116         case MLX5_TT_IPV4_TCP:
117                 format_id = 23;
118                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
119                                  inner_l4_sport);
120                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
121                                  inner_l4_dport);
122                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
123                                  inner_ip_src_addr);
124                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
125                                  inner_ip_dest_addr);
126                 break;
127         case MLX5_TT_IPV4:
128                 format_id = 23;
129                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
130                                  inner_l3_type);
131                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
132                                  inner_dmac_47_16);
133                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
134                                  inner_dmac_15_0);
135                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
136                                  inner_smac_47_16);
137                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
138                                  inner_smac_15_0);
139                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
140                                  inner_ip_src_addr);
141                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
142                                  inner_ip_dest_addr);
143                 break;
144         case MLX5_TT_IPV6_TCP:
145         case MLX5_TT_IPV6_UDP:
146                 format_id = 31;
147                 MLX5_SET_TO_ONES(match_definer_format_31, match_definer_mask,
148                                  inner_l4_sport);
149                 MLX5_SET_TO_ONES(match_definer_format_31, match_definer_mask,
150                                  inner_l4_dport);
151                 ipv6 = MLX5_ADDR_OF(match_definer_format_31, match_definer_mask,
152                                     inner_ip_dest_addr);
153                 memset(ipv6, 0xff, 16);
154                 ipv6 = MLX5_ADDR_OF(match_definer_format_31, match_definer_mask,
155                                     inner_ip_src_addr);
156                 memset(ipv6, 0xff, 16);
157                 break;
158         case MLX5_TT_IPV6:
159                 format_id = 32;
160                 ipv6 = MLX5_ADDR_OF(match_definer_format_32, match_definer_mask,
161                                     inner_ip_dest_addr);
162                 memset(ipv6, 0xff, 16);
163                 ipv6 = MLX5_ADDR_OF(match_definer_format_32, match_definer_mask,
164                                     inner_ip_src_addr);
165                 memset(ipv6, 0xff, 16);
166                 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask,
167                                  inner_dmac_47_16);
168                 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask,
169                                  inner_dmac_15_0);
170                 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask,
171                                  inner_smac_47_16);
172                 MLX5_SET_TO_ONES(match_definer_format_32, match_definer_mask,
173                                  inner_smac_15_0);
174                 break;
175         default:
176                 format_id = 23;
177                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
178                                  inner_l3_type);
179                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
180                                  inner_dmac_47_16);
181                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
182                                  inner_dmac_15_0);
183                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
184                                  inner_smac_47_16);
185                 MLX5_SET_TO_ONES(match_definer_format_23, match_definer_mask,
186                                  inner_smac_15_0);
187                 break;
188         }
189
190         return format_id;
191 }
192
193 static int mlx5_lag_set_definer(u32 *match_definer_mask,
194                                 enum mlx5_traffic_types tt, bool tunnel,
195                                 enum netdev_lag_hash hash)
196 {
197         int format_id;
198         u8 *ipv6;
199
200         if (tunnel)
201                 return mlx5_lag_set_definer_inner(match_definer_mask, tt);
202
203         switch (tt) {
204         case MLX5_TT_IPV4_UDP:
205         case MLX5_TT_IPV4_TCP:
206                 format_id = 22;
207                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
208                                  outer_l4_sport);
209                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
210                                  outer_l4_dport);
211                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
212                                  outer_ip_src_addr);
213                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
214                                  outer_ip_dest_addr);
215                 break;
216         case MLX5_TT_IPV4:
217                 format_id = 22;
218                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
219                                  outer_l3_type);
220                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
221                                  outer_dmac_47_16);
222                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
223                                  outer_dmac_15_0);
224                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
225                                  outer_smac_47_16);
226                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
227                                  outer_smac_15_0);
228                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
229                                  outer_ip_src_addr);
230                 MLX5_SET_TO_ONES(match_definer_format_22, match_definer_mask,
231                                  outer_ip_dest_addr);
232                 break;
233         case MLX5_TT_IPV6_TCP:
234         case MLX5_TT_IPV6_UDP:
235                 format_id = 29;
236                 MLX5_SET_TO_ONES(match_definer_format_29, match_definer_mask,
237                                  outer_l4_sport);
238                 MLX5_SET_TO_ONES(match_definer_format_29, match_definer_mask,
239                                  outer_l4_dport);
240                 ipv6 = MLX5_ADDR_OF(match_definer_format_29, match_definer_mask,
241                                     outer_ip_dest_addr);
242                 memset(ipv6, 0xff, 16);
243                 ipv6 = MLX5_ADDR_OF(match_definer_format_29, match_definer_mask,
244                                     outer_ip_src_addr);
245                 memset(ipv6, 0xff, 16);
246                 break;
247         case MLX5_TT_IPV6:
248                 format_id = 30;
249                 ipv6 = MLX5_ADDR_OF(match_definer_format_30, match_definer_mask,
250                                     outer_ip_dest_addr);
251                 memset(ipv6, 0xff, 16);
252                 ipv6 = MLX5_ADDR_OF(match_definer_format_30, match_definer_mask,
253                                     outer_ip_src_addr);
254                 memset(ipv6, 0xff, 16);
255                 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask,
256                                  outer_dmac_47_16);
257                 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask,
258                                  outer_dmac_15_0);
259                 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask,
260                                  outer_smac_47_16);
261                 MLX5_SET_TO_ONES(match_definer_format_30, match_definer_mask,
262                                  outer_smac_15_0);
263                 break;
264         default:
265                 format_id = 0;
266                 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask,
267                                  outer_smac_47_16);
268                 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask,
269                                  outer_smac_15_0);
270
271                 if (hash == NETDEV_LAG_HASH_VLAN_SRCMAC) {
272                         MLX5_SET_TO_ONES(match_definer_format_0,
273                                          match_definer_mask,
274                                          outer_first_vlan_vid);
275                         break;
276                 }
277
278                 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask,
279                                  outer_ethertype);
280                 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask,
281                                  outer_dmac_47_16);
282                 MLX5_SET_TO_ONES(match_definer_format_0, match_definer_mask,
283                                  outer_dmac_15_0);
284                 break;
285         }
286
287         return format_id;
288 }
289
290 static struct mlx5_lag_definer *
291 mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash,
292                         enum mlx5_traffic_types tt, bool tunnel, u8 *ports)
293 {
294         struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
295         struct mlx5_lag_definer *lag_definer;
296         u32 *match_definer_mask;
297         int format_id, err;
298
299         lag_definer = kzalloc(sizeof(*lag_definer), GFP_KERNEL);
300         if (!lag_definer)
301                 return ERR_PTR(-ENOMEM);
302
303         match_definer_mask = kvzalloc(MLX5_FLD_SZ_BYTES(match_definer,
304                                                         match_mask),
305                                       GFP_KERNEL);
306         if (!match_definer_mask) {
307                 err = -ENOMEM;
308                 goto free_lag_definer;
309         }
310
311         format_id = mlx5_lag_set_definer(match_definer_mask, tt, tunnel, hash);
312         lag_definer->definer =
313                 mlx5_create_match_definer(dev, MLX5_FLOW_NAMESPACE_PORT_SEL,
314                                           format_id, match_definer_mask);
315         if (IS_ERR(lag_definer->definer)) {
316                 err = PTR_ERR(lag_definer->definer);
317                 goto free_mask;
318         }
319
320         err = mlx5_lag_create_port_sel_table(ldev, lag_definer, ports);
321         if (err)
322                 goto destroy_match_definer;
323
324         kvfree(match_definer_mask);
325
326         return lag_definer;
327
328 destroy_match_definer:
329         mlx5_destroy_match_definer(dev, lag_definer->definer);
330 free_mask:
331         kvfree(match_definer_mask);
332 free_lag_definer:
333         kfree(lag_definer);
334         return ERR_PTR(err);
335 }
336
337 static void mlx5_lag_destroy_definer(struct mlx5_lag *ldev,
338                                      struct mlx5_lag_definer *lag_definer)
339 {
340         struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
341         int idx;
342         int i;
343         int j;
344
345         for (i = 0; i < ldev->ports; i++) {
346                 for (j = 0; j < ldev->buckets; j++) {
347                         idx = i * ldev->buckets + j;
348                         mlx5_del_flow_rules(lag_definer->rules[idx]);
349                 }
350         }
351         mlx5_destroy_flow_group(lag_definer->fg);
352         mlx5_destroy_flow_table(lag_definer->ft);
353         mlx5_destroy_match_definer(dev, lag_definer->definer);
354         kfree(lag_definer);
355 }
356
357 static void mlx5_lag_destroy_definers(struct mlx5_lag *ldev)
358 {
359         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
360         int tt;
361
362         for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
363                 if (port_sel->outer.definers[tt])
364                         mlx5_lag_destroy_definer(ldev,
365                                                  port_sel->outer.definers[tt]);
366                 if (port_sel->inner.definers[tt])
367                         mlx5_lag_destroy_definer(ldev,
368                                                  port_sel->inner.definers[tt]);
369         }
370 }
371
372 static int mlx5_lag_create_definers(struct mlx5_lag *ldev,
373                                     enum netdev_lag_hash hash_type,
374                                     u8 *ports)
375 {
376         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
377         struct mlx5_lag_definer *lag_definer;
378         int tt, err;
379
380         for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
381                 lag_definer = mlx5_lag_create_definer(ldev, hash_type, tt,
382                                                       false, ports);
383                 if (IS_ERR(lag_definer)) {
384                         err = PTR_ERR(lag_definer);
385                         goto destroy_definers;
386                 }
387                 port_sel->outer.definers[tt] = lag_definer;
388
389                 if (!port_sel->tunnel)
390                         continue;
391
392                 lag_definer =
393                         mlx5_lag_create_definer(ldev, hash_type, tt,
394                                                 true, ports);
395                 if (IS_ERR(lag_definer)) {
396                         err = PTR_ERR(lag_definer);
397                         goto destroy_definers;
398                 }
399                 port_sel->inner.definers[tt] = lag_definer;
400         }
401
402         return 0;
403
404 destroy_definers:
405         mlx5_lag_destroy_definers(ldev);
406         return err;
407 }
408
409 static void set_tt_map(struct mlx5_lag_port_sel *port_sel,
410                        enum netdev_lag_hash hash)
411 {
412         port_sel->tunnel = false;
413
414         switch (hash) {
415         case NETDEV_LAG_HASH_E34:
416                 port_sel->tunnel = true;
417                 fallthrough;
418         case NETDEV_LAG_HASH_L34:
419                 set_bit(MLX5_TT_IPV4_TCP, port_sel->tt_map);
420                 set_bit(MLX5_TT_IPV4_UDP, port_sel->tt_map);
421                 set_bit(MLX5_TT_IPV6_TCP, port_sel->tt_map);
422                 set_bit(MLX5_TT_IPV6_UDP, port_sel->tt_map);
423                 set_bit(MLX5_TT_IPV4, port_sel->tt_map);
424                 set_bit(MLX5_TT_IPV6, port_sel->tt_map);
425                 set_bit(MLX5_TT_ANY, port_sel->tt_map);
426                 break;
427         case NETDEV_LAG_HASH_E23:
428                 port_sel->tunnel = true;
429                 fallthrough;
430         case NETDEV_LAG_HASH_L23:
431                 set_bit(MLX5_TT_IPV4, port_sel->tt_map);
432                 set_bit(MLX5_TT_IPV6, port_sel->tt_map);
433                 set_bit(MLX5_TT_ANY, port_sel->tt_map);
434                 break;
435         default:
436                 set_bit(MLX5_TT_ANY, port_sel->tt_map);
437                 break;
438         }
439 }
440
441 #define SET_IGNORE_DESTS_BITS(tt_map, dests)                            \
442         do {                                                            \
443                 int idx;                                                \
444                                                                         \
445                 for_each_clear_bit(idx, tt_map, MLX5_NUM_TT)            \
446                         set_bit(idx, dests);                            \
447         } while (0)
448
449 static void mlx5_lag_set_inner_ttc_params(struct mlx5_lag *ldev,
450                                           struct ttc_params *ttc_params)
451 {
452         struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
453         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
454         struct mlx5_flow_table_attr *ft_attr;
455         int tt;
456
457         ttc_params->ns = mlx5_get_flow_namespace(dev,
458                                                  MLX5_FLOW_NAMESPACE_PORT_SEL);
459         ft_attr = &ttc_params->ft_attr;
460         ft_attr->level = MLX5_LAG_FT_LEVEL_INNER_TTC;
461
462         for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
463                 ttc_params->dests[tt].type =
464                         MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
465                 ttc_params->dests[tt].ft = port_sel->inner.definers[tt]->ft;
466         }
467         SET_IGNORE_DESTS_BITS(port_sel->tt_map, ttc_params->ignore_dests);
468 }
469
470 static void mlx5_lag_set_outer_ttc_params(struct mlx5_lag *ldev,
471                                           struct ttc_params *ttc_params)
472 {
473         struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
474         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
475         struct mlx5_flow_table_attr *ft_attr;
476         int tt;
477
478         ttc_params->ns = mlx5_get_flow_namespace(dev,
479                                                  MLX5_FLOW_NAMESPACE_PORT_SEL);
480         ft_attr = &ttc_params->ft_attr;
481         ft_attr->level = MLX5_LAG_FT_LEVEL_TTC;
482
483         for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
484                 ttc_params->dests[tt].type =
485                         MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
486                 ttc_params->dests[tt].ft = port_sel->outer.definers[tt]->ft;
487         }
488         SET_IGNORE_DESTS_BITS(port_sel->tt_map, ttc_params->ignore_dests);
489
490         ttc_params->inner_ttc = port_sel->tunnel;
491         if (!port_sel->tunnel)
492                 return;
493
494         for (tt = 0; tt < MLX5_NUM_TUNNEL_TT; tt++) {
495                 ttc_params->tunnel_dests[tt].type =
496                         MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
497                 ttc_params->tunnel_dests[tt].ft =
498                         mlx5_get_ttc_flow_table(port_sel->inner.ttc);
499         }
500 }
501
502 static int mlx5_lag_create_ttc_table(struct mlx5_lag *ldev)
503 {
504         struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
505         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
506         struct ttc_params ttc_params = {};
507
508         mlx5_lag_set_outer_ttc_params(ldev, &ttc_params);
509         port_sel->outer.ttc = mlx5_create_ttc_table(dev, &ttc_params);
510         if (IS_ERR(port_sel->outer.ttc))
511                 return PTR_ERR(port_sel->outer.ttc);
512
513         return 0;
514 }
515
516 static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev)
517 {
518         struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
519         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
520         struct ttc_params ttc_params = {};
521
522         mlx5_lag_set_inner_ttc_params(ldev, &ttc_params);
523         port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params);
524         if (IS_ERR(port_sel->inner.ttc))
525                 return PTR_ERR(port_sel->inner.ttc);
526
527         return 0;
528 }
529
530 int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
531                              enum netdev_lag_hash hash_type, u8 *ports)
532 {
533         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
534         int err;
535
536         set_tt_map(port_sel, hash_type);
537         err = mlx5_lag_create_definers(ldev, hash_type, ports);
538         if (err)
539                 return err;
540
541         if (port_sel->tunnel) {
542                 err = mlx5_lag_create_inner_ttc_table(ldev);
543                 if (err)
544                         goto destroy_definers;
545         }
546
547         err = mlx5_lag_create_ttc_table(ldev);
548         if (err)
549                 goto destroy_inner;
550
551         return 0;
552
553 destroy_inner:
554         if (port_sel->tunnel)
555                 mlx5_destroy_ttc_table(port_sel->inner.ttc);
556 destroy_definers:
557         mlx5_lag_destroy_definers(ldev);
558         return err;
559 }
560
561 static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
562                                                    struct mlx5_lag_definer *def,
563                                                    u8 *ports)
564 {
565         struct mlx5_flow_destination dest = {};
566         int idx;
567         int err;
568         int i;
569         int j;
570
571         dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
572         dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
573
574         for (i = 0; i < ldev->ports; i++) {
575                 for (j = 0; j < ldev->buckets; j++) {
576                         idx = i * ldev->buckets + j;
577                         if (ldev->v2p_map[i] == ports[i])
578                                 continue;
579
580                         dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev,
581                                                           vhca_id);
582                         err = mlx5_modify_rule_destination(def->rules[idx], &dest, NULL);
583                         if (err)
584                                 return err;
585                 }
586         }
587
588         return 0;
589 }
590
591 static int
592 mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
593                                       struct mlx5_lag_definer **definers,
594                                       u8 *ports)
595 {
596         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
597         int err;
598         int tt;
599
600         for_each_set_bit(tt, port_sel->tt_map, MLX5_NUM_TT) {
601                 err = __mlx5_lag_modify_definers_destinations(ldev, definers[tt], ports);
602                 if (err)
603                         return err;
604         }
605
606         return 0;
607 }
608
609 int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports)
610 {
611         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
612         int err;
613
614         err = mlx5_lag_modify_definers_destinations(ldev,
615                                                     port_sel->outer.definers,
616                                                     ports);
617         if (err)
618                 return err;
619
620         if (!port_sel->tunnel)
621                 return 0;
622
623         return mlx5_lag_modify_definers_destinations(ldev,
624                                                      port_sel->inner.definers,
625                                                      ports);
626 }
627
628 void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev)
629 {
630         struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
631
632         mlx5_destroy_ttc_table(port_sel->outer.ttc);
633         if (port_sel->tunnel)
634                 mlx5_destroy_ttc_table(port_sel->inner.ttc);
635         mlx5_lag_destroy_definers(ldev);
636         memset(port_sel, 0, sizeof(*port_sel));
637 }