@@ -22,6 +22,7 @@ struct lan966x_mac_entry {
22
22
u16 vid ;
23
23
u16 port_index ;
24
24
int row ;
25
+ bool lag ;
25
26
};
26
27
27
28
struct lan966x_mac_raw_entry {
@@ -69,15 +70,14 @@ static void lan966x_mac_select(struct lan966x *lan966x,
69
70
lan_wr (mach , lan966x , ANA_MACHDATA );
70
71
}
71
72
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 )
77
78
{
78
- int ret ;
79
+ lockdep_assert_held ( & lan966x -> mac_lock ) ;
79
80
80
- spin_lock (& lan966x -> mac_lock );
81
81
lan966x_mac_select (lan966x , mac , vid );
82
82
83
83
/* Issue a write command */
@@ -89,7 +89,19 @@ static int __lan966x_mac_learn(struct lan966x *lan966x, int pgid,
89
89
ANA_MACACCESS_MAC_TABLE_CMD_SET (MACACCESS_CMD_LEARN ),
90
90
lan966x , ANA_MACACCESS );
91
91
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 );
93
105
spin_unlock (& lan966x -> mac_lock );
94
106
95
107
return ret ;
@@ -119,6 +131,16 @@ int lan966x_mac_learn(struct lan966x *lan966x, int port,
119
131
return __lan966x_mac_learn (lan966x , port , false, mac , vid , type );
120
132
}
121
133
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
+
122
144
static int lan966x_mac_forget_locked (struct lan966x * lan966x ,
123
145
const unsigned char mac [ETH_ALEN ],
124
146
unsigned int vid ,
@@ -178,8 +200,9 @@ void lan966x_mac_init(struct lan966x *lan966x)
178
200
INIT_LIST_HEAD (& lan966x -> mac_entries );
179
201
}
180
202
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 )
183
206
{
184
207
struct lan966x_mac_entry * mac_entry ;
185
208
@@ -189,8 +212,9 @@ static struct lan966x_mac_entry *lan966x_mac_alloc_entry(const unsigned char *ma
189
212
190
213
memcpy (mac_entry -> mac , mac , ETH_ALEN );
191
214
mac_entry -> vid = vid ;
192
- mac_entry -> port_index = port_index ;
215
+ mac_entry -> port_index = port -> chip_port ;
193
216
mac_entry -> row = LAN966X_MAC_INVALID_ROW ;
217
+ mac_entry -> lag = port -> bond ? true : false;
194
218
return mac_entry ;
195
219
}
196
220
@@ -269,7 +293,7 @@ int lan966x_mac_add_entry(struct lan966x *lan966x, struct lan966x_port *port,
269
293
goto mac_learn ;
270
294
}
271
295
272
- mac_entry = lan966x_mac_alloc_entry (addr , vid , port -> chip_port );
296
+ mac_entry = lan966x_mac_alloc_entry (port , addr , vid );
273
297
if (!mac_entry ) {
274
298
spin_unlock (& lan966x -> mac_lock );
275
299
return - ENOMEM ;
@@ -278,7 +302,8 @@ int lan966x_mac_add_entry(struct lan966x *lan966x, struct lan966x_port *port,
278
302
list_add_tail (& mac_entry -> list , & lan966x -> mac_entries );
279
303
spin_unlock (& lan966x -> mac_lock );
280
304
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 );
282
307
283
308
mac_learn :
284
309
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,
309
334
return 0 ;
310
335
}
311
336
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
+
312
381
void lan966x_mac_purge_entries (struct lan966x * lan966x )
313
382
{
314
383
struct lan966x_mac_entry * mac_entry , * tmp ;
@@ -354,6 +423,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
354
423
struct lan966x_mac_entry * mac_entry , * tmp ;
355
424
unsigned char mac [ETH_ALEN ] __aligned (2 );
356
425
struct list_head mac_deleted_entries ;
426
+ struct lan966x_port * port ;
357
427
u32 dest_idx ;
358
428
u32 column ;
359
429
u16 vid ;
@@ -406,9 +476,10 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
406
476
/* Notify the bridge that the entry doesn't exist
407
477
* anymore in the HW
408
478
*/
479
+ port = lan966x -> ports [mac_entry -> port_index ];
409
480
lan966x_mac_notifiers (SWITCHDEV_FDB_DEL_TO_BRIDGE ,
410
481
mac_entry -> mac , mac_entry -> vid ,
411
- lan966x -> ports [ mac_entry -> port_index ] -> dev );
482
+ port -> bond ?: port -> dev );
412
483
list_del (& mac_entry -> list );
413
484
kfree (mac_entry );
414
485
}
@@ -440,7 +511,8 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
440
511
continue ;
441
512
}
442
513
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 );
444
516
if (!mac_entry ) {
445
517
spin_unlock (& lan966x -> mac_lock );
446
518
return ;
@@ -451,7 +523,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
451
523
spin_unlock (& lan966x -> mac_lock );
452
524
453
525
lan966x_mac_notifiers (SWITCHDEV_FDB_ADD_TO_BRIDGE ,
454
- mac , vid , lan966x -> ports [ dest_idx ] -> dev );
526
+ mac , vid , port -> bond ?: port -> dev );
455
527
}
456
528
}
457
529
0 commit comments