Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6

This commit is contained in:
David S. Miller 2011-04-06 12:27:34 -07:00
commit 4c844d97d2
7 changed files with 223 additions and 149 deletions

View file

@ -21,6 +21,8 @@
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/sched.h>
/*
* Some useful ethtool_ops methods that're device independent.
@ -1618,14 +1620,63 @@ out:
static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
{
struct ethtool_value id;
static bool busy;
int rc;
if (!dev->ethtool_ops->phys_id)
if (!dev->ethtool_ops->set_phys_id && !dev->ethtool_ops->phys_id)
return -EOPNOTSUPP;
if (busy)
return -EBUSY;
if (copy_from_user(&id, useraddr, sizeof(id)))
return -EFAULT;
return dev->ethtool_ops->phys_id(dev, id.data);
if (!dev->ethtool_ops->set_phys_id)
/* Do it the old way */
return dev->ethtool_ops->phys_id(dev, id.data);
rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE);
if (rc && rc != -EINVAL)
return rc;
/* Drop the RTNL lock while waiting, but prevent reentry or
* removal of the device.
*/
busy = true;
dev_hold(dev);
rtnl_unlock();
if (rc == 0) {
/* Driver will handle this itself */
schedule_timeout_interruptible(
id.data ? id.data : MAX_SCHEDULE_TIMEOUT);
} else {
/* Driver expects to be called periodically */
do {
rtnl_lock();
rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON);
rtnl_unlock();
if (rc)
break;
schedule_timeout_interruptible(HZ / 2);
rtnl_lock();
rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_OFF);
rtnl_unlock();
if (rc)
break;
schedule_timeout_interruptible(HZ / 2);
} while (!signal_pending(current) &&
(id.data == 0 || --id.data != 0));
}
rtnl_lock();
dev_put(dev);
busy = false;
(void)dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_INACTIVE);
return rc;
}
static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)