Skip to content

Commit 6f14078

Browse files
SunilKumarKoridavem330
authored andcommitted
octeontx2-af: DMAC filter support in MAC block
MAC block supports 32 dmac filters which are logically divided among all attached LMACS. For example MAC block0 having one LMAC then maximum supported filters are 32 where as MAC block1 having 4 enabled LMACS them maximum supported filteres are 8 for each LMAC. This patch adds mbox handlers to add/delete/update mac entry in DMAC filter table. Signed-off-by: Sunil Kumar Kori <[email protected]> Signed-off-by: Hariprasad Kelam <[email protected]> Signed-off-by: Sunil Kovvuri Goutham <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 39d7101 commit 6f14078

File tree

7 files changed

+425
-20
lines changed

7 files changed

+425
-20
lines changed

drivers/net/ethernet/marvell/octeontx2/af/cgx.c

Lines changed: 249 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ bool is_lmac_valid(struct cgx *cgx, int lmac_id)
8686
return test_bit(lmac_id, &cgx->lmac_bmap);
8787
}
8888

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+
89105
struct mac_ops *get_mac_ops(void *cgxd)
90106
{
91107
if (!cgxd)
@@ -211,37 +227,229 @@ static u64 mac2u64 (u8 *mac_addr)
211227
return mac;
212228
}
213229

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+
214238
int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
215239
{
216240
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
241+
struct lmac *lmac = lmac_pdata(lmac_id, cgx_dev);
217242
struct mac_ops *mac_ops;
243+
int index, id;
218244
u64 cfg;
219245

246+
/* access mac_ops to know csr_offset */
220247
mac_ops = cgx_dev->mac_ops;
248+
221249
/* copy 6bytes from macaddr */
222250
/* memcpy(&cfg, mac_addr, 6); */
223251

224252
cfg = mac2u64 (mac_addr);
225253

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)),
227259
cfg | CGX_DMAC_CAM_ADDR_ENABLE | ((u64)lmac_id << 49));
228260

229261
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);
231338
cgx_write(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
232339

233340
return 0;
234341
}
235342

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+
236437
u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id)
237438
{
238439
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
440+
struct lmac *lmac = lmac_pdata(lmac_id, cgx_dev);
239441
struct mac_ops *mac_ops;
442+
int index;
240443
u64 cfg;
444+
int id;
241445

242446
mac_ops = cgx_dev->mac_ops;
243447

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);
245453
return cfg & CGX_RX_DMAC_ADR_MASK;
246454
}
247455

@@ -297,35 +505,51 @@ int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
297505
void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable)
298506
{
299507
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;
300510
struct mac_ops *mac_ops;
511+
int index, i;
301512
u64 cfg = 0;
513+
int id;
302514

303515
if (!cgx)
304516
return;
305517

518+
id = get_sequence_id_of_lmac(cgx, lmac_id);
519+
306520
mac_ops = cgx->mac_ops;
307521
if (enable) {
308522
/* Enable promiscuous mode on LMAC */
309523
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);
312526
cgx_write(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
313527

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+
}
319536
} else {
320537
/* Disable promiscuous mode */
321538
cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
322539
cfg |= CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE;
323540
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+
}
329553
}
330554
}
331555

@@ -1234,6 +1458,15 @@ static int cgx_lmac_init(struct cgx *cgx)
12341458
}
12351459

12361460
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+
12371470
init_waitqueue_head(&lmac->wq_cmd_cmplt);
12381471
mutex_init(&lmac->cmd_lock);
12391472
spin_lock_init(&lmac->event_cb_lock);
@@ -1274,6 +1507,7 @@ static int cgx_lmac_exit(struct cgx *cgx)
12741507
continue;
12751508
cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, false);
12761509
cgx_configure_interrupt(cgx, lmac, lmac->lmac_id, true);
1510+
kfree(lmac->mac_to_index_bmap.bmap);
12771511
kfree(lmac->name);
12781512
kfree(lmac);
12791513
}

drivers/net/ethernet/marvell/octeontx2/af/cgx.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#define CGX_ID_MASK 0x7
2525
#define MAX_LMAC_PER_CGX 4
26+
#define MAX_DMAC_ENTRIES_PER_CGX 32
2627
#define CGX_FIFO_LEN 65536 /* 64K for both Rx & Tx */
2728
#define CGX_OFFSET(x) ((x) * MAX_LMAC_PER_CGX)
2829

@@ -46,6 +47,7 @@
4647
#define CGXX_CMRX_RX_DMAC_CTL0 (0x1F8 + mac_ops->csr_offset)
4748
#define CGX_DMAC_CTL0_CAM_ENABLE BIT_ULL(3)
4849
#define CGX_DMAC_CAM_ACCEPT BIT_ULL(3)
50+
#define CGX_DMAC_MCAST_MODE_CAM BIT_ULL(2)
4951
#define CGX_DMAC_MCAST_MODE BIT_ULL(1)
5052
#define CGX_DMAC_BCAST_MODE BIT_ULL(0)
5153
#define CGXX_CMRX_RX_DMAC_CAM0 (0x200 + mac_ops->csr_offset)
@@ -139,7 +141,11 @@ int cgx_get_rx_stats(void *cgxd, int lmac_id, int idx, u64 *rx_stat);
139141
int cgx_lmac_rx_tx_enable(void *cgxd, int lmac_id, bool enable);
140142
int cgx_lmac_tx_enable(void *cgxd, int lmac_id, bool enable);
141143
int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr);
144+
int cgx_lmac_addr_reset(u8 cgx_id, u8 lmac_id);
142145
u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id);
146+
int cgx_lmac_addr_add(u8 cgx_id, u8 lmac_id, u8 *mac_addr);
147+
int cgx_lmac_addr_del(u8 cgx_id, u8 lmac_id, u8 index);
148+
int cgx_lmac_addr_max_entries_get(u8 cgx_id, u8 lmac_id);
143149
void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable);
144150
void cgx_lmac_enadis_rx_pause_fwding(void *cgxd, int lmac_id, bool enable);
145151
int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable);
@@ -165,4 +171,5 @@ u8 cgx_get_lmacid(void *cgxd, u8 lmac_index);
165171
unsigned long cgx_get_lmac_bmap(void *cgxd);
166172
void cgx_lmac_write(int cgx_id, int lmac_id, u64 offset, u64 val);
167173
u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset);
174+
int cgx_lmac_addr_update(u8 cgx_id, u8 lmac_id, u8 *mac_addr, u8 index);
168175
#endif /* CGX_H */

0 commit comments

Comments
 (0)