You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by da...@apache.org on 2022/08/12 14:30:59 UTC
[incubator-nuttx] 04/05: arch: imx6: Apply the imxrt_enet.c changes to imx_enet.c (3/4)
This is an automated email from the ASF dual-hosted git repository.
davids5 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit fb8562763a08fee925ddb47ca4fce2fb597da53f
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Fri Aug 12 19:09:17 2022 +0900
arch: imx6: Apply the imxrt_enet.c changes to imx_enet.c (3/4)
Summary:
- This commit applies the following imxrt_enet.c changes to imx_enet.c
commit 522a949ed5b377a8a00c409da9bf1dd032fed939
Author: David Sidrane <Da...@NscDg.com>
Date: Wed Jul 13 11:00:11 2022 -0700
imxrt:enet Better interrupt state handeling
- NOTE: I also fixed typo and compile error in the above commit
Impact:
- imx_enet.c
Testing:
- Tested with qemu-6.2
Signed-off-by: Masayuki Ishikawa <Ma...@jp.sony.com>
---
arch/arm/src/imx6/imx_enet.c | 98 ++++++++++++++++++++++++++------------------
1 file changed, 58 insertions(+), 40 deletions(-)
diff --git a/arch/arm/src/imx6/imx_enet.c b/arch/arm/src/imx6/imx_enet.c
index 907202509f..33f962792b 100644
--- a/arch/arm/src/imx6/imx_enet.c
+++ b/arch/arm/src/imx6/imx_enet.c
@@ -279,6 +279,7 @@ struct imx_driver_s
uint8_t rxtail; /* The next RX descriptor to use */
uint8_t phyaddr; /* Selected PHY address */
struct wdog_s txtimeout; /* TX timeout timer */
+ uint32_t ints; /* Enabled interrupts */
struct work_s irqwork; /* For deferring interrupt work to the work queue */
struct work_s pollwork; /* For deferring poll work to the work queue */
struct enet_desc_s *txdesc; /* A pointer to the list of TX descriptor */
@@ -322,6 +323,11 @@ static inline uint32_t imx_enet_getreg32(struct imx_driver_s *priv,
static inline void imx_enet_putreg32(struct imx_driver_s *priv,
uint32_t value, uint32_t offset);
+static inline void imx_enet_modifyreg32(struct imx_driver_s *priv,
+ unsigned int offset,
+ uint32_t clearbits,
+ uint32_t setbits);
+
#ifndef IMXRT_BUFFERS_SWAP
# define imx_swap32(value) (value)
# define imx_swap16(value) (value)
@@ -424,6 +430,31 @@ static inline uint32_t imx_enet_getreg32(struct imx_driver_s *priv,
return getreg32(priv->base + offset);
}
+/****************************************************************************
+ * Name: imx_enet_modifyreg32
+ *
+ * Description:
+ * Atomically modify the specified bits in a memory mapped register
+ *
+ * Input Parameters:
+ * priv - private SPI device structure
+ * offset - offset to the register of interest
+ * clearbits - the 32-bit value to be written as 0s
+ * setbits - the 32-bit value to be written as 1s
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static inline void imx_enet_modifyreg32(struct imx_driver_s *priv,
+ unsigned int offset,
+ uint32_t clearbits,
+ uint32_t setbits)
+{
+ modifyreg32(priv->base + offset, clearbits, setbits);
+}
+
/****************************************************************************
* Name: imx_enet_putreg32
*
@@ -552,8 +583,6 @@ static bool imx_txringfull(struct imx_driver_s *priv)
static int imx_transmit(struct imx_driver_s *priv)
{
struct enet_desc_s *txdesc;
- irqstate_t flags;
- uint32_t regval;
uint8_t *buf;
/* Since this can be called from imx_receive, it is possible that
@@ -627,27 +656,20 @@ static int imx_transmit(struct imx_driver_s *priv)
DEBUGASSERT(txdesc->data == buf);
}
- /* Make the following operations atomic */
+ /* Start the TX transfer (if it was not already waiting for buffers) */
- flags = spin_lock_irqsave(NULL);
+ imx_enet_putreg32(priv, ENET_TDAR, IMX_ENET_TDAR_OFFSET);
/* Enable TX interrupts */
- regval = imx_enet_getreg32(priv, IMX_ENET_EIMR_OFFSET);
- regval |= TX_INTERRUPTS;
- imx_enet_putreg32(priv, regval, IMX_ENET_EIMR_OFFSET);
+ priv->ints |= TX_INTERRUPTS;
+ imx_enet_modifyreg32(priv, IMX_ENET_EIMR_OFFSET, 0, TX_INTERRUPTS);
/* Setup the TX timeout watchdog (perhaps restarting the timer) */
wd_start(&priv->txtimeout, IMX_TXTIMEOUT,
imx_txtimeout_expiry, (wdparm_t)priv);
- /* Start the TX transfer (if it was not already waiting for buffers) */
-
- imx_enet_putreg32(priv, ENET_TDAR, IMX_ENET_TDAR_OFFSET);
-
- spin_unlock_irqrestore(NULL, flags);
-
#if CONFIG_IMX_ENET_NTXBUFFERS == 1
priv->txbusy = false;
#endif
@@ -991,7 +1013,6 @@ static void imx_receive(struct imx_driver_s *priv)
static void imx_txdone(struct imx_driver_s *priv)
{
struct enet_desc_s *txdesc;
- uint32_t regval;
bool txdone;
/* We are here because a transmission completed, so the watchdog can be
@@ -1042,9 +1063,9 @@ static void imx_txdone(struct imx_driver_s *priv)
wd_cancel(&priv->txtimeout);
- regval = imx_enet_getreg32(priv, IMX_ENET_EIMR_OFFSET);
- regval &= ~TX_INTERRUPTS;
- imx_enet_putreg32(priv, regval, IMX_ENET_EIMR_OFFSET);
+ priv->ints &= ~TX_INTERRUPTS;
+ imx_enet_modifyreg32(priv, IMX_ENET_EIMR_OFFSET, TX_INTERRUPTS,
+ priv->ints);
}
/* There should be space for a new TX in any event. Poll the network for
@@ -1086,8 +1107,7 @@ static void imx_enet_interrupt_work(void *arg)
/* Get the set of unmasked, pending interrupt. */
- pending = imx_enet_getreg32(priv, IMX_ENET_EIR_OFFSET) &
- imx_enet_getreg32(priv, IMX_ENET_EIMR_OFFSET);
+ pending = imx_enet_getreg32(priv, IMX_ENET_EIR_OFFSET) & priv->ints;
/* Clear the pending interrupts */
@@ -1101,8 +1121,7 @@ static void imx_enet_interrupt_work(void *arg)
NETDEV_ERRORS(&priv->dev);
- nerr("ERROR: Network interface error occurred (0x%08" PRIX32 ")\n",
- (pending & ERROR_INTERRUPTS));
+ nerr("pending %" PRIx32 " ints %" PRIx32 "\n", pending, priv->ints);
}
if (pending & CRITICAL_ERROR)
@@ -1166,10 +1185,7 @@ static void imx_enet_interrupt_work(void *arg)
/* Re-enable Ethernet interrupts */
-#if 0
- up_enable_irq(IMX_IRQ_ENET0TMR);
-#endif
- up_enable_irq(IMX_IRQ_ENET0);
+ imx_enet_putreg32(priv, priv->ints, IMX_ENET_EIMR_OFFSET);
}
/****************************************************************************
@@ -1202,7 +1218,7 @@ static int imx_enet_interrupt(int irq, void *context, void *arg)
* condition here.
*/
- up_disable_irq(IMX_IRQ_ENET0);
+ imx_enet_putreg32(priv, 0, IMX_ENET_EIMR_OFFSET);
/* Schedule to perform the interrupt processing on the worker thread. */
@@ -1277,7 +1293,8 @@ static void imx_txtimeout_expiry(wdparm_t arg)
* condition with interrupt work that is already queued and in progress.
*/
- up_disable_irq(IMX_IRQ_ENET0);
+ imx_enet_putreg32(priv, 0, IMX_ENET_EIMR_OFFSET);
+ priv->ints = 0;
/* Schedule to perform the TX timeout processing on the worker thread,
* canceling any pending interrupt work.
@@ -1387,26 +1404,26 @@ static int imx_ifup_action(struct net_driver_s *dev, bool resetphy)
imx_enet_putreg32(priv, ENET_RDAR, IMX_ENET_RDAR_OFFSET);
+ imx_enet_putreg32(priv, 0, IMX_ENET_EIMR_OFFSET);
+
/* Clear all pending ENET interrupt */
- imx_enet_putreg32(priv, RX_INTERRUPTS | ERROR_INTERRUPTS | TX_INTERRUPTS,
- IMX_ENET_EIR_OFFSET);
+ imx_enet_putreg32(priv, 0xffffffff, IMX_ENET_EIR_OFFSET);
+
+ /* Mark the interrupt "up" and enable interrupts at the NVIC */
+
+ up_enable_irq(IMX_IRQ_ENET0);
+
+ priv->bifup = true;
/* Enable RX and error interrupts at the controller (TX interrupts are
* still disabled).
*/
- imx_enet_putreg32(priv, RX_INTERRUPTS | ERROR_INTERRUPTS,
- IMX_ENET_EIMR_OFFSET);
-
- /* Mark the interrupt "up" and enable interrupts at the NVIC */
-
- priv->bifup = true;
+ priv->ints = RX_INTERRUPTS | ERROR_INTERRUPTS;
+ imx_enet_modifyreg32(priv, IMX_ENET_EIMR_OFFSET, TX_INTERRUPTS,
+ priv->ints);
-#if 0
- up_enable_irq(IMX_IRQ_ENET0TMR);
-#endif
- up_enable_irq(IMX_IRQ_ENET0);
return OK;
}
@@ -1466,8 +1483,9 @@ static int imx_ifdown(struct net_driver_s *dev)
flags = enter_critical_section();
+ priv->ints = 0;
+ imx_enet_putreg32(priv, priv->ints, IMX_ENET_EIMR_OFFSET);
up_disable_irq(IMX_IRQ_ENET0);
- imx_enet_putreg32(priv, 0, IMX_ENET_EIMR_OFFSET);
/* Cancel the TX timeout timers */