Skip to content

Commit ceb9ea2

Browse files
Vadim Lomovtsevdavem330
authored andcommitted
net: thunderx: add multicast filter management support
The ThunderX NIC could be partitioned to up to 128 VFs and thus represented to system. Each VF is mapped to pair BGX:LMAC, and each of VF is configured by kernel individually. Eventually the bunch of VFs could be mapped onto same pair BGX:LMAC and thus could cause several multicast filtering configuration requests to LMAC with the same MAC addresses. This commit is to add ThunderX NIC BGX filtering manipulation routines. Signed-off-by: Vadim Lomovtsev <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3a34ecf commit ceb9ea2

File tree

2 files changed

+153
-1
lines changed

2 files changed

+153
-1
lines changed

drivers/net/ethernet/cavium/thunder/thunder_bgx.c

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,150 @@ static void bgx_flush_dmac_cam_filter(struct bgx *bgx, int lmacid)
258258
sizeof(u64), 0);
259259
}
260260

261+
static void bgx_lmac_remove_filters(struct lmac *lmac, u8 vf_id)
262+
{
263+
int i = 0;
264+
265+
if (!lmac)
266+
return;
267+
268+
/* We've got reset filters request from some of attached VF, while the
269+
* others might want to keep their configuration. So in this case lets
270+
* iterate over all of configured filters and decrease number of
271+
* referencies. if some addresses get zero refs remove them from list
272+
*/
273+
for (i = lmac->dmacs_cfg - 1; i >= 0; i--) {
274+
lmac->dmacs[i].vf_map &= ~BIT_ULL(vf_id);
275+
if (!lmac->dmacs[i].vf_map) {
276+
lmac->dmacs_cfg--;
277+
lmac->dmacs[i].dmac = 0;
278+
lmac->dmacs[i].vf_map = 0;
279+
}
280+
}
281+
}
282+
283+
static int bgx_lmac_save_filter(struct lmac *lmac, u64 dmac, u8 vf_id)
284+
{
285+
u8 i = 0;
286+
287+
if (!lmac)
288+
return -1;
289+
290+
/* At the same time we could have several VFs 'attached' to some
291+
* particular LMAC, and each VF is represented as network interface
292+
* for kernel. So from user perspective it should be possible to
293+
* manipulate with its' (VF) receive modes. However from PF
294+
* driver perspective we need to keep track of filter configurations
295+
* for different VFs to prevent filter values dupes
296+
*/
297+
for (i = 0; i < lmac->dmacs_cfg; i++) {
298+
if (lmac->dmacs[i].dmac == dmac) {
299+
lmac->dmacs[i].vf_map |= BIT_ULL(vf_id);
300+
return -1;
301+
}
302+
}
303+
304+
if (!(lmac->dmacs_cfg < lmac->dmacs_count))
305+
return -1;
306+
307+
/* keep it for further tracking */
308+
lmac->dmacs[lmac->dmacs_cfg].dmac = dmac;
309+
lmac->dmacs[lmac->dmacs_cfg].vf_map = BIT_ULL(vf_id);
310+
lmac->dmacs_cfg++;
311+
return 0;
312+
}
313+
314+
static int bgx_set_dmac_cam_filter_mac(struct bgx *bgx, int lmacid,
315+
u64 cam_dmac, u8 idx)
316+
{
317+
struct lmac *lmac = NULL;
318+
u64 cfg = 0;
319+
320+
/* skip zero addresses as meaningless */
321+
if (!cam_dmac || !bgx)
322+
return -1;
323+
324+
lmac = &bgx->lmac[lmacid];
325+
326+
/* configure DCAM filtering for designated LMAC */
327+
cfg = RX_DMACX_CAM_LMACID(lmacid & LMAC_ID_MASK) |
328+
RX_DMACX_CAM_EN | cam_dmac;
329+
bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM +
330+
((lmacid * lmac->dmacs_count) + idx) * sizeof(u64), cfg);
331+
return 0;
332+
}
333+
334+
void bgx_set_dmac_cam_filter(int node, int bgx_idx, int lmacid,
335+
u64 cam_dmac, u8 vf_id)
336+
{
337+
struct bgx *bgx = get_bgx(node, bgx_idx);
338+
struct lmac *lmac = NULL;
339+
340+
if (!bgx)
341+
return;
342+
343+
lmac = &bgx->lmac[lmacid];
344+
345+
if (!cam_dmac)
346+
cam_dmac = ether_addr_to_u64(lmac->mac);
347+
348+
/* since we might have several VFs attached to particular LMAC
349+
* and kernel could call mcast config for each of them with the
350+
* same MAC, check if requested MAC is already in filtering list and
351+
* updare/prepare list of MACs to be applied later to HW filters
352+
*/
353+
bgx_lmac_save_filter(lmac, cam_dmac, vf_id);
354+
}
355+
EXPORT_SYMBOL(bgx_set_dmac_cam_filter);
356+
357+
void bgx_set_xcast_mode(int node, int bgx_idx, int lmacid, u8 mode)
358+
{
359+
struct bgx *bgx = get_bgx(node, bgx_idx);
360+
struct lmac *lmac = NULL;
361+
u64 cfg = 0;
362+
u8 i = 0;
363+
364+
if (!bgx)
365+
return;
366+
367+
lmac = &bgx->lmac[lmacid];
368+
369+
cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_RX_DMAC_CTL);
370+
if (mode & BGX_XCAST_BCAST_ACCEPT)
371+
cfg |= BCAST_ACCEPT;
372+
else
373+
cfg &= ~BCAST_ACCEPT;
374+
375+
/* disable all MCASTs and DMAC filtering */
376+
cfg &= ~(CAM_ACCEPT | BGX_MCAST_MODE(MCAST_MODE_MASK));
377+
378+
/* check requested bits and set filtergin mode appropriately */
379+
if (mode & (BGX_XCAST_MCAST_ACCEPT)) {
380+
cfg |= (BGX_MCAST_MODE(MCAST_MODE_ACCEPT));
381+
} else if (mode & BGX_XCAST_MCAST_FILTER) {
382+
cfg |= (BGX_MCAST_MODE(MCAST_MODE_CAM_FILTER) | CAM_ACCEPT);
383+
for (i = 0; i < lmac->dmacs_cfg; i++)
384+
bgx_set_dmac_cam_filter_mac(bgx, lmacid,
385+
lmac->dmacs[i].dmac, i);
386+
}
387+
bgx_reg_write(bgx, lmacid, BGX_CMRX_RX_DMAC_CTL, cfg);
388+
}
389+
EXPORT_SYMBOL(bgx_set_xcast_mode);
390+
391+
void bgx_reset_xcast_mode(int node, int bgx_idx, int lmacid, u8 vf_id)
392+
{
393+
struct bgx *bgx = get_bgx(node, bgx_idx);
394+
395+
if (!bgx)
396+
return;
397+
398+
bgx_lmac_remove_filters(&bgx->lmac[lmacid], vf_id);
399+
bgx_flush_dmac_cam_filter(bgx, lmacid);
400+
bgx_set_xcast_mode(node, bgx_idx, lmacid,
401+
(BGX_XCAST_BCAST_ACCEPT | BGX_XCAST_MCAST_ACCEPT));
402+
}
403+
EXPORT_SYMBOL(bgx_reset_xcast_mode);
404+
261405
void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
262406
{
263407
struct bgx *bgx = get_bgx(node, bgx_idx);

drivers/net/ethernet/cavium/thunder/thunder_bgx.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define DEFAULT_PAUSE_TIME 0xFFFF
3131

3232
#define BGX_ID_MASK 0x3
33+
#define LMAC_ID_MASK 0x3
3334

3435
#define MAX_DMAC_PER_LMAC_TNS_BYPASS_MODE 2
3536

@@ -57,7 +58,7 @@
5758
#define BGX_CMRX_RX_FIFO_LEN 0x108
5859
#define BGX_CMR_RX_DMACX_CAM 0x200
5960
#define RX_DMACX_CAM_EN BIT_ULL(48)
60-
#define RX_DMACX_CAM_LMACID(x) (x << 49)
61+
#define RX_DMACX_CAM_LMACID(x) (((u64)x) << 49)
6162
#define RX_DMAC_COUNT 32
6263
#define BGX_CMR_RX_STREERING 0x300
6364
#define RX_TRAFFIC_STEER_RULE_COUNT 8
@@ -205,6 +206,13 @@
205206
#define LMAC_INTR_LINK_UP BIT(0)
206207
#define LMAC_INTR_LINK_DOWN BIT(1)
207208

209+
#define BGX_XCAST_BCAST_ACCEPT BIT(0)
210+
#define BGX_XCAST_MCAST_ACCEPT BIT(1)
211+
#define BGX_XCAST_MCAST_FILTER BIT(2)
212+
213+
void bgx_set_dmac_cam_filter(int node, int bgx_idx, int lmacid, u64 mac, u8 vf);
214+
void bgx_reset_xcast_mode(int node, int bgx_idx, int lmacid, u8 vf);
215+
void bgx_set_xcast_mode(int node, int bgx_idx, int lmacid, u8 mode);
208216
void octeon_mdiobus_force_mod_depencency(void);
209217
void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable);
210218
void bgx_add_dmac_addr(u64 dmac, int node, int bgx_idx, int lmac);

0 commit comments

Comments
 (0)