diff options
Diffstat (limited to 'drivers/net/fec.c')
| -rw-r--r-- | drivers/net/fec.c | 110 | 
1 files changed, 56 insertions, 54 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index edfff92a6d8..768b840aeb6 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  |