From 01789349ee52e4a3faf376f1485303d9723c4f1f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 16 Aug 2011 06:29:00 +0000 Subject: 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 --- include/linux/netdevice.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ddee79bb8f15..96e4f7e0ad68 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -723,6 +723,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. -- cgit v1.2.3 From b81693d9149c598302e8eb9c20cb20330d922c8e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 16 Aug 2011 06:29:02 +0000 Subject: net: remove ndo_set_multicast_list callback Remove no longer used operation. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- Documentation/networking/netdevices.txt | 4 ++-- include/linux/netdevice.h | 4 ---- net/core/dev.c | 6 ++---- net/core/dev_addr_lists.c | 4 ++-- net/ipv4/igmp.c | 2 +- 5 files changed, 7 insertions(+), 13 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 87b3d15f523a..89358341682a 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -73,7 +73,7 @@ dev->hard_start_xmit: has to lock by itself when needed. It is recommended to use a try lock for this and return NETDEV_TX_LOCKED when the spin lock fails. The locking there should also properly protect against - set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated. + set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated. Don't use it for new drivers. Context: Process with BHs disabled or BH (timer), @@ -92,7 +92,7 @@ dev->tx_timeout: Context: BHs disabled Notes: netif_queue_stopped() is guaranteed true -dev->set_multicast_list: +dev->set_rx_mode: Synchronization: netif_tx_lock spinlock. Context: BHs disabled diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 96e4f7e0ad68..125f9fb8ece4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -726,9 +726,6 @@ struct netdev_tc_txq { * 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. - * * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); * This function is called when the Media Access Control address * needs to be changed. If this interface is not defined, the @@ -870,7 +867,6 @@ struct net_device_ops { void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); - void (*ndo_set_multicast_list)(struct net_device *dev); int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_validate_addr)(struct net_device *dev); diff --git a/net/core/dev.c b/net/core/dev.c index 6eb03fdaf075..ead0366ee1e4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4537,8 +4537,6 @@ void __dev_set_rx_mode(struct net_device *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) @@ -4888,7 +4886,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) return -EOPNOTSUPP; case SIOCADDMULTI: - if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || + if (!ops->ndo_set_rx_mode || ifr->ifr_hwaddr.sa_family != AF_UNSPEC) return -EINVAL; if (!netif_device_present(dev)) @@ -4896,7 +4894,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data); case SIOCDELMULTI: - if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || + if (!ops->ndo_set_rx_mode || ifr->ifr_hwaddr.sa_family != AF_UNSPEC) return -EINVAL; if (!netif_device_present(dev)) diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index e2e66939ed00..283d1b863876 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -591,8 +591,8 @@ EXPORT_SYMBOL(dev_mc_del_global); * addresses that have no users left. The source device must be * locked by netif_tx_lock_bh. * - * This function is intended to be called from the dev->set_multicast_list - * or dev->set_rx_mode function of layered software devices. + * This function is intended to be called from the ndo_set_rx_mode + * function of layered software devices. */ int dev_mc_sync(struct net_device *to, struct net_device *from) { diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 70695221a10d..ce57bdee14cb 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1009,7 +1009,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr) /* Checking for IFF_MULTICAST here is WRONG-WRONG-WRONG. We will get multicast token leakage, when IFF_MULTICAST - is changed. This check should be done in dev->set_multicast_list + is changed. This check should be done in ndo_set_rx_mode routine. Something sort of: if (dev->mc_list && dev->flags&IFF_MULTICAST) { do it; } --ANK -- cgit v1.2.3 From 3c9c36bcedd426f2be2826da43e5163de61735f7 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Gollapudi Date: Fri, 26 Aug 2011 09:45:41 +0000 Subject: net: Define NETDEV_FCOE_WWNN, NETDEV_FCOE_WWPN only when CONFIG_LIBFCOE is enabled bnx2fc driver calls netdev->netdev_ops->ndo_fcoe_get_wwn() and it may not be defined with the current Kconfig dependencies. ndo_fcoe_get_wwn is dependent on CONFIG_FCOE, but bnx2fc does not select CONFIG_FCOE, as it does not depend on fcoe driver. Since both fcoe and bnx2fc drivers select CONFIG_LIBFCOE, define NETDEV_FCOE_WWNN and NETDEV_FCOE_WWPN when CONFIG_LIBFCOE is defined. Reported-by: Stephen Rothwell Reported-by: Randy Dunlap Cc: Yi Zou Signed-off-by: Bhanu Prakash Gollapudi Signed-off-by: Michael Chan Reviewed-by: Yi Zou Acked-by: Randy Dunlap Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 125f9fb8ece4..0a7f619f284e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -922,11 +922,15 @@ struct net_device_ops { u16 xid, struct scatterlist *sgl, unsigned int sgc); +#endif + +#if defined(CONFIG_LIBFCOE) || defined(CONFIG_LIBFCOE_MODULE) #define NETDEV_FCOE_WWNN 0 #define NETDEV_FCOE_WWPN 1 int (*ndo_fcoe_get_wwn)(struct net_device *dev, u64 *wwn, int type); #endif + #ifdef CONFIG_RFS_ACCEL int (*ndo_rx_flow_steer)(struct net_device *dev, const struct sk_buff *skb, -- cgit v1.2.3 From 4bc71cb983fd2844e603bf633df2bb53385182d2 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 3 Sep 2011 03:34:30 +0000 Subject: net: consolidate and fix ethtool_ops->get_settings calling This patch does several things: - introduces __ethtool_get_settings which is called from ethtool code and from drivers as well. Put ASSERT_RTNL there. - dev_ethtool_get_settings() is replaced by __ethtool_get_settings() - changes calling in drivers so rtnl locking is respected. In iboe_get_rate was previously ->get_settings() called unlocked. This fixes it. Also prb_calc_retire_blk_tmo() in af_packet.c had the same problem. Also fixed by calling __dev_get_by_index() instead of dev_get_by_index() and holding rtnl_lock for both calls. - introduces rtnl_lock in bnx2fc_vport_create() and fcoe_vport_create() so bnx2fc_if_create() and fcoe_if_create() are called locked as they are from other places. - use __ethtool_get_settings() in bonding code Signed-off-by: Jiri Pirko v2->v3: -removed dev_ethtool_get_settings() -added ASSERT_RTNL into __ethtool_get_settings() -prb_calc_retire_blk_tmo - use __dev_get_by_index() and lock around it and __ethtool_get_settings() call v1->v2: add missing export_symbol Reviewed-by: Ben Hutchings [except FCoE bits] Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- arch/mips/txx9/generic/setup_tx4939.c | 2 +- drivers/net/bonding/bond_main.c | 13 ++++----- drivers/net/macvlan.c | 3 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 4 ++- drivers/scsi/fcoe/fcoe.c | 4 ++- include/linux/ethtool.h | 3 ++ include/linux/netdevice.h | 3 -- include/rdma/ib_addr.h | 6 +++- net/8021q/vlan_dev.c | 3 +- net/bridge/br_if.c | 2 +- net/core/dev.c | 24 ---------------- net/core/ethtool.c | 20 ++++++++++---- net/core/net-sysfs.c | 4 +-- net/packet/af_packet.c | 52 ++++++++++++++++++----------------- 14 files changed, 69 insertions(+), 74 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index e9f95dcde379..ba3cec3155df 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -321,7 +321,7 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) static u32 tx4939_get_eth_speed(struct net_device *dev) { struct ethtool_cmd cmd; - if (dev_ethtool_get_settings(dev, &cmd)) + if (__ethtool_get_settings(dev, &cmd)) return 100; /* default 100Mbps */ return ethtool_cmd_speed(&cmd); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 8cb75a6efec3..1dcb07ce5263 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -557,7 +557,7 @@ down: static int bond_update_speed_duplex(struct slave *slave) { struct net_device *slave_dev = slave->dev; - struct ethtool_cmd etool = { .cmd = ETHTOOL_GSET }; + struct ethtool_cmd ecmd; u32 slave_speed; int res; @@ -565,18 +565,15 @@ static int bond_update_speed_duplex(struct slave *slave) slave->speed = SPEED_100; slave->duplex = DUPLEX_FULL; - if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings) - return -1; - - res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool); + res = __ethtool_get_settings(slave_dev, &ecmd); if (res < 0) return -1; - slave_speed = ethtool_cmd_speed(&etool); + slave_speed = ethtool_cmd_speed(&ecmd); if (slave_speed == 0 || slave_speed == ((__u32) -1)) return -1; - switch (etool.duplex) { + switch (ecmd.duplex) { case DUPLEX_FULL: case DUPLEX_HALF: break; @@ -585,7 +582,7 @@ static int bond_update_speed_duplex(struct slave *slave) } slave->speed = slave_speed; - slave->duplex = etool.duplex; + slave->duplex = ecmd.duplex; return 0; } diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 836e13fcb3ec..b100c90e8507 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -543,7 +543,8 @@ static int macvlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { const struct macvlan_dev *vlan = netdev_priv(dev); - return dev_ethtool_get_settings(vlan->lowerdev, cmd); + + return __ethtool_get_settings(vlan->lowerdev, cmd); } static const struct ethtool_ops macvlan_ethtool_ops = { diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 2c780a78fcbd..820a1840c3f7 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -673,7 +673,7 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport) struct net_device *netdev = interface->netdev; struct ethtool_cmd ecmd; - if (!dev_ethtool_get_settings(netdev, &ecmd)) { + if (!__ethtool_get_settings(netdev, &ecmd)) { lport->link_supported_speeds &= ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); if (ecmd.supported & (SUPPORTED_1000baseT_Half | @@ -1001,9 +1001,11 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled) "this interface\n"); return -EIO; } + rtnl_lock(); mutex_lock(&bnx2fc_dev_lock); vn_port = bnx2fc_if_create(interface, &vport->dev, 1); mutex_unlock(&bnx2fc_dev_lock); + rtnl_unlock(); if (IS_ERR(vn_port)) { printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n", diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 3416ab673814..83aa3ac52c40 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2043,7 +2043,7 @@ int fcoe_link_speed_update(struct fc_lport *lport) struct net_device *netdev = fcoe_netdev(lport); struct ethtool_cmd ecmd; - if (!dev_ethtool_get_settings(netdev, &ecmd)) { + if (!__ethtool_get_settings(netdev, &ecmd)) { lport->link_supported_speeds &= ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); if (ecmd.supported & (SUPPORTED_1000baseT_Half | @@ -2452,7 +2452,9 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled) } mutex_lock(&fcoe_config_mutex); + rtnl_lock(); vn_port = fcoe_if_create(fcoe, &vport->dev, 1); + rtnl_unlock(); mutex_unlock(&fcoe_config_mutex); if (IS_ERR(vn_port)) { diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 3829712ccc05..8571f18c38a6 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -728,6 +728,9 @@ enum ethtool_sfeatures_retval_bits { /* needed by dev_disable_lro() */ extern int __ethtool_set_flags(struct net_device *dev, u32 flags); +extern int __ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd); + /** * enum ethtool_phys_id_state - indicator state for physical identification * @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0a7f619f284e..43b32983ba10 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2589,9 +2589,6 @@ static inline int netif_is_bond_slave(struct net_device *dev) extern struct pernet_operations __net_initdata loopback_net_ops; -int dev_ethtool_get_settings(struct net_device *dev, - struct ethtool_cmd *cmd); - static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev) { if (dev->features & NETIF_F_RXCSUM) diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index ae8c68f30f1b..639a4491fc0d 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -218,8 +218,12 @@ static inline int iboe_get_rate(struct net_device *dev) { struct ethtool_cmd cmd; u32 speed; + int err; - if (dev_ethtool_get_settings(dev, &cmd)) + rtnl_lock(); + err = __ethtool_get_settings(dev, &cmd); + rtnl_unlock(); + if (err) return IB_RATE_PORT_CURRENT; speed = ethtool_cmd_speed(&cmd); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index eba705b92d6f..c8cf9391417e 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -610,7 +610,8 @@ static int vlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { const struct vlan_dev_info *vlan = vlan_dev_info(dev); - return dev_ethtool_get_settings(vlan->real_dev, cmd); + + return __ethtool_get_settings(vlan->real_dev, cmd); } static void vlan_ethtool_get_drvinfo(struct net_device *dev, diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index b365bba84d19..043a5eb8cafc 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -35,7 +35,7 @@ static int port_cost(struct net_device *dev) { struct ethtool_cmd ecmd; - if (!dev_ethtool_get_settings(dev, &ecmd)) { + if (!__ethtool_get_settings(dev, &ecmd)) { switch (ethtool_cmd_speed(&ecmd)) { case SPEED_10000: return 2; diff --git a/net/core/dev.c b/net/core/dev.c index b2e262ed3963..4b9981caf06f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4565,30 +4565,6 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } -/** - * dev_ethtool_get_settings - call device's ethtool_ops::get_settings() - * @dev: device - * @cmd: memory area for ethtool_ops::get_settings() result - * - * The cmd arg is initialized properly (cleared and - * ethtool_cmd::cmd field set to ETHTOOL_GSET). - * - * Return device's ethtool_ops::get_settings() result value or - * -EOPNOTSUPP when device doesn't expose - * ethtool_ops::get_settings() operation. - */ -int dev_ethtool_get_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - - memset(cmd, 0, sizeof(struct ethtool_cmd)); - cmd->cmd = ETHTOOL_GSET; - return dev->ethtool_ops->get_settings(dev, cmd); -} -EXPORT_SYMBOL(dev_ethtool_get_settings); - /** * dev_get_flags - get flags reported to userspace * @dev: device diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 6cdba5fc2bed..f44481707124 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -569,15 +569,25 @@ int __ethtool_set_flags(struct net_device *dev, u32 data) return 0; } -static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) +int __ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; - int err; + ASSERT_RTNL(); - if (!dev->ethtool_ops->get_settings) + if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) return -EOPNOTSUPP; - err = dev->ethtool_ops->get_settings(dev, &cmd); + memset(cmd, 0, sizeof(struct ethtool_cmd)); + cmd->cmd = ETHTOOL_GSET; + return dev->ethtool_ops->get_settings(dev, cmd); +} +EXPORT_SYMBOL(__ethtool_get_settings); + +static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) +{ + int err; + struct ethtool_cmd cmd; + + err = __ethtool_get_settings(dev, &cmd); if (err < 0) return err; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 56e42ab7cbc6..7604a635376b 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -147,7 +147,7 @@ static ssize_t show_speed(struct device *dev, if (netif_running(netdev)) { struct ethtool_cmd cmd; - if (!dev_ethtool_get_settings(netdev, &cmd)) + if (!__ethtool_get_settings(netdev, &cmd)) ret = sprintf(buf, fmt_udec, ethtool_cmd_speed(&cmd)); } rtnl_unlock(); @@ -165,7 +165,7 @@ static ssize_t show_duplex(struct device *dev, if (netif_running(netdev)) { struct ethtool_cmd cmd; - if (!dev_ethtool_get_settings(netdev, &cmd)) + if (!__ethtool_get_settings(netdev, &cmd)) ret = sprintf(buf, "%s\n", cmd.duplex ? "full" : "half"); } diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2ea3d63e1d4c..25e68f56b4ba 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -530,33 +530,35 @@ static int prb_calc_retire_blk_tmo(struct packet_sock *po, { struct net_device *dev; unsigned int mbits = 0, msec = 0, div = 0, tmo = 0; + struct ethtool_cmd ecmd; + int err; - dev = dev_get_by_index(sock_net(&po->sk), po->ifindex); - if (unlikely(dev == NULL)) + rtnl_lock(); + dev = __dev_get_by_index(sock_net(&po->sk), po->ifindex); + if (unlikely(!dev)) { + rtnl_unlock(); return DEFAULT_PRB_RETIRE_TOV; - - if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { - struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; - - if (!dev->ethtool_ops->get_settings(dev, &ecmd)) { - switch (ecmd.speed) { - case SPEED_10000: - msec = 1; - div = 10000/1000; - break; - case SPEED_1000: - msec = 1; - div = 1000/1000; - break; - /* - * If the link speed is so slow you don't really - * need to worry about perf anyways - */ - case SPEED_100: - case SPEED_10: - default: - return DEFAULT_PRB_RETIRE_TOV; - } + } + err = __ethtool_get_settings(dev, &ecmd); + rtnl_unlock(); + if (!err) { + switch (ecmd.speed) { + case SPEED_10000: + msec = 1; + div = 10000/1000; + break; + case SPEED_1000: + msec = 1; + div = 1000/1000; + break; + /* + * If the link speed is so slow you don't really + * need to worry about perf anyways + */ + case SPEED_100: + case SPEED_10: + default: + return DEFAULT_PRB_RETIRE_TOV; } } -- cgit v1.2.3 From 5f8444a3fa617076f8da51a3e8ecce01a5d7f738 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 8 Oct 2011 03:05:24 +0000 Subject: if_link: Add additional parameter to IFLA_VF_INFO for spoof checking Add configuration setting for drivers to turn spoof checking on or off for discrete VFs. v2 - Fix indentation problem, wrap the ifla_vf_info structure in #ifdef __KERNEL__ to prevent user space from accessing and change function paramater for the spoof check setting netdev op from u8 to bool. v3 - Preset spoof check setting to -1 so that user space tools such as ip can detect that the driver didn't report a spoofcheck setting. Prevents incorrect display of spoof check settings for drivers that don't report it. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher --- include/linux/if_link.h | 10 ++++++++++ include/linux/netdevice.h | 3 +++ net/core/rtnetlink.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 3 deletions(-) (limited to 'include/linux/netdevice.h') diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 0ee969a5593d..c52d4b5f872a 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -279,6 +279,7 @@ enum { IFLA_VF_MAC, /* Hardware queue specific attributes */ IFLA_VF_VLAN, IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ + IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ __IFLA_VF_MAX, }; @@ -300,13 +301,22 @@ struct ifla_vf_tx_rate { __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ }; +struct ifla_vf_spoofchk { + __u32 vf; + __u32 setting; +}; +#ifdef __KERNEL__ + +/* We don't want this structure exposed to user space */ struct ifla_vf_info { __u32 vf; __u8 mac[32]; __u32 vlan; __u32 qos; __u32 tx_rate; + __u32 spoofchk; }; +#endif /* VF ports management section * diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 43b32983ba10..0db1f5f6d4a8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -781,6 +781,7 @@ struct netdev_tc_txq { * int (*ndo_set_vf_mac)(struct net_device *dev, int vf, u8* mac); * int (*ndo_set_vf_vlan)(struct net_device *dev, int vf, u16 vlan, u8 qos); * int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate); + * int (*ndo_set_vf_spoofchk)(struct net_device *dev, int vf, bool setting); * int (*ndo_get_vf_config)(struct net_device *dev, * int vf, struct ifla_vf_info *ivf); * int (*ndo_set_vf_port)(struct net_device *dev, int vf, @@ -900,6 +901,8 @@ struct net_device_ops { int queue, u16 vlan, u8 qos); int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate); + int (*ndo_set_vf_spoofchk)(struct net_device *dev, + int vf, bool setting); int (*ndo_get_vf_config)(struct net_device *dev, int vf, struct ifla_vf_info *ivf); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 39f8dd6a2821..9083e82bdae5 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -731,7 +731,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev) size += num_vfs * (nla_total_size(sizeof(struct ifla_vf_mac)) + nla_total_size(sizeof(struct ifla_vf_vlan)) + - nla_total_size(sizeof(struct ifla_vf_tx_rate))); + nla_total_size(sizeof(struct ifla_vf_tx_rate)) + + nla_total_size(sizeof(struct ifla_vf_spoofchk))); return size; } else return 0; @@ -954,13 +955,27 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, struct ifla_vf_mac vf_mac; struct ifla_vf_vlan vf_vlan; struct ifla_vf_tx_rate vf_tx_rate; + struct ifla_vf_spoofchk vf_spoofchk; + + /* + * Not all SR-IOV capable drivers support the + * spoofcheck query. Preset to -1 so the user + * space tool can detect that the driver didn't + * report anything. + */ + ivi.spoofchk = -1; if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) break; - vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; + vf_mac.vf = + vf_vlan.vf = + vf_tx_rate.vf = + vf_spoofchk.vf = ivi.vf; + memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; vf_tx_rate.rate = ivi.tx_rate; + vf_spoofchk.setting = ivi.spoofchk; vf = nla_nest_start(skb, IFLA_VF_INFO); if (!vf) { nla_nest_cancel(skb, vfinfo); @@ -968,7 +983,10 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, } NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); - NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); + NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), + &vf_tx_rate); + NLA_PUT(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk), + &vf_spoofchk); nla_nest_end(skb, vf); } nla_nest_end(skb, vfinfo); @@ -1202,6 +1220,15 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) ivt->rate); break; } + case IFLA_VF_SPOOFCHK: { + struct ifla_vf_spoofchk *ivs; + ivs = nla_data(vf); + err = -EOPNOTSUPP; + if (ops->ndo_set_vf_spoofchk) + err = ops->ndo_set_vf_spoofchk(dev, ivs->vf, + ivs->setting); + break; + } default: err = -EINVAL; break; -- cgit v1.2.3