@@ -8,6 +8,7 @@ struct lan966x_fdb_event_work {
8
8
struct work_struct work ;
9
9
struct switchdev_notifier_fdb_info fdb_info ;
10
10
struct net_device * dev ;
11
+ struct net_device * orig_dev ;
11
12
struct lan966x * lan966x ;
12
13
unsigned long event ;
13
14
};
@@ -127,75 +128,119 @@ void lan966x_fdb_deinit(struct lan966x *lan966x)
127
128
lan966x_fdb_purge_entries (lan966x );
128
129
}
129
130
130
- static void lan966x_fdb_event_work (struct work_struct * work )
131
+ void lan966x_fdb_flush_workqueue (struct lan966x * lan966x )
132
+ {
133
+ flush_workqueue (lan966x -> fdb_work );
134
+ }
135
+
136
+ static void lan966x_fdb_port_event_work (struct lan966x_fdb_event_work * fdb_work )
131
137
{
132
- struct lan966x_fdb_event_work * fdb_work =
133
- container_of (work , struct lan966x_fdb_event_work , work );
134
138
struct switchdev_notifier_fdb_info * fdb_info ;
135
- struct net_device * dev = fdb_work -> dev ;
136
139
struct lan966x_port * port ;
137
140
struct lan966x * lan966x ;
138
- int ret ;
139
141
140
- fdb_info = & fdb_work -> fdb_info ;
141
142
lan966x = fdb_work -> lan966x ;
143
+ port = netdev_priv (fdb_work -> orig_dev );
144
+ fdb_info = & fdb_work -> fdb_info ;
142
145
143
- if (lan966x_netdevice_check (dev )) {
144
- port = netdev_priv (dev );
146
+ switch (fdb_work -> event ) {
147
+ case SWITCHDEV_FDB_ADD_TO_DEVICE :
148
+ if (!fdb_info -> added_by_user )
149
+ break ;
150
+ lan966x_mac_add_entry (lan966x , port , fdb_info -> addr ,
151
+ fdb_info -> vid );
152
+ break ;
153
+ case SWITCHDEV_FDB_DEL_TO_DEVICE :
154
+ if (!fdb_info -> added_by_user )
155
+ break ;
156
+ lan966x_mac_del_entry (lan966x , fdb_info -> addr ,
157
+ fdb_info -> vid );
158
+ break ;
159
+ }
160
+ }
161
+
162
+ static void lan966x_fdb_bridge_event_work (struct lan966x_fdb_event_work * fdb_work )
163
+ {
164
+ struct switchdev_notifier_fdb_info * fdb_info ;
165
+ struct lan966x * lan966x ;
166
+ int ret ;
145
167
146
- switch (fdb_work -> event ) {
147
- case SWITCHDEV_FDB_ADD_TO_DEVICE :
148
- if (!fdb_info -> added_by_user )
149
- break ;
150
- lan966x_mac_add_entry (lan966x , port , fdb_info -> addr ,
151
- fdb_info -> vid );
168
+ lan966x = fdb_work -> lan966x ;
169
+ fdb_info = & fdb_work -> fdb_info ;
170
+
171
+ /* In case the bridge is called */
172
+ switch (fdb_work -> event ) {
173
+ case SWITCHDEV_FDB_ADD_TO_DEVICE :
174
+ /* If there is no front port in this vlan, there is no
175
+ * point to copy the frame to CPU because it would be
176
+ * just dropped at later point. So add it only if
177
+ * there is a port but it is required to store the fdb
178
+ * entry for later point when a port actually gets in
179
+ * the vlan.
180
+ */
181
+ lan966x_fdb_add_entry (lan966x , fdb_info );
182
+ if (!lan966x_vlan_cpu_member_cpu_vlan_mask (lan966x ,
183
+ fdb_info -> vid ))
152
184
break ;
153
- case SWITCHDEV_FDB_DEL_TO_DEVICE :
154
- if (!fdb_info -> added_by_user )
155
- break ;
156
- lan966x_mac_del_entry (lan966x , fdb_info -> addr ,
157
- fdb_info -> vid );
185
+
186
+ lan966x_mac_cpu_learn (lan966x , fdb_info -> addr ,
187
+ fdb_info -> vid );
188
+ break ;
189
+ case SWITCHDEV_FDB_DEL_TO_DEVICE :
190
+ ret = lan966x_fdb_del_entry (lan966x , fdb_info );
191
+ if (!lan966x_vlan_cpu_member_cpu_vlan_mask (lan966x ,
192
+ fdb_info -> vid ))
158
193
break ;
159
- }
160
- } else {
161
- if (!netif_is_bridge_master (dev ))
162
- goto out ;
163
-
164
- /* In case the bridge is called */
165
- switch (fdb_work -> event ) {
166
- case SWITCHDEV_FDB_ADD_TO_DEVICE :
167
- /* If there is no front port in this vlan, there is no
168
- * point to copy the frame to CPU because it would be
169
- * just dropped at later point. So add it only if
170
- * there is a port but it is required to store the fdb
171
- * entry for later point when a port actually gets in
172
- * the vlan.
173
- */
174
- lan966x_fdb_add_entry (lan966x , fdb_info );
175
- if (!lan966x_vlan_cpu_member_cpu_vlan_mask (lan966x ,
176
- fdb_info -> vid ))
177
- break ;
178
-
179
- lan966x_mac_cpu_learn (lan966x , fdb_info -> addr ,
180
- fdb_info -> vid );
194
+
195
+ if (ret )
196
+ lan966x_mac_cpu_forget (lan966x , fdb_info -> addr ,
197
+ fdb_info -> vid );
198
+ break ;
199
+ }
200
+ }
201
+
202
+ static void lan966x_fdb_lag_event_work (struct lan966x_fdb_event_work * fdb_work )
203
+ {
204
+ struct switchdev_notifier_fdb_info * fdb_info ;
205
+ struct lan966x_port * port ;
206
+ struct lan966x * lan966x ;
207
+
208
+ if (!lan966x_lag_first_port (fdb_work -> orig_dev , fdb_work -> dev ))
209
+ return ;
210
+
211
+ lan966x = fdb_work -> lan966x ;
212
+ port = netdev_priv (fdb_work -> dev );
213
+ fdb_info = & fdb_work -> fdb_info ;
214
+
215
+ switch (fdb_work -> event ) {
216
+ case SWITCHDEV_FDB_ADD_TO_DEVICE :
217
+ if (!fdb_info -> added_by_user )
181
218
break ;
182
- case SWITCHDEV_FDB_DEL_TO_DEVICE :
183
- ret = lan966x_fdb_del_entry (lan966x , fdb_info );
184
- if (!lan966x_vlan_cpu_member_cpu_vlan_mask (lan966x ,
185
- fdb_info -> vid ))
186
- break ;
187
-
188
- if (ret )
189
- lan966x_mac_cpu_forget (lan966x , fdb_info -> addr ,
190
- fdb_info -> vid );
219
+ lan966x_mac_add_entry (lan966x , port , fdb_info -> addr ,
220
+ fdb_info -> vid );
221
+ break ;
222
+ case SWITCHDEV_FDB_DEL_TO_DEVICE :
223
+ if (!fdb_info -> added_by_user )
191
224
break ;
192
- }
225
+ lan966x_mac_del_entry (lan966x , fdb_info -> addr , fdb_info -> vid );
226
+ break ;
193
227
}
228
+ }
229
+
230
+ static void lan966x_fdb_event_work (struct work_struct * work )
231
+ {
232
+ struct lan966x_fdb_event_work * fdb_work =
233
+ container_of (work , struct lan966x_fdb_event_work , work );
234
+
235
+ if (lan966x_netdevice_check (fdb_work -> orig_dev ))
236
+ lan966x_fdb_port_event_work (fdb_work );
237
+ else if (netif_is_bridge_master (fdb_work -> orig_dev ))
238
+ lan966x_fdb_bridge_event_work (fdb_work );
239
+ else if (netif_is_lag_master (fdb_work -> orig_dev ))
240
+ lan966x_fdb_lag_event_work (fdb_work );
194
241
195
- out :
196
242
kfree (fdb_work -> fdb_info .addr );
197
243
kfree (fdb_work );
198
- dev_put (dev );
199
244
}
200
245
201
246
int lan966x_handle_fdb (struct net_device * dev ,
@@ -221,7 +266,8 @@ int lan966x_handle_fdb(struct net_device *dev,
221
266
if (!fdb_work )
222
267
return - ENOMEM ;
223
268
224
- fdb_work -> dev = orig_dev ;
269
+ fdb_work -> dev = dev ;
270
+ fdb_work -> orig_dev = orig_dev ;
225
271
fdb_work -> lan966x = lan966x ;
226
272
fdb_work -> event = event ;
227
273
INIT_WORK (& fdb_work -> work , lan966x_fdb_event_work );
@@ -231,7 +277,6 @@ int lan966x_handle_fdb(struct net_device *dev,
231
277
goto err_addr_alloc ;
232
278
233
279
ether_addr_copy ((u8 * )fdb_work -> fdb_info .addr , fdb_info -> addr );
234
- dev_hold (orig_dev );
235
280
236
281
queue_work (lan966x -> fdb_work , & fdb_work -> work );
237
282
break ;
0 commit comments