netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Robert Hancock <hancock@sedsystems.ca>
To: netdev@vger.kernel.org
Cc: anirudh@xilinx.com, John.Linn@xilinx.com, andrew@lunn.ch,
	Robert Hancock <hancock@sedsystems.ca>
Subject: [PATCH net-next v4 08/20] net: axienet: Cleanup DMA device reset and halt process
Date: Wed,  5 Jun 2019 14:42:21 -0600	[thread overview]
Message-ID: <1559767353-17301-9-git-send-email-hancock@sedsystems.ca> (raw)
In-Reply-To: <1559767353-17301-1-git-send-email-hancock@sedsystems.ca>

The Xilinx DMA blocks each have their own reset register, but they both
reset the entire DMA engine, so only one of them needs to be reset.

Also, when stopping the device, we need to not just command the DMA
blocks to stop, but wait for them to stop, and trigger a device reset
to ensure that they are completely stopped.

Signed-off-by: Robert Hancock <hancock@sedsystems.ca>
---
 drivers/net/ethernet/xilinx/xilinx_axienet.h      |  2 +
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 54 +++++++++++++++++------
 2 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 4a135ed..1ffb113 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -83,6 +83,8 @@
 #define XAXIDMA_CR_RUNSTOP_MASK	0x00000001 /* Start/stop DMA channel */
 #define XAXIDMA_CR_RESET_MASK	0x00000004 /* Reset DMA engine */
 
+#define XAXIDMA_SR_HALT_MASK	0x00000001 /* Indicates DMA channel halted */
+
 #define XAXIDMA_BD_NDESC_OFFSET		0x00 /* Next descriptor pointer */
 #define XAXIDMA_BD_BUFA_OFFSET		0x08 /* Buffer address */
 #define XAXIDMA_BD_CTRL_LEN_OFFSET	0x18 /* Control/buffer length */
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index e735ca7..bdc6e80 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -434,17 +434,20 @@ static void axienet_setoptions(struct net_device *ndev, u32 options)
 	lp->options |= options;
 }
 
-static void __axienet_device_reset(struct axienet_local *lp, off_t offset)
+static void __axienet_device_reset(struct axienet_local *lp)
 {
 	u32 timeout;
 	/* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset
 	 * process of Axi DMA takes a while to complete as all pending
 	 * commands/transfers will be flushed or completed during this
 	 * reset process.
+	 * Note that even though both TX and RX have their own reset register,
+	 * they both reset the entire DMA core, so only one needs to be used.
 	 */
-	axienet_dma_out32(lp, offset, XAXIDMA_CR_RESET_MASK);
+	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, XAXIDMA_CR_RESET_MASK);
 	timeout = DELAY_OF_ONE_MILLISEC;
-	while (axienet_dma_in32(lp, offset) & XAXIDMA_CR_RESET_MASK) {
+	while (axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET) &
+				XAXIDMA_CR_RESET_MASK) {
 		udelay(1);
 		if (--timeout == 0) {
 			netdev_err(lp->ndev, "%s: DMA reset timeout!\n",
@@ -470,8 +473,7 @@ static void axienet_device_reset(struct net_device *ndev)
 	u32 axienet_status;
 	struct axienet_local *lp = netdev_priv(ndev);
 
-	__axienet_device_reset(lp, XAXIDMA_TX_CR_OFFSET);
-	__axienet_device_reset(lp, XAXIDMA_RX_CR_OFFSET);
+	__axienet_device_reset(lp);
 
 	lp->max_frm_size = XAE_MAX_VLAN_FRAME_SIZE;
 	lp->options |= XAE_OPTION_VLAN;
@@ -981,20 +983,45 @@ static int axienet_open(struct net_device *ndev)
  */
 static int axienet_stop(struct net_device *ndev)
 {
-	u32 cr;
+	u32 cr, sr;
+	int count;
 	struct axienet_local *lp = netdev_priv(ndev);
 
 	dev_dbg(&ndev->dev, "axienet_close()\n");
 
-	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
-			  cr & (~XAXIDMA_CR_RUNSTOP_MASK));
-	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
-			  cr & (~XAXIDMA_CR_RUNSTOP_MASK));
 	axienet_setoptions(ndev, lp->options &
 			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
 
+	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+	cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK);
+	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
+
+	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+	cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK);
+	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
+
+	axienet_iow(lp, XAE_IE_OFFSET, 0);
+
+	/* Give DMAs a chance to halt gracefully */
+	sr = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
+	for (count = 0; !(sr & XAXIDMA_SR_HALT_MASK) && count < 5; ++count) {
+		msleep(20);
+		sr = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
+	}
+
+	sr = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
+	for (count = 0; !(sr & XAXIDMA_SR_HALT_MASK) && count < 5; ++count) {
+		msleep(20);
+		sr = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
+	}
+
+	/* Do a reset to ensure DMA is really stopped */
+	mutex_lock(&lp->mii_bus->mdio_lock);
+	axienet_mdio_disable(lp);
+	__axienet_device_reset(lp);
+	axienet_mdio_enable(lp);
+	mutex_unlock(&lp->mii_bus->mdio_lock);
+
 	tasklet_kill(&lp->dma_err_tasklet);
 
 	free_irq(lp->tx_irq, ndev);
@@ -1326,8 +1353,7 @@ static void axienet_dma_err_handler(unsigned long data)
 	 */
 	mutex_lock(&lp->mii_bus->mdio_lock);
 	axienet_mdio_disable(lp);
-	__axienet_device_reset(lp, XAXIDMA_TX_CR_OFFSET);
-	__axienet_device_reset(lp, XAXIDMA_RX_CR_OFFSET);
+	__axienet_device_reset(lp);
 	axienet_mdio_enable(lp);
 	mutex_unlock(&lp->mii_bus->mdio_lock);
 
-- 
1.8.3.1


  parent reply	other threads:[~2019-06-05 20:43 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-05 20:42 [PATCH net-next v4 00/20] Xilinx axienet driver updates (v4) Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 01/20] net: axienet: Fix casting of pointers to u32 Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 02/20] net: axienet: Use standard IO accessors Robert Hancock
2019-06-06 14:12   ` Andrew Lunn
2019-06-05 20:42 ` [PATCH net-next v4 03/20] net: axienet: fix MDIO bus naming Robert Hancock
2019-06-06 14:12   ` Andrew Lunn
2019-06-05 20:42 ` [PATCH net-next v4 04/20] net: axienet: add X86 and ARM as supported platforms Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 05/20] net: axienet: Use clock framework to get device clock rate Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 06/20] net: axienet: fix teardown order of MDIO bus Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 07/20] net: axienet: Re-initialize MDIO registers properly after reset Robert Hancock
2019-06-06 21:05   ` David Miller
2019-06-05 20:42 ` Robert Hancock [this message]
2019-06-05 20:42 ` [PATCH net-next v4 09/20] net: axienet: Make RX/TX ring sizes configurable Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 10/20] net: axienet: Add DMA registers to ethtool register dump Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 11/20] net: axienet: Support shared interrupts Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 12/20] net: axienet: Add optional support for Ethernet core interrupt Robert Hancock
2019-06-06 21:06   ` David Miller
2019-06-05 20:42 ` [PATCH net-next v4 13/20] net: axienet: Fix race condition causing TX hang Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 14/20] net: axienet: Make missing MAC address non-fatal Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 15/20] net: axienet: stop interface during shutdown Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 16/20] net: axienet: document device tree mdio child node Robert Hancock
2019-06-06 14:16   ` Andrew Lunn
2019-06-05 20:42 ` [PATCH net-next v4 17/20] net: axienet: Fix MDIO bus parent node detection Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 18/20] net: axienet: document axistream-connected attribute Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 19/20] net: axienet: make use of axistream-connected attribute optional Robert Hancock
2019-06-05 20:42 ` [PATCH net-next v4 20/20] net: axienet: convert to phylink API Robert Hancock
2019-06-06 21:07   ` David Miller
2019-06-06 21:03 ` [PATCH net-next v4 00/20] Xilinx axienet driver updates (v4) David Miller

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=1559767353-17301-9-git-send-email-hancock@sedsystems.ca \
    --to=hancock@sedsystems.ca \
    --cc=John.Linn@xilinx.com \
    --cc=andrew@lunn.ch \
    --cc=anirudh@xilinx.com \
    --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).