|
@@ -638,12 +638,16 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
|
|
|
if (ndev->flags & IFF_PROMISC) {
|
|
|
/* Enable promiscuous mode */
|
|
|
cpsw_set_promiscious(ndev, true);
|
|
|
+ cpsw_ale_set_allmulti(priv->ale, IFF_ALLMULTI);
|
|
|
return;
|
|
|
} else {
|
|
|
/* Disable promiscuous mode */
|
|
|
cpsw_set_promiscious(ndev, false);
|
|
|
}
|
|
|
|
|
|
+ /* Restore allmulti on vlans if necessary */
|
|
|
+ cpsw_ale_set_allmulti(priv->ale, priv->ndev->flags & IFF_ALLMULTI);
|
|
|
+
|
|
|
/* Clear all mcast from ALE */
|
|
|
cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port);
|
|
|
|
|
@@ -1149,6 +1153,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
|
|
|
const int port = priv->host_port;
|
|
|
u32 reg;
|
|
|
int i;
|
|
|
+ int unreg_mcast_mask;
|
|
|
|
|
|
reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
|
|
|
CPSW2_PORT_VLAN;
|
|
@@ -1158,9 +1163,14 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
|
|
|
for (i = 0; i < priv->data.slaves; i++)
|
|
|
slave_write(priv->slaves + i, vlan, reg);
|
|
|
|
|
|
+ if (priv->ndev->flags & IFF_ALLMULTI)
|
|
|
+ unreg_mcast_mask = ALE_ALL_PORTS;
|
|
|
+ else
|
|
|
+ unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
|
|
|
+
|
|
|
cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
|
|
|
ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
|
|
|
- (ALE_PORT_1 | ALE_PORT_2) << port);
|
|
|
+ unreg_mcast_mask << port);
|
|
|
}
|
|
|
|
|
|
static void cpsw_init_host_port(struct cpsw_priv *priv)
|
|
@@ -1620,11 +1630,17 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
|
|
|
unsigned short vid)
|
|
|
{
|
|
|
int ret;
|
|
|
+ int unreg_mcast_mask;
|
|
|
+
|
|
|
+ if (priv->ndev->flags & IFF_ALLMULTI)
|
|
|
+ unreg_mcast_mask = ALE_ALL_PORTS;
|
|
|
+ else
|
|
|
+ unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
|
|
|
|
|
|
ret = cpsw_ale_add_vlan(priv->ale, vid,
|
|
|
ALE_ALL_PORTS << priv->host_port,
|
|
|
0, ALE_ALL_PORTS << priv->host_port,
|
|
|
- (ALE_PORT_1 | ALE_PORT_2) << priv->host_port);
|
|
|
+ unreg_mcast_mask << priv->host_port);
|
|
|
if (ret != 0)
|
|
|
return ret;
|
|
|
|