|
|
@@ -3086,39 +3086,42 @@ static void bcmgenet_timeout(struct net_device *dev)
|
|
|
netif_tx_wake_all_queues(dev);
|
|
|
}
|
|
|
|
|
|
-#define MAX_MC_COUNT 16
|
|
|
+#define MAX_MDF_FILTER 17
|
|
|
|
|
|
static inline void bcmgenet_set_mdf_addr(struct bcmgenet_priv *priv,
|
|
|
unsigned char *addr,
|
|
|
- int *i,
|
|
|
- int *mc)
|
|
|
+ int *i)
|
|
|
{
|
|
|
- u32 reg;
|
|
|
-
|
|
|
bcmgenet_umac_writel(priv, addr[0] << 8 | addr[1],
|
|
|
UMAC_MDF_ADDR + (*i * 4));
|
|
|
bcmgenet_umac_writel(priv, addr[2] << 24 | addr[3] << 16 |
|
|
|
addr[4] << 8 | addr[5],
|
|
|
UMAC_MDF_ADDR + ((*i + 1) * 4));
|
|
|
- reg = bcmgenet_umac_readl(priv, UMAC_MDF_CTRL);
|
|
|
- reg |= (1 << (MAX_MC_COUNT - *mc));
|
|
|
- bcmgenet_umac_writel(priv, reg, UMAC_MDF_CTRL);
|
|
|
*i += 2;
|
|
|
- (*mc)++;
|
|
|
}
|
|
|
|
|
|
static void bcmgenet_set_rx_mode(struct net_device *dev)
|
|
|
{
|
|
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
|
|
struct netdev_hw_addr *ha;
|
|
|
- int i, mc;
|
|
|
+ int i, nfilter;
|
|
|
u32 reg;
|
|
|
|
|
|
netif_dbg(priv, hw, dev, "%s: %08X\n", __func__, dev->flags);
|
|
|
|
|
|
- /* Promiscuous mode */
|
|
|
+ /* Number of filters needed */
|
|
|
+ nfilter = netdev_uc_count(dev) + netdev_mc_count(dev) + 2;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Turn on promicuous mode for three scenarios
|
|
|
+ * 1. IFF_PROMISC flag is set
|
|
|
+ * 2. IFF_ALLMULTI flag is set
|
|
|
+ * 3. The number of filters needed exceeds the number filters
|
|
|
+ * supported by the hardware.
|
|
|
+ */
|
|
|
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
|
|
- if (dev->flags & IFF_PROMISC) {
|
|
|
+ if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) ||
|
|
|
+ (nfilter > MAX_MDF_FILTER)) {
|
|
|
reg |= CMD_PROMISC;
|
|
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
|
|
bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL);
|
|
|
@@ -3128,32 +3131,24 @@ static void bcmgenet_set_rx_mode(struct net_device *dev)
|
|
|
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
|
|
}
|
|
|
|
|
|
- /* UniMac doesn't support ALLMULTI */
|
|
|
- if (dev->flags & IFF_ALLMULTI) {
|
|
|
- netdev_warn(dev, "ALLMULTI is not supported\n");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
/* update MDF filter */
|
|
|
i = 0;
|
|
|
- mc = 0;
|
|
|
/* Broadcast */
|
|
|
- bcmgenet_set_mdf_addr(priv, dev->broadcast, &i, &mc);
|
|
|
+ bcmgenet_set_mdf_addr(priv, dev->broadcast, &i);
|
|
|
/* my own address.*/
|
|
|
- bcmgenet_set_mdf_addr(priv, dev->dev_addr, &i, &mc);
|
|
|
- /* Unicast list*/
|
|
|
- if (netdev_uc_count(dev) > (MAX_MC_COUNT - mc))
|
|
|
- return;
|
|
|
+ bcmgenet_set_mdf_addr(priv, dev->dev_addr, &i);
|
|
|
|
|
|
- if (!netdev_uc_empty(dev))
|
|
|
- netdev_for_each_uc_addr(ha, dev)
|
|
|
- bcmgenet_set_mdf_addr(priv, ha->addr, &i, &mc);
|
|
|
- /* Multicast */
|
|
|
- if (netdev_mc_empty(dev) || netdev_mc_count(dev) >= (MAX_MC_COUNT - mc))
|
|
|
- return;
|
|
|
+ /* Unicast */
|
|
|
+ netdev_for_each_uc_addr(ha, dev)
|
|
|
+ bcmgenet_set_mdf_addr(priv, ha->addr, &i);
|
|
|
|
|
|
+ /* Multicast */
|
|
|
netdev_for_each_mc_addr(ha, dev)
|
|
|
- bcmgenet_set_mdf_addr(priv, ha->addr, &i, &mc);
|
|
|
+ bcmgenet_set_mdf_addr(priv, ha->addr, &i);
|
|
|
+
|
|
|
+ /* Enable filters */
|
|
|
+ reg = GENMASK(MAX_MDF_FILTER - 1, MAX_MDF_FILTER - nfilter);
|
|
|
+ bcmgenet_umac_writel(priv, reg, UMAC_MDF_CTRL);
|
|
|
}
|
|
|
|
|
|
/* Set the hardware MAC address. */
|