From: Joe Jin Date: Thu, 17 May 2012 06:16:29 +0000 (+0800) Subject: net: introduce IFF_UNICAST_FLT private flag X-Git-Tag: v2.6.39-400.9.0~423^2~19^2~11^2~374 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ee08dd56ae32f4d9f6f128adf61d51bfd7417a1d;p=users%2Fjedix%2Flinux-maple.git net: introduce IFF_UNICAST_FLT private flag Use IFF_UNICAST_FTL to find out if driver handles unicast address filtering. In case it does not, promisc mode is entered. Patch also fixes following drivers: stmmac, niu: support uc filtering and yet it propagated ndo_set_multicast_list bna, benet, pxa168_eth, ks8851, ks8851_mll, ksz884x : has set ndo_set_rx_mode but do not support uc filtering Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller (backported from commit 01789349ee52e4a3faf376f1485303d9723c4f1f) Signed-off-by: Joe Jin --- diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b217be8b2123..85aa6751d263 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -8467,6 +8468,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->vlan_features = dev->hw_features; dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->features |= dev->hw_features; + dev->priv_flags |= IFF_UNICAST_FLT; if ((rc = register_netdev(dev))) { dev_err(&pdev->dev, "Cannot register net device\n"); diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 02991f7fce92..d789f63e8938 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -10709,6 +10710,8 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, dev->netdev_ops = &bnx2x_netdev_ops; bnx2x_set_ethtool_ops(dev); + dev->priv_flags |= IFF_UNICAST_FLT; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_LRO | NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX; diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index c9957b7f17b5..90b4921cac9b 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -3639,6 +3640,8 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->features |= netdev->hw_features | highdma; netdev->vlan_features = netdev->features & VLAN_FEAT; + netdev->priv_flags |= IFF_UNICAST_FLT; + netdev->netdev_ops = &cxgb4_netdev_ops; SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops); } diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index e71c08e547e4..60bae0256a3b 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c @@ -2612,6 +2612,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + netdev->priv_flags |= IFF_UNICAST_FLT; #ifdef HAVE_NET_DEVICE_OPS netdev->netdev_ops = &cxgb4vf_netdev_ops; #else diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 02da62fbfe6b..ef9494b94b94 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1078,6 +1078,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, netdev->vlan_features |= NETIF_F_HW_CSUM; netdev->vlan_features |= NETIF_F_SG; + netdev->priv_flags |= IFF_UNICAST_FLT; + adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); /* initialize eeprom parameters */ diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 4c1d22159e13..f8faa2eb9c3f 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -2441,6 +2442,8 @@ static int __devinit enic_probe(struct pci_dev *pdev, if (using_dac) netdev->features |= NETIF_F_HIGHDMA; + netdev->priv_flags |= IFF_UNICAST_FLT; + err = register_netdev(netdev); if (err) { dev_err(dev, "Cannot register net device, aborting\n"); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 7421803d2401..5a06e0386f22 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -1936,6 +1937,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (hw->mac.type >= e1000_82576) netdev->features |= NETIF_F_SCTP_CSUM; + netdev->priv_flags |= IFF_UNICAST_FLT; + adapter->en_mng_pt = igb_enable_mng_pass_thru(hw); /* before reading the NVM, reset the controller to put the device in a diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f915412dd50c..1792f479912c 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -7585,6 +7586,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->vlan_features |= NETIF_F_IPV6_CSUM; netdev->vlan_features |= NETIF_F_SG; + netdev->priv_flags |= IFF_UNICAST_FLT; + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED); diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 3b880a27f8d1..45b007827024 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -3358,6 +3359,8 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + netdev->priv_flags |= IFF_UNICAST_FLT; + /* The HW MAC address was set and/or determined in sw_init */ memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index a5d9b1c310b3..9ad378ed3132 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2919,6 +2919,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM; + dev->priv_flags |= IFF_UNICAST_FLT; + SET_NETDEV_DEV(dev, &pdev->dev); if (mp->shared->win_protect) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index f051b9b63271..f1b3ddfbe943 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -9700,7 +9701,7 @@ static const struct net_device_ops niu_netdev_ops = { .ndo_stop = niu_close, .ndo_start_xmit = niu_start_xmit, .ndo_get_stats = niu_get_stats, - .ndo_set_multicast_list = niu_set_rx_mode, + .ndo_set_rx_mode = niu_set_rx_mode, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = niu_set_mac_addr, .ndo_do_ioctl = niu_ioctl, @@ -9836,6 +9837,8 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, niu_set_basic_features(dev); + dev->priv_flags |= IFF_UNICAST_FLT; + np->regs = pci_ioremap_bar(pdev, 0); if (!np->regs) { dev_err(&pdev->dev, "Cannot map device registers, aborting\n"); diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c index b264f0f45605..7ff794ef43af 100644 --- a/drivers/net/octeon/octeon_mgmt.c +++ b/drivers/net/octeon/octeon_mgmt.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1101,6 +1102,8 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev) tasklet_init(&p->tx_clean_tasklet, octeon_mgmt_clean_tx_tasklet, (unsigned long)p); + netdev->priv_flags |= IFF_UNICAST_FLT; + netdev->netdev_ops = &octeon_mgmt_ops; netdev->ethtool_ops = &octeon_mgmt_ethtool_ops; diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index e25e44a45c28..8e3a24e19df1 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1281,7 +1282,7 @@ static int stmmac_config(struct net_device *dev, struct ifmap *map) } /** - * stmmac_multicast_list - entry point for multicast addressing + * stmmac_set_rx_mode - entry point for multicast addressing * @dev : pointer to the device structure * Description: * This function is a driver entry point which gets called by the kernel @@ -1289,7 +1290,7 @@ static int stmmac_config(struct net_device *dev, struct ifmap *map) * Return value: * void. */ -static void stmmac_multicast_list(struct net_device *dev) +static void stmmac_set_rx_mode(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); @@ -1432,7 +1433,7 @@ static const struct net_device_ops stmmac_netdev_ops = { .ndo_stop = stmmac_release, .ndo_change_mtu = stmmac_change_mtu, .ndo_fix_features = stmmac_fix_features, - .ndo_set_multicast_list = stmmac_multicast_list, + .ndo_set_rx_mode = stmmac_set_rx_mode, .ndo_tx_timeout = stmmac_tx_timeout, .ndo_do_ioctl = stmmac_ioctl, .ndo_set_config = stmmac_config, @@ -1512,10 +1513,12 @@ static int stmmac_mac_device_setup(struct net_device *dev) struct mac_device_info *device; - if (priv->plat->has_gmac) + if (priv->plat->has_gmac) { + dev->priv_flags |= IFF_UNICAST_FLT; device = dwmac1000_setup(priv->ioaddr); - else + } else { device = dwmac100_setup(priv->ioaddr); + } if (!device) return -ENOMEM; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f6853247a620..b3263740972b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -891,6 +891,7 @@ static int virtnet_probe(struct virtio_device *vdev) return -ENOMEM; /* Set up network device as normal. */ + dev->priv_flags |= IFF_UNICAST_FLT; dev->netdev_ops = &virtnet_netdev; dev->features = NETIF_F_HIGHDMA; SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops); diff --git a/include/linux/if.h b/include/linux/if.h index 03489ca92ded..db20bd4fd16b 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -78,6 +78,7 @@ * datapath port */ #define IFF_TX_SKB_SHARING 0x10000 /* The interface supports sharing * skbs on transmit */ +#define IFF_UNICAST_FLT 0x20000 /* Supports unicast filtering */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f19686d7bb6f..6d6d03f6c517 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -749,6 +749,8 @@ struct netdev_tc_txq { * * void (*ndo_set_rx_mode)(struct net_device *dev); * This function is called device changes address list filtering. + * If driver handles unicast address filtering, it should set + * IFF_UNICAST_FLT to its priv_flags. * * void (*ndo_set_multicast_list)(struct net_device *dev); * This function is called when the multicast address list changes. diff --git a/net/core/dev.c b/net/core/dev.c index 226ee7fd150a..72c7201f3d43 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4479,9 +4479,7 @@ void __dev_set_rx_mode(struct net_device *dev) if (!netif_device_present(dev)) return; - if (ops->ndo_set_rx_mode) - ops->ndo_set_rx_mode(dev); - else { + if (!(dev->priv_flags & IFF_UNICAST_FLT)) { /* Unicast addresses changes may only happen under the rtnl, * therefore calling __dev_set_promiscuity here is safe. */ @@ -4492,10 +4490,12 @@ void __dev_set_rx_mode(struct net_device *dev) __dev_set_promiscuity(dev, -1); dev->uc_promisc = 0; } - - if (ops->ndo_set_multicast_list) - ops->ndo_set_multicast_list(dev); } + + if (ops->ndo_set_rx_mode) + ops->ndo_set_rx_mode(dev); + else if (ops->ndo_set_multicast_list) + ops->ndo_set_multicast_list(dev); } void dev_set_rx_mode(struct net_device *dev)