aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@freescale.com>2015-07-31 11:38:32 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-31 18:41:49 -0400
commit614b42426cc3483e8d5bc68a158c2dd47dc831d0 (patch)
treef27c5e32b6d61f7101ea09bb39486697801013e4
parent8486830549189b109bfd40e8d38c6dd8b8f476db (diff)
gianfar: Fix suspend/resume for wol magic packet
If we disable NAPI in the first place we can mask the device's interrupts (and halt it) without fearing that imask may be concurrently accessed from interrupt context, so there's no need to do local_irq_save() around gfar_halt_nodisable(). lock_rx_qs()/unlock_tx_qs() are just obsoleted and potentially buggy routines. The txlock is currently used in the driver only to manage TX congestion, it has nothing to do with halting the device. With these changes, the TX processing is stopped before gfar_halt(). Compact gfar_halt() is used instead of gfar_halt_nodisable(), as it disables Rx/TX DMA h/w blocks and the Rx/TX h/w queues. gfar_start() re-enables all these blocks on resume. Enabling the magic-packet mode remains the same, note that the RX block is re-enabled just before entering sleep mode. Add IRQF_NO_SUSPEND flag for the error interrupt line, to signal that the interrupt line must remain active during sleep in order to wake the system by magic packet (MAG) reception interrupt. (On some systems the MAG interrupt did trigger w/o this flag as well, but on others it didn't.) Without these fixes, when suspended during fair Tx traffic the interface occasionally failed to be woken up by magic packet. Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c98
1 files changed, 30 insertions, 68 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index caad327e3f22..084c25d1467f 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -565,24 +565,6 @@ static void gfar_ints_enable(struct gfar_private *priv)
565 } 565 }
566} 566}
567 567
568#ifdef CONFIG_PM
569static void lock_tx_qs(struct gfar_private *priv)
570{
571 int i;
572
573 for (i = 0; i < priv->num_tx_queues; i++)
574 spin_lock(&priv->tx_queue[i]->txlock);
575}
576
577static void unlock_tx_qs(struct gfar_private *priv)
578{
579 int i;
580
581 for (i = 0; i < priv->num_tx_queues; i++)
582 spin_unlock(&priv->tx_queue[i]->txlock);
583}
584#endif
585
586static int gfar_alloc_tx_queues(struct gfar_private *priv) 568static int gfar_alloc_tx_queues(struct gfar_private *priv)
587{ 569{
588 int i; 570 int i;
@@ -1542,48 +1524,37 @@ static int gfar_suspend(struct device *dev)
1542 struct gfar_private *priv = dev_get_drvdata(dev); 1524 struct gfar_private *priv = dev_get_drvdata(dev);
1543 struct net_device *ndev = priv->ndev; 1525 struct net_device *ndev = priv->ndev;
1544 struct gfar __iomem *regs = priv->gfargrp[0].regs; 1526 struct gfar __iomem *regs = priv->gfargrp[0].regs;
1545 unsigned long flags;
1546 u32 tempval; 1527 u32 tempval;
1547
1548 int magic_packet = priv->wol_en && 1528 int magic_packet = priv->wol_en &&
1549 (priv->device_flags & 1529 (priv->device_flags &
1550 FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); 1530 FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
1551 1531
1532 if (!netif_running(ndev))
1533 return 0;
1534
1535 disable_napi(priv);
1536 netif_tx_lock(ndev);
1552 netif_device_detach(ndev); 1537 netif_device_detach(ndev);
1538 netif_tx_unlock(ndev);
1553 1539
1554 if (netif_running(ndev)) { 1540 gfar_halt(priv);
1555 1541
1556 local_irq_save(flags); 1542 if (magic_packet) {
1557 lock_tx_qs(priv); 1543 /* Enable interrupt on Magic Packet */
1544 gfar_write(&regs->imask, IMASK_MAG);
1558 1545
1559 gfar_halt_nodisable(priv); 1546 /* Enable Magic Packet mode */
1547 tempval = gfar_read(&regs->maccfg2);
1548 tempval |= MACCFG2_MPEN;
1549 gfar_write(&regs->maccfg2, tempval);
1560 1550
1561 /* Disable Tx, and Rx if wake-on-LAN is disabled. */ 1551 /* re-enable the Rx block */
1562 tempval = gfar_read(&regs->maccfg1); 1552 tempval = gfar_read(&regs->maccfg1);
1563 1553 tempval |= MACCFG1_RX_EN;
1564 tempval &= ~MACCFG1_TX_EN;
1565
1566 if (!magic_packet)
1567 tempval &= ~MACCFG1_RX_EN;
1568
1569 gfar_write(&regs->maccfg1, tempval); 1554 gfar_write(&regs->maccfg1, tempval);
1570 1555
1571 unlock_tx_qs(priv); 1556 } else {
1572 local_irq_restore(flags); 1557 phy_stop(priv->phydev);
1573
1574 disable_napi(priv);
1575
1576 if (magic_packet) {
1577 /* Enable interrupt on Magic Packet */
1578 gfar_write(&regs->imask, IMASK_MAG);
1579
1580 /* Enable Magic Packet mode */
1581 tempval = gfar_read(&regs->maccfg2);
1582 tempval |= MACCFG2_MPEN;
1583 gfar_write(&regs->maccfg2, tempval);
1584 } else {
1585 phy_stop(priv->phydev);
1586 }
1587 } 1558 }
1588 1559
1589 return 0; 1560 return 0;
@@ -1594,37 +1565,26 @@ static int gfar_resume(struct device *dev)
1594 struct gfar_private *priv = dev_get_drvdata(dev); 1565 struct gfar_private *priv = dev_get_drvdata(dev);
1595 struct net_device *ndev = priv->ndev; 1566 struct net_device *ndev = priv->ndev;
1596 struct gfar __iomem *regs = priv->gfargrp[0].regs; 1567 struct gfar __iomem *regs = priv->gfargrp[0].regs;
1597 unsigned long flags;
1598 u32 tempval; 1568 u32 tempval;
1599 int magic_packet = priv->wol_en && 1569 int magic_packet = priv->wol_en &&
1600 (priv->device_flags & 1570 (priv->device_flags &
1601 FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); 1571 FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
1602 1572
1603 if (!netif_running(ndev)) { 1573 if (!netif_running(ndev))
1604 netif_device_attach(ndev);
1605 return 0; 1574 return 0;
1606 }
1607 1575
1608 if (!magic_packet && priv->phydev) 1576 if (magic_packet) {
1577 /* Disable Magic Packet mode */
1578 tempval = gfar_read(&regs->maccfg2);
1579 tempval &= ~MACCFG2_MPEN;
1580 gfar_write(&regs->maccfg2, tempval);
1581 } else {
1609 phy_start(priv->phydev); 1582 phy_start(priv->phydev);
1610 1583 }
1611 /* Disable Magic Packet mode, in case something
1612 * else woke us up.
1613 */
1614 local_irq_save(flags);
1615 lock_tx_qs(priv);
1616
1617 tempval = gfar_read(&regs->maccfg2);
1618 tempval &= ~MACCFG2_MPEN;
1619 gfar_write(&regs->maccfg2, tempval);
1620 1584
1621 gfar_start(priv); 1585 gfar_start(priv);
1622 1586
1623 unlock_tx_qs(priv);
1624 local_irq_restore(flags);
1625
1626 netif_device_attach(ndev); 1587 netif_device_attach(ndev);
1627
1628 enable_napi(priv); 1588 enable_napi(priv);
1629 1589
1630 return 0; 1590 return 0;
@@ -2047,7 +2007,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
2047 /* Install our interrupt handlers for Error, 2007 /* Install our interrupt handlers for Error,
2048 * Transmit, and Receive 2008 * Transmit, and Receive
2049 */ 2009 */
2050 err = request_irq(gfar_irq(grp, ER)->irq, gfar_error, 0, 2010 err = request_irq(gfar_irq(grp, ER)->irq, gfar_error,
2011 IRQF_NO_SUSPEND,
2051 gfar_irq(grp, ER)->name, grp); 2012 gfar_irq(grp, ER)->name, grp);
2052 if (err < 0) { 2013 if (err < 0) {
2053 netif_err(priv, intr, dev, "Can't get IRQ %d\n", 2014 netif_err(priv, intr, dev, "Can't get IRQ %d\n",
@@ -2070,7 +2031,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
2070 goto rx_irq_fail; 2031 goto rx_irq_fail;
2071 } 2032 }
2072 } else { 2033 } else {
2073 err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0, 2034 err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt,
2035 IRQF_NO_SUSPEND,
2074 gfar_irq(grp, TX)->name, grp); 2036 gfar_irq(grp, TX)->name, grp);
2075 if (err < 0) { 2037 if (err < 0) {
2076 netif_err(priv, intr, dev, "Can't get IRQ %d\n", 2038 netif_err(priv, intr, dev, "Can't get IRQ %d\n",