diff options
Diffstat (limited to 'net/ethtool/ioctl.c')
| -rw-r--r-- | net/ethtool/ioctl.c | 15 | 
1 files changed, 13 insertions, 2 deletions
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 6bb778e10461..4a51e0ec295c 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1436,15 +1436,26 @@ static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)  static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)  { -	struct ethtool_wolinfo wol; +	struct ethtool_wolinfo wol, cur_wol;  	int ret; -	if (!dev->ethtool_ops->set_wol) +	if (!dev->ethtool_ops->get_wol || !dev->ethtool_ops->set_wol)  		return -EOPNOTSUPP; +	memset(&cur_wol, 0, sizeof(struct ethtool_wolinfo)); +	cur_wol.cmd = ETHTOOL_GWOL; +	dev->ethtool_ops->get_wol(dev, &cur_wol); +  	if (copy_from_user(&wol, useraddr, sizeof(wol)))  		return -EFAULT; +	if (wol.wolopts & ~cur_wol.supported) +		return -EINVAL; + +	if (wol.wolopts == cur_wol.wolopts && +	    !memcmp(wol.sopass, cur_wol.sopass, sizeof(wol.sopass))) +		return 0; +  	ret = dev->ethtool_ops->set_wol(dev, &wol);  	if (ret)  		return ret;  |