@@ -22,6 +22,7 @@ struct lan966x_mac_entry {
2222 u16 vid ;
2323 u16 port_index ;
2424 int row ;
25+ bool lag ;
2526};
2627
2728struct lan966x_mac_raw_entry {
@@ -69,15 +70,14 @@ static void lan966x_mac_select(struct lan966x *lan966x,
6970 lan_wr (mach , lan966x , ANA_MACHDATA );
7071}
7172
72- static int __lan966x_mac_learn (struct lan966x * lan966x , int pgid ,
73- bool cpu_copy ,
74- const unsigned char mac [ETH_ALEN ],
75- unsigned int vid ,
76- enum macaccess_entry_type type )
73+ static int __lan966x_mac_learn_locked (struct lan966x * lan966x , int pgid ,
74+ bool cpu_copy ,
75+ const unsigned char mac [ETH_ALEN ],
76+ unsigned int vid ,
77+ enum macaccess_entry_type type )
7778{
78- int ret ;
79+ lockdep_assert_held ( & lan966x -> mac_lock ) ;
7980
80- spin_lock (& lan966x -> mac_lock );
8181 lan966x_mac_select (lan966x , mac , vid );
8282
8383 /* Issue a write command */
@@ -89,7 +89,19 @@ static int __lan966x_mac_learn(struct lan966x *lan966x, int pgid,
8989 ANA_MACACCESS_MAC_TABLE_CMD_SET (MACACCESS_CMD_LEARN ),
9090 lan966x , ANA_MACACCESS );
9191
92- ret = lan966x_mac_wait_for_completion (lan966x );
92+ return lan966x_mac_wait_for_completion (lan966x );
93+ }
94+
95+ static int __lan966x_mac_learn (struct lan966x * lan966x , int pgid ,
96+ bool cpu_copy ,
97+ const unsigned char mac [ETH_ALEN ],
98+ unsigned int vid ,
99+ enum macaccess_entry_type type )
100+ {
101+ int ret ;
102+
103+ spin_lock (& lan966x -> mac_lock );
104+ ret = __lan966x_mac_learn_locked (lan966x , pgid , cpu_copy , mac , vid , type );
93105 spin_unlock (& lan966x -> mac_lock );
94106
95107 return ret ;
@@ -119,6 +131,16 @@ int lan966x_mac_learn(struct lan966x *lan966x, int port,
119131 return __lan966x_mac_learn (lan966x , port , false, mac , vid , type );
120132}
121133
134+ static int lan966x_mac_learn_locked (struct lan966x * lan966x , int port ,
135+ const unsigned char mac [ETH_ALEN ],
136+ unsigned int vid ,
137+ enum macaccess_entry_type type )
138+ {
139+ WARN_ON (type != ENTRYTYPE_NORMAL && type != ENTRYTYPE_LOCKED );
140+
141+ return __lan966x_mac_learn_locked (lan966x , port , false, mac , vid , type );
142+ }
143+
122144static int lan966x_mac_forget_locked (struct lan966x * lan966x ,
123145 const unsigned char mac [ETH_ALEN ],
124146 unsigned int vid ,
@@ -178,8 +200,9 @@ void lan966x_mac_init(struct lan966x *lan966x)
178200 INIT_LIST_HEAD (& lan966x -> mac_entries );
179201}
180202
181- static struct lan966x_mac_entry * lan966x_mac_alloc_entry (const unsigned char * mac ,
182- u16 vid , u16 port_index )
203+ static struct lan966x_mac_entry * lan966x_mac_alloc_entry (struct lan966x_port * port ,
204+ const unsigned char * mac ,
205+ u16 vid )
183206{
184207 struct lan966x_mac_entry * mac_entry ;
185208
@@ -189,8 +212,9 @@ static struct lan966x_mac_entry *lan966x_mac_alloc_entry(const unsigned char *ma
189212
190213 memcpy (mac_entry -> mac , mac , ETH_ALEN );
191214 mac_entry -> vid = vid ;
192- mac_entry -> port_index = port_index ;
215+ mac_entry -> port_index = port -> chip_port ;
193216 mac_entry -> row = LAN966X_MAC_INVALID_ROW ;
217+ mac_entry -> lag = port -> bond ? true : false;
194218 return mac_entry ;
195219}
196220
@@ -269,7 +293,7 @@ int lan966x_mac_add_entry(struct lan966x *lan966x, struct lan966x_port *port,
269293 goto mac_learn ;
270294 }
271295
272- mac_entry = lan966x_mac_alloc_entry (addr , vid , port -> chip_port );
296+ mac_entry = lan966x_mac_alloc_entry (port , addr , vid );
273297 if (!mac_entry ) {
274298 spin_unlock (& lan966x -> mac_lock );
275299 return - ENOMEM ;
@@ -278,7 +302,8 @@ int lan966x_mac_add_entry(struct lan966x *lan966x, struct lan966x_port *port,
278302 list_add_tail (& mac_entry -> list , & lan966x -> mac_entries );
279303 spin_unlock (& lan966x -> mac_lock );
280304
281- lan966x_fdb_call_notifiers (SWITCHDEV_FDB_OFFLOADED , addr , vid , port -> dev );
305+ lan966x_fdb_call_notifiers (SWITCHDEV_FDB_OFFLOADED , addr , vid ,
306+ port -> bond ?: port -> dev );
282307
283308mac_learn :
284309 lan966x_mac_learn (lan966x , port -> chip_port , addr , vid , ENTRYTYPE_LOCKED );
@@ -309,6 +334,50 @@ int lan966x_mac_del_entry(struct lan966x *lan966x, const unsigned char *addr,
309334 return 0 ;
310335}
311336
337+ void lan966x_mac_lag_replace_port_entry (struct lan966x * lan966x ,
338+ struct lan966x_port * src ,
339+ struct lan966x_port * dst )
340+ {
341+ struct lan966x_mac_entry * mac_entry ;
342+
343+ spin_lock (& lan966x -> mac_lock );
344+ list_for_each_entry (mac_entry , & lan966x -> mac_entries , list ) {
345+ if (mac_entry -> port_index == src -> chip_port &&
346+ mac_entry -> lag ) {
347+ lan966x_mac_forget_locked (lan966x , mac_entry -> mac ,
348+ mac_entry -> vid ,
349+ ENTRYTYPE_LOCKED );
350+
351+ lan966x_mac_learn_locked (lan966x , dst -> chip_port ,
352+ mac_entry -> mac , mac_entry -> vid ,
353+ ENTRYTYPE_LOCKED );
354+ mac_entry -> port_index = dst -> chip_port ;
355+ }
356+ }
357+ spin_unlock (& lan966x -> mac_lock );
358+ }
359+
360+ void lan966x_mac_lag_remove_port_entry (struct lan966x * lan966x ,
361+ struct lan966x_port * src )
362+ {
363+ struct lan966x_mac_entry * mac_entry , * tmp ;
364+
365+ spin_lock (& lan966x -> mac_lock );
366+ list_for_each_entry_safe (mac_entry , tmp , & lan966x -> mac_entries ,
367+ list ) {
368+ if (mac_entry -> port_index == src -> chip_port &&
369+ mac_entry -> lag ) {
370+ lan966x_mac_forget_locked (lan966x , mac_entry -> mac ,
371+ mac_entry -> vid ,
372+ ENTRYTYPE_LOCKED );
373+
374+ list_del (& mac_entry -> list );
375+ kfree (mac_entry );
376+ }
377+ }
378+ spin_unlock (& lan966x -> mac_lock );
379+ }
380+
312381void lan966x_mac_purge_entries (struct lan966x * lan966x )
313382{
314383 struct lan966x_mac_entry * mac_entry , * tmp ;
@@ -354,6 +423,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
354423 struct lan966x_mac_entry * mac_entry , * tmp ;
355424 unsigned char mac [ETH_ALEN ] __aligned (2 );
356425 struct list_head mac_deleted_entries ;
426+ struct lan966x_port * port ;
357427 u32 dest_idx ;
358428 u32 column ;
359429 u16 vid ;
@@ -406,9 +476,10 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
406476 /* Notify the bridge that the entry doesn't exist
407477 * anymore in the HW
408478 */
479+ port = lan966x -> ports [mac_entry -> port_index ];
409480 lan966x_mac_notifiers (SWITCHDEV_FDB_DEL_TO_BRIDGE ,
410481 mac_entry -> mac , mac_entry -> vid ,
411- lan966x -> ports [ mac_entry -> port_index ] -> dev );
482+ port -> bond ?: port -> dev );
412483 list_del (& mac_entry -> list );
413484 kfree (mac_entry );
414485 }
@@ -440,7 +511,8 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
440511 continue ;
441512 }
442513
443- mac_entry = lan966x_mac_alloc_entry (mac , vid , dest_idx );
514+ port = lan966x -> ports [dest_idx ];
515+ mac_entry = lan966x_mac_alloc_entry (port , mac , vid );
444516 if (!mac_entry ) {
445517 spin_unlock (& lan966x -> mac_lock );
446518 return ;
@@ -451,7 +523,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
451523 spin_unlock (& lan966x -> mac_lock );
452524
453525 lan966x_mac_notifiers (SWITCHDEV_FDB_ADD_TO_BRIDGE ,
454- mac , vid , lan966x -> ports [ dest_idx ] -> dev );
526+ mac , vid , port -> bond ?: port -> dev );
455527 }
456528}
457529
0 commit comments