@@ -502,6 +502,49 @@ static int mlx5e_add_eth_addr_rule(struct mlx5e_priv *priv,
502
502
return err ;
503
503
}
504
504
505
+ static int mlx5e_vport_context_update_vlans (struct mlx5e_priv * priv )
506
+ {
507
+ struct net_device * ndev = priv -> netdev ;
508
+ int max_list_size ;
509
+ int list_size ;
510
+ u16 * vlans ;
511
+ int vlan ;
512
+ int err ;
513
+ int i ;
514
+
515
+ list_size = 0 ;
516
+ for_each_set_bit (vlan , priv -> vlan .active_vlans , VLAN_N_VID )
517
+ list_size ++ ;
518
+
519
+ max_list_size = 1 << MLX5_CAP_GEN (priv -> mdev , log_max_vlan_list );
520
+
521
+ if (list_size > max_list_size ) {
522
+ netdev_warn (ndev ,
523
+ "netdev vlans list size (%d) > (%d) max vport list size, some vlans will be dropped\n" ,
524
+ list_size , max_list_size );
525
+ list_size = max_list_size ;
526
+ }
527
+
528
+ vlans = kcalloc (list_size , sizeof (* vlans ), GFP_KERNEL );
529
+ if (!vlans )
530
+ return - ENOMEM ;
531
+
532
+ i = 0 ;
533
+ for_each_set_bit (vlan , priv -> vlan .active_vlans , VLAN_N_VID ) {
534
+ if (i >= list_size )
535
+ break ;
536
+ vlans [i ++ ] = vlan ;
537
+ }
538
+
539
+ err = mlx5_modify_nic_vport_vlans (priv -> mdev , vlans , list_size );
540
+ if (err )
541
+ netdev_err (ndev , "Failed to modify vport vlans list err(%d)\n" ,
542
+ err );
543
+
544
+ kfree (vlans );
545
+ return err ;
546
+ }
547
+
505
548
enum mlx5e_vlan_rule_type {
506
549
MLX5E_VLAN_RULE_TYPE_UNTAGGED ,
507
550
MLX5E_VLAN_RULE_TYPE_ANY_VID ,
@@ -552,6 +595,10 @@ static int mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
552
595
1 );
553
596
break ;
554
597
default : /* MLX5E_VLAN_RULE_TYPE_MATCH_VID */
598
+ err = mlx5e_vport_context_update_vlans (priv );
599
+ if (err )
600
+ goto add_vlan_rule_out ;
601
+
555
602
ft_ix = & priv -> vlan .active_vlans_ft_ix [vid ];
556
603
MLX5_SET (fte_match_param , match_value , outer_headers .vlan_tag ,
557
604
1 );
@@ -588,6 +635,7 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
588
635
case MLX5E_VLAN_RULE_TYPE_MATCH_VID :
589
636
mlx5_del_flow_table_entry (priv -> ft .vlan ,
590
637
priv -> vlan .active_vlans_ft_ix [vid ]);
638
+ mlx5e_vport_context_update_vlans (priv );
591
639
break ;
592
640
}
593
641
}
@@ -619,6 +667,8 @@ int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
619
667
{
620
668
struct mlx5e_priv * priv = netdev_priv (dev );
621
669
670
+ set_bit (vid , priv -> vlan .active_vlans );
671
+
622
672
return mlx5e_add_vlan_rule (priv , MLX5E_VLAN_RULE_TYPE_MATCH_VID , vid );
623
673
}
624
674
@@ -627,6 +677,8 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
627
677
{
628
678
struct mlx5e_priv * priv = netdev_priv (dev );
629
679
680
+ clear_bit (vid , priv -> vlan .active_vlans );
681
+
630
682
mlx5e_del_vlan_rule (priv , MLX5E_VLAN_RULE_TYPE_MATCH_VID , vid );
631
683
632
684
return 0 ;
0 commit comments