From e6440d65f1e29974096ef2cf0807e74521e06ff9 Mon Sep 17 00:00:00 2001 From: Thomas Kaiser Date: Mon, 1 May 2017 17:20:12 +0200 Subject: [PATCH] Fix Multicast issues with sun8i-emac https://forum.armbian.com/index.php?/topic/3236-appletalkagain/ --- .../sun8i-dev/fix-ethernet-multicasts.patch | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 patch/kernel/sun8i-dev/fix-ethernet-multicasts.patch diff --git a/patch/kernel/sun8i-dev/fix-ethernet-multicasts.patch b/patch/kernel/sun8i-dev/fix-ethernet-multicasts.patch new file mode 100644 index 000000000..e8147a714 --- /dev/null +++ b/patch/kernel/sun8i-dev/fix-ethernet-multicasts.patch @@ -0,0 +1,86 @@ +From 43934e114a3a3358a570480c8974e4e52769cd11 Mon Sep 17 00:00:00 2001 +From: Corentin Labbe +Date: Tue, 25 Apr 2017 15:53:58 +0200 +Subject: [PATCH] net: sun8i-emac: fix multicast + +Signed-off-by: Corentin Labbe +--- + drivers/net/ethernet/allwinner/sun8i-emac.c | 43 ++++++++++++++++++++++------- + 1 file changed, 33 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/allwinner/sun8i-emac.c b/drivers/net/ethernet/allwinner/sun8i-emac.c +index 110412c..e02cfd8 100644 +--- a/drivers/net/ethernet/allwinner/sun8i-emac.c ++++ b/drivers/net/ethernet/allwinner/sun8i-emac.c +@@ -94,6 +94,10 @@ + #define EMAC_FRM_FLT_CTL BIT(13) + #define EMAC_FRM_FLT_MULTICAST BIT(16) + ++/* Mac address */ ++#define EMAC_MAX_MACADDR 8 ++#define MAC_ADDR_TYPE_DST BIT(31) ++ + /* Used in BASIC_CTL0 */ + #define EMAC_BCTL0_FD BIT(0) + #define EMAC_BCTL0_LOOPBACK BIT(1) +@@ -520,9 +524,16 @@ static void sun8i_emac_set_macaddr(struct sun8i_emac_priv *priv, + { + u32 v; + ++ if (index > 7) { ++ dev_err(priv->dev, "Too many MAC addr\n"); ++ return; ++ } ++ + dev_info(priv->dev, "device MAC address slot %d %pM", index, addr); + + v = (addr[5] << 8) | addr[4]; ++ if (index > 0) ++ v |= MAC_ADDR_TYPE_DST; + writel(v, priv->base + EMAC_MACADDR_HI + index * 8); + + v = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; +@@ -1741,21 +1752,33 @@ static void sun8i_emac_set_rx_mode(struct net_device *ndev) + u32 v = 0; + int i = 0; + struct netdev_hw_addr *ha; ++ int macaddrs = netdev_uc_count(ndev) + netdev_mc_count(ndev) + 1; + +- /* Receive all multicast frames */ +- v |= EMAC_FRM_FLT_MULTICAST; + /* Receive all control frames */ + v |= EMAC_FRM_FLT_CTL; +- if (ndev->flags & IFF_PROMISC) +- v |= EMAC_FRM_FLT_RXALL; +- if (netdev_uc_count(ndev) > 7) { +- v |= EMAC_FRM_FLT_RXALL; +- } else { +- netdev_for_each_uc_addr(ha, ndev) { +- i++; +- sun8i_emac_set_macaddr(priv, ha->addr, i); ++ ++ if (ndev->flags & IFF_PROMISC) { ++ v = EMAC_FRM_FLT_RXALL; ++ } else if (ndev->flags & IFF_ALLMULTI) { ++ v |= EMAC_FRM_FLT_MULTICAST; ++ } else if (macaddrs <= EMAC_MAX_MACADDR) { ++ if (!netdev_mc_empty(ndev)) { ++ netdev_for_each_mc_addr(ha, ndev) { ++ i++; ++ sun8i_emac_set_macaddr(priv, ha->addr, i); ++ } ++ } ++ if (!netdev_uc_empty(ndev)) { ++ netdev_for_each_uc_addr(ha, ndev) { ++ i++; ++ sun8i_emac_set_macaddr(priv, ha->addr, i); ++ } + } ++ } else { ++ netdev_info(ndev, "Too many address, switching to promiscuous\n"); ++ v = EMAC_FRM_FLT_RXALL; + } ++ + writel(v, priv->base + EMAC_RX_FRM_FLT); + } +