[NET]: ethtool ops are the only way

During the transition to the ethtool_ops way of doing things, we supported
calling the device's ->do_ioctl method to allow unconverted drivers to
continue working.  Those days are long behind us, all in-tree drivers
use the ethtool_ops way, and so we no longer need to support this.

The bonding driver is the biggest beneficiary of this; it no longer
needs to call ioctl() as a fallback if ethtool_ops aren't supported.

Also put a proper copyright statement on ethtool.c.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Matthew Wilcox 2007-07-31 14:00:02 -07:00 коммит произвёл David S. Miller
Родитель f1543f8b83
Коммит 61a44b9c4b
4 изменённых файлов: 33 добавлений и 86 удалений

Просмотреть файл

@ -613,38 +613,20 @@ down:
static int bond_update_speed_duplex(struct slave *slave) static int bond_update_speed_duplex(struct slave *slave)
{ {
struct net_device *slave_dev = slave->dev; struct net_device *slave_dev = slave->dev;
static int (* ioctl)(struct net_device *, struct ifreq *, int);
struct ifreq ifr;
struct ethtool_cmd etool; struct ethtool_cmd etool;
int res;
/* Fake speed and duplex */ /* Fake speed and duplex */
slave->speed = SPEED_100; slave->speed = SPEED_100;
slave->duplex = DUPLEX_FULL; slave->duplex = DUPLEX_FULL;
if (slave_dev->ethtool_ops) { if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings)
int res; return -1;
if (!slave_dev->ethtool_ops->get_settings) { res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
return -1; if (res < 0)
}
res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
if (res < 0) {
return -1;
}
goto verify;
}
ioctl = slave_dev->do_ioctl;
strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
etool.cmd = ETHTOOL_GSET;
ifr.ifr_data = (char*)&etool;
if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) {
return -1; return -1;
}
verify:
switch (etool.speed) { switch (etool.speed) {
case SPEED_10: case SPEED_10:
case SPEED_100: case SPEED_100:
@ -690,7 +672,6 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de
static int (* ioctl)(struct net_device *, struct ifreq *, int); static int (* ioctl)(struct net_device *, struct ifreq *, int);
struct ifreq ifr; struct ifreq ifr;
struct mii_ioctl_data *mii; struct mii_ioctl_data *mii;
struct ethtool_value etool;
if (bond->params.use_carrier) { if (bond->params.use_carrier) {
return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
@ -721,9 +702,10 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de
} }
} }
/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */ /*
/* for a period of time so we attempt to get link status */ * Some drivers cache ETHTOOL_GLINK for a period of time so we only
/* from it last if the above MII ioctls fail... */ * attempt to get link status from it if the above MII ioctls fail.
*/
if (slave_dev->ethtool_ops) { if (slave_dev->ethtool_ops) {
if (slave_dev->ethtool_ops->get_link) { if (slave_dev->ethtool_ops->get_link) {
u32 link; u32 link;
@ -734,23 +716,9 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de
} }
} }
if (ioctl) {
strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
etool.cmd = ETHTOOL_GLINK;
ifr.ifr_data = (char*)&etool;
if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) {
if (etool.data == 1) {
return BMSR_LSTATUS;
} else {
dprintk("SIOCETHTOOL shows link down\n");
return 0;
}
}
}
/* /*
* If reporting, report that either there's no dev->do_ioctl, * If reporting, report that either there's no dev->do_ioctl,
* or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we * or both SIOCGMIIREG and get_link failed (meaning that we
* cannot report link status). If not reporting, pretend * cannot report link status). If not reporting, pretend
* we're ok. * we're ok.
*/ */

Просмотреть файл

@ -668,9 +668,6 @@ int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (real_dev->do_ioctl && netif_device_present(real_dev)) if (real_dev->do_ioctl && netif_device_present(real_dev))
err = real_dev->do_ioctl(real_dev, &ifrr, cmd); err = real_dev->do_ioctl(real_dev, &ifrr, cmd);
break; break;
case SIOCETHTOOL:
err = dev_ethtool(&ifrr);
} }
if (!err) if (!err)

Просмотреть файл

@ -29,35 +29,24 @@
* Determine initial path cost based on speed. * Determine initial path cost based on speed.
* using recommendations from 802.1d standard * using recommendations from 802.1d standard
* *
* Need to simulate user ioctl because not all device's that support * Since driver might sleep need to not be holding any locks.
* ethtool, use ethtool_ops. Also, since driver might sleep need to
* not be holding any locks.
*/ */
static int port_cost(struct net_device *dev) static int port_cost(struct net_device *dev)
{ {
struct ethtool_cmd ecmd = { ETHTOOL_GSET }; if (dev->ethtool_ops->get_settings) {
struct ifreq ifr; struct ethtool_cmd ecmd = { ETHTOOL_GSET };
mm_segment_t old_fs; int err = dev->ethtool_ops->get_settings(dev, &ecmd);
int err; if (!err) {
switch(ecmd.speed) {
strncpy(ifr.ifr_name, dev->name, IFNAMSIZ); case SPEED_100:
ifr.ifr_data = (void __user *) &ecmd; return 19;
case SPEED_1000:
old_fs = get_fs(); return 4;
set_fs(KERNEL_DS); case SPEED_10000:
err = dev_ethtool(&ifr); return 2;
set_fs(old_fs); case SPEED_10:
return 100;
if (!err) { }
switch(ecmd.speed) {
case SPEED_100:
return 19;
case SPEED_1000:
return 4;
case SPEED_10000:
return 2;
case SPEED_10:
return 100;
} }
} }

Просмотреть файл

@ -3,10 +3,12 @@
* Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx> * Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx>
* *
* This file is where we call all the ethtool_ops commands to get * This file is where we call all the ethtool_ops commands to get
* the information ethtool needs. We fall back to calling do_ioctl() * the information ethtool needs.
* for drivers which haven't been converted to ethtool_ops yet.
* *
* It's GPL, stupid. * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -821,7 +823,7 @@ int dev_ethtool(struct ifreq *ifr)
return -ENODEV; return -ENODEV;
if (!dev->ethtool_ops) if (!dev->ethtool_ops)
goto ioctl; return -EOPNOTSUPP;
if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd))) if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
return -EFAULT; return -EFAULT;
@ -960,7 +962,7 @@ int dev_ethtool(struct ifreq *ifr)
rc = ethtool_set_gso(dev, useraddr); rc = ethtool_set_gso(dev, useraddr);
break; break;
default: default:
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
if (dev->ethtool_ops->complete) if (dev->ethtool_ops->complete)
@ -970,15 +972,6 @@ int dev_ethtool(struct ifreq *ifr)
netdev_features_change(dev); netdev_features_change(dev);
return rc; return rc;
ioctl:
/* Keep existing behaviour for the moment. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (dev->do_ioctl)
return dev->do_ioctl(dev, ifr, SIOCETHTOOL);
return -EOPNOTSUPP;
} }
EXPORT_SYMBOL(dev_ethtool); EXPORT_SYMBOL(dev_ethtool);