Skip to content

Commit

Permalink
net: xilinx: axienet: Support IFF_ALLMULTI
Browse files Browse the repository at this point in the history
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 <sean.anderson@linux.dev>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20240822154059.1066595-6-sean.anderson@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Sean Anderson authored and Jakub Kicinski committed Aug 26, 2024
1 parent 7a826fb commit 749e67d
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/xilinx/xilinx_axienet.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@
#define XAE_FFE_OFFSET 0x0000070C /* Frame Filter Enable */
#define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */
#define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */
#define XAE_AM0_OFFSET 0x00000750 /* Frame Filter Mask Value Bytes 3-0 */
#define XAE_AM1_OFFSET 0x00000754 /* Frame Filter Mask Value Bytes 7-4 */

#define XAE_TX_VLAN_DATA_OFFSET 0x00004000 /* TX VLAN data table address */
#define XAE_RX_VLAN_DATA_OFFSET 0x00008000 /* RX VLAN data table address */
Expand Down
34 changes: 20 additions & 14 deletions drivers/net/ethernet/xilinx/xilinx_axienet_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,18 +437,27 @@ static void axienet_set_multicast_list(struct net_device *ndev)
u32 reg, af0reg, af1reg;
struct axienet_local *lp = netdev_priv(ndev);

if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) ||
netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
reg = axienet_ior(lp, XAE_FMI_OFFSET);
reg = axienet_ior(lp, XAE_FMI_OFFSET);
reg &= ~XAE_FMI_PM_MASK;
if (ndev->flags & IFF_PROMISC)
reg |= XAE_FMI_PM_MASK;
else
reg &= ~XAE_FMI_PM_MASK;
axienet_iow(lp, XAE_FMI_OFFSET, reg);

if (ndev->flags & IFF_ALLMULTI ||
netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
reg &= 0xFFFFFF00;
axienet_iow(lp, XAE_FMI_OFFSET, reg);
axienet_iow(lp, XAE_AF0_OFFSET, 1); /* Multicast bit */
axienet_iow(lp, XAE_AF1_OFFSET, 0);
axienet_iow(lp, XAE_AM0_OFFSET, 1); /* ditto */
axienet_iow(lp, XAE_AM1_OFFSET, 0);
axienet_iow(lp, XAE_FFE_OFFSET, 1);
i = 1;
} else if (!netdev_mc_empty(ndev)) {
struct netdev_hw_addr *ha;

reg = axienet_ior(lp, XAE_FMI_OFFSET);
reg &= ~XAE_FMI_PM_MASK;
axienet_iow(lp, XAE_FMI_OFFSET, reg);

netdev_for_each_mc_addr(ha, ndev) {
if (i >= XAE_MULTICAST_CAM_TABLE_NUM)
break;
Expand All @@ -461,24 +470,21 @@ static void axienet_set_multicast_list(struct net_device *ndev)
af1reg = (ha->addr[4]);
af1reg |= (ha->addr[5] << 8);

reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
reg &= 0xFFFFFF00;
reg |= i;

axienet_iow(lp, XAE_FMI_OFFSET, reg);
axienet_iow(lp, XAE_AF0_OFFSET, af0reg);
axienet_iow(lp, XAE_AF1_OFFSET, af1reg);
axienet_iow(lp, XAE_AM0_OFFSET, 0xffffffff);
axienet_iow(lp, XAE_AM1_OFFSET, 0x0000ffff);
axienet_iow(lp, XAE_FFE_OFFSET, 1);
i++;
}
} else {
reg = axienet_ior(lp, XAE_FMI_OFFSET);
reg &= ~XAE_FMI_PM_MASK;

axienet_iow(lp, XAE_FMI_OFFSET, reg);
}

for (; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
reg &= 0xFFFFFF00;
reg |= i;
axienet_iow(lp, XAE_FMI_OFFSET, reg);
axienet_iow(lp, XAE_FFE_OFFSET, 0);
Expand Down

0 comments on commit 749e67d

Please sign in to comment.