Skip to content

Commit

Permalink
fec: use interrupt for MDIO completion indication
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
baruchsiach authored and davem330 committed Jul 13, 2010
1 parent 15fd0cd commit 97b72e4
Showing 1 changed file with 25 additions and 30 deletions.
55 changes: 25 additions & 30 deletions drivers/net/fec.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,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);
Expand All @@ -205,7 +206,7 @@ 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)
Expand Down Expand Up @@ -334,6 +335,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;
Expand Down Expand Up @@ -608,32 +614,26 @@ static void fec_enet_adjust_link(struct net_device *dev)
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 |
FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(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 */
Expand All @@ -644,12 +644,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 |
Expand All @@ -658,13 +656,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;
Expand Down Expand Up @@ -1216,7 +1213,8 @@ 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_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII,
fep->hwp + FEC_IMASK);
}

static void
Expand All @@ -1236,9 +1234,6 @@ fec_stop(struct net_device *dev)
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);
}

Expand Down

0 comments on commit 97b72e4

Please sign in to comment.