@@ -86,6 +86,22 @@ bool is_lmac_valid(struct cgx *cgx, int lmac_id)
86
86
return test_bit (lmac_id , & cgx -> lmac_bmap );
87
87
}
88
88
89
+ /* Helper function to get sequential index
90
+ * given the enabled LMAC of a CGX
91
+ */
92
+ static int get_sequence_id_of_lmac (struct cgx * cgx , int lmac_id )
93
+ {
94
+ int tmp , id = 0 ;
95
+
96
+ for_each_set_bit (tmp , & cgx -> lmac_bmap , MAX_LMAC_PER_CGX ) {
97
+ if (tmp == lmac_id )
98
+ break ;
99
+ id ++ ;
100
+ }
101
+
102
+ return id ;
103
+ }
104
+
89
105
struct mac_ops * get_mac_ops (void * cgxd )
90
106
{
91
107
if (!cgxd )
@@ -211,37 +227,229 @@ static u64 mac2u64 (u8 *mac_addr)
211
227
return mac ;
212
228
}
213
229
230
+ static void cfg2mac (u64 cfg , u8 * mac_addr )
231
+ {
232
+ int i , index = 0 ;
233
+
234
+ for (i = ETH_ALEN - 1 ; i >= 0 ; i -- , index ++ )
235
+ mac_addr [i ] = (cfg >> (8 * index )) & 0xFF ;
236
+ }
237
+
214
238
int cgx_lmac_addr_set (u8 cgx_id , u8 lmac_id , u8 * mac_addr )
215
239
{
216
240
struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
241
+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
217
242
struct mac_ops * mac_ops ;
243
+ int index , id ;
218
244
u64 cfg ;
219
245
246
+ /* access mac_ops to know csr_offset */
220
247
mac_ops = cgx_dev -> mac_ops ;
248
+
221
249
/* copy 6bytes from macaddr */
222
250
/* memcpy(&cfg, mac_addr, 6); */
223
251
224
252
cfg = mac2u64 (mac_addr );
225
253
226
- cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (lmac_id * 0x8 )),
254
+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
255
+
256
+ index = id * lmac -> mac_to_index_bmap .max ;
257
+
258
+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )),
227
259
cfg | CGX_DMAC_CAM_ADDR_ENABLE | ((u64 )lmac_id << 49 ));
228
260
229
261
cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
230
- cfg |= CGX_DMAC_CTL0_CAM_ENABLE ;
262
+ cfg |= (CGX_DMAC_CTL0_CAM_ENABLE | CGX_DMAC_BCAST_MODE |
263
+ CGX_DMAC_MCAST_MODE );
264
+ cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
265
+
266
+ return 0 ;
267
+ }
268
+
269
+ int cgx_lmac_addr_add (u8 cgx_id , u8 lmac_id , u8 * mac_addr )
270
+ {
271
+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
272
+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
273
+ struct mac_ops * mac_ops ;
274
+ int index , idx ;
275
+ u64 cfg = 0 ;
276
+ int id ;
277
+
278
+ if (!lmac )
279
+ return - ENODEV ;
280
+
281
+ mac_ops = cgx_dev -> mac_ops ;
282
+ /* Get available index where entry is to be installed */
283
+ idx = rvu_alloc_rsrc (& lmac -> mac_to_index_bmap );
284
+ if (idx < 0 )
285
+ return idx ;
286
+
287
+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
288
+
289
+ index = id * lmac -> mac_to_index_bmap .max + idx ;
290
+
291
+ cfg = mac2u64 (mac_addr );
292
+ cfg |= CGX_DMAC_CAM_ADDR_ENABLE ;
293
+ cfg |= ((u64 )lmac_id << 49 );
294
+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), cfg );
295
+
296
+ cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
297
+ cfg |= (CGX_DMAC_BCAST_MODE | CGX_DMAC_CAM_ACCEPT );
298
+
299
+ if (is_multicast_ether_addr (mac_addr )) {
300
+ cfg &= ~GENMASK_ULL (2 , 1 );
301
+ cfg |= CGX_DMAC_MCAST_MODE_CAM ;
302
+ lmac -> mcast_filters_count ++ ;
303
+ } else if (!lmac -> mcast_filters_count ) {
304
+ cfg |= CGX_DMAC_MCAST_MODE ;
305
+ }
306
+
307
+ cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
308
+
309
+ return idx ;
310
+ }
311
+
312
+ int cgx_lmac_addr_reset (u8 cgx_id , u8 lmac_id )
313
+ {
314
+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
315
+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
316
+ struct mac_ops * mac_ops ;
317
+ u8 index = 0 , id ;
318
+ u64 cfg ;
319
+
320
+ if (!lmac )
321
+ return - ENODEV ;
322
+
323
+ mac_ops = cgx_dev -> mac_ops ;
324
+ /* Restore index 0 to its default init value as done during
325
+ * cgx_lmac_init
326
+ */
327
+ set_bit (0 , lmac -> mac_to_index_bmap .bmap );
328
+
329
+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
330
+
331
+ index = id * lmac -> mac_to_index_bmap .max + index ;
332
+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), 0 );
333
+
334
+ /* Reset CGXX_CMRX_RX_DMAC_CTL0 register to default state */
335
+ cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
336
+ cfg &= ~CGX_DMAC_CAM_ACCEPT ;
337
+ cfg |= (CGX_DMAC_BCAST_MODE | CGX_DMAC_MCAST_MODE );
231
338
cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
232
339
233
340
return 0 ;
234
341
}
235
342
343
+ /* Allows caller to change macaddress associated with index
344
+ * in dmac filter table including index 0 reserved for
345
+ * interface mac address
346
+ */
347
+ int cgx_lmac_addr_update (u8 cgx_id , u8 lmac_id , u8 * mac_addr , u8 index )
348
+ {
349
+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
350
+ struct mac_ops * mac_ops ;
351
+ struct lmac * lmac ;
352
+ u64 cfg ;
353
+ int id ;
354
+
355
+ lmac = lmac_pdata (lmac_id , cgx_dev );
356
+ if (!lmac )
357
+ return - ENODEV ;
358
+
359
+ mac_ops = cgx_dev -> mac_ops ;
360
+ /* Validate the index */
361
+ if (index >= lmac -> mac_to_index_bmap .max )
362
+ return - EINVAL ;
363
+
364
+ /* ensure index is already set */
365
+ if (!test_bit (index , lmac -> mac_to_index_bmap .bmap ))
366
+ return - EINVAL ;
367
+
368
+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
369
+
370
+ index = id * lmac -> mac_to_index_bmap .max + index ;
371
+
372
+ cfg = cgx_read (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )));
373
+ cfg &= ~CGX_RX_DMAC_ADR_MASK ;
374
+ cfg |= mac2u64 (mac_addr );
375
+
376
+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), cfg );
377
+ return 0 ;
378
+ }
379
+
380
+ int cgx_lmac_addr_del (u8 cgx_id , u8 lmac_id , u8 index )
381
+ {
382
+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
383
+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
384
+ struct mac_ops * mac_ops ;
385
+ u8 mac [ETH_ALEN ];
386
+ u64 cfg ;
387
+ int id ;
388
+
389
+ if (!lmac )
390
+ return - ENODEV ;
391
+
392
+ mac_ops = cgx_dev -> mac_ops ;
393
+ /* Validate the index */
394
+ if (index >= lmac -> mac_to_index_bmap .max )
395
+ return - EINVAL ;
396
+
397
+ /* Skip deletion for reserved index i.e. index 0 */
398
+ if (index == 0 )
399
+ return 0 ;
400
+
401
+ rvu_free_rsrc (& lmac -> mac_to_index_bmap , index );
402
+
403
+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
404
+
405
+ index = id * lmac -> mac_to_index_bmap .max + index ;
406
+
407
+ /* Read MAC address to check whether it is ucast or mcast */
408
+ cfg = cgx_read (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )));
409
+
410
+ cfg2mac (cfg , mac );
411
+ if (is_multicast_ether_addr (mac ))
412
+ lmac -> mcast_filters_count -- ;
413
+
414
+ if (!lmac -> mcast_filters_count ) {
415
+ cfg = cgx_read (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
416
+ cfg &= ~GENMASK_ULL (2 , 1 );
417
+ cfg |= CGX_DMAC_MCAST_MODE ;
418
+ cgx_write (cgx_dev , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
419
+ }
420
+
421
+ cgx_write (cgx_dev , 0 , (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8 )), 0 );
422
+
423
+ return 0 ;
424
+ }
425
+
426
+ int cgx_lmac_addr_max_entries_get (u8 cgx_id , u8 lmac_id )
427
+ {
428
+ struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
429
+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
430
+
431
+ if (lmac )
432
+ return lmac -> mac_to_index_bmap .max ;
433
+
434
+ return 0 ;
435
+ }
436
+
236
437
u64 cgx_lmac_addr_get (u8 cgx_id , u8 lmac_id )
237
438
{
238
439
struct cgx * cgx_dev = cgx_get_pdata (cgx_id );
440
+ struct lmac * lmac = lmac_pdata (lmac_id , cgx_dev );
239
441
struct mac_ops * mac_ops ;
442
+ int index ;
240
443
u64 cfg ;
444
+ int id ;
241
445
242
446
mac_ops = cgx_dev -> mac_ops ;
243
447
244
- cfg = cgx_read (cgx_dev , 0 , CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 );
448
+ id = get_sequence_id_of_lmac (cgx_dev , lmac_id );
449
+
450
+ index = id * lmac -> mac_to_index_bmap .max ;
451
+
452
+ cfg = cgx_read (cgx_dev , 0 , CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 );
245
453
return cfg & CGX_RX_DMAC_ADR_MASK ;
246
454
}
247
455
@@ -297,35 +505,51 @@ int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
297
505
void cgx_lmac_promisc_config (int cgx_id , int lmac_id , bool enable )
298
506
{
299
507
struct cgx * cgx = cgx_get_pdata (cgx_id );
508
+ struct lmac * lmac = lmac_pdata (lmac_id , cgx );
509
+ u16 max_dmac = lmac -> mac_to_index_bmap .max ;
300
510
struct mac_ops * mac_ops ;
511
+ int index , i ;
301
512
u64 cfg = 0 ;
513
+ int id ;
302
514
303
515
if (!cgx )
304
516
return ;
305
517
518
+ id = get_sequence_id_of_lmac (cgx , lmac_id );
519
+
306
520
mac_ops = cgx -> mac_ops ;
307
521
if (enable ) {
308
522
/* Enable promiscuous mode on LMAC */
309
523
cfg = cgx_read (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
310
- cfg &= ~( CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE ) ;
311
- cfg |= CGX_DMAC_BCAST_MODE ;
524
+ cfg &= ~CGX_DMAC_CAM_ACCEPT ;
525
+ cfg |= ( CGX_DMAC_BCAST_MODE | CGX_DMAC_MCAST_MODE ) ;
312
526
cgx_write (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
313
527
314
- cfg = cgx_read (cgx , 0 ,
315
- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ));
316
- cfg &= ~CGX_DMAC_CAM_ADDR_ENABLE ;
317
- cgx_write (cgx , 0 ,
318
- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ), cfg );
528
+ for (i = 0 ; i < max_dmac ; i ++ ) {
529
+ index = id * max_dmac + i ;
530
+ cfg = cgx_read (cgx , 0 ,
531
+ (CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 ));
532
+ cfg &= ~CGX_DMAC_CAM_ADDR_ENABLE ;
533
+ cgx_write (cgx , 0 ,
534
+ (CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 ), cfg );
535
+ }
319
536
} else {
320
537
/* Disable promiscuous mode */
321
538
cfg = cgx_read (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 );
322
539
cfg |= CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE ;
323
540
cgx_write (cgx , lmac_id , CGXX_CMRX_RX_DMAC_CTL0 , cfg );
324
- cfg = cgx_read (cgx , 0 ,
325
- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ));
326
- cfg |= CGX_DMAC_CAM_ADDR_ENABLE ;
327
- cgx_write (cgx , 0 ,
328
- (CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8 ), cfg );
541
+ for (i = 0 ; i < max_dmac ; i ++ ) {
542
+ index = id * max_dmac + i ;
543
+ cfg = cgx_read (cgx , 0 ,
544
+ (CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8 ));
545
+ if ((cfg & CGX_RX_DMAC_ADR_MASK ) != 0 ) {
546
+ cfg |= CGX_DMAC_CAM_ADDR_ENABLE ;
547
+ cgx_write (cgx , 0 ,
548
+ (CGXX_CMRX_RX_DMAC_CAM0 +
549
+ index * 0x8 ),
550
+ cfg );
551
+ }
552
+ }
329
553
}
330
554
}
331
555
@@ -1234,6 +1458,15 @@ static int cgx_lmac_init(struct cgx *cgx)
1234
1458
}
1235
1459
1236
1460
lmac -> cgx = cgx ;
1461
+ lmac -> mac_to_index_bmap .max =
1462
+ MAX_DMAC_ENTRIES_PER_CGX / cgx -> lmac_count ;
1463
+ err = rvu_alloc_bitmap (& lmac -> mac_to_index_bmap );
1464
+ if (err )
1465
+ return err ;
1466
+
1467
+ /* Reserve first entry for default MAC address */
1468
+ set_bit (0 , lmac -> mac_to_index_bmap .bmap );
1469
+
1237
1470
init_waitqueue_head (& lmac -> wq_cmd_cmplt );
1238
1471
mutex_init (& lmac -> cmd_lock );
1239
1472
spin_lock_init (& lmac -> event_cb_lock );
@@ -1274,6 +1507,7 @@ static int cgx_lmac_exit(struct cgx *cgx)
1274
1507
continue ;
1275
1508
cgx -> mac_ops -> mac_pause_frm_config (cgx , lmac -> lmac_id , false);
1276
1509
cgx_configure_interrupt (cgx , lmac , lmac -> lmac_id , true);
1510
+ kfree (lmac -> mac_to_index_bmap .bmap );
1277
1511
kfree (lmac -> name );
1278
1512
kfree (lmac );
1279
1513
}
0 commit comments