All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: netdev@vger.kernel.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Subject: [PATCH 10/13] ftgmac100: Add a reset task and use it for link changes
Date: Sun,  2 Apr 2017 13:35:20 +1000	[thread overview]
Message-ID: <20170402033523.9482-11-benh@kernel.crashing.org> (raw)
In-Reply-To: <20170402033523.9482-1-benh@kernel.crashing.org>

Link speed changes require a full HW reset. This isn't done
properly at the moment. It will involve delays and thus isn't
suitable to do from the link poll callback.

So let's create a reset_task that we can queue up when the
link changes. It will be useful for various cases of error
handling as well.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/net/ethernet/faraday/ftgmac100.c | 85 +++++++++++++++++++++++++++-----
 1 file changed, 72 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 96c6bc2..d616c0a 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -74,6 +74,7 @@ struct ftgmac100 {
 	struct device *dev;
 	struct ncsi_dev *ndev;
 	struct napi_struct napi;
+	struct work_struct reset_task;
 	struct mii_bus *mii_bus;
 
 	/* Link management */
@@ -872,7 +873,6 @@ static void ftgmac100_adjust_link(struct net_device *netdev)
 	struct ftgmac100 *priv = netdev_priv(netdev);
 	struct phy_device *phydev = netdev->phydev;
 	int new_speed;
-	int ier;
 
 	/* We store "no link" as speed 0 */
 	if (!phydev->link)
@@ -899,20 +899,11 @@ static void ftgmac100_adjust_link(struct net_device *netdev)
 	priv->cur_speed = new_speed;
 	priv->cur_duplex = phydev->duplex;
 
-	ier = ioread32(priv->base + FTGMAC100_OFFSET_IER);
-
-	/* disable all interrupts */
+	/* Disable all interrupts */
 	iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
 
-	netif_stop_queue(netdev);
-	ftgmac100_stop_hw(priv);
-
-	netif_start_queue(netdev);
-	ftgmac100_init_hw(priv);
-	ftgmac100_start_hw(priv);
-
-	/* re-enable interrupts */
-	iowrite32(ier, priv->base + FTGMAC100_OFFSET_IER);
+	/* Reset the adapter asynchronously */
+	schedule_work(&priv->reset_task);
 }
 
 static int ftgmac100_mii_probe(struct ftgmac100 *priv)
@@ -1137,6 +1128,59 @@ static int ftgmac100_init_all(struct ftgmac100 *priv, bool ignore_alloc_err)
 	return err;
 }
 
+static void ftgmac100_reset_task(struct work_struct *work)
+{
+	struct ftgmac100 *priv = container_of(work, struct ftgmac100,
+					      reset_task);
+	struct net_device *netdev = priv->netdev;
+	int err;
+
+	netdev_dbg(netdev, "Resetting NIC...\n");
+
+	/* Block PHY polling */
+	if (netdev->phydev)
+		mutex_lock(&netdev->phydev->lock);
+
+	rtnl_lock();
+
+	/* Check if the interface is still up */
+	if (!netif_running(netdev))
+		goto bail;
+
+	/* Stop the network stack */
+	netif_trans_update(netdev);
+	napi_disable(&priv->napi);
+	netif_tx_disable(netdev);
+
+	/* Stop and reset the MAC */
+	ftgmac100_stop_hw(priv);
+	err = ftgmac100_reset_hw(priv);
+	if (err) {
+		/* Not much we can do ... it might come back... */
+		netdev_err(netdev, "attempting to continue...\n");
+	}
+
+	/* Free all rx and tx buffers */
+	ftgmac100_free_buffers(priv);
+
+	/* The ring pointers have been reset in HW, reflect this here */
+	priv->rx_pointer = 0;
+	priv->tx_clean_pointer = 0;
+	priv->tx_pointer = 0;
+	priv->tx_pending = 0;
+
+	/* Setup everything again and restart chip */
+	ftgmac100_init_all(priv, true);
+
+	netdev_dbg(netdev, "Reset done !\n");
+ bail:
+	rtnl_unlock();
+
+	/* Unblock PHY polling */
+	if (netdev->phydev)
+		mutex_unlock(&netdev->phydev->lock);
+}
+
 static int ftgmac100_open(struct net_device *netdev)
 {
 	struct ftgmac100 *priv = netdev_priv(netdev);
@@ -1222,6 +1266,14 @@ static int ftgmac100_stop(struct net_device *netdev)
 {
 	struct ftgmac100 *priv = netdev_priv(netdev);
 
+	/* Note about the reset task: We are called with the rtnl lock
+	 * held, so we are synchronized against the core of the reset
+	 * task. We must not try to synchronously cancel it otherwise
+	 * we can deadlock. But since it will test for netif_running()
+	 * which has already been cleared by the net core, we don't
+	 * anything special to do.
+	 */
+
 	/* disable all interrupts */
 	iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
 
@@ -1397,6 +1449,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
 	priv = netdev_priv(netdev);
 	priv->netdev = netdev;
 	priv->dev = &pdev->dev;
+	INIT_WORK(&priv->reset_task, ftgmac100_reset_task);
 
 	spin_lock_init(&priv->tx_lock);
 
@@ -1500,6 +1553,12 @@ static int ftgmac100_remove(struct platform_device *pdev)
 	priv = netdev_priv(netdev);
 
 	unregister_netdev(netdev);
+
+	/* There's a small chance the reset task will have been re-queued,
+	 * during stop, make sure it's gone before we free the structure.
+	 */
+	cancel_work_sync(&priv->reset_task);
+
 	ftgmac100_destroy_mdio(netdev);
 
 	iounmap(priv->base);
-- 
2.9.3

  parent reply	other threads:[~2017-04-02  3:36 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-02  3:35 [PATCH 00/13] ftgmac100: Rework batch 1 - Link & Interrupts Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 01/13] ftgmac100: Use netdev->irq instead of private copy Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 02/13] ftgmac100: Remove "banner" comments Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 03/13] ftgmac100: Reorder struct fields and comment Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 04/13] ftgmac100: Remove "enabled" flags Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 05/13] ftgmac100: Cleanup speed/duplex tracking and fix duplex config Benjamin Herrenschmidt
2017-04-02 18:28   ` Andrew Lunn
2017-04-02 21:03     ` Benjamin Herrenschmidt
2017-04-02 21:35     ` Benjamin Herrenschmidt
2017-04-02 21:27   ` Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 06/13] ftgmac100: Split ring alloc, init and rx buffer alloc Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 07/13] ftgmac100: Move napi_add/del to open/close Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 08/13] ftgmac100: Request the interrupt only after HW is reset Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 09/13] ftgmac100: Move the bulk of inits to a separate function Benjamin Herrenschmidt
2017-04-02  3:35 ` Benjamin Herrenschmidt [this message]
2017-04-02 18:42   ` [PATCH 10/13] ftgmac100: Add a reset task and use it for link changes Andrew Lunn
2017-04-02 21:05     ` Benjamin Herrenschmidt
2017-04-02 21:24     ` Benjamin Herrenschmidt
2017-04-03  6:46       ` Benjamin Herrenschmidt
2017-04-02 20:56   ` Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 11/13] ftgmac100: Rework MAC reset and init Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 12/13] ftgmac100: Remove useless tests in interrupt handler Benjamin Herrenschmidt
2017-04-02  3:35 ` [PATCH 13/13] ftgmac100: Rework NAPI & interrupts handling Benjamin Herrenschmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170402033523.9482-11-benh@kernel.crashing.org \
    --to=benh@kernel.crashing.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.