@@ -8,6 +8,7 @@ struct lan966x_fdb_event_work {
88 struct work_struct work ;
99 struct switchdev_notifier_fdb_info fdb_info ;
1010 struct net_device * dev ;
11+ struct net_device * orig_dev ;
1112 struct lan966x * lan966x ;
1213 unsigned long event ;
1314};
@@ -127,75 +128,119 @@ void lan966x_fdb_deinit(struct lan966x *lan966x)
127128 lan966x_fdb_purge_entries (lan966x );
128129}
129130
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 )
131137{
132- struct lan966x_fdb_event_work * fdb_work =
133- container_of (work , struct lan966x_fdb_event_work , work );
134138 struct switchdev_notifier_fdb_info * fdb_info ;
135- struct net_device * dev = fdb_work -> dev ;
136139 struct lan966x_port * port ;
137140 struct lan966x * lan966x ;
138- int ret ;
139141
140- fdb_info = & fdb_work -> fdb_info ;
141142 lan966x = fdb_work -> lan966x ;
143+ port = netdev_priv (fdb_work -> orig_dev );
144+ fdb_info = & fdb_work -> fdb_info ;
142145
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 ;
145167
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 ))
152184 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 ))
158193 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 )
181218 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 )
191224 break ;
192- }
225+ lan966x_mac_del_entry (lan966x , fdb_info -> addr , fdb_info -> vid );
226+ break ;
193227 }
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 );
194241
195- out :
196242 kfree (fdb_work -> fdb_info .addr );
197243 kfree (fdb_work );
198- dev_put (dev );
199244}
200245
201246int lan966x_handle_fdb (struct net_device * dev ,
@@ -221,7 +266,8 @@ int lan966x_handle_fdb(struct net_device *dev,
221266 if (!fdb_work )
222267 return - ENOMEM ;
223268
224- fdb_work -> dev = orig_dev ;
269+ fdb_work -> dev = dev ;
270+ fdb_work -> orig_dev = orig_dev ;
225271 fdb_work -> lan966x = lan966x ;
226272 fdb_work -> event = event ;
227273 INIT_WORK (& fdb_work -> work , lan966x_fdb_event_work );
@@ -231,7 +277,6 @@ int lan966x_handle_fdb(struct net_device *dev,
231277 goto err_addr_alloc ;
232278
233279 ether_addr_copy ((u8 * )fdb_work -> fdb_info .addr , fdb_info -> addr );
234- dev_hold (orig_dev );
235280
236281 queue_work (lan966x -> fdb_work , & fdb_work -> work );
237282 break ;
0 commit comments