mirror of https://gitee.com/openkylin/linux.git
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ba722f9b6f
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 */
|
__dev_mc_sync(ndev, cpsw_add_mc_addr, cpsw_del_mc_addr);
|
||||||
cpsw_ale_flush_multicast(cpsw->ale, ALE_ALL_PORTS, vid);
|
|
||||||
|
|
||||||
if (!netdev_mc_empty(ndev)) {
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
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,
|
||||||
}
|
}
|
||||||
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,
|
||||||
}
|
}
|
||||||
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);
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue