aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArun Parameswaran <aparames@broadcom.com>2015-05-20 14:35:30 -0700
committerDavid S. Miller <davem@davemloft.net>2015-05-22 16:14:17 -0400
commitf96dee13b8e10f00840124255bed1d8b4c6afd6f (patch)
treedd3502ddd833a82c514fa07615c9fefe1b3fa058
parentbridge: fix parsing of MLDv2 reports (diff)
downloadlinux-dev-f96dee13b8e10f00840124255bed1d8b4c6afd6f.tar.xz
linux-dev-f96dee13b8e10f00840124255bed1d8b4c6afd6f.zip
net: core: 'ethtool' issue with querying phy settings
When trying to configure the settings for PHY1, using commands like 'ethtool -s eth0 phyad 1 speed 100', the 'ethtool' seems to modify other settings apart from the speed of the PHY1, in the above case. The ethtool seems to query the settings for PHY0, and use this as the base to apply the new settings to the PHY1. This is causing the other settings of the PHY 1 to be wrongly configured. The issue is caused by the '_ethtool_get_settings()' API, which gets called because of the 'ETHTOOL_GSET' command, is clearing the 'cmd' pointer (of type 'struct ethtool_cmd') by calling memset. This clears all the parameters (if any) passed for the 'ETHTOOL_GSET' cmd. So the driver's callback is always invoked with 'cmd->phy_address' as '0'. The '_ethtool_get_settings()' is called from other files in the 'net/core'. So the fix is applied to the 'ethtool_get_settings()' which is only called in the context of the 'ethtool'. Signed-off-by: Arun Parameswaran <aparames@broadcom.com> Reviewed-by: Ray Jui <rjui@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/ethtool.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 1d00b8922902..1347e11f5cc9 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -359,7 +359,15 @@ 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 (!dev->ethtool_ops->get_settings)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
+ return -EFAULT;
+
+ cmd.cmd = ETHTOOL_GSET;
+
+ err = dev->ethtool_ops->get_settings(dev, &cmd);
if (err < 0)
return err;