Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6
This commit is contained in:
commit
4c844d97d2
7 changed files with 223 additions and 149 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue