summaryrefslogtreecommitdiffstats
path: root/drivers/net/fec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fec.c')
-rw-r--r--drivers/net/fec.c110
1 files changed, 56 insertions, 54 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index edfff92..768b840 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -118,6 +118,8 @@ static unsigned char fec_mac_default[] = {
#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
+#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
+
/* The FEC stores dest/src/type, data, and checksum for receive packets.
*/
#define PKT_MAXBUF_SIZE 1518
@@ -187,6 +189,7 @@ struct fec_enet_private {
int index;
int link;
int full_duplex;
+ struct completion mdio_done;
};
static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
@@ -205,12 +208,12 @@ static void fec_stop(struct net_device *dev);
#define FEC_MMFR_TA (2 << 16)
#define FEC_MMFR_DATA(v) (v & 0xffff)
-#define FEC_MII_TIMEOUT 10000
+#define FEC_MII_TIMEOUT 1000 /* us */
/* Transmitter timeout */
#define TX_TIMEOUT (2 * HZ)
-static int
+static netdev_tx_t
fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
@@ -334,6 +337,11 @@ fec_enet_interrupt(int irq, void * dev_id)
ret = IRQ_HANDLED;
fec_enet_tx(dev);
}
+
+ if (int_events & FEC_ENET_MII) {
+ ret = IRQ_HANDLED;
+ complete(&fep->mdio_done);
+ }
} while (int_events);
return ret;
@@ -608,18 +616,13 @@ spin_unlock:
phy_print_status(phy_dev);
}
-/*
- * NOTE: a MII transaction is during around 25 us, so polling it...
- */
static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
struct fec_enet_private *fep = bus->priv;
- int timeout = FEC_MII_TIMEOUT;
+ unsigned long time_left;
fep->mii_timeout = 0;
-
- /* clear MII end of transfer bit*/
- writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
+ init_completion(&fep->mdio_done);
/* start a read op */
writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
@@ -627,13 +630,12 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */
- while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) {
- cpu_relax();
- if (timeout-- < 0) {
- fep->mii_timeout = 1;
- printk(KERN_ERR "FEC: MDIO read timeout\n");
- return -ETIMEDOUT;
- }
+ time_left = wait_for_completion_timeout(&fep->mdio_done,
+ usecs_to_jiffies(FEC_MII_TIMEOUT));
+ if (time_left == 0) {
+ fep->mii_timeout = 1;
+ printk(KERN_ERR "FEC: MDIO read timeout\n");
+ return -ETIMEDOUT;
}
/* return value */
@@ -644,12 +646,10 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
u16 value)
{
struct fec_enet_private *fep = bus->priv;
- int timeout = FEC_MII_TIMEOUT;
+ unsigned long time_left;
fep->mii_timeout = 0;
-
- /* clear MII end of transfer bit*/
- writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
+ init_completion(&fep->mdio_done);
/* start a read op */
writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
@@ -658,13 +658,12 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
fep->hwp + FEC_MII_DATA);
/* wait for end of transfer */
- while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) {
- cpu_relax();
- if (timeout-- < 0) {
- fep->mii_timeout = 1;
- printk(KERN_ERR "FEC: MDIO write timeout\n");
- return -ETIMEDOUT;
- }
+ time_left = wait_for_completion_timeout(&fep->mdio_done,
+ usecs_to_jiffies(FEC_MII_TIMEOUT));
+ if (time_left == 0) {
+ fep->mii_timeout = 1;
+ printk(KERN_ERR "FEC: MDIO write timeout\n");
+ return -ETIMEDOUT;
}
return 0;
@@ -679,30 +678,24 @@ static int fec_enet_mii_probe(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
struct phy_device *phy_dev = NULL;
- int phy_addr;
+ int ret;
fep->phy_dev = NULL;
/* find the first phy */
- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- if (fep->mii_bus->phy_map[phy_addr]) {
- phy_dev = fep->mii_bus->phy_map[phy_addr];
- break;
- }
- }
-
+ phy_dev = phy_find_first(fep->mii_bus);
if (!phy_dev) {
printk(KERN_ERR "%s: no PHY found\n", dev->name);
return -ENODEV;
}
/* attach the mac to the phy */
- phy_dev = phy_connect(dev, dev_name(&phy_dev->dev),
+ ret = phy_connect_direct(dev, phy_dev,
&fec_enet_adjust_link, 0,
PHY_INTERFACE_MODE_MII);
- if (IS_ERR(phy_dev)) {
+ if (ret) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
- return PTR_ERR(phy_dev);
+ return ret;
}
/* mask with MAC supported features */
@@ -834,7 +827,7 @@ static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!phydev)
return -ENODEV;
- return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+ return phy_mii_ioctl(phydev, rq, cmd);
}
static void fec_enet_free_buffers(struct net_device *dev)
@@ -1222,7 +1215,7 @@ fec_restart(struct net_device *dev, int duplex)
writel(0, fep->hwp + FEC_R_DES_ACTIVE);
/* Enable interrupts we wish to service */
- writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->hwp + FEC_IMASK);
+ writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
}
static void
@@ -1241,11 +1234,8 @@ fec_stop(struct net_device *dev)
/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
-
- /* Clear outstanding MII command interrupts. */
- writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
-
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+ writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
}
static int __devinit
@@ -1365,10 +1355,11 @@ fec_drv_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
static int
-fec_suspend(struct platform_device *dev, pm_message_t state)
+fec_suspend(struct device *dev)
{
- struct net_device *ndev = platform_get_drvdata(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep;
if (ndev) {
@@ -1381,9 +1372,9 @@ fec_suspend(struct platform_device *dev, pm_message_t state)
}
static int
-fec_resume(struct platform_device *dev)
+fec_resume(struct device *dev)
{
- struct net_device *ndev = platform_get_drvdata(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep;
if (ndev) {
@@ -1395,15 +1386,26 @@ fec_resume(struct platform_device *dev)
return 0;
}
+static const struct dev_pm_ops fec_pm_ops = {
+ .suspend = fec_suspend,
+ .resume = fec_resume,
+ .freeze = fec_suspend,
+ .thaw = fec_resume,
+ .poweroff = fec_suspend,
+ .restore = fec_resume,
+};
+#endif
+
static struct platform_driver fec_driver = {
.driver = {
- .name = "fec",
- .owner = THIS_MODULE,
+ .name = "fec",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &fec_pm_ops,
+#endif
},
- .probe = fec_probe,
- .remove = __devexit_p(fec_drv_remove),
- .suspend = fec_suspend,
- .resume = fec_resume,
+ .probe = fec_probe,
+ .remove = __devexit_p(fec_drv_remove),
};
static int __init
OpenPOWER on IntegriCloud