Commit ba722f9b authored by David S. Miller's avatar David S. Miller

Merge branch 'net-ethernet-ti-cpsw-fix-mcast-packet-lost'

Ivan Khoronzhuk says:

====================
net: ethernet: ti: cpsw fix mcast packet lost

The patchset omits redundant refresh of mcast address table and
prevents mcast packet lost.

Based on net-next/master
tested on am572x evm
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5985d563 5da19489
...@@ -570,7 +570,7 @@ static inline int cpsw_get_slave_port(u32 slave_num) ...@@ -570,7 +570,7 @@ static inline int cpsw_get_slave_port(u32 slave_num)
return slave_num + 1; return slave_num + 1;
} }
static void cpsw_add_mcast(struct cpsw_priv *priv, u8 *addr) static void cpsw_add_mcast(struct cpsw_priv *priv, const u8 *addr)
{ {
struct cpsw_common *cpsw = priv->cpsw; struct cpsw_common *cpsw = priv->cpsw;
...@@ -662,16 +662,35 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) ...@@ -662,16 +662,35 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
} }
} }
static void cpsw_ndo_set_rx_mode(struct net_device *ndev) static int cpsw_add_mc_addr(struct net_device *ndev, const u8 *addr)
{
struct cpsw_priv *priv = netdev_priv(ndev);
cpsw_add_mcast(priv, addr);
return 0;
}
static int cpsw_del_mc_addr(struct net_device *ndev, const u8 *addr)
{ {
struct cpsw_priv *priv = netdev_priv(ndev); struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw; struct cpsw_common *cpsw = priv->cpsw;
int vid; int vid, flags;
if (cpsw->data.dual_emac) if (cpsw->data.dual_emac) {
vid = cpsw->slaves[priv->emac_port].port_vlan; vid = cpsw->slaves[priv->emac_port].port_vlan;
else flags = ALE_VLAN;
vid = cpsw->data.default_vlan; } else {
vid = 0;
flags = 0;
}
cpsw_ale_del_mcast(cpsw->ale, addr, 0, flags, vid);
return 0;
}
static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
{
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
if (ndev->flags & IFF_PROMISC) { if (ndev->flags & IFF_PROMISC) {
/* Enable promiscuous mode */ /* Enable promiscuous mode */
...@@ -684,19 +703,9 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) ...@@ -684,19 +703,9 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
} }
/* Restore allmulti on vlans if necessary */ /* Restore allmulti on vlans if necessary */
cpsw_ale_set_allmulti(cpsw->ale, priv->ndev->flags & IFF_ALLMULTI); cpsw_ale_set_allmulti(cpsw->ale, ndev->flags & IFF_ALLMULTI);
/* Clear all mcast from ALE */
cpsw_ale_flush_multicast(cpsw->ale, ALE_ALL_PORTS, vid);
if (!netdev_mc_empty(ndev)) { __dev_mc_sync(ndev, cpsw_add_mc_addr, cpsw_del_mc_addr);
struct netdev_hw_addr *ha;
/* program multicast address list into ALE register */
netdev_for_each_mc_addr(ha, ndev) {
cpsw_add_mcast(priv, ha->addr);
}
}
} }
static void cpsw_intr_enable(struct cpsw_common *cpsw) static void cpsw_intr_enable(struct cpsw_common *cpsw)
...@@ -1956,6 +1965,7 @@ static int cpsw_ndo_stop(struct net_device *ndev) ...@@ -1956,6 +1965,7 @@ static int cpsw_ndo_stop(struct net_device *ndev)
struct cpsw_common *cpsw = priv->cpsw; struct cpsw_common *cpsw = priv->cpsw;
cpsw_info(priv, ifdown, "shutting down cpsw device\n"); cpsw_info(priv, ifdown, "shutting down cpsw device\n");
__dev_mc_unsync(priv->ndev, cpsw_del_mc_addr);
netif_tx_stop_all_queues(priv->ndev); netif_tx_stop_all_queues(priv->ndev);
netif_carrier_off(priv->ndev); netif_carrier_off(priv->ndev);
......
...@@ -136,7 +136,7 @@ static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr) ...@@ -136,7 +136,7 @@ static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8); addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
} }
static inline void cpsw_ale_set_addr(u32 *ale_entry, u8 *addr) static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
{ {
int i; int i;
...@@ -175,7 +175,7 @@ static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry) ...@@ -175,7 +175,7 @@ static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
return idx; return idx;
} }
static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid) static int cpsw_ale_match_addr(struct cpsw_ale *ale, const u8 *addr, u16 vid)
{ {
u32 ale_entry[ALE_ENTRY_WORDS]; u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx; int type, idx;
...@@ -309,7 +309,7 @@ static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry, ...@@ -309,7 +309,7 @@ static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
} }
} }
int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
int flags, u16 vid) int flags, u16 vid)
{ {
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
...@@ -336,7 +336,7 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, ...@@ -336,7 +336,7 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
} }
EXPORT_SYMBOL_GPL(cpsw_ale_add_ucast); EXPORT_SYMBOL_GPL(cpsw_ale_add_ucast);
int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port, int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
int flags, u16 vid) int flags, u16 vid)
{ {
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
...@@ -352,7 +352,7 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port, ...@@ -352,7 +352,7 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
} }
EXPORT_SYMBOL_GPL(cpsw_ale_del_ucast); EXPORT_SYMBOL_GPL(cpsw_ale_del_ucast);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
int flags, u16 vid, int mcast_state) int flags, u16 vid, int mcast_state)
{ {
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
...@@ -386,7 +386,7 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, ...@@ -386,7 +386,7 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
} }
EXPORT_SYMBOL_GPL(cpsw_ale_add_mcast); EXPORT_SYMBOL_GPL(cpsw_ale_add_mcast);
int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
int flags, u16 vid) int flags, u16 vid)
{ {
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
......
...@@ -105,13 +105,13 @@ void cpsw_ale_start(struct cpsw_ale *ale); ...@@ -105,13 +105,13 @@ void cpsw_ale_start(struct cpsw_ale *ale);
void cpsw_ale_stop(struct cpsw_ale *ale); void cpsw_ale_stop(struct cpsw_ale *ale);
int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid); int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid);
int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
int flags, u16 vid); int flags, u16 vid);
int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port, int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
int flags, u16 vid); int flags, u16 vid);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
int flags, u16 vid, int mcast_state); int flags, u16 vid, int mcast_state);
int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
int flags, u16 vid); int flags, u16 vid);
int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag, int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
int reg_mcast, int unreg_mcast); int reg_mcast, int unreg_mcast);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment