@@ -2706,10 +2706,135 @@ static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
2706
2706
return __mlxsw_sp_inetaddr_lag_event (lag_dev , lag_dev , event , 1 );
2707
2707
}
2708
2708
2709
+ static struct mlxsw_sp_fid * mlxsw_sp_bridge_fid_get (struct mlxsw_sp * mlxsw_sp ,
2710
+ struct net_device * l3_dev )
2711
+ {
2712
+ u16 fid ;
2713
+
2714
+ if (is_vlan_dev (l3_dev ))
2715
+ fid = vlan_dev_vlan_id (l3_dev );
2716
+ else if (mlxsw_sp -> master_bridge .dev == l3_dev )
2717
+ fid = 1 ;
2718
+ else
2719
+ return mlxsw_sp_vfid_find (mlxsw_sp , l3_dev );
2720
+
2721
+ return mlxsw_sp_fid_find (mlxsw_sp , fid );
2722
+ }
2723
+
2724
+ static enum mlxsw_reg_ritr_if_type mlxsw_sp_rif_type_get (u16 fid )
2725
+ {
2726
+ if (mlxsw_sp_fid_is_vfid (fid ))
2727
+ return MLXSW_REG_RITR_FID_IF ;
2728
+ else
2729
+ return MLXSW_REG_RITR_VLAN_IF ;
2730
+ }
2731
+
2732
+ static int mlxsw_sp_rif_bridge_op (struct mlxsw_sp * mlxsw_sp ,
2733
+ struct net_device * l3_dev ,
2734
+ u16 fid , u16 rif ,
2735
+ bool create )
2736
+ {
2737
+ enum mlxsw_reg_ritr_if_type rif_type ;
2738
+ char ritr_pl [MLXSW_REG_RITR_LEN ];
2739
+
2740
+ rif_type = mlxsw_sp_rif_type_get (fid );
2741
+ mlxsw_reg_ritr_pack (ritr_pl , create , rif_type , rif , l3_dev -> mtu ,
2742
+ l3_dev -> dev_addr );
2743
+ mlxsw_reg_ritr_fid_set (ritr_pl , rif_type , fid );
2744
+
2745
+ return mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (ritr ), ritr_pl );
2746
+ }
2747
+
2748
+ static int mlxsw_sp_rif_bridge_create (struct mlxsw_sp * mlxsw_sp ,
2749
+ struct net_device * l3_dev ,
2750
+ struct mlxsw_sp_fid * f )
2751
+ {
2752
+ struct mlxsw_sp_rif * r ;
2753
+ u16 rif ;
2754
+ int err ;
2755
+
2756
+ rif = mlxsw_sp_avail_rif_get (mlxsw_sp );
2757
+ if (rif == MLXSW_SP_RIF_MAX )
2758
+ return - ERANGE ;
2759
+
2760
+ err = mlxsw_sp_rif_bridge_op (mlxsw_sp , l3_dev , f -> fid , rif , true);
2761
+ if (err )
2762
+ return err ;
2763
+
2764
+ err = mlxsw_sp_rif_fdb_op (mlxsw_sp , l3_dev -> dev_addr , f -> fid , true);
2765
+ if (err )
2766
+ goto err_rif_fdb_op ;
2767
+
2768
+ r = mlxsw_sp_rif_alloc (rif , l3_dev , f );
2769
+ if (!r ) {
2770
+ err = - ENOMEM ;
2771
+ goto err_rif_alloc ;
2772
+ }
2773
+
2774
+ f -> r = r ;
2775
+ mlxsw_sp -> rifs [rif ] = r ;
2776
+
2777
+ netdev_dbg (l3_dev , "RIF=%d created\n" , rif );
2778
+
2779
+ return 0 ;
2780
+
2781
+ err_rif_alloc :
2782
+ mlxsw_sp_rif_fdb_op (mlxsw_sp , l3_dev -> dev_addr , f -> fid , false);
2783
+ err_rif_fdb_op :
2784
+ mlxsw_sp_rif_bridge_op (mlxsw_sp , l3_dev , f -> fid , rif , false);
2785
+ return err ;
2786
+ }
2787
+
2788
+ void mlxsw_sp_rif_bridge_destroy (struct mlxsw_sp * mlxsw_sp ,
2789
+ struct mlxsw_sp_rif * r )
2790
+ {
2791
+ struct net_device * l3_dev = r -> dev ;
2792
+ struct mlxsw_sp_fid * f = r -> f ;
2793
+ u16 rif = r -> rif ;
2794
+
2795
+ mlxsw_sp -> rifs [rif ] = NULL ;
2796
+ f -> r = NULL ;
2797
+
2798
+ kfree (r );
2799
+
2800
+ mlxsw_sp_rif_fdb_op (mlxsw_sp , l3_dev -> dev_addr , f -> fid , false);
2801
+
2802
+ mlxsw_sp_rif_bridge_op (mlxsw_sp , l3_dev , f -> fid , rif , false);
2803
+
2804
+ netdev_dbg (l3_dev , "RIF=%d destroyed\n" , rif );
2805
+ }
2806
+
2807
+ static int mlxsw_sp_inetaddr_bridge_event (struct net_device * l3_dev ,
2808
+ struct net_device * br_dev ,
2809
+ unsigned long event )
2810
+ {
2811
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_lower_get (l3_dev );
2812
+ struct mlxsw_sp_fid * f ;
2813
+
2814
+ /* FID can either be an actual FID if the L3 device is the
2815
+ * VLAN-aware bridge or a VLAN device on top. Otherwise, the
2816
+ * L3 device is a VLAN-unaware bridge and we get a vFID.
2817
+ */
2818
+ f = mlxsw_sp_bridge_fid_get (mlxsw_sp , l3_dev );
2819
+ if (WARN_ON (!f ))
2820
+ return - EINVAL ;
2821
+
2822
+ switch (event ) {
2823
+ case NETDEV_UP :
2824
+ return mlxsw_sp_rif_bridge_create (mlxsw_sp , l3_dev , f );
2825
+ case NETDEV_DOWN :
2826
+ mlxsw_sp_rif_bridge_destroy (mlxsw_sp , f -> r );
2827
+ break ;
2828
+ }
2829
+
2830
+ return 0 ;
2831
+ }
2832
+
2709
2833
static int mlxsw_sp_inetaddr_vlan_event (struct net_device * vlan_dev ,
2710
2834
unsigned long event )
2711
2835
{
2712
2836
struct net_device * real_dev = vlan_dev_real_dev (vlan_dev );
2837
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_lower_get (vlan_dev );
2713
2838
u16 vid = vlan_dev_vlan_id (vlan_dev );
2714
2839
2715
2840
if (mlxsw_sp_port_dev_check (real_dev ))
@@ -2718,6 +2843,10 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
2718
2843
else if (netif_is_lag_master (real_dev ))
2719
2844
return __mlxsw_sp_inetaddr_lag_event (vlan_dev , real_dev , event ,
2720
2845
vid );
2846
+ else if (netif_is_bridge_master (real_dev ) &&
2847
+ mlxsw_sp -> master_bridge .dev == real_dev )
2848
+ return mlxsw_sp_inetaddr_bridge_event (vlan_dev , real_dev ,
2849
+ event );
2721
2850
2722
2851
return 0 ;
2723
2852
}
@@ -2743,6 +2872,8 @@ static int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
2743
2872
err = mlxsw_sp_inetaddr_port_event (dev , event );
2744
2873
else if (netif_is_lag_master (dev ))
2745
2874
err = mlxsw_sp_inetaddr_lag_event (dev , event );
2875
+ else if (netif_is_bridge_master (dev ))
2876
+ err = mlxsw_sp_inetaddr_bridge_event (dev , dev , event );
2746
2877
else if (is_vlan_dev (dev ))
2747
2878
err = mlxsw_sp_inetaddr_vlan_event (dev , event );
2748
2879
@@ -3416,6 +3547,8 @@ static void mlxsw_sp_master_bridge_vlan_unlink(struct mlxsw_sp *mlxsw_sp,
3416
3547
struct mlxsw_sp_fid * f ;
3417
3548
3418
3549
f = mlxsw_sp_fid_find (mlxsw_sp , fid );
3550
+ if (f && f -> r )
3551
+ mlxsw_sp_rif_bridge_destroy (mlxsw_sp , f -> r );
3419
3552
if (f && -- f -> ref_count == 0 )
3420
3553
mlxsw_sp_fid_destroy (mlxsw_sp , f );
3421
3554
}
@@ -3514,13 +3647,17 @@ static void mlxsw_sp_vfid_destroy(struct mlxsw_sp *mlxsw_sp,
3514
3647
struct mlxsw_sp_fid * f )
3515
3648
{
3516
3649
u16 vfid = mlxsw_sp_fid_to_vfid (f -> fid );
3650
+ u16 fid = f -> fid ;
3517
3651
3518
3652
clear_bit (vfid , mlxsw_sp -> vfids .mapped );
3519
3653
list_del (& f -> list );
3520
3654
3521
- mlxsw_sp_vfid_op (mlxsw_sp , f -> fid , false);
3655
+ if (f -> r )
3656
+ mlxsw_sp_rif_bridge_destroy (mlxsw_sp , f -> r );
3522
3657
3523
3658
kfree (f );
3659
+
3660
+ mlxsw_sp_vfid_op (mlxsw_sp , fid , false);
3524
3661
}
3525
3662
3526
3663
static int mlxsw_sp_vport_fid_map (struct mlxsw_sp_port * mlxsw_sp_vport , u16 fid ,
0 commit comments