diff options
-rw-r--r-- | drivers/net/fec.c | 55 |
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 | ||
192 | static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); | 193 | static 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 | */ | ||
614 | static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | 617 | static 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 | ||
1222 | static void | 1220 | static 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 | ||