@@ -71,8 +71,21 @@ mlxsw_sp_port_orig_get(struct net_device *dev,
7171 struct mlxsw_sp_port * mlxsw_sp_port )
7272{
7373 struct mlxsw_sp_port * mlxsw_sp_vport ;
74+ struct mlxsw_sp_fid * fid ;
7475 u16 vid ;
7576
77+ if (netif_is_bridge_master (dev )) {
78+ fid = mlxsw_sp_vfid_find (mlxsw_sp_port -> mlxsw_sp ,
79+ dev );
80+ if (fid ) {
81+ mlxsw_sp_vport =
82+ mlxsw_sp_port_vport_find_by_fid (mlxsw_sp_port ,
83+ fid -> fid );
84+ WARN_ON (!mlxsw_sp_vport );
85+ return mlxsw_sp_vport ;
86+ }
87+ }
88+
7689 if (!is_vlan_dev (dev ))
7790 return mlxsw_sp_port ;
7891
@@ -166,9 +179,10 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
166179 return mlxsw_sp_port_stp_state_set (mlxsw_sp_port , state );
167180}
168181
169- static int __mlxsw_sp_port_flood_set (struct mlxsw_sp_port * mlxsw_sp_port ,
170- u16 idx_begin , u16 idx_end , bool uc_set ,
171- bool bm_set )
182+ static int __mlxsw_sp_port_flood_table_set (struct mlxsw_sp_port * mlxsw_sp_port ,
183+ u16 idx_begin , u16 idx_end ,
184+ enum mlxsw_sp_flood_table table ,
185+ bool set )
172186{
173187 struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
174188 u16 local_port = mlxsw_sp_port -> local_port ;
@@ -186,31 +200,48 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
186200 if (!sftr_pl )
187201 return - ENOMEM ;
188202
189- mlxsw_reg_sftr_pack (sftr_pl , MLXSW_SP_FLOOD_TABLE_UC , idx_begin ,
190- table_type , range , local_port , uc_set );
203+ mlxsw_reg_sftr_pack (sftr_pl , table , idx_begin ,
204+ table_type , range , local_port , set );
191205 err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (sftr ), sftr_pl );
206+
207+ kfree (sftr_pl );
208+ return err ;
209+ }
210+
211+ static int __mlxsw_sp_port_flood_set (struct mlxsw_sp_port * mlxsw_sp_port ,
212+ u16 idx_begin , u16 idx_end , bool uc_set ,
213+ bool bc_set , bool mc_set )
214+ {
215+ int err ;
216+
217+ err = __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , idx_begin , idx_end ,
218+ MLXSW_SP_FLOOD_TABLE_UC , uc_set );
192219 if (err )
193- goto buffer_out ;
220+ return err ;
194221
195- mlxsw_reg_sftr_pack (sftr_pl , MLXSW_SP_FLOOD_TABLE_BM , idx_begin ,
196- table_type , range , local_port , bm_set );
197- err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (sftr ), sftr_pl );
222+ err = __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , idx_begin , idx_end ,
223+ MLXSW_SP_FLOOD_TABLE_BC , bc_set );
198224 if (err )
199225 goto err_flood_bm_set ;
200226
201- goto buffer_out ;
227+ err = __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , idx_begin , idx_end ,
228+ MLXSW_SP_FLOOD_TABLE_MC , mc_set );
229+ if (err )
230+ goto err_flood_mc_set ;
231+ return 0 ;
202232
233+ err_flood_mc_set :
234+ __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , idx_begin , idx_end ,
235+ MLXSW_SP_FLOOD_TABLE_BC , !bc_set );
203236err_flood_bm_set :
204- mlxsw_reg_sftr_pack (sftr_pl , MLXSW_SP_FLOOD_TABLE_UC , idx_begin ,
205- table_type , range , local_port , !uc_set );
206- mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (sftr ), sftr_pl );
207- buffer_out :
208- kfree (sftr_pl );
237+ __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , idx_begin , idx_end ,
238+ MLXSW_SP_FLOOD_TABLE_UC , !uc_set );
209239 return err ;
210240}
211241
212- static int mlxsw_sp_port_uc_flood_set (struct mlxsw_sp_port * mlxsw_sp_port ,
213- bool set )
242+ static int mlxsw_sp_port_flood_table_set (struct mlxsw_sp_port * mlxsw_sp_port ,
243+ enum mlxsw_sp_flood_table table ,
244+ bool set )
214245{
215246 struct net_device * dev = mlxsw_sp_port -> dev ;
216247 u16 vid , last_visited_vid ;
@@ -220,13 +251,13 @@ static int mlxsw_sp_port_uc_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
220251 u16 fid = mlxsw_sp_vport_fid_get (mlxsw_sp_port )-> fid ;
221252 u16 vfid = mlxsw_sp_fid_to_vfid (fid );
222253
223- return __mlxsw_sp_port_flood_set (mlxsw_sp_port , vfid , vfid ,
224- set , true );
254+ return __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , vfid ,
255+ vfid , table , set );
225256 }
226257
227258 for_each_set_bit (vid , mlxsw_sp_port -> active_vlans , VLAN_N_VID ) {
228- err = __mlxsw_sp_port_flood_set (mlxsw_sp_port , vid , vid , set ,
229- true );
259+ err = __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , vid , vid ,
260+ table , set );
230261 if (err ) {
231262 last_visited_vid = vid ;
232263 goto err_port_flood_set ;
@@ -237,21 +268,53 @@ static int mlxsw_sp_port_uc_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
237268
238269err_port_flood_set :
239270 for_each_set_bit (vid , mlxsw_sp_port -> active_vlans , last_visited_vid )
240- __mlxsw_sp_port_flood_set (mlxsw_sp_port , vid , vid , !set , true);
271+ __mlxsw_sp_port_flood_table_set (mlxsw_sp_port , vid , vid , table ,
272+ !set );
241273 netdev_err (dev , "Failed to configure unicast flooding\n" );
242274 return err ;
243275}
244276
277+ static int mlxsw_sp_port_mc_disabled_set (struct mlxsw_sp_port * mlxsw_sp_port ,
278+ struct switchdev_trans * trans ,
279+ bool mc_disabled )
280+ {
281+ int set ;
282+ int err = 0 ;
283+
284+ if (switchdev_trans_ph_prepare (trans ))
285+ return 0 ;
286+
287+ if (mlxsw_sp_port -> mc_router != mlxsw_sp_port -> mc_flood ) {
288+ set = mc_disabled ?
289+ mlxsw_sp_port -> mc_flood : mlxsw_sp_port -> mc_router ;
290+ err = mlxsw_sp_port_flood_table_set (mlxsw_sp_port ,
291+ MLXSW_SP_FLOOD_TABLE_MC ,
292+ set );
293+ }
294+
295+ if (!err )
296+ mlxsw_sp_port -> mc_disabled = mc_disabled ;
297+
298+ return err ;
299+ }
300+
245301int mlxsw_sp_vport_flood_set (struct mlxsw_sp_port * mlxsw_sp_vport , u16 fid ,
246302 bool set )
247303{
304+ bool mc_set = set ;
248305 u16 vfid ;
249306
250307 /* In case of vFIDs, index into the flooding table is relative to
251308 * the start of the vFIDs range.
252309 */
253310 vfid = mlxsw_sp_fid_to_vfid (fid );
254- return __mlxsw_sp_port_flood_set (mlxsw_sp_vport , vfid , vfid , set , set );
311+
312+ if (set )
313+ mc_set = mlxsw_sp_vport -> mc_disabled ?
314+ mlxsw_sp_vport -> mc_flood : mlxsw_sp_vport -> mc_router ;
315+
316+ return __mlxsw_sp_port_flood_set (mlxsw_sp_vport , vfid , vfid , set , set ,
317+ mc_set );
255318}
256319
257320static int mlxsw_sp_port_learning_set (struct mlxsw_sp_port * mlxsw_sp_port ,
@@ -297,8 +360,9 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
297360 return 0 ;
298361
299362 if ((uc_flood ^ brport_flags ) & BR_FLOOD ) {
300- err = mlxsw_sp_port_uc_flood_set (mlxsw_sp_port ,
301- !mlxsw_sp_port -> uc_flood );
363+ err = mlxsw_sp_port_flood_table_set (mlxsw_sp_port ,
364+ MLXSW_SP_FLOOD_TABLE_UC ,
365+ !mlxsw_sp_port -> uc_flood );
302366 if (err )
303367 return err ;
304368 }
@@ -318,8 +382,9 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
318382
319383err_port_learning_set :
320384 if ((uc_flood ^ brport_flags ) & BR_FLOOD )
321- mlxsw_sp_port_uc_flood_set (mlxsw_sp_port ,
322- mlxsw_sp_port -> uc_flood );
385+ mlxsw_sp_port_flood_table_set (mlxsw_sp_port ,
386+ MLXSW_SP_FLOOD_TABLE_UC ,
387+ mlxsw_sp_port -> uc_flood );
323388 return err ;
324389}
325390
@@ -371,6 +436,22 @@ static int mlxsw_sp_port_attr_br_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port,
371436 return 0 ;
372437}
373438
439+ static int mlxsw_sp_port_attr_mc_router_set (struct mlxsw_sp_port * mlxsw_sp_port ,
440+ struct switchdev_trans * trans ,
441+ bool is_port_mc_router )
442+ {
443+ if (switchdev_trans_ph_prepare (trans ))
444+ return 0 ;
445+
446+ mlxsw_sp_port -> mc_router = is_port_mc_router ;
447+ if (!mlxsw_sp_port -> mc_disabled )
448+ return mlxsw_sp_port_flood_table_set (mlxsw_sp_port ,
449+ MLXSW_SP_FLOOD_TABLE_MC ,
450+ is_port_mc_router );
451+
452+ return 0 ;
453+ }
454+
374455static int mlxsw_sp_port_attr_set (struct net_device * dev ,
375456 const struct switchdev_attr * attr ,
376457 struct switchdev_trans * trans )
@@ -400,6 +481,14 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
400481 attr -> orig_dev ,
401482 attr -> u .vlan_filtering );
402483 break ;
484+ case SWITCHDEV_ATTR_ID_PORT_MROUTER :
485+ err = mlxsw_sp_port_attr_mc_router_set (mlxsw_sp_port , trans ,
486+ attr -> u .mrouter );
487+ break ;
488+ case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED :
489+ err = mlxsw_sp_port_mc_disabled_set (mlxsw_sp_port , trans ,
490+ attr -> u .mc_disabled );
491+ break ;
403492 default :
404493 err = - EOPNOTSUPP ;
405494 break ;
@@ -545,6 +634,7 @@ static int mlxsw_sp_port_fid_map(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid,
545634static int mlxsw_sp_port_fid_join (struct mlxsw_sp_port * mlxsw_sp_port ,
546635 u16 fid_begin , u16 fid_end )
547636{
637+ bool mc_flood ;
548638 int fid , err ;
549639
550640 for (fid = fid_begin ; fid <= fid_end ; fid ++ ) {
@@ -553,8 +643,12 @@ static int mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port,
553643 goto err_port_fid_join ;
554644 }
555645
646+ mc_flood = mlxsw_sp_port -> mc_disabled ?
647+ mlxsw_sp_port -> mc_flood : mlxsw_sp_port -> mc_router ;
648+
556649 err = __mlxsw_sp_port_flood_set (mlxsw_sp_port , fid_begin , fid_end ,
557- mlxsw_sp_port -> uc_flood , true);
650+ mlxsw_sp_port -> uc_flood , true,
651+ mc_flood );
558652 if (err )
559653 goto err_port_flood_set ;
560654
@@ -570,7 +664,7 @@ static int mlxsw_sp_port_fid_join(struct mlxsw_sp_port *mlxsw_sp_port,
570664 for (fid -- ; fid >= fid_begin ; fid -- )
571665 mlxsw_sp_port_fid_map (mlxsw_sp_port , fid , false);
572666 __mlxsw_sp_port_flood_set (mlxsw_sp_port , fid_begin , fid_end , false,
573- false);
667+ false, false );
574668err_port_flood_set :
575669 fid = fid_end ;
576670err_port_fid_join :
@@ -588,7 +682,7 @@ static void mlxsw_sp_port_fid_leave(struct mlxsw_sp_port *mlxsw_sp_port,
588682 mlxsw_sp_port_fid_map (mlxsw_sp_port , fid , false);
589683
590684 __mlxsw_sp_port_flood_set (mlxsw_sp_port , fid_begin , fid_end , false,
591- false);
685+ false, false );
592686
593687 for (fid = fid_begin ; fid <= fid_end ; fid ++ )
594688 __mlxsw_sp_port_fid_leave (mlxsw_sp_port , fid );
0 commit comments