Skip to content

Commit 764a4af

Browse files
committed
Merge branch 'octeontx2-dmasc-filtering'
Hariprasad Kelam says: ==================== DMAC based packet filtering Each MAC block supports 32 DMAC filters which can be configured to accept or drop packets based on address match This patch series adds mbox handlers and extends ntuple filter callbacks to accomdate DMAC filters such that user can install DMAC based filters on interface from ethtool. Patch1 adds necessary mbox handlers such that mbox consumers like PF netdev can add/delete/update DMAC filters and Patch2 adds debugfs support to dump current list of installed filters. Patch3 adds support to call mbox handlers upon receiving DMAC filters from ethtool ntuple commands. Change-log: v2 - - fixed indentation issues. v3 - - fixed kdoc warnings ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 39d7101 + 79d2be3 commit 764a4af

File tree

14 files changed

+955
-39
lines changed

14 files changed

+955
-39
lines changed

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

Lines changed: 277 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,257 @@ 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);
231264
cgx_write(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
232265

233266
return 0;
234267
}
235268

269+
u64 cgx_read_dmac_ctrl(void *cgxd, int lmac_id)
270+
{
271+
struct mac_ops *mac_ops;
272+
struct cgx *cgx = cgxd;
273+
274+
if (!cgxd || !is_lmac_valid(cgxd, lmac_id))
275+
return 0;
276+
277+
cgx = cgxd;
278+
/* Get mac_ops to know csr offset */
279+
mac_ops = cgx->mac_ops;
280+
281+
return cgx_read(cgxd, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
282+
}
283+
284+
u64 cgx_read_dmac_entry(void *cgxd, int index)
285+
{
286+
struct mac_ops *mac_ops;
287+
struct cgx *cgx;
288+
289+
if (!cgxd)
290+
return 0;
291+
292+
cgx = cgxd;
293+
mac_ops = cgx->mac_ops;
294+
return cgx_read(cgx, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 8)));
295+
}
296+
297+
int cgx_lmac_addr_add(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
298+
{
299+
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
300+
struct lmac *lmac = lmac_pdata(lmac_id, cgx_dev);
301+
struct mac_ops *mac_ops;
302+
int index, idx;
303+
u64 cfg = 0;
304+
int id;
305+
306+
if (!lmac)
307+
return -ENODEV;
308+
309+
mac_ops = cgx_dev->mac_ops;
310+
/* Get available index where entry is to be installed */
311+
idx = rvu_alloc_rsrc(&lmac->mac_to_index_bmap);
312+
if (idx < 0)
313+
return idx;
314+
315+
id = get_sequence_id_of_lmac(cgx_dev, lmac_id);
316+
317+
index = id * lmac->mac_to_index_bmap.max + idx;
318+
319+
cfg = mac2u64 (mac_addr);
320+
cfg |= CGX_DMAC_CAM_ADDR_ENABLE;
321+
cfg |= ((u64)lmac_id << 49);
322+
cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), cfg);
323+
324+
cfg = cgx_read(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
325+
cfg |= (CGX_DMAC_BCAST_MODE | CGX_DMAC_CAM_ACCEPT);
326+
327+
if (is_multicast_ether_addr(mac_addr)) {
328+
cfg &= ~GENMASK_ULL(2, 1);
329+
cfg |= CGX_DMAC_MCAST_MODE_CAM;
330+
lmac->mcast_filters_count++;
331+
} else if (!lmac->mcast_filters_count) {
332+
cfg |= CGX_DMAC_MCAST_MODE;
333+
}
334+
335+
cgx_write(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
336+
337+
return idx;
338+
}
339+
340+
int cgx_lmac_addr_reset(u8 cgx_id, u8 lmac_id)
341+
{
342+
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
343+
struct lmac *lmac = lmac_pdata(lmac_id, cgx_dev);
344+
struct mac_ops *mac_ops;
345+
u8 index = 0, id;
346+
u64 cfg;
347+
348+
if (!lmac)
349+
return -ENODEV;
350+
351+
mac_ops = cgx_dev->mac_ops;
352+
/* Restore index 0 to its default init value as done during
353+
* cgx_lmac_init
354+
*/
355+
set_bit(0, lmac->mac_to_index_bmap.bmap);
356+
357+
id = get_sequence_id_of_lmac(cgx_dev, lmac_id);
358+
359+
index = id * lmac->mac_to_index_bmap.max + index;
360+
cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), 0);
361+
362+
/* Reset CGXX_CMRX_RX_DMAC_CTL0 register to default state */
363+
cfg = cgx_read(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
364+
cfg &= ~CGX_DMAC_CAM_ACCEPT;
365+
cfg |= (CGX_DMAC_BCAST_MODE | CGX_DMAC_MCAST_MODE);
366+
cgx_write(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
367+
368+
return 0;
369+
}
370+
371+
/* Allows caller to change macaddress associated with index
372+
* in dmac filter table including index 0 reserved for
373+
* interface mac address
374+
*/
375+
int cgx_lmac_addr_update(u8 cgx_id, u8 lmac_id, u8 *mac_addr, u8 index)
376+
{
377+
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
378+
struct mac_ops *mac_ops;
379+
struct lmac *lmac;
380+
u64 cfg;
381+
int id;
382+
383+
lmac = lmac_pdata(lmac_id, cgx_dev);
384+
if (!lmac)
385+
return -ENODEV;
386+
387+
mac_ops = cgx_dev->mac_ops;
388+
/* Validate the index */
389+
if (index >= lmac->mac_to_index_bmap.max)
390+
return -EINVAL;
391+
392+
/* ensure index is already set */
393+
if (!test_bit(index, lmac->mac_to_index_bmap.bmap))
394+
return -EINVAL;
395+
396+
id = get_sequence_id_of_lmac(cgx_dev, lmac_id);
397+
398+
index = id * lmac->mac_to_index_bmap.max + index;
399+
400+
cfg = cgx_read(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)));
401+
cfg &= ~CGX_RX_DMAC_ADR_MASK;
402+
cfg |= mac2u64 (mac_addr);
403+
404+
cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), cfg);
405+
return 0;
406+
}
407+
408+
int cgx_lmac_addr_del(u8 cgx_id, u8 lmac_id, u8 index)
409+
{
410+
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
411+
struct lmac *lmac = lmac_pdata(lmac_id, cgx_dev);
412+
struct mac_ops *mac_ops;
413+
u8 mac[ETH_ALEN];
414+
u64 cfg;
415+
int id;
416+
417+
if (!lmac)
418+
return -ENODEV;
419+
420+
mac_ops = cgx_dev->mac_ops;
421+
/* Validate the index */
422+
if (index >= lmac->mac_to_index_bmap.max)
423+
return -EINVAL;
424+
425+
/* Skip deletion for reserved index i.e. index 0 */
426+
if (index == 0)
427+
return 0;
428+
429+
rvu_free_rsrc(&lmac->mac_to_index_bmap, index);
430+
431+
id = get_sequence_id_of_lmac(cgx_dev, lmac_id);
432+
433+
index = id * lmac->mac_to_index_bmap.max + index;
434+
435+
/* Read MAC address to check whether it is ucast or mcast */
436+
cfg = cgx_read(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)));
437+
438+
cfg2mac(cfg, mac);
439+
if (is_multicast_ether_addr(mac))
440+
lmac->mcast_filters_count--;
441+
442+
if (!lmac->mcast_filters_count) {
443+
cfg = cgx_read(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
444+
cfg &= ~GENMASK_ULL(2, 1);
445+
cfg |= CGX_DMAC_MCAST_MODE;
446+
cgx_write(cgx_dev, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
447+
}
448+
449+
cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), 0);
450+
451+
return 0;
452+
}
453+
454+
int cgx_lmac_addr_max_entries_get(u8 cgx_id, u8 lmac_id)
455+
{
456+
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
457+
struct lmac *lmac = lmac_pdata(lmac_id, cgx_dev);
458+
459+
if (lmac)
460+
return lmac->mac_to_index_bmap.max;
461+
462+
return 0;
463+
}
464+
236465
u64 cgx_lmac_addr_get(u8 cgx_id, u8 lmac_id)
237466
{
238467
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
468+
struct lmac *lmac = lmac_pdata(lmac_id, cgx_dev);
239469
struct mac_ops *mac_ops;
470+
int index;
240471
u64 cfg;
472+
int id;
241473

242474
mac_ops = cgx_dev->mac_ops;
243475

244-
cfg = cgx_read(cgx_dev, 0, CGXX_CMRX_RX_DMAC_CAM0 + lmac_id * 0x8);
476+
id = get_sequence_id_of_lmac(cgx_dev, lmac_id);
477+
478+
index = id * lmac->mac_to_index_bmap.max;
479+
480+
cfg = cgx_read(cgx_dev, 0, CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8);
245481
return cfg & CGX_RX_DMAC_ADR_MASK;
246482
}
247483

@@ -297,35 +533,51 @@ int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
297533
void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable)
298534
{
299535
struct cgx *cgx = cgx_get_pdata(cgx_id);
536+
struct lmac *lmac = lmac_pdata(lmac_id, cgx);
537+
u16 max_dmac = lmac->mac_to_index_bmap.max;
300538
struct mac_ops *mac_ops;
539+
int index, i;
301540
u64 cfg = 0;
541+
int id;
302542

303543
if (!cgx)
304544
return;
305545

546+
id = get_sequence_id_of_lmac(cgx, lmac_id);
547+
306548
mac_ops = cgx->mac_ops;
307549
if (enable) {
308550
/* Enable promiscuous mode on LMAC */
309551
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;
552+
cfg &= ~CGX_DMAC_CAM_ACCEPT;
553+
cfg |= (CGX_DMAC_BCAST_MODE | CGX_DMAC_MCAST_MODE);
312554
cgx_write(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0, cfg);
313555

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);
556+
for (i = 0; i < max_dmac; i++) {
557+
index = id * max_dmac + i;
558+
cfg = cgx_read(cgx, 0,
559+
(CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8));
560+
cfg &= ~CGX_DMAC_CAM_ADDR_ENABLE;
561+
cgx_write(cgx, 0,
562+
(CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8), cfg);
563+
}
319564
} else {
320565
/* Disable promiscuous mode */
321566
cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_DMAC_CTL0);
322567
cfg |= CGX_DMAC_CAM_ACCEPT | CGX_DMAC_MCAST_MODE;
323568
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);
569+
for (i = 0; i < max_dmac; i++) {
570+
index = id * max_dmac + i;
571+
cfg = cgx_read(cgx, 0,
572+
(CGXX_CMRX_RX_DMAC_CAM0 + index * 0x8));
573+
if ((cfg & CGX_RX_DMAC_ADR_MASK) != 0) {
574+
cfg |= CGX_DMAC_CAM_ADDR_ENABLE;
575+
cgx_write(cgx, 0,
576+
(CGXX_CMRX_RX_DMAC_CAM0 +
577+
index * 0x8),
578+
cfg);
579+
}
580+
}
329581
}
330582
}
331583

@@ -1234,6 +1486,15 @@ static int cgx_lmac_init(struct cgx *cgx)
12341486
}
12351487

12361488
lmac->cgx = cgx;
1489+
lmac->mac_to_index_bmap.max =
1490+
MAX_DMAC_ENTRIES_PER_CGX / cgx->lmac_count;
1491+
err = rvu_alloc_bitmap(&lmac->mac_to_index_bmap);
1492+
if (err)
1493+
return err;
1494+
1495+
/* Reserve first entry for default MAC address */
1496+
set_bit(0, lmac->mac_to_index_bmap.bmap);
1497+
12371498
init_waitqueue_head(&lmac->wq_cmd_cmplt);
12381499
mutex_init(&lmac->cmd_lock);
12391500
spin_lock_init(&lmac->event_cb_lock);
@@ -1274,6 +1535,7 @@ static int cgx_lmac_exit(struct cgx *cgx)
12741535
continue;
12751536
cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, false);
12761537
cgx_configure_interrupt(cgx, lmac, lmac->lmac_id, true);
1538+
kfree(lmac->mac_to_index_bmap.bmap);
12771539
kfree(lmac->name);
12781540
kfree(lmac);
12791541
}

0 commit comments

Comments
 (0)