Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef1f4364 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'gianfar-wol-fixes'



Claudiu Manoil says:

====================
gianfar: wol magic packet fixes

These changes were already validated as part of FSL SDK.
Patch 2 fixes occasional wake-on magic packet failures during
traffic, probably due to incorrect traffic stop/ device halt
sequence and incorrect usage of txlock.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5175f710 b0734b6d
Loading
Loading
Loading
Loading
+32 −72
Original line number Diff line number Diff line
@@ -565,22 +565,6 @@ static void gfar_ints_enable(struct gfar_private *priv)
	}
}

static void lock_tx_qs(struct gfar_private *priv)
{
	int i;

	for (i = 0; i < priv->num_tx_queues; i++)
		spin_lock(&priv->tx_queue[i]->txlock);
}

static void unlock_tx_qs(struct gfar_private *priv)
{
	int i;

	for (i = 0; i < priv->num_tx_queues; i++)
		spin_unlock(&priv->tx_queue[i]->txlock);
}

static int gfar_alloc_tx_queues(struct gfar_private *priv)
{
	int i;
@@ -1376,7 +1360,6 @@ static int gfar_probe(struct platform_device *ofdev)
	priv->dev = &ofdev->dev;
	SET_NETDEV_DEV(dev, &ofdev->dev);

	spin_lock_init(&priv->bflock);
	INIT_WORK(&priv->reset_task, gfar_reset_task);

	platform_set_drvdata(ofdev, priv);
@@ -1470,8 +1453,7 @@ static int gfar_probe(struct platform_device *ofdev)
		goto register_fail;
	}

	device_init_wakeup(&dev->dev,
			   priv->device_flags &
	device_set_wakeup_capable(&dev->dev, priv->device_flags &
				  FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);

	/* fill out IRQ number and name fields */
@@ -1540,36 +1522,20 @@ static int gfar_suspend(struct device *dev)
	struct gfar_private *priv = dev_get_drvdata(dev);
	struct net_device *ndev = priv->ndev;
	struct gfar __iomem *regs = priv->gfargrp[0].regs;
	unsigned long flags;
	u32 tempval;

	int magic_packet = priv->wol_en &&
			   (priv->device_flags &
			    FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);

	netif_device_detach(ndev);

	if (netif_running(ndev)) {

		local_irq_save(flags);
		lock_tx_qs(priv);

		gfar_halt_nodisable(priv);

		/* Disable Tx, and Rx if wake-on-LAN is disabled. */
		tempval = gfar_read(&regs->maccfg1);

		tempval &= ~MACCFG1_TX_EN;

		if (!magic_packet)
			tempval &= ~MACCFG1_RX_EN;

		gfar_write(&regs->maccfg1, tempval);

		unlock_tx_qs(priv);
		local_irq_restore(flags);
	if (!netif_running(ndev))
		return 0;

	disable_napi(priv);
	netif_tx_lock(ndev);
	netif_device_detach(ndev);
	netif_tx_unlock(ndev);

	gfar_halt(priv);

	if (magic_packet) {
		/* Enable interrupt on Magic Packet */
@@ -1579,10 +1545,15 @@ static int gfar_suspend(struct device *dev)
		tempval = gfar_read(&regs->maccfg2);
		tempval |= MACCFG2_MPEN;
		gfar_write(&regs->maccfg2, tempval);

		/* re-enable the Rx block */
		tempval = gfar_read(&regs->maccfg1);
		tempval |= MACCFG1_RX_EN;
		gfar_write(&regs->maccfg1, tempval);

	} else {
		phy_stop(priv->phydev);
	}
	}

	return 0;
}
@@ -1592,37 +1563,26 @@ static int gfar_resume(struct device *dev)
	struct gfar_private *priv = dev_get_drvdata(dev);
	struct net_device *ndev = priv->ndev;
	struct gfar __iomem *regs = priv->gfargrp[0].regs;
	unsigned long flags;
	u32 tempval;
	int magic_packet = priv->wol_en &&
			   (priv->device_flags &
			    FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);

	if (!netif_running(ndev)) {
		netif_device_attach(ndev);
	if (!netif_running(ndev))
		return 0;
	}

	if (!magic_packet && priv->phydev)
		phy_start(priv->phydev);

	/* Disable Magic Packet mode, in case something
	 * else woke us up.
	 */
	local_irq_save(flags);
	lock_tx_qs(priv);

	if (magic_packet) {
		/* Disable Magic Packet mode */
		tempval = gfar_read(&regs->maccfg2);
		tempval &= ~MACCFG2_MPEN;
		gfar_write(&regs->maccfg2, tempval);
	} else {
		phy_start(priv->phydev);
	}

	gfar_start(priv);

	unlock_tx_qs(priv);
	local_irq_restore(flags);

	netif_device_attach(ndev);

	enable_napi(priv);

	return 0;
@@ -2045,7 +2005,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
		/* Install our interrupt handlers for Error,
		 * Transmit, and Receive
		 */
		err = request_irq(gfar_irq(grp, ER)->irq, gfar_error, 0,
		err = request_irq(gfar_irq(grp, ER)->irq, gfar_error,
				  IRQF_NO_SUSPEND,
				  gfar_irq(grp, ER)->name, grp);
		if (err < 0) {
			netif_err(priv, intr, dev, "Can't get IRQ %d\n",
@@ -2068,7 +2029,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
			goto rx_irq_fail;
		}
	} else {
		err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0,
		err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt,
				  IRQF_NO_SUSPEND,
				  gfar_irq(grp, TX)->name, grp);
		if (err < 0) {
			netif_err(priv, intr, dev, "Can't get IRQ %d\n",
@@ -2169,8 +2131,6 @@ static int gfar_enet_open(struct net_device *dev)
	if (err)
		return err;

	device_set_wakeup_enable(&dev->dev, priv->wol_en);

	return err;
}

+0 −3
Original line number Diff line number Diff line
@@ -1145,9 +1145,6 @@ struct gfar_private {
	int oldduplex;
	int oldlink;

	/* Bitfield update lock */
	spinlock_t bflock;

	uint32_t msg_enable;

	struct work_struct reset_task;
+1 −4
Original line number Diff line number Diff line
@@ -653,7 +653,6 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
	struct gfar_private *priv = netdev_priv(dev);
	unsigned long flags;

	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
	    wol->wolopts != 0)
@@ -664,9 +663,7 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)

	device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC);

	spin_lock_irqsave(&priv->bflock, flags);
	priv->wol_en = !!device_may_wakeup(&dev->dev);
	spin_unlock_irqrestore(&priv->bflock, flags);

	return 0;
}