diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 67 |
1 files changed, 33 insertions, 34 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 1ae075a246a3..c7b84bb22f75 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -976,8 +976,8 @@ fec_restart(struct net_device *ndev) writel((__force u32)cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); - /* Clear any outstanding interrupt, except MDIO. */ - writel((0xffffffff & ~FEC_ENET_MII), fep->hwp + FEC_IEVENT); + /* Clear any outstanding interrupt. */ + writel(0xffffffff, fep->hwp + FEC_IEVENT); fec_enet_bd_init(ndev); @@ -1123,7 +1123,7 @@ fec_restart(struct net_device *ndev) if (fep->link) writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); else - writel(0, fep->hwp + FEC_IMASK); + writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); /* Init the interrupt coalescing */ fec_enet_itr_coal_init(ndev); @@ -1652,10 +1652,6 @@ fec_enet_interrupt(int irq, void *dev_id) irqreturn_t ret = IRQ_NONE; int_events = readl(fep->hwp + FEC_IEVENT); - - /* Don't clear MDIO events, we poll for those */ - int_events &= ~FEC_ENET_MII; - writel(int_events, fep->hwp + FEC_IEVENT); fec_enet_collect_events(fep, int_events); @@ -1663,12 +1659,16 @@ fec_enet_interrupt(int irq, void *dev_id) ret = IRQ_HANDLED; if (napi_schedule_prep(&fep->napi)) { - /* Disable interrupts */ - writel(0, fep->hwp + FEC_IMASK); + /* Disable the NAPI interrupts */ + writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK); __napi_schedule(&fep->napi); } } + if (int_events & FEC_ENET_MII) { + ret = IRQ_HANDLED; + complete(&fep->mdio_done); + } return ret; } @@ -1818,24 +1818,11 @@ static void fec_enet_adjust_link(struct net_device *ndev) phy_print_status(phy_dev); } -static int fec_enet_mdio_wait(struct fec_enet_private *fep) -{ - uint ievent; - int ret; - - ret = readl_poll_timeout_atomic(fep->hwp + FEC_IEVENT, ievent, - ievent & FEC_ENET_MII, 2, 30000); - - if (!ret) - writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); - - return ret; -} - static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct fec_enet_private *fep = bus->priv; struct device *dev = &fep->pdev->dev; + unsigned long time_left; int ret = 0, frame_start, frame_addr, frame_op; bool is_c45 = !!(regnum & MII_ADDR_C45); @@ -1843,6 +1830,8 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) if (ret < 0) return ret; + reinit_completion(&fep->mdio_done); + if (is_c45) { frame_start = FEC_MMFR_ST_C45; @@ -1854,9 +1843,11 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) fep->hwp + FEC_MII_DATA); /* wait for end of transfer */ - ret = fec_enet_mdio_wait(fep); - if (ret) { + time_left = wait_for_completion_timeout(&fep->mdio_done, + usecs_to_jiffies(FEC_MII_TIMEOUT)); + if (time_left == 0) { netdev_err(fep->netdev, "MDIO address write timeout\n"); + ret = -ETIMEDOUT; goto out; } @@ -1875,9 +1866,11 @@ 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 */ - ret = fec_enet_mdio_wait(fep); - if (ret) { + time_left = wait_for_completion_timeout(&fep->mdio_done, + usecs_to_jiffies(FEC_MII_TIMEOUT)); + if (time_left == 0) { netdev_err(fep->netdev, "MDIO read timeout\n"); + ret = -ETIMEDOUT; goto out; } @@ -1895,6 +1888,7 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, { struct fec_enet_private *fep = bus->priv; struct device *dev = &fep->pdev->dev; + unsigned long time_left; int ret, frame_start, frame_addr; bool is_c45 = !!(regnum & MII_ADDR_C45); @@ -1904,6 +1898,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, else ret = 0; + reinit_completion(&fep->mdio_done); + if (is_c45) { frame_start = FEC_MMFR_ST_C45; @@ -1915,9 +1911,11 @@ 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 */ - ret = fec_enet_mdio_wait(fep); - if (ret) { + time_left = wait_for_completion_timeout(&fep->mdio_done, + usecs_to_jiffies(FEC_MII_TIMEOUT)); + if (time_left == 0) { netdev_err(fep->netdev, "MDIO address write timeout\n"); + ret = -ETIMEDOUT; goto out; } } else { @@ -1933,9 +1931,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 */ - ret = fec_enet_mdio_wait(fep); - if (ret) + time_left = wait_for_completion_timeout(&fep->mdio_done, + usecs_to_jiffies(FEC_MII_TIMEOUT)); + if (time_left == 0) { netdev_err(fep->netdev, "MDIO write timeout\n"); + ret = -ETIMEDOUT; + } out: pm_runtime_mark_last_busy(dev); @@ -2144,9 +2145,6 @@ static int fec_enet_mii_init(struct platform_device *pdev) writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - /* Clear any pending transaction complete indication */ - writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); - fep->mii_bus = mdiobus_alloc(); if (fep->mii_bus == NULL) { err = -ENOMEM; @@ -3688,6 +3686,7 @@ fec_probe(struct platform_device *pdev) fep->irq[i] = irq; } + init_completion(&fep->mdio_done); ret = fec_enet_mii_init(pdev); if (ret) goto failed_mii_init; |