Commit 263aa157 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] ethtool power manglement hooks

Several ethernet drivers have been broken by the ethtool support because
the ioctl code used to power the interface up and down as needed. Rather
than add this to each driver call Jeff Garzik suggested we add hooks
for before/after ethtool processing.

This patch implements them which makes fixing the PM stuff easier,
as the epic100 patch to follow will show. It also cleans up the
via-velocity driver pm/ethtool logic a great deal. As per Jeff's
request the before handler is allowed to fail the operation.

--

The contribution herein included is a creation of Red Hat Inc. It is hereby
submitted under the license of the existing files and as a derivative work
thereof. I know of no reason for not having the right to submit the
work herein included.

(Bluff your way in legalese ;))
parent 369a5360
...@@ -351,6 +351,8 @@ struct ethtool_ops { ...@@ -351,6 +351,8 @@ struct ethtool_ops {
int (*phys_id)(struct net_device *, u32); int (*phys_id)(struct net_device *, u32);
int (*get_stats_count)(struct net_device *); int (*get_stats_count)(struct net_device *);
void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
int (*begin)(struct net_device *);
void (*complete)(struct net_device *);
}; };
/* CMDs currently supported */ /* CMDs currently supported */
......
...@@ -652,6 +652,7 @@ int dev_ethtool(struct ifreq *ifr) ...@@ -652,6 +652,7 @@ int dev_ethtool(struct ifreq *ifr)
struct net_device *dev = __dev_get_by_name(ifr->ifr_name); struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
void __user *useraddr = ifr->ifr_data; void __user *useraddr = ifr->ifr_data;
u32 ethcmd; u32 ethcmd;
int rc;
/* /*
* XXX: This can be pushed down into the ethtool_* handlers that * XXX: This can be pushed down into the ethtool_* handlers that
...@@ -669,71 +670,110 @@ int dev_ethtool(struct ifreq *ifr) ...@@ -669,71 +670,110 @@ int dev_ethtool(struct ifreq *ifr)
if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd))) if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
return -EFAULT; return -EFAULT;
if(dev->ethtool_ops->begin)
if ((rc = dev->ethtool_ops->begin(dev)) < 0)
return rc;
switch (ethcmd) { switch (ethcmd) {
case ETHTOOL_GSET: case ETHTOOL_GSET:
return ethtool_get_settings(dev, useraddr); rc = ethtool_get_settings(dev, useraddr);
break;
case ETHTOOL_SSET: case ETHTOOL_SSET:
return ethtool_set_settings(dev, useraddr); rc = ethtool_set_settings(dev, useraddr);
break;
case ETHTOOL_GDRVINFO: case ETHTOOL_GDRVINFO:
return ethtool_get_drvinfo(dev, useraddr); rc = ethtool_get_drvinfo(dev, useraddr);
break;
case ETHTOOL_GREGS: case ETHTOOL_GREGS:
return ethtool_get_regs(dev, useraddr); rc = ethtool_get_regs(dev, useraddr);
break;
case ETHTOOL_GWOL: case ETHTOOL_GWOL:
return ethtool_get_wol(dev, useraddr); rc = ethtool_get_wol(dev, useraddr);
break;
case ETHTOOL_SWOL: case ETHTOOL_SWOL:
return ethtool_set_wol(dev, useraddr); rc = ethtool_set_wol(dev, useraddr);
break;
case ETHTOOL_GMSGLVL: case ETHTOOL_GMSGLVL:
return ethtool_get_msglevel(dev, useraddr); rc = ethtool_get_msglevel(dev, useraddr);
break;
case ETHTOOL_SMSGLVL: case ETHTOOL_SMSGLVL:
return ethtool_set_msglevel(dev, useraddr); rc = ethtool_set_msglevel(dev, useraddr);
break;
case ETHTOOL_NWAY_RST: case ETHTOOL_NWAY_RST:
return ethtool_nway_reset(dev); rc = ethtool_nway_reset(dev);
break;
case ETHTOOL_GLINK: case ETHTOOL_GLINK:
return ethtool_get_link(dev, useraddr); rc = ethtool_get_link(dev, useraddr);
break;
case ETHTOOL_GEEPROM: case ETHTOOL_GEEPROM:
return ethtool_get_eeprom(dev, useraddr); rc = ethtool_get_eeprom(dev, useraddr);
break;
case ETHTOOL_SEEPROM: case ETHTOOL_SEEPROM:
return ethtool_set_eeprom(dev, useraddr); rc = ethtool_set_eeprom(dev, useraddr);
break;
case ETHTOOL_GCOALESCE: case ETHTOOL_GCOALESCE:
return ethtool_get_coalesce(dev, useraddr); rc = ethtool_get_coalesce(dev, useraddr);
break;
case ETHTOOL_SCOALESCE: case ETHTOOL_SCOALESCE:
return ethtool_set_coalesce(dev, useraddr); rc = ethtool_set_coalesce(dev, useraddr);
break;
case ETHTOOL_GRINGPARAM: case ETHTOOL_GRINGPARAM:
return ethtool_get_ringparam(dev, useraddr); rc = ethtool_get_ringparam(dev, useraddr);
break;
case ETHTOOL_SRINGPARAM: case ETHTOOL_SRINGPARAM:
return ethtool_set_ringparam(dev, useraddr); rc = ethtool_set_ringparam(dev, useraddr);
break;
case ETHTOOL_GPAUSEPARAM: case ETHTOOL_GPAUSEPARAM:
return ethtool_get_pauseparam(dev, useraddr); rc = ethtool_get_pauseparam(dev, useraddr);
break;
case ETHTOOL_SPAUSEPARAM: case ETHTOOL_SPAUSEPARAM:
return ethtool_set_pauseparam(dev, useraddr); rc = ethtool_set_pauseparam(dev, useraddr);
break;
case ETHTOOL_GRXCSUM: case ETHTOOL_GRXCSUM:
return ethtool_get_rx_csum(dev, useraddr); rc = ethtool_get_rx_csum(dev, useraddr);
break;
case ETHTOOL_SRXCSUM: case ETHTOOL_SRXCSUM:
return ethtool_set_rx_csum(dev, useraddr); rc = ethtool_set_rx_csum(dev, useraddr);
break;
case ETHTOOL_GTXCSUM: case ETHTOOL_GTXCSUM:
return ethtool_get_tx_csum(dev, useraddr); rc = ethtool_get_tx_csum(dev, useraddr);
break;
case ETHTOOL_STXCSUM: case ETHTOOL_STXCSUM:
return ethtool_set_tx_csum(dev, useraddr); rc = ethtool_set_tx_csum(dev, useraddr);
break;
case ETHTOOL_GSG: case ETHTOOL_GSG:
return ethtool_get_sg(dev, useraddr); rc = ethtool_get_sg(dev, useraddr);
break;
case ETHTOOL_SSG: case ETHTOOL_SSG:
return ethtool_set_sg(dev, useraddr); rc = ethtool_set_sg(dev, useraddr);
break;
case ETHTOOL_GTSO: case ETHTOOL_GTSO:
return ethtool_get_tso(dev, useraddr); rc = ethtool_get_tso(dev, useraddr);
break;
case ETHTOOL_STSO: case ETHTOOL_STSO:
return ethtool_set_tso(dev, useraddr); rc = ethtool_set_tso(dev, useraddr);
break;
case ETHTOOL_TEST: case ETHTOOL_TEST:
return ethtool_self_test(dev, useraddr); rc = ethtool_self_test(dev, useraddr);
break;
case ETHTOOL_GSTRINGS: case ETHTOOL_GSTRINGS:
return ethtool_get_strings(dev, useraddr); rc = ethtool_get_strings(dev, useraddr);
break;
case ETHTOOL_PHYS_ID: case ETHTOOL_PHYS_ID:
return ethtool_phys_id(dev, useraddr); rc = ethtool_phys_id(dev, useraddr);
break;
case ETHTOOL_GSTATS: case ETHTOOL_GSTATS:
return ethtool_get_stats(dev, useraddr); rc = ethtool_get_stats(dev, useraddr);
break;
default: default:
return -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
if(dev->ethtool_ops->complete)
dev->ethtool_ops->complete(dev);
return rc;
ioctl: ioctl:
if (dev->do_ioctl) if (dev->do_ioctl)
return dev->do_ioctl(dev, ifr, SIOCETHTOOL); return dev->do_ioctl(dev, ifr, SIOCETHTOOL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment