Skip to content

Commit 749e67d

Browse files
Sean Andersonkuba-moo
authored andcommitted
net: xilinx: axienet: Support IFF_ALLMULTI
Add support for IFF_ALLMULTI by configuring a single filter to match the multicast address bit. This allows us to keep promiscuous mode disabled, even when we have more than four multicast addresses. An even better solution would be to "pack" addresses into the available CAM registers, but that can wait for a future series. Signed-off-by: Sean Anderson <[email protected]> Reviewed-by: Simon Horman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 7a826fb commit 749e67d

File tree

2 files changed

+22
-14
lines changed

2 files changed

+22
-14
lines changed

drivers/net/ethernet/xilinx/xilinx_axienet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@
175175
#define XAE_FFE_OFFSET 0x0000070C /* Frame Filter Enable */
176176
#define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */
177177
#define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */
178+
#define XAE_AM0_OFFSET 0x00000750 /* Frame Filter Mask Value Bytes 3-0 */
179+
#define XAE_AM1_OFFSET 0x00000754 /* Frame Filter Mask Value Bytes 7-4 */
178180

179181
#define XAE_TX_VLAN_DATA_OFFSET 0x00004000 /* TX VLAN data table address */
180182
#define XAE_RX_VLAN_DATA_OFFSET 0x00008000 /* RX VLAN data table address */

drivers/net/ethernet/xilinx/xilinx_axienet_main.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -437,18 +437,27 @@ static void axienet_set_multicast_list(struct net_device *ndev)
437437
u32 reg, af0reg, af1reg;
438438
struct axienet_local *lp = netdev_priv(ndev);
439439

440-
if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) ||
441-
netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
442-
reg = axienet_ior(lp, XAE_FMI_OFFSET);
440+
reg = axienet_ior(lp, XAE_FMI_OFFSET);
441+
reg &= ~XAE_FMI_PM_MASK;
442+
if (ndev->flags & IFF_PROMISC)
443443
reg |= XAE_FMI_PM_MASK;
444+
else
445+
reg &= ~XAE_FMI_PM_MASK;
446+
axienet_iow(lp, XAE_FMI_OFFSET, reg);
447+
448+
if (ndev->flags & IFF_ALLMULTI ||
449+
netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
450+
reg &= 0xFFFFFF00;
444451
axienet_iow(lp, XAE_FMI_OFFSET, reg);
452+
axienet_iow(lp, XAE_AF0_OFFSET, 1); /* Multicast bit */
453+
axienet_iow(lp, XAE_AF1_OFFSET, 0);
454+
axienet_iow(lp, XAE_AM0_OFFSET, 1); /* ditto */
455+
axienet_iow(lp, XAE_AM1_OFFSET, 0);
456+
axienet_iow(lp, XAE_FFE_OFFSET, 1);
457+
i = 1;
445458
} else if (!netdev_mc_empty(ndev)) {
446459
struct netdev_hw_addr *ha;
447460

448-
reg = axienet_ior(lp, XAE_FMI_OFFSET);
449-
reg &= ~XAE_FMI_PM_MASK;
450-
axienet_iow(lp, XAE_FMI_OFFSET, reg);
451-
452461
netdev_for_each_mc_addr(ha, ndev) {
453462
if (i >= XAE_MULTICAST_CAM_TABLE_NUM)
454463
break;
@@ -461,24 +470,21 @@ static void axienet_set_multicast_list(struct net_device *ndev)
461470
af1reg = (ha->addr[4]);
462471
af1reg |= (ha->addr[5] << 8);
463472

464-
reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
473+
reg &= 0xFFFFFF00;
465474
reg |= i;
466475

467476
axienet_iow(lp, XAE_FMI_OFFSET, reg);
468477
axienet_iow(lp, XAE_AF0_OFFSET, af0reg);
469478
axienet_iow(lp, XAE_AF1_OFFSET, af1reg);
479+
axienet_iow(lp, XAE_AM0_OFFSET, 0xffffffff);
480+
axienet_iow(lp, XAE_AM1_OFFSET, 0x0000ffff);
470481
axienet_iow(lp, XAE_FFE_OFFSET, 1);
471482
i++;
472483
}
473-
} else {
474-
reg = axienet_ior(lp, XAE_FMI_OFFSET);
475-
reg &= ~XAE_FMI_PM_MASK;
476-
477-
axienet_iow(lp, XAE_FMI_OFFSET, reg);
478484
}
479485

480486
for (; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
481-
reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
487+
reg &= 0xFFFFFF00;
482488
reg |= i;
483489
axienet_iow(lp, XAE_FMI_OFFSET, reg);
484490
axienet_iow(lp, XAE_FFE_OFFSET, 0);

0 commit comments

Comments
 (0)