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