Commit 26bc6d92 authored by Jeff Garzik's avatar Jeff Garzik

[netdrvr e100] fix ethtool/mii interface up/down issues:

* Bug fix: Not able to set autoneg on using ethtool when interface
  down, Not able to change speed/duplex using ethtool/mii when interface
  up, Ethtool shows autoneg on when forced to 100/Full

Contributed by Scott Feldman @ Intel
parent afbac516
...@@ -3263,10 +3263,8 @@ static int ...@@ -3263,10 +3263,8 @@ static int
e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
{ {
struct e100_private *bdp; struct e100_private *bdp;
int current_duplex;
int e100_new_speed_duplex; int e100_new_speed_duplex;
int ethtool_new_speed_duplex; int ethtool_new_speed_duplex;
int speed_duplex_change_required;
struct ethtool_cmd ecmd; struct ethtool_cmd ecmd;
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN)) {
...@@ -3274,48 +3272,33 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) ...@@ -3274,48 +3272,33 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
} }
bdp = dev->priv; bdp = dev->priv;
if (netif_running(dev)) {
return -EBUSY;
}
if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) { if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) {
return -EFAULT; return -EFAULT;
} }
current_duplex =
(bdp->cur_dplx_mode == HALF_DUPLEX) ? DUPLEX_HALF : DUPLEX_FULL;
speed_duplex_change_required = (ecmd.speed != bdp->cur_line_speed)
|| (ecmd.duplex != current_duplex);
if ((ecmd.autoneg == AUTONEG_ENABLE) && speed_duplex_change_required) {
return -EINVAL;
}
if ((ecmd.autoneg == AUTONEG_ENABLE) if ((ecmd.autoneg == AUTONEG_ENABLE)
&& (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) { && (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) {
bdp->params.e100_speed_duplex = E100_AUTONEG; bdp->params.e100_speed_duplex = E100_AUTONEG;
e100_set_speed_duplex(bdp); e100_set_speed_duplex(bdp);
} else { } else {
if (speed_duplex_change_required) {
if (ecmd.speed == SPEED_10) { if (ecmd.speed == SPEED_10) {
if (ecmd.duplex == DUPLEX_HALF) { if (ecmd.duplex == DUPLEX_HALF) {
e100_new_speed_duplex = e100_new_speed_duplex =
E100_SPEED_10_HALF; E100_SPEED_10_HALF;
ethtool_new_speed_duplex = ethtool_new_speed_duplex =
SUPPORTED_10baseT_Half; SUPPORTED_10baseT_Half;
} else { } else {
e100_new_speed_duplex = e100_new_speed_duplex =
E100_SPEED_10_FULL; E100_SPEED_10_FULL;
ethtool_new_speed_duplex = ethtool_new_speed_duplex =
SUPPORTED_10baseT_Full; SUPPORTED_10baseT_Full;
} }
} else { } else {
if (ecmd.duplex == DUPLEX_HALF) { if (ecmd.duplex == DUPLEX_HALF) {
e100_new_speed_duplex = e100_new_speed_duplex =
E100_SPEED_100_HALF; E100_SPEED_100_HALF;
ethtool_new_speed_duplex = ethtool_new_speed_duplex =
SUPPORTED_100baseT_Half; SUPPORTED_100baseT_Half;
} else { } else {
e100_new_speed_duplex = e100_new_speed_duplex =
E100_SPEED_100_FULL; E100_SPEED_100_FULL;
...@@ -3332,7 +3315,6 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) ...@@ -3332,7 +3315,6 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }
}
return 0; return 0;
} }
...@@ -3848,9 +3830,6 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -3848,9 +3830,6 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCSMIIREG: case SIOCSMIIREG:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if (netif_running(dev)) {
return -EBUSY;
}
/* If reg = 0 && change speed/duplex */ /* If reg = 0 && change speed/duplex */
if (data_ptr->reg_num == 0 && if (data_ptr->reg_num == 0 &&
(data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) /* restart cmd */ (data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) /* restart cmd */
...@@ -3870,10 +3849,9 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -3870,10 +3849,9 @@ e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
bdp->params.e100_speed_duplex = E100_SPEED_10_HALF; bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;
e100_set_speed_duplex(bdp); e100_set_speed_duplex(bdp);
} }
else { else
e100_mdi_write(bdp, data_ptr->reg_num, bdp->phy_addr, /* Only allows changing speed/duplex */
data_ptr->val_in); return -EINVAL;
}
break; break;
......
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