51
51
#include "en_tc.h"
52
52
#include "eswitch.h"
53
53
#include "vxlan.h"
54
+ #include "fs_core.h"
54
55
55
56
struct mlx5_nic_flow_attr {
56
57
u32 action ;
57
58
u32 flow_tag ;
58
59
u32 mod_hdr_id ;
59
60
u32 hairpin_tirn ;
61
+ struct mlx5_flow_table * hairpin_ft ;
60
62
};
61
63
62
64
enum {
63
65
MLX5E_TC_FLOW_ESWITCH = BIT (0 ),
64
66
MLX5E_TC_FLOW_NIC = BIT (1 ),
65
67
MLX5E_TC_FLOW_OFFLOADED = BIT (2 ),
66
68
MLX5E_TC_FLOW_HAIRPIN = BIT (3 ),
69
+ MLX5E_TC_FLOW_HAIRPIN_RSS = BIT (4 ),
67
70
};
68
71
69
72
struct mlx5e_tc_flow {
@@ -100,8 +103,14 @@ struct mlx5e_hairpin {
100
103
struct mlx5_hairpin * pair ;
101
104
102
105
struct mlx5_core_dev * func_mdev ;
106
+ struct mlx5e_priv * func_priv ;
103
107
u32 tdn ;
104
108
u32 tirn ;
109
+
110
+ int num_channels ;
111
+ struct mlx5e_rqt indir_rqt ;
112
+ u32 indir_tirn [MLX5E_NUM_INDIR_TIRS ];
113
+ struct mlx5e_ttc_table ttc ;
105
114
};
106
115
107
116
struct mlx5e_hairpin_entry {
@@ -290,6 +299,151 @@ static void mlx5e_hairpin_destroy_transport(struct mlx5e_hairpin *hp)
290
299
mlx5_core_dealloc_transport_domain (hp -> func_mdev , hp -> tdn );
291
300
}
292
301
302
+ static void mlx5e_hairpin_fill_rqt_rqns (struct mlx5e_hairpin * hp , void * rqtc )
303
+ {
304
+ u32 indirection_rqt [MLX5E_INDIR_RQT_SIZE ], rqn ;
305
+ struct mlx5e_priv * priv = hp -> func_priv ;
306
+ int i , ix , sz = MLX5E_INDIR_RQT_SIZE ;
307
+
308
+ mlx5e_build_default_indir_rqt (indirection_rqt , sz ,
309
+ hp -> num_channels );
310
+
311
+ for (i = 0 ; i < sz ; i ++ ) {
312
+ ix = i ;
313
+ if (priv -> channels .params .rss_hfunc == ETH_RSS_HASH_XOR )
314
+ ix = mlx5e_bits_invert (i , ilog2 (sz ));
315
+ ix = indirection_rqt [ix ];
316
+ rqn = hp -> pair -> rqn [ix ];
317
+ MLX5_SET (rqtc , rqtc , rq_num [i ], rqn );
318
+ }
319
+ }
320
+
321
+ static int mlx5e_hairpin_create_indirect_rqt (struct mlx5e_hairpin * hp )
322
+ {
323
+ int inlen , err , sz = MLX5E_INDIR_RQT_SIZE ;
324
+ struct mlx5e_priv * priv = hp -> func_priv ;
325
+ struct mlx5_core_dev * mdev = priv -> mdev ;
326
+ void * rqtc ;
327
+ u32 * in ;
328
+
329
+ inlen = MLX5_ST_SZ_BYTES (create_rqt_in ) + sizeof (u32 ) * sz ;
330
+ in = kvzalloc (inlen , GFP_KERNEL );
331
+ if (!in )
332
+ return - ENOMEM ;
333
+
334
+ rqtc = MLX5_ADDR_OF (create_rqt_in , in , rqt_context );
335
+
336
+ MLX5_SET (rqtc , rqtc , rqt_actual_size , sz );
337
+ MLX5_SET (rqtc , rqtc , rqt_max_size , sz );
338
+
339
+ mlx5e_hairpin_fill_rqt_rqns (hp , rqtc );
340
+
341
+ err = mlx5_core_create_rqt (mdev , in , inlen , & hp -> indir_rqt .rqtn );
342
+ if (!err )
343
+ hp -> indir_rqt .enabled = true;
344
+
345
+ kvfree (in );
346
+ return err ;
347
+ }
348
+
349
+ static int mlx5e_hairpin_create_indirect_tirs (struct mlx5e_hairpin * hp )
350
+ {
351
+ struct mlx5e_priv * priv = hp -> func_priv ;
352
+ u32 in [MLX5_ST_SZ_DW (create_tir_in )];
353
+ int tt , i , err ;
354
+ void * tirc ;
355
+
356
+ for (tt = 0 ; tt < MLX5E_NUM_INDIR_TIRS ; tt ++ ) {
357
+ memset (in , 0 , MLX5_ST_SZ_BYTES (create_tir_in ));
358
+ tirc = MLX5_ADDR_OF (create_tir_in , in , ctx );
359
+
360
+ MLX5_SET (tirc , tirc , transport_domain , hp -> tdn );
361
+ MLX5_SET (tirc , tirc , disp_type , MLX5_TIRC_DISP_TYPE_INDIRECT );
362
+ MLX5_SET (tirc , tirc , indirect_table , hp -> indir_rqt .rqtn );
363
+ mlx5e_build_indir_tir_ctx_hash (& priv -> channels .params , tt , tirc , false);
364
+
365
+ err = mlx5_core_create_tir (hp -> func_mdev , in ,
366
+ MLX5_ST_SZ_BYTES (create_tir_in ), & hp -> indir_tirn [tt ]);
367
+ if (err ) {
368
+ mlx5_core_warn (hp -> func_mdev , "create indirect tirs failed, %d\n" , err );
369
+ goto err_destroy_tirs ;
370
+ }
371
+ }
372
+ return 0 ;
373
+
374
+ err_destroy_tirs :
375
+ for (i = 0 ; i < tt ; i ++ )
376
+ mlx5_core_destroy_tir (hp -> func_mdev , hp -> indir_tirn [i ]);
377
+ return err ;
378
+ }
379
+
380
+ static void mlx5e_hairpin_destroy_indirect_tirs (struct mlx5e_hairpin * hp )
381
+ {
382
+ int tt ;
383
+
384
+ for (tt = 0 ; tt < MLX5E_NUM_INDIR_TIRS ; tt ++ )
385
+ mlx5_core_destroy_tir (hp -> func_mdev , hp -> indir_tirn [tt ]);
386
+ }
387
+
388
+ static void mlx5e_hairpin_set_ttc_params (struct mlx5e_hairpin * hp ,
389
+ struct ttc_params * ttc_params )
390
+ {
391
+ struct mlx5_flow_table_attr * ft_attr = & ttc_params -> ft_attr ;
392
+ int tt ;
393
+
394
+ memset (ttc_params , 0 , sizeof (* ttc_params ));
395
+
396
+ ttc_params -> any_tt_tirn = hp -> tirn ;
397
+
398
+ for (tt = 0 ; tt < MLX5E_NUM_INDIR_TIRS ; tt ++ )
399
+ ttc_params -> indir_tirn [tt ] = hp -> indir_tirn [tt ];
400
+
401
+ ft_attr -> max_fte = MLX5E_NUM_TT ;
402
+ ft_attr -> level = MLX5E_TC_TTC_FT_LEVEL ;
403
+ ft_attr -> prio = MLX5E_TC_PRIO ;
404
+ }
405
+
406
+ static int mlx5e_hairpin_rss_init (struct mlx5e_hairpin * hp )
407
+ {
408
+ struct mlx5e_priv * priv = hp -> func_priv ;
409
+ struct ttc_params ttc_params ;
410
+ int err ;
411
+
412
+ err = mlx5e_hairpin_create_indirect_rqt (hp );
413
+ if (err )
414
+ return err ;
415
+
416
+ err = mlx5e_hairpin_create_indirect_tirs (hp );
417
+ if (err )
418
+ goto err_create_indirect_tirs ;
419
+
420
+ mlx5e_hairpin_set_ttc_params (hp , & ttc_params );
421
+ err = mlx5e_create_ttc_table (priv , & ttc_params , & hp -> ttc );
422
+ if (err )
423
+ goto err_create_ttc_table ;
424
+
425
+ netdev_dbg (priv -> netdev , "add hairpin: using %d channels rss ttc table id %x\n" ,
426
+ hp -> num_channels , hp -> ttc .ft .t -> id );
427
+
428
+ return 0 ;
429
+
430
+ err_create_ttc_table :
431
+ mlx5e_hairpin_destroy_indirect_tirs (hp );
432
+ err_create_indirect_tirs :
433
+ mlx5e_destroy_rqt (priv , & hp -> indir_rqt );
434
+
435
+ return err ;
436
+ }
437
+
438
+ static void mlx5e_hairpin_rss_cleanup (struct mlx5e_hairpin * hp )
439
+ {
440
+ struct mlx5e_priv * priv = hp -> func_priv ;
441
+
442
+ mlx5e_destroy_ttc_table (priv , & hp -> ttc );
443
+ mlx5e_hairpin_destroy_indirect_tirs (hp );
444
+ mlx5e_destroy_rqt (priv , & hp -> indir_rqt );
445
+ }
446
+
293
447
static struct mlx5e_hairpin *
294
448
mlx5e_hairpin_create (struct mlx5e_priv * priv , struct mlx5_hairpin_params * params ,
295
449
int peer_ifindex )
@@ -313,13 +467,23 @@ mlx5e_hairpin_create(struct mlx5e_priv *priv, struct mlx5_hairpin_params *params
313
467
}
314
468
hp -> pair = pair ;
315
469
hp -> func_mdev = func_mdev ;
470
+ hp -> func_priv = priv ;
471
+ hp -> num_channels = params -> num_channels ;
316
472
317
473
err = mlx5e_hairpin_create_transport (hp );
318
474
if (err )
319
475
goto create_transport_err ;
320
476
477
+ if (hp -> num_channels > 1 ) {
478
+ err = mlx5e_hairpin_rss_init (hp );
479
+ if (err )
480
+ goto rss_init_err ;
481
+ }
482
+
321
483
return hp ;
322
484
485
+ rss_init_err :
486
+ mlx5e_hairpin_destroy_transport (hp );
323
487
create_transport_err :
324
488
mlx5_core_hairpin_destroy (hp -> pair );
325
489
create_pair_err :
@@ -329,6 +493,8 @@ mlx5e_hairpin_create(struct mlx5e_priv *priv, struct mlx5_hairpin_params *params
329
493
330
494
static void mlx5e_hairpin_destroy (struct mlx5e_hairpin * hp )
331
495
{
496
+ if (hp -> num_channels > 1 )
497
+ mlx5e_hairpin_rss_cleanup (hp );
332
498
mlx5e_hairpin_destroy_transport (hp );
333
499
mlx5_core_hairpin_destroy (hp -> pair );
334
500
kvfree (hp );
@@ -400,6 +566,8 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
400
566
struct mlx5_core_dev * peer_mdev ;
401
567
struct mlx5e_hairpin_entry * hpe ;
402
568
struct mlx5e_hairpin * hp ;
569
+ u64 link_speed64 ;
570
+ u32 link_speed ;
403
571
u8 match_prio ;
404
572
u16 peer_id ;
405
573
int err ;
@@ -433,6 +601,13 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
433
601
MLX5_CAP_GEN (priv -> mdev , log_min_hairpin_wq_data_sz ));
434
602
params .q_counter = priv -> q_counter ;
435
603
604
+ /* set hairpin pair per each 50Gbs share of the link */
605
+ mlx5e_get_max_linkspeed (priv -> mdev , & link_speed );
606
+ link_speed = max_t (u32 , link_speed , 50000 );
607
+ link_speed64 = link_speed ;
608
+ do_div (link_speed64 , 50000 );
609
+ params .num_channels = link_speed64 ;
610
+
436
611
hp = mlx5e_hairpin_create (priv , & params , peer_ifindex );
437
612
if (IS_ERR (hp )) {
438
613
err = PTR_ERR (hp );
@@ -448,8 +623,14 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
448
623
hash_hairpin_info (peer_id , match_prio ));
449
624
450
625
attach_flow :
451
- flow -> nic_attr -> hairpin_tirn = hpe -> hp -> tirn ;
626
+ if (hpe -> hp -> num_channels > 1 ) {
627
+ flow -> flags |= MLX5E_TC_FLOW_HAIRPIN_RSS ;
628
+ flow -> nic_attr -> hairpin_ft = hpe -> hp -> ttc .ft .t ;
629
+ } else {
630
+ flow -> nic_attr -> hairpin_tirn = hpe -> hp -> tirn ;
631
+ }
452
632
list_add (& flow -> hairpin , & hpe -> flows );
633
+
453
634
return 0 ;
454
635
455
636
create_hairpin_err :
@@ -497,20 +678,24 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
497
678
bool table_created = false;
498
679
int err , dest_ix = 0 ;
499
680
500
- if (attr -> action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST ) {
501
- if (flow -> flags & MLX5E_TC_FLOW_HAIRPIN ) {
502
- err = mlx5e_hairpin_flow_add (priv , flow , parse_attr );
503
- if (err ) {
504
- rule = ERR_PTR (err );
505
- goto err_add_hairpin_flow ;
506
- }
681
+ if (flow -> flags & MLX5E_TC_FLOW_HAIRPIN ) {
682
+ err = mlx5e_hairpin_flow_add (priv , flow , parse_attr );
683
+ if (err ) {
684
+ rule = ERR_PTR (err );
685
+ goto err_add_hairpin_flow ;
686
+ }
687
+ if (flow -> flags & MLX5E_TC_FLOW_HAIRPIN_RSS ) {
688
+ dest [dest_ix ].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE ;
689
+ dest [dest_ix ].ft = attr -> hairpin_ft ;
690
+ } else {
507
691
dest [dest_ix ].type = MLX5_FLOW_DESTINATION_TYPE_TIR ;
508
692
dest [dest_ix ].tir_num = attr -> hairpin_tirn ;
509
- } else {
510
- dest [dest_ix ].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE ;
511
- dest [dest_ix ].ft = priv -> fs .vlan .ft .t ;
512
693
}
513
694
dest_ix ++ ;
695
+ } else if (attr -> action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST ) {
696
+ dest [dest_ix ].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE ;
697
+ dest [dest_ix ].ft = priv -> fs .vlan .ft .t ;
698
+ dest_ix ++ ;
514
699
}
515
700
516
701
if (attr -> action & MLX5_FLOW_CONTEXT_ACTION_COUNT ) {
@@ -551,7 +736,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
551
736
MLX5E_TC_PRIO ,
552
737
tc_tbl_size ,
553
738
MLX5E_TC_TABLE_NUM_GROUPS ,
554
- 0 , 0 );
739
+ MLX5E_TC_FT_LEVEL , 0 );
555
740
if (IS_ERR (priv -> fs .tc .t )) {
556
741
netdev_err (priv -> netdev ,
557
742
"Failed to create tc offload table\n" );
0 commit comments