ACPI: Remove assorted unused declarations of functions
[linux-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / lag / port_sel.c
CommitLineData
1065e001
MG
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
dc48516e 7enum {
8e25a2bc
MG
8 MLX5_LAG_FT_LEVEL_TTC,
9 MLX5_LAG_FT_LEVEL_INNER_TTC,
dc48516e
MG
10 MLX5_LAG_FT_LEVEL_DEFINER,
11};
12
13static struct mlx5_flow_group *
14mlx5_create_hash_flow_group(struct mlx5_flow_table *ft,
7e978e77 15 struct mlx5_flow_definer *definer,
352899f3 16 u8 rules)
dc48516e
MG
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);
352899f3 29 MLX5_SET(create_flow_group_in, in, end_flow_index, rules - 1);
dc48516e
MG
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
38static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
39 struct mlx5_lag_definer *lag_definer,
7e978e77 40 u8 *ports)
dc48516e
MG
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;
352899f3
MB
48 int idx;
49 int j;
dc48516e 50
352899f3 51 ft_attr.max_fte = ldev->ports * ldev->buckets;
dc48516e
MG
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,
7e978e77 67 lag_definer->definer,
352899f3 68 ft_attr.max_fte);
dc48516e
MG
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;
7e978e77 77 for (i = 0; i < ldev->ports; i++) {
352899f3
MB
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 }
dc48516e
MG
96 }
97 }
98
99 return 0;
100
101destroy_fg:
102 mlx5_destroy_flow_group(lag_definer->fg);
103destroy_ft:
104 mlx5_destroy_flow_table(lag_definer->ft);
105 return err;
106}
107
e465550b
MG
108static 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
193static 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
dc48516e
MG
290static struct mlx5_lag_definer *
291mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash,
7e978e77 292 enum mlx5_traffic_types tt, bool tunnel, u8 *ports)
dc48516e
MG
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)
c7ebe23c 301 return ERR_PTR(-ENOMEM);
dc48516e
MG
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
7e978e77 320 err = mlx5_lag_create_port_sel_table(ldev, lag_definer, ports);
dc48516e
MG
321 if (err)
322 goto destroy_match_definer;
323
324 kvfree(match_definer_mask);
325
326 return lag_definer;
327
328destroy_match_definer:
329 mlx5_destroy_match_definer(dev, lag_definer->definer);
330free_mask:
331 kvfree(match_definer_mask);
332free_lag_definer:
333 kfree(lag_definer);
334 return ERR_PTR(err);
335}
336
337static 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;
352899f3 341 int idx;
dc48516e 342 int i;
352899f3 343 int j;
dc48516e 344
352899f3
MB
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 }
dc48516e
MG
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
357static 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
372static int mlx5_lag_create_definers(struct mlx5_lag *ldev,
373 enum netdev_lag_hash hash_type,
7e978e77 374 u8 *ports)
dc48516e
MG
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,
7e978e77 382 false, ports);
dc48516e
MG
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,
7e978e77 394 true, ports);
dc48516e
MG
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
404destroy_definers:
405 mlx5_lag_destroy_definers(ldev);
406 return err;
407}
408
1065e001
MG
409static 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}
8e25a2bc
MG
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
449static 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
470static 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
502static 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
516static 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);
a042d7f5 523 port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params);
8e25a2bc
MG
524 if (IS_ERR(port_sel->inner.ttc))
525 return PTR_ERR(port_sel->inner.ttc);
526
527 return 0;
528}
b7267869
MG
529
530int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
7e978e77 531 enum netdev_lag_hash hash_type, u8 *ports)
b7267869
MG
532{
533 struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
534 int err;
535
536 set_tt_map(port_sel, hash_type);
7e978e77 537 err = mlx5_lag_create_definers(ldev, hash_type, ports);
b7267869
MG
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
553destroy_inner:
554 if (port_sel->tunnel)
555 mlx5_destroy_ttc_table(port_sel->inner.ttc);
556destroy_definers:
557 mlx5_lag_destroy_definers(ldev);
558 return err;
559}
560
352899f3
MB
561static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
562 struct mlx5_lag_definer *def,
563 u8 *ports)
b7267869 564{
b7267869 565 struct mlx5_flow_destination dest = {};
352899f3 566 int idx;
b7267869 567 int err;
7e978e77 568 int i;
352899f3 569 int j;
b7267869
MG
570
571 dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
572 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
573
352899f3
MB
574 for (i = 0; i < ldev->ports; i++) {
575 for (j = 0; j < ldev->buckets; j++) {
576 idx = i * ldev->buckets + j;
7e978e77
MB
577 if (ldev->v2p_map[i] == ports[i])
578 continue;
352899f3
MB
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);
b7267869
MG
583 if (err)
584 return err;
585 }
586 }
587
588 return 0;
589}
590
352899f3
MB
591static int
592mlx5_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
7e978e77 609int mlx5_lag_port_sel_modify(struct mlx5_lag *ldev, u8 *ports)
b7267869
MG
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,
7e978e77 616 ports);
b7267869
MG
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,
7e978e77 625 ports);
b7267869
MG
626}
627
628void 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);
ffdf4531 636 memset(port_sel, 0, sizeof(*port_sel));
b7267869 637}