Commit 52ef1eac authored by Jeff Garzik's avatar Jeff Garzik

Use new MII lib helper generic_mii_ioctl in several net drivers:

8139too, epic100, fealnx, sundance and via-rhine.

In the process, several of these net drivers gained MII ioctl
locking fixes simply by virtue of being brought in line with
standardized code.
parent 949682fe
......@@ -578,7 +578,6 @@ struct rtl8139_private {
signed char phys[4]; /* MII device addresses. */
char twistie, twist_row, twist_col; /* Twister tune state. */
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int medialock:1; /* Don't sense media type. */
spinlock_t lock;
chip_t chipset;
pid_t thr_pid;
......@@ -986,6 +985,8 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
tp->mii.dev = dev;
tp->mii.mdio_read = mdio_read;
tp->mii.mdio_write = mdio_write;
tp->mii.phy_id_mask = 0x3f;
tp->mii.reg_num_mask = 0x1f;
/* dev is fully set up and ready to use now */
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
......@@ -1041,7 +1042,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
tp->default_port = option & 0xFF;
if (tp->default_port)
tp->medialock = 1;
tp->mii.force_media = 1;
}
if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0)
tp->mii.full_duplex = full_duplex[board_idx];
......@@ -2439,58 +2440,25 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
}
static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct rtl8139_private *tp = dev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
int rc = 0;
int phy = tp->phys[0] & 0x3f;
struct rtl8139_private *np = dev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
int rc;
if (!netif_running(dev))
return -EINVAL;
if (cmd != SIOCETHTOOL) {
/* With SIOCETHTOOL, this would corrupt the pointer. */
data->phy_id &= 0x3f;
data->reg_num &= 0x1f;
}
switch (cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCGMIIPHY: /* Get the address of the PHY in use. */
data->phy_id = phy;
/* Fall Through */
case SIOCGMIIREG: /* Read the specified MII register. */
data->val_out = mdio_read (dev, data->phy_id, data->reg_num);
break;
case SIOCSMIIREG: /* Write the specified MII register */
if (!capable (CAP_NET_ADMIN)) {
rc = -EPERM;
break;
}
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
if (data->phy_id == phy) {
u16 value = data->val_in;
switch (data->reg_num) {
case 0:
/* Check for autonegotiation on or reset. */
tp->medialock = (value & 0x9000) ? 0 : 1;
if (tp->medialock)
tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;
break;
case 4: tp->mii.advertising = value; break;
}
}
mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
break;
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii, data, cmd);
spin_unlock_irq(&np->lock);
default:
rc = -EOPNOTSUPP;
break;
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
return rc;
......
......@@ -429,6 +429,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
ep->mii.dev = dev;
ep->mii.mdio_read = mdio_read;
ep->mii.mdio_write = mdio_write;
ep->mii.phy_id_mask = 0x1f;
ep->mii.reg_num_mask = 0x1f;
ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space)
......@@ -1426,63 +1428,36 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct epic_private *ep = dev->priv;
struct epic_private *np = dev->priv;
long ioaddr = dev->base_addr;
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
int rc;
switch(cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
/* power-up, if interface is down */
if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = ep->phys[0] & 0x1f;
/* Fall Through */
/* ethtool commands */
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCGMIIREG: /* Read MII PHY register. */
if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
#if 0 /* Just leave on if the ioctl() is ever used. */
if (! netif_running(dev)) {
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
}
#endif
return 0;
/* all other ioctls (the SIOC[GS]MIIxxx ioctls) */
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fixup rc */
rc = 0;
}
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
if (data->phy_id == ep->phys[0]) {
u16 value = data->val_in;
switch (data->reg_num) {
case 0:
/* Check for autonegotiation on or reset. */
ep->mii.force_media = (value & 0x9000) ? 0 : 1;
if (ep->mii.force_media)
ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;
break;
case 4: ep->mii.advertising = value; break;
}
/* Perhaps check_duplex(dev), depending on chip semantics. */
}
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
#if 0 /* Leave on if the ioctl() is used. */
if (! netif_running(dev)) {
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
}
#endif
return 0;
default:
return -EOPNOTSUPP;
/* power-down, if interface is down */
if (! netif_running(dev)) {
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
}
return rc;
}
......
......@@ -559,6 +559,8 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
np->mii.dev = dev;
np->mii.mdio_read = mdio_read;
np->mii.mdio_write = mdio_write;
np->mii.phy_id_mask = 0x1f;
np->mii.reg_num_mask = 0x1f;
ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
if (!ring_space) {
......@@ -1833,28 +1835,25 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct netdev_private *np = dev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
int rc;
switch (cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
/* Fall Through */
if (!netif_running(dev))
return -EINVAL;
case SIOCGMIIREG: /* Read MII PHY register. */
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
return 0;
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
return 0;
default:
return -EOPNOTSUPP;
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
return rc;
}
......
......@@ -573,6 +573,8 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
np->mii_if.dev = dev;
np->mii_if.mdio_read = mdio_read;
np->mii_if.mdio_write = mdio_write;
np->mii_if.phy_id_mask = 0x1f;
np->mii_if.reg_num_mask = 0x1f;
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
......@@ -1550,27 +1552,25 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
switch(cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
/* Fall Through */
case SIOCGMIIREG: /* Read MII PHY register. */
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
return 0;
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
return 0;
default:
return -EOPNOTSUPP;
struct netdev_private *np = dev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
int rc;
if (!netif_running(dev))
return -EINVAL;
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii_if, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
return rc;
}
static int netdev_close(struct net_device *dev)
......
......@@ -516,7 +516,7 @@ static void via_rhine_rx(struct net_device *dev);
static void via_rhine_error(struct net_device *dev, int intr_status);
static void via_rhine_set_rx_mode(struct net_device *dev);
static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int via_rhine_close(struct net_device *dev);
static inline void clear_tally_counters(long ioaddr);
......@@ -715,6 +715,8 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
np->mii_if.dev = dev;
np->mii_if.mdio_read = mdio_read;
np->mii_if.mdio_write = mdio_write;
np->mii_if.phy_id_mask = 0x1f;
np->mii_if.reg_num_mask = 0x1f;
if (dev->mem_start)
option = dev->mem_start;
......@@ -740,7 +742,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
dev->stop = via_rhine_close;
dev->get_stats = via_rhine_get_stats;
dev->set_multicast_list = via_rhine_set_rx_mode;
dev->do_ioctl = via_rhine_ioctl;
dev->do_ioctl = netdev_ioctl;
dev->tx_timeout = via_rhine_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
if (np->drv_flags & ReqTxAlign)
......@@ -1586,7 +1588,7 @@ static void via_rhine_set_rx_mode(struct net_device *dev)
writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
}
static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
{
struct netdev_private *np = dev->priv;
u32 ethcmd;
......@@ -1669,41 +1671,28 @@ static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
return -EOPNOTSUPP;
}
static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct netdev_private *np = dev->priv;
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
unsigned long flags;
int retval;
if (cmd == SIOCETHTOOL)
return via_rhine_ethtool_ioctl(dev, (void *) rq->ifr_data);
struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
int rc;
spin_lock_irqsave(&np->lock, flags);
retval = 0;
switch(cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = np->phys[0] & 0x1f;
/* Fall Through */
if (!netif_running(dev))
return -EINVAL;
case SIOCGMIIREG: /* Read MII PHY register. */
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
break;
if (cmd == SIOCETHTOOL)
rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN)) {
retval = -EPERM;
break;
}
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
break;
default:
retval = -EOPNOTSUPP;
else {
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(dev, &np->mii_if, data, cmd);
spin_unlock_irq(&np->lock);
if (rc == 1) /* don't care about duplex change, fix up rc */
rc = 0;
}
spin_unlock_irqrestore(&np->lock, flags);
return retval;
return rc;
}
static int via_rhine_close(struct net_device *dev)
......
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