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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).