@@ -66,7 +66,8 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev,
66
66
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS :
67
67
attr -> u .brport_flags =
68
68
(mlxsw_sp_port -> learning ? BR_LEARNING : 0 ) |
69
- (mlxsw_sp_port -> learning_sync ? BR_LEARNING_SYNC : 0 );
69
+ (mlxsw_sp_port -> learning_sync ? BR_LEARNING_SYNC : 0 ) |
70
+ (mlxsw_sp_port -> uc_flood ? BR_FLOOD : 0 );
70
71
break ;
71
72
default :
72
73
return - EOPNOTSUPP ;
@@ -123,15 +124,89 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
123
124
return mlxsw_sp_port_stp_state_set (mlxsw_sp_port , state );
124
125
}
125
126
127
+ static int __mlxsw_sp_port_flood_set (struct mlxsw_sp_port * mlxsw_sp_port ,
128
+ u16 fid_begin , u16 fid_end , bool set ,
129
+ bool only_uc )
130
+ {
131
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
132
+ u16 range = fid_end - fid_begin + 1 ;
133
+ char * sftr_pl ;
134
+ int err ;
135
+
136
+ sftr_pl = kmalloc (MLXSW_REG_SFTR_LEN , GFP_KERNEL );
137
+ if (!sftr_pl )
138
+ return - ENOMEM ;
139
+
140
+ mlxsw_reg_sftr_pack (sftr_pl , MLXSW_SP_FLOOD_TABLE_UC , fid_begin ,
141
+ MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST , range ,
142
+ mlxsw_sp_port -> local_port , set );
143
+ err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (sftr ), sftr_pl );
144
+ if (err )
145
+ goto buffer_out ;
146
+
147
+ /* Flooding control allows one to decide whether a given port will
148
+ * flood unicast traffic for which there is no FDB entry.
149
+ */
150
+ if (only_uc )
151
+ goto buffer_out ;
152
+
153
+ mlxsw_reg_sftr_pack (sftr_pl , MLXSW_SP_FLOOD_TABLE_BM , fid_begin ,
154
+ MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST , range ,
155
+ mlxsw_sp_port -> local_port , set );
156
+ err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (sftr ), sftr_pl );
157
+
158
+ buffer_out :
159
+ kfree (sftr_pl );
160
+ return err ;
161
+ }
162
+
163
+ static int mlxsw_sp_port_uc_flood_set (struct mlxsw_sp_port * mlxsw_sp_port ,
164
+ bool set )
165
+ {
166
+ struct net_device * dev = mlxsw_sp_port -> dev ;
167
+ u16 vid , last_visited_vid ;
168
+ int err ;
169
+
170
+ for_each_set_bit (vid , mlxsw_sp_port -> active_vlans , VLAN_N_VID ) {
171
+ err = __mlxsw_sp_port_flood_set (mlxsw_sp_port , vid , vid , set ,
172
+ true);
173
+ if (err ) {
174
+ last_visited_vid = vid ;
175
+ goto err_port_flood_set ;
176
+ }
177
+ }
178
+
179
+ return 0 ;
180
+
181
+ err_port_flood_set :
182
+ for_each_set_bit (vid , mlxsw_sp_port -> active_vlans , last_visited_vid )
183
+ __mlxsw_sp_port_flood_set (mlxsw_sp_port , vid , vid , !set , true);
184
+ netdev_err (dev , "Failed to configure unicast flooding\n" );
185
+ return err ;
186
+ }
187
+
126
188
static int mlxsw_sp_port_attr_br_flags_set (struct mlxsw_sp_port * mlxsw_sp_port ,
127
189
struct switchdev_trans * trans ,
128
190
unsigned long brport_flags )
129
191
{
192
+ unsigned long uc_flood = mlxsw_sp_port -> uc_flood ? BR_FLOOD : 0 ;
193
+ bool set ;
194
+ int err ;
195
+
130
196
if (switchdev_trans_ph_prepare (trans ))
131
197
return 0 ;
132
198
199
+ if ((uc_flood ^ brport_flags ) & BR_FLOOD ) {
200
+ set = mlxsw_sp_port -> uc_flood ? false : true;
201
+ err = mlxsw_sp_port_uc_flood_set (mlxsw_sp_port , set );
202
+ if (err )
203
+ return err ;
204
+ }
205
+
206
+ mlxsw_sp_port -> uc_flood = brport_flags & BR_FLOOD ? 1 : 0 ;
133
207
mlxsw_sp_port -> learning = brport_flags & BR_LEARNING ? 1 : 0 ;
134
208
mlxsw_sp_port -> learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0 ;
209
+
135
210
return 0 ;
136
211
}
137
212
@@ -247,42 +322,6 @@ static int mlxsw_sp_port_fid_unmap(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid)
247
322
return mlxsw_sp_port_vid_to_fid_set (mlxsw_sp_port , mt , false, fid , fid );
248
323
}
249
324
250
- static int __mlxsw_sp_port_flood_set (struct mlxsw_sp_port * mlxsw_sp_port ,
251
- u16 fid_begin , u16 fid_end , bool set ,
252
- bool only_uc )
253
- {
254
- struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
255
- u16 range = fid_end - fid_begin + 1 ;
256
- char * sftr_pl ;
257
- int err ;
258
-
259
- sftr_pl = kmalloc (MLXSW_REG_SFTR_LEN , GFP_KERNEL );
260
- if (!sftr_pl )
261
- return - ENOMEM ;
262
-
263
- mlxsw_reg_sftr_pack (sftr_pl , MLXSW_SP_FLOOD_TABLE_UC , fid_begin ,
264
- MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST , range ,
265
- mlxsw_sp_port -> local_port , set );
266
- err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (sftr ), sftr_pl );
267
- if (err )
268
- goto buffer_out ;
269
-
270
- /* Flooding control allows one to decide whether a given port will
271
- * flood unicast traffic for which there is no FDB entry.
272
- */
273
- if (only_uc )
274
- goto buffer_out ;
275
-
276
- mlxsw_reg_sftr_pack (sftr_pl , MLXSW_SP_FLOOD_TABLE_BM , fid_begin ,
277
- MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST , range ,
278
- mlxsw_sp_port -> local_port , set );
279
- err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (sftr ), sftr_pl );
280
-
281
- buffer_out :
282
- kfree (sftr_pl );
283
- return err ;
284
- }
285
-
286
325
static int mlxsw_sp_port_add_vids (struct net_device * dev , u16 vid_begin ,
287
326
u16 vid_end )
288
327
{
0 commit comments