[patch net-next-2.6 v2] net: consolidate and fix ethtool_ops->get_settings calling
From: Jiri Pirko <hidden>
Date: 2011-09-02 12:27:14
Also in:
bridge, linux-mips, linux-scsi
Subsystem:
bonding driver, broadcom bnx2fc 10 gigabit fcoe driver, ethernet bridge, fcoe subsystem (libfc, libfcoe, fcoe), mips, networking drivers, networking [ethtool], networking [general], packet sockets, scsi subsystem, the rest · Maintainers:
Jay Vosburgh, Saurav Kashyap, Javed Hasan, Nikolay Aleksandrov, Ido Schimmel, Hannes Reinecke, Thomas Bogendoerfer, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Willem de Bruijn, "James E.J. Bottomley", "Martin K. Petersen", Linus Torvalds
This patch does several things: - introduces __ethtool_get_settings which is called from ethtool code and from dev_ethtool_get_settings() as well. - dev_ethtool_get_settings() becomes rtnl wrapper for __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 - 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. - prb_calc_retire_blk_tmo() in af_packet.c was not calling get_settings with rntl_lock. So use dev_ethtool_get_settings here. - use __ethtool_get_settings() in bonding code Signed-off-by: Jiri Pirko <redacted> v1->v2: add missing export_symbol --- 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 ++ net/8021q/vlan_dev.c | 3 +- net/bridge/br_if.c | 2 +- net/core/dev.c | 17 +++++--------- net/core/ethtool.c | 18 ++++++++++---- net/core/net-sysfs.c | 4 +- net/packet/af_packet.c | 41 +++++++++++++++----------------- 12 files changed, 60 insertions(+), 54 deletions(-)
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c
index e9f95dc..ba3cec3 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 8cb75a6..1dcb07c 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 836e13f..b100c90 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 2c780a7..820a184 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 3416ab6..83aa3ac 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 3829712..8571f18 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/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index eba705b..c8cf939 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 b365bba..043a5eb 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 11b0fc7..abdc0e3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c@@ -4570,22 +4570,17 @@ void dev_set_rx_mode(struct net_device *dev) * @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. + * This is wrapper taking rtnl lock for __ethtool_get_settings() */ int dev_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) - return -EOPNOTSUPP; + int ret; - memset(cmd, 0, sizeof(struct ethtool_cmd)); - cmd->cmd = ETHTOOL_GSET; - return dev->ethtool_ops->get_settings(dev, cmd); + rtnl_lock(); + ret = __ethtool_get_settings(dev, cmd); + rtnl_unlock(); + return ret; } EXPORT_SYMBOL(dev_ethtool_get_settings);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 6cdba5f..307297c 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c@@ -569,15 +569,23 @@ int __ethtool_set_flags(struct net_device *dev, u32 data) return 0; } +int __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(__ethtool_get_settings); + static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) { - struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; int err; + struct ethtool_cmd cmd; - if (!dev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - - err = dev->ethtool_ops->get_settings(dev, &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 90fdb46..48e6279 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c@@ -172,7 +172,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();
@@ -190,7 +190,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 2ea3d63..1bcc794 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c@@ -530,33 +530,30 @@ 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; dev = dev_get_by_index(sock_net(&po->sk), po->ifindex); if (unlikely(dev == NULL)) 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; - } + if (!dev_ethtool_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; } }
--
1.7.6