aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fec.c
diff options
context:
space:
mode:
authorBaruch Siach <baruch@tkos.co.il>2010-07-11 17:12:51 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-12 23:21:48 -0400
commit97b72e4320a9aaa4a7f1592ee7d2da7e2c9bd349 (patch)
tree9712577d22be873356e0b7e07d651128ee53035a /drivers/net/fec.c
parent15fd0cd9a2ad24a78fbee369dec8ca660979d57e (diff)
fec: use interrupt for MDIO completion indication
With the move to phylib (commit e6b043d) I was seeing sporadic "MDIO write timeout" messages. Measure of the actual time spent showed latency times of more than 1600us. This patch uses the MII event indication of the FEC hardware to detect completion of MDIO transactions. Signed-off-by: Baruch Siach <baruch@tkos.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/fec.c')
-rw-r--r--drivers/net/fec.c55
1 files changed, 25 insertions, 30 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index b4afd7a6ee29..937f1b4a3483 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -187,6 +187,7 @@ struct fec_enet_private {
187 int index; 187 int index;
188 int link; 188 int link;
189 int full_duplex; 189 int full_duplex;
190 struct completion mdio_done;
190}; 191};
191 192
192static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); 193static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
@@ -205,7 +206,7 @@ static void fec_stop(struct net_device *dev);
205#define FEC_MMFR_TA (2 << 16) 206#define FEC_MMFR_TA (2 << 16)
206#define FEC_MMFR_DATA(v) (v & 0xffff) 207#define FEC_MMFR_DATA(v) (v & 0xffff)
207 208
208#define FEC_MII_TIMEOUT 10000 209#define FEC_MII_TIMEOUT 1000 /* us */
209 210
210/* Transmitter timeout */ 211/* Transmitter timeout */
211#define TX_TIMEOUT (2 * HZ) 212#define TX_TIMEOUT (2 * HZ)
@@ -334,6 +335,11 @@ fec_enet_interrupt(int irq, void * dev_id)
334 ret = IRQ_HANDLED; 335 ret = IRQ_HANDLED;
335 fec_enet_tx(dev); 336 fec_enet_tx(dev);
336 } 337 }
338
339 if (int_events & FEC_ENET_MII) {
340 ret = IRQ_HANDLED;
341 complete(&fep->mdio_done);
342 }
337 } while (int_events); 343 } while (int_events);
338 344
339 return ret; 345 return ret;
@@ -608,18 +614,13 @@ spin_unlock:
608 phy_print_status(phy_dev); 614 phy_print_status(phy_dev);
609} 615}
610 616
611/*
612 * NOTE: a MII transaction is during around 25 us, so polling it...
613 */
614static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) 617static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
615{ 618{
616 struct fec_enet_private *fep = bus->priv; 619 struct fec_enet_private *fep = bus->priv;
617 int timeout = FEC_MII_TIMEOUT; 620 unsigned long time_left;
618 621
619 fep->mii_timeout = 0; 622 fep->mii_timeout = 0;
620 623 init_completion(&fep->mdio_done);
621 /* clear MII end of transfer bit*/
622 writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
623 624
624 /* start a read op */ 625 /* start a read op */
625 writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | 626 writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
@@ -627,13 +628,12 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
627 FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); 628 FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
628 629
629 /* wait for end of transfer */ 630 /* wait for end of transfer */
630 while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { 631 time_left = wait_for_completion_timeout(&fep->mdio_done,
631 cpu_relax(); 632 usecs_to_jiffies(FEC_MII_TIMEOUT));
632 if (timeout-- < 0) { 633 if (time_left == 0) {
633 fep->mii_timeout = 1; 634 fep->mii_timeout = 1;
634 printk(KERN_ERR "FEC: MDIO read timeout\n"); 635 printk(KERN_ERR "FEC: MDIO read timeout\n");
635 return -ETIMEDOUT; 636 return -ETIMEDOUT;
636 }
637 } 637 }
638 638
639 /* return value */ 639 /* return value */
@@ -644,12 +644,10 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
644 u16 value) 644 u16 value)
645{ 645{
646 struct fec_enet_private *fep = bus->priv; 646 struct fec_enet_private *fep = bus->priv;
647 int timeout = FEC_MII_TIMEOUT; 647 unsigned long time_left;
648 648
649 fep->mii_timeout = 0; 649 fep->mii_timeout = 0;
650 650 init_completion(&fep->mdio_done);
651 /* clear MII end of transfer bit*/
652 writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
653 651
654 /* start a read op */ 652 /* start a read op */
655 writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | 653 writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
@@ -658,13 +656,12 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
658 fep->hwp + FEC_MII_DATA); 656 fep->hwp + FEC_MII_DATA);
659 657
660 /* wait for end of transfer */ 658 /* wait for end of transfer */
661 while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { 659 time_left = wait_for_completion_timeout(&fep->mdio_done,
662 cpu_relax(); 660 usecs_to_jiffies(FEC_MII_TIMEOUT));
663 if (timeout-- < 0) { 661 if (time_left == 0) {
664 fep->mii_timeout = 1; 662 fep->mii_timeout = 1;
665 printk(KERN_ERR "FEC: MDIO write timeout\n"); 663 printk(KERN_ERR "FEC: MDIO write timeout\n");
666 return -ETIMEDOUT; 664 return -ETIMEDOUT;
667 }
668 } 665 }
669 666
670 return 0; 667 return 0;
@@ -1216,7 +1213,8 @@ fec_restart(struct net_device *dev, int duplex)
1216 writel(0, fep->hwp + FEC_R_DES_ACTIVE); 1213 writel(0, fep->hwp + FEC_R_DES_ACTIVE);
1217 1214
1218 /* Enable interrupts we wish to service */ 1215 /* Enable interrupts we wish to service */
1219 writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->hwp + FEC_IMASK); 1216 writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII,
1217 fep->hwp + FEC_IMASK);
1220} 1218}
1221 1219
1222static void 1220static void
@@ -1236,9 +1234,6 @@ fec_stop(struct net_device *dev)
1236 writel(1, fep->hwp + FEC_ECNTRL); 1234 writel(1, fep->hwp + FEC_ECNTRL);
1237 udelay(10); 1235 udelay(10);
1238 1236
1239 /* Clear outstanding MII command interrupts. */
1240 writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
1241
1242 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); 1237 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
1243} 1238}
1244 1239