diff --git a/TODO b/TODO index a364e4e8ed..36347d1036 100644 --- a/TODO +++ b/TODO @@ -1059,12 +1059,12 @@ o Network (net/, drivers/net) TIVA ----------------------- ------ LM3S YES NO TM4C YES YES - eZ80 NO NO + eZ80 YES NO Kinetis YES YES (not tested) LPC17xx YES YES (not tested) LPC43xx YES YES (not tested) DMxxx NIC NO NO - PIC32 NO NO + PIC32 YES NO SAM3/4 YES YES SAMA5D ----------------------- ------ EMACA YES YES (not tested) diff --git a/arch/mips/src/pic32mz/pic32mz-ethernet.c b/arch/mips/src/pic32mz/pic32mz-ethernet.c index 649a2314ca..356edab2d1 100644 --- a/arch/mips/src/pic32mz/pic32mz-ethernet.c +++ b/arch/mips/src/pic32mz/pic32mz-ethernet.c @@ -3174,6 +3174,7 @@ static inline int pic32mz_phyinit(struct pic32mz_driver_s *priv) nerr("ERROR: No PHY detected\n"); return -ENODEV; } + ninfo("phyaddr: %d\n", phyaddr); /* Save the discovered PHY device address */ @@ -3187,6 +3188,7 @@ static inline int pic32mz_phyinit(struct pic32mz_driver_s *priv) { return ret; } + pic32mz_showmii(phyaddr, "After reset"); /* Set the MII/RMII operation mode. This usually requires access to a diff --git a/arch/z80/src/ez80/Kconfig b/arch/z80/src/ez80/Kconfig index 7529e2c7ad..759160a512 100644 --- a/arch/z80/src/ez80/Kconfig +++ b/arch/z80/src/ez80/Kconfig @@ -117,6 +117,26 @@ config ARCH_MCFILTER ---help--- Enables multicast MAC address filtering (not fully implemented) +choice + prompt "Work queue" + default EZ80_EMAC_LPWORK if SCHED_LPWORK + default EZ80_EMAC_HPWORK if !SCHED_LPWORK && SCHED_HPWORK + depends on SCHED_WORKQUEUE + ---help--- + Work queue support is required to use the Ethernet driver. If the + low priority work queue is available, then it should be used by the + driver. + +config EZ80_EMAC_HPWORK + bool "High priority" + depends on SCHED_HPWORK + +config EZ80_EMAC_LPWORK + bool "Low priority" + depends on SCHED_LPWORK + +endchoice # Work queue + endif # EZ80_EMAC config ARCH_TIMERHOOK diff --git a/arch/z80/src/ez80/Make.defs b/arch/z80/src/ez80/Make.defs index 7e79e19d65..5b4defd8e7 100644 --- a/arch/z80/src/ez80/Make.defs +++ b/arch/z80/src/ez80/Make.defs @@ -44,7 +44,7 @@ CMN_CSRCS += up_reprioritizertr.c up_idle.c up_assert.c up_doirq.c CMN_CSRCS += up_mdelay.c up_stackframe.c up_udelay.c up_usestack.c CMN_CSRCS += up_puts.c -CHIP_ASRCS = ez80_startup.asm ez80_io.asm ez80_up_irq_save.asm +CHIP_ASRCS = ez80_startup.asm ez80_io.asm ez80_irqsave.asm CHIP_ASRCS += ez80_saveusercontext.asm ez80_restorecontext.asm ifeq ($(CONFIG_ARCH_CHIP_EZ80F91),y) CHIP_ASRCS += ez80f91_init.asm diff --git a/arch/z80/src/ez80/ez80_emac.c b/arch/z80/src/ez80/ez80_emac.c index 0020991551..f5655fdc49 100644 --- a/arch/z80/src/ez80/ez80_emac.c +++ b/arch/z80/src/ez80/ez80_emac.c @@ -56,6 +56,11 @@ #include #include #include + +#ifdef CONFIG_NET_NOINTS +# include +#endif + #include #include #include @@ -75,6 +80,26 @@ /* Configuration ************************************************************/ +/* If processing is not done at the interrupt level, then work queue support + * is required. + */ + +#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE) +# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE) +#endif + +/* Use the low priority work queue if possible */ + +#if defined(CONFIG_SCHED_WORKQUEUE) +# if defined(CONFIG_EZ80_EMAC_HPWORK) +# define ETHWORK HPWORK +# elif defined(CONFIG_EZ80_EMAC_LPWORK) +# define ETHWORK LPWORK +# else +# error Neither CONFIG_EZ80_EMAC_HPWORK nor CONFIG_EZ80_EMAC_LPWORK defined +# endif +#endif + #ifndef CONFIG_EZ80_RAMADDR # define CONFIG_EZ80_RAMADDR EZ80_EMACSRAM #endif @@ -321,6 +346,12 @@ struct ez80emac_driver_s WDOG_ID txpoll; /* TX poll timer */ WDOG_ID txtimeout; /* TX timeout timer */ +#ifdef CONFIG_NET_NOINTS + struct work_s txwork; /* For deferring Tx-related work to the work queue */ + struct work_s rxwork; /* For deferring Rx-related work to the work queue */ + struct work_s syswork; /* For deferring system work to the work queue */ +#endif + #if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_NET) struct ez80mac_statistics_s stat; #endif @@ -375,20 +406,49 @@ static int ez80emac_receive(struct ez80emac_driver_s *priv); /* Interrupt handling */ +static inline void ez80emac_txinterrupt_process(FAR struct ez80emac_driver_s *priv); +#ifdef CONFIG_NET_NOINTS +static void ez80emac_txinterrupt_work(FAR void *arg); +#endif static int ez80emac_txinterrupt(int irq, FAR void *context); + +static inline void ez80emac_rxinterrupt_process(FAR struct ez80emac_driver_s *priv); +#ifdef CONFIG_NET_NOINTS +static void ez80emac_rxinterrupt_work(FAR void *arg); +#endif static int ez80emac_rxinterrupt(int irq, FAR void *context); + +static inline void ez80emac_sysinterrupt_process(FAR struct ez80emac_driver_s *priv); +#ifdef CONFIG_NET_NOINTS +static void ez80emac_sysinterrupt_work(FAR void *arg); +#endif static int ez80emac_sysinterrupt(int irq, FAR void *context); /* Watchdog timer expirations */ -static void ez80emac_polltimer(int argc, uint32_t arg, ...); -static void ez80emac_txtimeout(int argc, uint32_t arg, ...); +static inline void ez80emac_txtimeout_process(FAR struct ez80emac_driver_s *priv); +#ifdef CONFIG_NET_NOINTS +static void ez80emac_txtimeout_work(FAR void *arg); +#endif +static void ez80emac_txtimeout_expiry(int argc, uint32_t arg, ...); + +static inline void ez80emac_poll_process(FAR struct ez80emac_driver_s *priv); +#ifdef CONFIG_NET_NOINTS +static void ez80emac_poll_work(FAR void *arg); +#endif +static void ez80emac_poll_expiry(int argc, uint32_t arg, ...); /* NuttX callback functions */ static int ez80emac_ifup(struct net_driver_s *dev); static int ez80emac_ifdown(struct net_driver_s *dev); + +static inline void ez80emac_txavail_process(FAR struct ez80emac_driver_s *priv); +#ifdef CONFIG_NET_NOINTS +static void ez80emac_txavail_work(FAR void *arg); +#endif static int ez80emac_txavail(struct net_driver_s *dev); + #ifdef CONFIG_NET_IGMP static int ez80emac_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); static int ez80emac_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac); @@ -1051,7 +1111,8 @@ static int ez80emac_transmit(struct ez80emac_driver_s *priv) /* Setup the TX timeout watchdog (perhaps restarting the timer) */ - (void)wd_start(priv->txtimeout, EMAC_TXTIMEOUT, ez80emac_txtimeout, 1, (uint32_t)priv); + (void)wd_start(priv->txtimeout, EMAC_TXTIMEOUT, + ez80emac_txtimeout_expiry, 1, (uint32_t)priv); return OK; } @@ -1414,23 +1475,25 @@ static int ez80emac_receive(struct ez80emac_driver_s *priv) } /**************************************************************************** - * Function: ez80emac_txinterrupt + * Function: ez80emac_txinterrupt_process * * Description: - * Process Rx-related interrupt events + * Tx Interrupt processing. This may be performed either within the + * interrupt handler or on the worker thread, depending upon the configuration * * Parameters: - * priv - Driver data instance - * istat - Snapshot of ISTAT register containing Rx events to provess + * priv - Reference to the driver state structure * * Returned Value: - * None + * None + * + * Assumptions: + * The network is locked. * ****************************************************************************/ -static int ez80emac_txinterrupt(int irq, FAR void *context) +static inline void ez80emac_txinterrupt_process(FAR struct ez80emac_driver_s *priv) { - FAR struct ez80emac_driver_s *priv = &g_emac; FAR struct ez80emac_desc_s *txhead = priv->txhead; uint8_t regval; uint8_t istat; @@ -1514,28 +1577,117 @@ static int ez80emac_txinterrupt(int irq, FAR void *context) wd_cancel(priv->txtimeout); } +} + +/**************************************************************************** + * Function: ez80emac_txinterrupt_work + * + * Description: + * Perform Tx interrupt related work from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() was called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void ez80emac_txinterrupt_work(FAR void *arg) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; + net_lock_t state; + + /* Process pending Ethernet interrupts */ + + state = net_lock(); + ez80emac_txinterrupt_process(priv); + net_unlock(state); + + /* Re-enable Ethernet Tx interrupts */ + + up_enable_irq(EZ80_EMACRX_IRQ); +} +#endif + +/**************************************************************************** + * Function: ez80emac_txinterrupt + * + * Description: + * Process Tx-related interrupt events + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + * Assumptions: + * + ****************************************************************************/ + +static int ez80emac_txinterrupt(int irq, FAR void *context) +{ + FAR struct ez80emac_driver_s *priv = &g_emac; + +#ifdef CONFIG_NET_NOINTS + /* Disable further Ethernet Tx interrupts. Because Ethernet interrupts are + * also disabled if the TX timeout event occurs, there can be no race + * condition here. + */ + + up_disable_irq(EZ80_EMACTX_IRQ); + + /* TODO: Determine if a TX transfer just completed */ + + { + /* If a TX transfer just completed, then cancel the TX timeout so + * there will be no race condition between any subsequent timeout + * expiration and the deferred interrupt processing. + */ + + wd_cancel(priv->txtimeout); + } + + /* Schedule to perform the Tx interrupt processing on the worker thread. */ + + work_queue(ETHWORK, &priv->txwork, ez80emac_txinterrupt_work, priv, 0); + +#else + /* Process the interrupt now */ + + ez80emac_txinterrupt_process(priv); +#endif return OK; } /**************************************************************************** - * Function: ez80emac_rxinterrupt + * Function: ez80emac_rxinterrupt_process * * Description: - * Process Rx-related interrupt events + * Rx Interrupt processing. This may be performed either within the + * interrupt handler or on the worker thread, depending upon the + * configuration * * Parameters: - * priv - Driver data instance - * istat - Snapshot of ISTAT register containing Rx events to provess + * priv - Reference to the driver state structure * * Returned Value: * None * + * Assumptions: + * The network is locked. + * ****************************************************************************/ -static int ez80emac_rxinterrupt(int irq, FAR void *context) +static inline void ez80emac_rxinterrupt_process(FAR struct ez80emac_driver_s *priv) { - FAR struct ez80emac_driver_s *priv = &g_emac; uint8_t istat; /* EMAC Rx interrupts: @@ -1558,14 +1710,48 @@ static int ez80emac_rxinterrupt(int irq, FAR void *context) /* Process any RX packets pending the RX buffer */ (void)ez80emac_receive(priv); - return OK; } /**************************************************************************** - * Function: ez80emac_sysinterrupt + * Function: ez80emac_rxinterrupt_work * * Description: - * Hardware interrupt handler + * Perform Rx interrupt related work from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() was called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void ez80emac_rxinterrupt_work(FAR void *arg) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; + net_lock_t state; + + /* Process pending Ethernet interrupts */ + + state = net_lock(); + ez80emac_rxinterrupt_process(priv); + net_unlock(state); + + /* Re-enable Ethernet Rx interrupts */ + + up_enable_irq(EZ80_EMACRX_IRQ); +} +#endif + +/**************************************************************************** + * Function: ez80emac_rxinterrupt + * + * Description: + * Process Rx-related interrupt events * * Parameters: * irq - Number of the IRQ that generated the interrupt @@ -1578,9 +1764,63 @@ static int ez80emac_rxinterrupt(int irq, FAR void *context) * ****************************************************************************/ -static int ez80emac_sysinterrupt(int irq, FAR void *context) +static int ez80emac_rxinterrupt(int irq, FAR void *context) { FAR struct ez80emac_driver_s *priv = &g_emac; + +#ifdef CONFIG_NET_NOINTS + /* Disable further Ethernet Rx interrupts. Because Ethernet interrupts are + * also disabled if the TX timeout event occurs, there can be no race + * condition here. + */ + + up_disable_irq(EZ80_EMACRX_IRQ); + + /* TODO: Determine if a TX transfer just completed */ + + { + /* If a TX transfer just completed, then cancel the TX timeout so + * there will be no race condition between any subsequent timeout + * expiration and the deferred interrupt processing. + */ + + wd_cancel(priv->txtimeout); + } + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(ETHWORK, &priv->rxwork, ez80emac_rxinterrupt_work, priv, 0); + +#else + /* Process the interrupt now */ + + ez80emac_rxinterrupt_process(priv); +#endif + + return OK; +} + +/**************************************************************************** + * Function: ez80emac_sysinterrupt_process + * + * Description: + * System interrupt processing. This may be performed either within the + * interrupt handler or on the worker thread, depending upon the + * configuration + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static inline void ez80emac_sysinterrupt_process(FAR struct ez80emac_driver_s *priv) +{ uint8_t events; uint8_t istat; @@ -1636,30 +1876,119 @@ static int ez80emac_sysinterrupt(int irq, FAR void *context) EMAC_STAT(priv, rx_errors); EMAC_STAT(priv, rx_ovrerrors); } - return OK; } /**************************************************************************** - * Function: ez80emac_txtimeout + * Function: ez80emac_sysinterrupt_work * * Description: - * Our TX watchdog timed out. Called from the timer interrupt handler. - * The last TX never completed. Reset the hardware and start again. + * Perform system interrupt related work from the worker thread * * Parameters: - * argc - The number of available arguments - * arg - The first argument + * arg - The argument passed when work_queue() was called. * * Returned Value: - * None + * OK on success + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void ez80emac_sysinterrupt_work(FAR void *arg) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; + net_lock_t state; + + /* Process pending Ethernet interrupts */ + + state = net_lock(); + ez80emac_sysinterrupt_process(priv); + net_unlock(state); + + /* Re-enable Ethernet system interrupts */ + + up_enable_irq(EZ80_EMACSYS_IRQ); +} +#endif + +/**************************************************************************** + * Function: ez80emac_sysinterrupt + * + * Description: + * System interrupt handler + * + * Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success * * Assumptions: * ****************************************************************************/ -static void ez80emac_txtimeout(int argc, uint32_t arg, ...) +static int ez80emac_sysinterrupt(int irq, FAR void *context) +{ + FAR struct ez80emac_driver_s *priv = &g_emac; + +#ifdef CONFIG_NET_NOINTS + /* Disable further Ethernet interrupts. Because Ethernet interrupts are + * also disabled if the TX timeout event occurs, there can be no race + * condition here. + */ + + up_disable_irq(EZ80_EMACSYS_IRQ); + + /* TODO: Determine if a TX transfer just completed */ + + { + /* If a TX transfer just completed, then cancel the TX timeout so + * there will be no race condition between any subsequent timeout + * expiration and the deferred interrupt processing. + */ + + wd_cancel(priv->txtimeout); + } + + /* Cancel any pending poll work */ + + work_cancel(HPWORK, &priv->syswork); + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(ETHWORK, &priv->syswork, ez80emac_sysinterrupt_work, priv, 0); + +#else + /* Process the interrupt now */ + + ez80emac_sysinterrupt_process(priv); +#endif + + return OK; +} + +/**************************************************************************** + * Function: ez80emac_txtimeout_process + * + * Description: + * Process a TX timeout. Called from the either the watchdog timer + * expiration logic or from the worker thread, depending upon the + * configuration. The timeout means that the last TX never completed. + * Reset the hardware and start again. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void ez80emac_txtimeout_process(FAR struct ez80emac_driver_s *priv) { - FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; irqstate_t flags; /* Increment statistics and dump debug info */ @@ -1680,7 +2009,144 @@ static void ez80emac_txtimeout(int argc, uint32_t arg, ...) } /**************************************************************************** - * Function: ez80emac_polltimer + * Function: ez80emac_txtimeout_work + * + * Description: + * Perform TX timeout related work from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void ez80emac_txtimeout_work(FAR void *arg) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; + net_lock_t state; + + /* Process pending Ethernet interrupts */ + + state = net_lock(); + ez80emac_txtimeout_process(priv); + net_unlock(state); +} +#endif + +/**************************************************************************** + * Function: ez80emac_txtimeout_expiry + * + * Description: + * Our TX watchdog timed out. Called from the timer interrupt handler. + * The last TX never completed. Reset the hardware and start again. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void ez80emac_txtimeout_expiry(int argc, wdparm_t arg, ...) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; + +#ifdef CONFIG_NET_NOINTS + /* Disable further Ethernet Tx interrupts. This will prevent some race + * conditions with interrupt work. There is still a potential race + * condition with interrupt work that is already queued and in progress. + */ + + up_disable_irq(EZ80_EMACTX_IRQ); + + /* Cancel any pending poll or Tx interrupt work. This will have no + * effect on work that has already been started. + */ + + work_cancel(ETHWORK, &priv->txwork); + + /* Schedule to perform the TX timeout processing on the worker thread. */ + + work_queue(ETHWORK, &priv->txwork, ez80emac_txtimeout_work, priv, 0); +#else + /* Process the timeout now */ + + ez80emac_txtimeout_process(priv); +#endif +} + +/**************************************************************************** + * Function: ez80emac_poll_process + * + * Description: + * Perform the periodic poll. This may be called either from watchdog + * timer logic or from the worker thread, depending upon the configuration. + * + * Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static inline void ez80emac_poll_process(FAR struct ez80emac_driver_s *priv) +{ + /* Poll the network for new XMIT data */ + + (void)devif_timer(&priv->dev, ez80emac_txpoll); + + /* Setup the watchdog poll timer again */ + + (void)wd_start(priv->txpoll, EMAC_WDDELAY, ez80emac_poll_expiry, 1, priv); +} + +/**************************************************************************** + * Function: ez80emac_poll_work + * + * Description: + * Perform periodic polling from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void ez80emac_poll_work(FAR void *arg) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; + net_lock_t state; + + /* Perform the poll */ + + state = net_lock(); + ez80emac_poll_process(priv); + net_unlock(state); +} +#endif + +/**************************************************************************** + * Function: ez80emac_poll_expiry * * Description: * Periodic timer handler. Called from the timer interrupt handler. @@ -1693,20 +2159,39 @@ static void ez80emac_txtimeout(int argc, uint32_t arg, ...) * None * * Assumptions: + * Global interrupts are disabled by the watchdog logic. * ****************************************************************************/ -static void ez80emac_polltimer(int argc, uint32_t arg, ...) +static void ez80emac_poll_expiry(int argc, wdparm_t arg, ...) { - struct ez80emac_driver_s *priv = (struct ez80emac_driver_s *)arg; + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; - /* Poll the network for new XMIT data */ +#ifdef CONFIG_NET_NOINTS + /* Is our single work structure available? It may not be if there are + * pending interrupt actions. + */ - (void)devif_timer(&priv->dev, ez80emac_txpoll); + if (work_available(&priv->syswork)) + { + /* Schedule to perform the interrupt processing on the worker thread. */ - /* Setup the watchdog poll timer again */ + work_queue(ETHWORK, &priv->syswork, ez80emac_poll_work, priv, 0); + } + else + { + /* No.. Just re-start the watchdog poll timer, missing one polling + * cycle. + */ - (void)wd_start(priv->txpoll, EMAC_WDDELAY, ez80emac_polltimer, 1, arg); + (void)wd_start(priv->txpoll, EMAC_WDDELAY, ez80emac_poll_expiry, 1, arg); + } + +#else + /* Process the interrupt now */ + + ez80emac_poll_process(priv); +#endif } /**************************************************************************** @@ -1792,7 +2277,8 @@ static int ez80emac_ifup(FAR struct net_driver_s *dev) /* Set and activate a timer process */ - (void)wd_start(priv->txpoll, EMAC_WDDELAY, ez80emac_polltimer, 1, (uint32_t)priv); + (void)wd_start(priv->txpoll, EMAC_WDDELAY, ez80emac_poll_expiry, + 1, (uint32_t)priv); /* Enable the Ethernet interrupts */ @@ -1855,15 +2341,13 @@ static int ez80emac_ifdown(struct net_driver_s *dev) } /**************************************************************************** - * Function: ez80emac_txavail + * Function: ez80emac_txavail_process * * Description: - * Driver callback invoked when new TX data is available. This is a - * stimulus perform an out-of-cycle poll and, thereby, reduce the TX - * latency. + * Perform an out-of-cycle poll. * * Parameters: - * dev - Reference to the NuttX driver state structure + * dev - Reference to the NuttX driver state structure * * Returned Value: * None @@ -1873,26 +2357,102 @@ static int ez80emac_ifdown(struct net_driver_s *dev) * ****************************************************************************/ -static int ez80emac_txavail(struct net_driver_s *dev) +static inline void ez80emac_txavail_process(FAR struct ez80emac_driver_s *priv) { - struct ez80emac_driver_s *priv = (struct ez80emac_driver_s *)dev->d_private; - irqstate_t flags; - - flags = enter_critical_section(); - /* Ignore the notification if the interface is not yet up */ if (priv->bifup) { - /* Check if there is room in the hardware to hold another outgoing packet. */ /* If so, then poll the network for new XMIT data */ (void)devif_poll(&priv->dev, ez80emac_txpoll); } +} +/**************************************************************************** + * Function: ez80emac_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NOINTS +static void ez80emac_txavail_work(FAR void *arg) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)arg; + net_lock_t state; + + /* Perform the poll */ + + state = net_lock(); + ez80emac_txavail_process(priv); + net_unlock(state); +} +#endif + +/**************************************************************************** + * Function: ez80emac_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int ez80emac_txavail(FAR struct net_driver_s *dev) +{ + FAR struct ez80emac_driver_s *priv = (FAR struct ez80emac_driver_s *)dev->d_private; + +#ifdef CONFIG_NET_NOINTS + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ + + if (work_available(&priv->syswork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(ETHWORK, &priv->syswork, ez80emac_txavail_work, priv, 0); + } + +#else + irqstate_t flags; + + /* Disable interrupts because this function may be called from interrupt + * level processing. + */ + + flags = enter_critical_section(); + + /* Perform the out-of-cycle poll now */ + + ez80emac_txavail_process(priv); leave_critical_section(flags); +#endif + return OK; } diff --git a/arch/z80/src/ez80/ez80_irqsave.asm b/arch/z80/src/ez80/ez80_irqsave.asm index de3ad4a6e2..25edb630df 100644 --- a/arch/z80/src/ez80/ez80_irqsave.asm +++ b/arch/z80/src/ez80/ez80_irqsave.asm @@ -1,5 +1,5 @@ ;************************************************************************** -; arch/z80/src/ez80/ez80_up_irq_save.asm +; arch/z80/src/ez80/ez80_irqsave.asm ; ; Copyright (C) 2008 Gregory Nutt. All rights reserved. ; Author: Gregory Nutt diff --git a/configs/ez80f910200zco/dhcpd/defconfig b/configs/ez80f910200zco/dhcpd/defconfig index 5439089c19..126bf74026 100644 --- a/configs/ez80f910200zco/dhcpd/defconfig +++ b/configs/ez80f910200zco/dhcpd/defconfig @@ -148,6 +148,7 @@ CONFIG_EZ80_NRXPKTBUFS=64 CONFIG_EZ80_MDCDIV=0 CONFIG_EZ80_TXPOLLTIMERMS=10 # CONFIG_ARCH_MCFILTER is not set +CONFIG_EZ80_EMAC_HPWORK=y CONFIG_ARCH_TIMERHOOK=y # @@ -289,6 +290,7 @@ CONFIG_NAME_MAX=32 # CONFIG_SCHED_STARTHOOK is not set # CONFIG_SCHED_ATEXIT is not set # CONFIG_SCHED_ONEXIT is not set +# CONFIG_SIG_EVTHREAD is not set # # Signal Numbers @@ -296,13 +298,17 @@ CONFIG_NAME_MAX=32 CONFIG_SIG_SIGUSR1=1 CONFIG_SIG_SIGUSR2=2 CONFIG_SIG_SIGALARM=3 +CONFIG_SIG_SIGWORK=17 # CONFIG_MODULE is not set # # Work queue support # -# CONFIG_SCHED_WORKQUEUE is not set -# CONFIG_SCHED_HPWORK is not set +CONFIG_SCHED_WORKQUEUE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=224 +CONFIG_SCHED_HPWORKPERIOD=50000 +CONFIG_SCHED_HPWORKSTACKSIZE=2048 # CONFIG_SCHED_LPWORK is not set # @@ -393,7 +399,6 @@ CONFIG_ARCH_HAVE_NETDEV_STATISTICS=y # CONFIG_NET_DM90x0 is not set # CONFIG_ENC28J60 is not set # CONFIG_ENCX24J600 is not set - # CONFIG_NET_SLIP is not set # CONFIG_NET_FTMAC100 is not set @@ -495,7 +500,7 @@ CONFIG_SYSLOG_CONSOLE=y CONFIG_ARCH_HAVE_NET=y CONFIG_ARCH_HAVE_PHY=y CONFIG_NET=y -# CONFIG_NET_NOINTS is not set +CONFIG_NET_NOINTS=y # CONFIG_NET_PROMISCUOUS is not set # diff --git a/configs/ez80f910200zco/httpd/defconfig b/configs/ez80f910200zco/httpd/defconfig index 9e38b8322f..4177c0bc9b 100644 --- a/configs/ez80f910200zco/httpd/defconfig +++ b/configs/ez80f910200zco/httpd/defconfig @@ -148,6 +148,7 @@ CONFIG_EZ80_NRXPKTBUFS=64 CONFIG_EZ80_MDCDIV=0 CONFIG_EZ80_TXPOLLTIMERMS=10 # CONFIG_ARCH_MCFILTER is not set +CONFIG_EZ80_EMAC_HPWORK=y CONFIG_ARCH_TIMERHOOK=y # @@ -295,6 +296,7 @@ CONFIG_NAME_MAX=32 # CONFIG_SCHED_STARTHOOK is not set # CONFIG_SCHED_ATEXIT is not set # CONFIG_SCHED_ONEXIT is not set +# CONFIG_SIG_EVTHREAD is not set # # Signal Numbers @@ -303,13 +305,17 @@ CONFIG_SIG_SIGUSR1=1 CONFIG_SIG_SIGUSR2=2 CONFIG_SIG_SIGALARM=3 CONFIG_SIG_SIGCONDTIMEDOUT=16 +CONFIG_SIG_SIGWORK=17 # CONFIG_MODULE is not set # # Work queue support # -# CONFIG_SCHED_WORKQUEUE is not set -# CONFIG_SCHED_HPWORK is not set +CONFIG_SCHED_WORKQUEUE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=224 +CONFIG_SCHED_HPWORKPERIOD=50000 +CONFIG_SCHED_HPWORKSTACKSIZE=2048 # CONFIG_SCHED_LPWORK is not set # @@ -402,7 +408,6 @@ CONFIG_ARCH_HAVE_NETDEV_STATISTICS=y # CONFIG_NET_DM90x0 is not set # CONFIG_ENC28J60 is not set # CONFIG_ENCX24J600 is not set - # CONFIG_NET_SLIP is not set # CONFIG_NET_FTMAC100 is not set @@ -504,7 +509,7 @@ CONFIG_SYSLOG_CONSOLE=y CONFIG_ARCH_HAVE_NET=y CONFIG_ARCH_HAVE_PHY=y CONFIG_NET=y -# CONFIG_NET_NOINTS is not set +CONFIG_NET_NOINTS=y # CONFIG_NET_PROMISCUOUS is not set # diff --git a/configs/ez80f910200zco/nettest/defconfig b/configs/ez80f910200zco/nettest/defconfig index 1123421f92..99250b29d5 100644 --- a/configs/ez80f910200zco/nettest/defconfig +++ b/configs/ez80f910200zco/nettest/defconfig @@ -148,6 +148,7 @@ CONFIG_EZ80_NRXPKTBUFS=64 CONFIG_EZ80_MDCDIV=0 CONFIG_EZ80_TXPOLLTIMERMS=10 # CONFIG_ARCH_MCFILTER is not set +CONFIG_EZ80_EMAC_HPWORK=y CONFIG_ARCH_TIMERHOOK=y # @@ -289,6 +290,7 @@ CONFIG_NAME_MAX=32 # CONFIG_SCHED_STARTHOOK is not set # CONFIG_SCHED_ATEXIT is not set # CONFIG_SCHED_ONEXIT is not set +# CONFIG_SIG_EVTHREAD is not set # # Signal Numbers @@ -296,13 +298,17 @@ CONFIG_NAME_MAX=32 CONFIG_SIG_SIGUSR1=1 CONFIG_SIG_SIGUSR2=2 CONFIG_SIG_SIGALARM=3 +CONFIG_SIG_SIGWORK=17 # CONFIG_MODULE is not set # # Work queue support # -# CONFIG_SCHED_WORKQUEUE is not set -# CONFIG_SCHED_HPWORK is not set +CONFIG_SCHED_WORKQUEUE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=224 +CONFIG_SCHED_HPWORKPERIOD=50000 +CONFIG_SCHED_HPWORKSTACKSIZE=2048 # CONFIG_SCHED_LPWORK is not set # @@ -394,7 +400,6 @@ CONFIG_ARCH_HAVE_NETDEV_STATISTICS=y # CONFIG_NET_DM90x0 is not set # CONFIG_ENC28J60 is not set # CONFIG_ENCX24J600 is not set - # CONFIG_NET_SLIP is not set # CONFIG_NET_FTMAC100 is not set @@ -496,7 +501,7 @@ CONFIG_SYSLOG_CONSOLE=y CONFIG_ARCH_HAVE_NET=y CONFIG_ARCH_HAVE_PHY=y CONFIG_NET=y -# CONFIG_NET_NOINTS is not set +CONFIG_NET_NOINTS=y # CONFIG_NET_PROMISCUOUS is not set # diff --git a/configs/ez80f910200zco/nsh/defconfig b/configs/ez80f910200zco/nsh/defconfig index 6eacbefa3e..04dda2443e 100644 --- a/configs/ez80f910200zco/nsh/defconfig +++ b/configs/ez80f910200zco/nsh/defconfig @@ -148,6 +148,7 @@ CONFIG_EZ80_NRXPKTBUFS=64 CONFIG_EZ80_MDCDIV=0 CONFIG_EZ80_TXPOLLTIMERMS=10 # CONFIG_ARCH_MCFILTER is not set +CONFIG_EZ80_EMAC_HPWORK=y CONFIG_ARCH_TIMERHOOK=y # @@ -295,6 +296,7 @@ CONFIG_NAME_MAX=32 # CONFIG_SCHED_STARTHOOK is not set # CONFIG_SCHED_ATEXIT is not set # CONFIG_SCHED_ONEXIT is not set +# CONFIG_SIG_EVTHREAD is not set # # Signal Numbers @@ -303,13 +305,17 @@ CONFIG_SIG_SIGUSR1=1 CONFIG_SIG_SIGUSR2=2 CONFIG_SIG_SIGALARM=3 CONFIG_SIG_SIGCONDTIMEDOUT=16 +CONFIG_SIG_SIGWORK=17 # CONFIG_MODULE is not set # # Work queue support # -# CONFIG_SCHED_WORKQUEUE is not set -# CONFIG_SCHED_HPWORK is not set +CONFIG_SCHED_WORKQUEUE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=224 +CONFIG_SCHED_HPWORKPERIOD=50000 +CONFIG_SCHED_HPWORKSTACKSIZE=2048 # CONFIG_SCHED_LPWORK is not set # @@ -404,7 +410,6 @@ CONFIG_ARCH_HAVE_NETDEV_STATISTICS=y # CONFIG_NET_DM90x0 is not set # CONFIG_ENC28J60 is not set # CONFIG_ENCX24J600 is not set - # CONFIG_NET_SLIP is not set # CONFIG_NET_FTMAC100 is not set @@ -507,7 +512,7 @@ CONFIG_SYSLOG_CONSOLE=y CONFIG_ARCH_HAVE_NET=y CONFIG_ARCH_HAVE_PHY=y CONFIG_NET=y -# CONFIG_NET_NOINTS is not set +CONFIG_NET_NOINTS=y # CONFIG_NET_PROMISCUOUS is not set # diff --git a/configs/ez80f910200zco/poll/defconfig b/configs/ez80f910200zco/poll/defconfig index e7919f583d..770d89d9bb 100644 --- a/configs/ez80f910200zco/poll/defconfig +++ b/configs/ez80f910200zco/poll/defconfig @@ -148,6 +148,7 @@ CONFIG_EZ80_NRXPKTBUFS=64 CONFIG_EZ80_MDCDIV=0 CONFIG_EZ80_TXPOLLTIMERMS=10 # CONFIG_ARCH_MCFILTER is not set +CONFIG_EZ80_EMAC_HPWORK=y CONFIG_ARCH_TIMERHOOK=y # @@ -295,6 +296,7 @@ CONFIG_NAME_MAX=32 # CONFIG_SCHED_STARTHOOK is not set # CONFIG_SCHED_ATEXIT is not set # CONFIG_SCHED_ONEXIT is not set +# CONFIG_SIG_EVTHREAD is not set # # Signal Numbers @@ -303,13 +305,17 @@ CONFIG_SIG_SIGUSR1=1 CONFIG_SIG_SIGUSR2=2 CONFIG_SIG_SIGALARM=3 CONFIG_SIG_SIGCONDTIMEDOUT=16 +CONFIG_SIG_SIGWORK=17 # CONFIG_MODULE is not set # # Work queue support # -# CONFIG_SCHED_WORKQUEUE is not set -# CONFIG_SCHED_HPWORK is not set +CONFIG_SCHED_WORKQUEUE=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=224 +CONFIG_SCHED_HPWORKPERIOD=50000 +CONFIG_SCHED_HPWORKSTACKSIZE=2048 # CONFIG_SCHED_LPWORK is not set # @@ -401,7 +407,6 @@ CONFIG_ARCH_HAVE_NETDEV_STATISTICS=y # CONFIG_NET_DM90x0 is not set # CONFIG_ENC28J60 is not set # CONFIG_ENCX24J600 is not set - # CONFIG_NET_SLIP is not set # CONFIG_NET_FTMAC100 is not set @@ -506,7 +511,7 @@ CONFIG_SYSLOG_CONSOLE=y CONFIG_ARCH_HAVE_NET=y CONFIG_ARCH_HAVE_PHY=y CONFIG_NET=y -# CONFIG_NET_NOINTS is not set +CONFIG_NET_NOINTS=y # CONFIG_NET_PROMISCUOUS is not set # diff --git a/include/debug.h b/include/debug.h index c2fc93dd53..0bde25605b 100644 --- a/include/debug.h +++ b/include/debug.h @@ -810,7 +810,7 @@ #ifdef CONFIG_DEBUG_CRYPTO_INFO # define cryptinfo _info #else -# define cryptinfo(x...) +# define cryptinfo (void) #endif #ifdef CONFIG_DEBUG_INPUT_ERROR