LPC17xx Ethernet: Improve CONFIG_NET_NOINTS implementation

This commit is contained in:
Gregory Nutt 2015-06-01 08:07:32 -06:00
parent aaeee801b8
commit 4f05c80794
4 changed files with 413 additions and 132 deletions

2
TODO
View File

@ -880,7 +880,7 @@ o Network (net/, drivers/net)
LM3S NO NO
TM4C YES YES
eZ80 NO NO
LPC17xx YES (could be issues) YES (not tested)
LPC17xx YES YES (not tested)
DMxxx NIC NO NO
PIC32 NO NO
RGMP ??? ???

View File

@ -729,14 +729,6 @@ config NET_MULTICAST
---help---
Enable receipt of multicast (and unicast) frames. Automatically set
if NET_IGMP is selected.
config NET_WORKER_THREAD
bool "Net worker thread enable"
default y
depends on SCHED_WORKQUEUE
---help---
Enable use of ethernet worker thread (depends on CONFIG_SCHED_WORKQUEUE).
endmenu
menu "LCD device driver options"

View File

@ -52,12 +52,15 @@
#include <nuttx/wdog.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#ifdef CONFIG_NET_PKT
# include <nuttx/net/pkt.h>
#endif
@ -72,15 +75,22 @@
#include <arch/board/board.h>
/* Does this chip have and ethernet controller? */
/* Does this chip have and Ethernet controller? */
#if LPC17_NETHCONTROLLERS > 0
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* If processing is not done at the interrupt level, then high priority
* work queue support is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_HPWORK)
# error High priority work queue support is required
#endif
/* CONFIG_LPC17_NINTERFACES determines the number of physical interfaces
* that will be supported -- unless it is more than actually supported by the
* hardware!
@ -150,8 +160,10 @@
/* Interrupts ***************************************************************/
#define ETH_RXINTS (ETH_INT_RXOVR | ETH_INT_RXERR | ETH_INT_RXFIN | ETH_INT_RXDONE)
#define ETH_TXINTS (ETH_INT_TXUNR | ETH_INT_TXERR | ETH_INT_TXFIN | ETH_INT_TXDONE)
#define ETH_RXINTS (ETH_INT_RXOVR | ETH_INT_RXERR | \
ETH_INT_RXFIN | ETH_INT_RXDONE)
#define ETH_TXINTS (ETH_INT_TXUNR | ETH_INT_TXERR | \
ETH_INT_TXFIN | ETH_INT_TXDONE)
/* Misc. Helpers ***********************************************************/
@ -285,19 +297,20 @@ struct lpc17_driver_s
WDOG_ID lp_txpoll; /* TX poll timer */
WDOG_ID lp_txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_WORKER_THREAD
struct work_s irqwork_txdone; /* Interrupt continuation work queue support */
struct work_s irqwork_rxdone; /* Interrupt continuation work queue support */
#ifdef CONFIG_NET_NOINTS
struct work_s lp_txwork; /* TX work continuation */
struct work_s lp_rxwork; /* RX work continuation */
struct work_s lp_pollwork; /* Poll work continuation */
uint32_t status;
#endif /*CONFIG_NET_WORKER_THREAD*/
#endif /* CONFIG_NET_NOINTS */
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
struct lpc17_statistics_s lp_stat;
#endif
/* This holds the information visible to uIP/NuttX */
/* This holds the information visible to the NuttX networking layer */
struct net_driver_s lp_dev; /* Interface understood by uIP */
struct net_driver_s lp_dev; /* Interface understood by the network layer */
};
/****************************************************************************
@ -346,18 +359,27 @@ static int lpc17_txpoll(struct net_driver_s *dev);
/* Interrupt handling */
static void lpc17_response(struct lpc17_driver_s *priv);
static void lpc17_rxdone(struct lpc17_driver_s *priv);
static void lpc17_txdone(struct lpc17_driver_s *priv);
#ifdef CONFIG_NET_WORKER_THREAD
static void lpc17_eth_irqworker_txdone(FAR void *arg);
static void lpc17_eth_irqworker_rxdone(FAR void *arg);
#endif /*CONFIG_NET_WORKER_THREAD*/
static void lpc17_rxdone_process(struct lpc17_driver_s *priv);
static void lpc17_txdone_process(struct lpc17_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc17_txdone_work(FAR void *arg);
static void lpc17_rxdone_work(FAR void *arg);
#endif /* CONFIG_NET_NOINTS */
static int lpc17_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static void lpc17_polltimer(int argc, uint32_t arg, ...);
static void lpc17_txtimeout(int argc, uint32_t arg, ...);
static void lpc17_txtimeout_process(FAR struct lpc17_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc17_txtimeout_work(FAR void *arg);
#endif /* CONFIG_NET_NOINTS */
static void lpc17_txtimeout_expiry(int argc, uint32_t arg, ...);
static void lpc17_poll_process(FAR struct lpc17_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc17_poll_work(FAR void *arg);
#endif /* CONFIG_NET_NOINTS */
static void lpc17_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@ -366,6 +388,11 @@ static void lpc17_ipv6multicast(FAR struct lpc17_driver_s *priv);
#endif
static int lpc17_ifup(struct net_driver_s *dev);
static int lpc17_ifdown(struct net_driver_s *dev);
static void lpc17_txavail_process(FAR struct lpc17_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc17_txavail_work(FAR void *arg);
#endif
static int lpc17_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static uint32_t lpc17_calcethcrc(const uint8_t *data, size_t length);
@ -663,7 +690,7 @@ static int lpc17_transmit(struct lpc17_driver_s *priv)
/* Setup the TX timeout watchdog (perhaps restarting the timer) */
(void)wd_start(priv->lp_txtimeout, LPC17_TXTIMEOUT, lpc17_txtimeout,
(void)wd_start(priv->lp_txtimeout, LPC17_TXTIMEOUT, lpc17_txtimeout_expiry,
1, (uint32_t)priv);
return OK;
}
@ -672,8 +699,9 @@ static int lpc17_transmit(struct lpc17_driver_s *priv)
* Function: lpc17_txpoll
*
* Description:
* The transmitter is available, check if uIP has any outgoing packets ready
* to send. This is a callback from devif_poll(). devif_poll() may be called:
* The transmitter is available, check if the network layer has any
* outgoing packets ready to send. This is a callback from devif_poll().
* devif_poll() may be called:
*
* 1. When the preceding TX packet send is complete,
* 2. When the preceding TX packet send timesout and the interface is reset
@ -784,19 +812,21 @@ static void lpc17_response(struct lpc17_driver_s *priv)
}
else
{
/* No.. mark the Tx as pending and halt further Tx interrupts */
/* No.. mark the Tx as pending and halt further RX interrupts that
* could generate more TX activity.
*/
DEBUGASSERT((priv->lp_inten & ETH_INT_TXDONE) != 0);
priv->lp_txpending = true;
priv->lp_inten &= ~ETH_TXINTS;
priv->lp_inten &= ~ETH_RXINTS;
lpc17_putreg(priv->lp_inten, LPC17_ETH_INTEN);
EMAC_STAT(priv, tx_pending);
}
}
/****************************************************************************
* Function: lpc17_rxdone
* Function: lpc17_rxdone_process
*
* Description:
* An interrupt was received indicating the availability of a new RX packet
@ -812,7 +842,7 @@ static void lpc17_response(struct lpc17_driver_s *priv)
*
****************************************************************************/
static void lpc17_rxdone(struct lpc17_driver_s *priv)
static void lpc17_rxdone_process(struct lpc17_driver_s *priv)
{
uint32_t *rxstat;
bool fragment;
@ -1036,7 +1066,7 @@ static void lpc17_rxdone(struct lpc17_driver_s *priv)
}
/****************************************************************************
* Function: lpc17_txdone
* Function: lpc17_txdone_process
*
* Description:
* An interrupt was received indicating that the last TX packet(s) is done
@ -1052,19 +1082,8 @@ static void lpc17_rxdone(struct lpc17_driver_s *priv)
*
****************************************************************************/
static void lpc17_txdone(struct lpc17_driver_s *priv)
static void lpc17_txdone_process(struct lpc17_driver_s *priv)
{
/* Cancel the pending Tx timeout */
wd_cancel(priv->lp_txtimeout);
/* Disable further Tx interrupts. Tx interrupts may be re-enabled again
* depending upon the result of the poll.
*/
priv->lp_inten &= ~ETH_TXINTS;
lpc17_putreg(priv->lp_inten, LPC17_ETH_INTEN);
/* Verify that the hardware is ready to send another packet. Since a Tx
* just completed, this must be the case.
*/
@ -1084,11 +1103,11 @@ static void lpc17_txdone(struct lpc17_driver_s *priv)
lpc17_transmit(priv);
priv->lp_inten |= ETH_RXINTS;
priv->lp_inten |= ETH_RXINTS;
lpc17_putreg(priv->lp_inten, LPC17_ETH_INTEN);
}
/* Otherwise poll uIP for new XMIT data */
/* Otherwise poll the network layer for new XMIT data */
else
{
@ -1097,7 +1116,7 @@ static void lpc17_txdone(struct lpc17_driver_s *priv)
}
/****************************************************************************
* Function: lpc17_eth_irqworker_txdone and lpc17_eth_irqworker_rxdone
* Function: lpc17_txdone_work and lpc17_rxdone_work
*
* Description:
* Perform interrupt handling logic outside of the interrupt handler (on
@ -1113,28 +1132,55 @@ static void lpc17_txdone(struct lpc17_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_WORKER_THREAD
static void lpc17_eth_irqworker_txdone(FAR void *arg)
#ifdef CONFIG_NET_NOINTS
static void lpc17_txdone_work(FAR void *arg)
{
FAR struct lpc17_driver_s *priv = (FAR struct lpc17_driver_s *)arg;
irqstate_t flags;
net_lock_t state;
DEBUGASSERT(priv);
lpc17_txdone(priv);
/* Perform pending TX work. At this point TX interrupts are disable but
* may be re-enabled again depending on the actions of
* lpc17_txdone_process().
*/
work_cancel(HPWORK, &priv->irqwork_txdone);
state = net_lock();
lpc17_txdone_process(priv);
net_unlock(state);
}
static void lpc17_eth_irqworker_rxdone(FAR void *arg)
static void lpc17_rxdone_work(FAR void *arg)
{
FAR struct lpc17_driver_s *priv = (FAR struct lpc17_driver_s *)arg;
irqstate_t flags;
net_lock_t state;
DEBUGASSERT(priv);
lpc17_rxdone(priv);
work_cancel(HPWORK, &priv->irqwork_rxdone);
/* Perform pending RX work. RX interrupts were disabled prior to
* scheduling this work to prevent work queue overruns.
*/
state = net_lock();
lpc17_rxdone_process(priv);
net_unlock(state);
/* Re-enable RX interrupts (this must be atomic). Skip this step if the
* lp-txpending TX underrun state is in effect.
*/
flags = irqsave();
if (!priv->lp_txpending)
{
priv->lp_inten |= ETH_RXINTS;
lpc17_putreg(priv->lp_inten, LPC17_ETH_INTEN);
}
irqrestore(flags);
}
#endif /*CONFIG_NET_WORKER_THREAD */
#endif /* CONFIG_NET_NOINTS */
/****************************************************************************
* Function: lpc17_interrupt
@ -1218,7 +1264,7 @@ static int lpc17_interrupt(int irq, void *context)
/* Check for receive events ***************************************/
/* RX ERROR -- Triggered on receive errors: AlignmentError,
* RangeError, LengthError, SymbolError, CRCError or NoDescriptor
* or Overrun. NOTE: (1) We will still need to call lpc17_rxdone
* or Overrun. NOTE: (1) We will still need to call lpc17_rxdone_process
* on RX errors to bump the considx over the bad packet. (2) The
* DMA engine reports bogus length errors, making this a pretty
* useless check anyway.
@ -1248,21 +1294,34 @@ static int lpc17_interrupt(int irq, void *context)
/* We have received at least one new incoming packet. */
#ifdef CONFIG_NET_WORKER_THREAD
work_queue(HPWORK, &priv->irqwork_rxdone,
(worker_t)lpc17_eth_irqworker_rxdone,
#ifdef CONFIG_NET_NOINTS
/* Disable further TX interrupts for now. TX interrupts will
* be re-enabled after the work has been processed.
*/
priv->lp_inten &= ~ETH_RXINTS;
lpc17_putreg(priv->lp_inten, LPC17_ETH_INTEN);
/* Cancel any pending RX done work */
work_cancel(HPWORK, &priv->lp_rxwork);
/* Schedule TX-related work to be performed on the work thread */
work_queue(HPWORK, &priv->lp_rxwork,
(worker_t)lpc17_rxdone_work,
(FAR void *)priv, 0);
#else /*CONFIG_NET_WORKER_THREAD*/
lpc17_rxdone(priv);
#else /* CONFIG_NET_NOINTS */
lpc17_rxdone_process(priv);
#endif /*CONFIG_NET_WORKER_THREAD*/
#endif /* CONFIG_NET_NOINTS */
}
/* Check for Tx events ********************************************/
/* TX ERROR -- Triggered on transmit errors: LateCollision,
* ExcessiveCollision and ExcessiveDefer, NoDescriptor or Underrun.
* NOTE: We will still need to call lpc17_txdone() in order to
* NOTE: We will still need to call lpc17_txdone_process() in order to
* clean up after the failed transmit.
*/
@ -1292,20 +1351,35 @@ static int lpc17_interrupt(int irq, void *context)
EMAC_STAT(priv, tx_done);
/* A packet transmission just completed */
/* Cancel the pending Tx timeout */
#ifdef CONFIG_NET_WORKER_THREAD
/* Disable the Ethernet interrupt for now, will be re-enabled
* later
wd_cancel(priv->lp_txtimeout);
/* Disable further Tx interrupts. Tx interrupts may be
* re-enabled again depending upon the actions of
* lpc17_txdone_process()
*/
work_queue(HPWORK, &priv->irqwork_txdone,
(worker_t)lpc17_eth_irqworker_txdone,
priv->lp_inten &= ~ETH_TXINTS;
lpc17_putreg(priv->lp_inten, LPC17_ETH_INTEN);
#ifdef CONFIG_NET_NOINTS
/* Cancel any pending TX done work */
work_cancel(HPWORK, &priv->lp_txwork);
/* Schedule TX-related work to be performed on the work thread */
work_queue(HPWORK, &priv->lp_txwork,
(worker_t)lpc17_txdone_work,
(FAR void *)priv, 0);
#else /*CONFIG_NET_WORKER_THREAD*/
lpc17_txdone(priv);
#else /* CONFIG_NET_NOINTS */
/* Perform the TX work at the interrupt level */
#endif /*CONFIG_NET_WORKER_THREAD*/
lpc17_txdone_process(priv);
#endif /* CONFIG_NET_NOINTS */
}
}
}
@ -1324,7 +1398,74 @@ static int lpc17_interrupt(int irq, void *context)
}
/****************************************************************************
* Function: lpc17_txtimeout
* Function: lpc17_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 void lpc17_txtimeout_process(FAR struct lpc17_driver_s *priv)
{
/* Increment statistics and dump debug info */
EMAC_STAT(priv, tx_timeouts);
if (priv->lp_ifup)
{
/* Then reset the hardware. ifup() will reset the interface, then bring
* it back up.
*/
(void)lpc17_ifup(&priv->lp_dev);
/* Then poll the network layer for new XMIT data */
(void)devif_poll(&priv->lp_dev, lpc17_txpoll);
}
}
/****************************************************************************
* Function: lpc17_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:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc17_txtimeout_work(FAR void *arg)
{
FAR struct lpc17_driver_s *priv = (FAR struct lpc17_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
lpc17_txtimeout_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: lpc17_txtimeout_expiry
*
* Description:
* Our TX watchdog timed out. Called from the timer interrupt handler.
@ -1342,48 +1483,55 @@ static int lpc17_interrupt(int irq, void *context)
*
****************************************************************************/
static void lpc17_txtimeout(int argc, uint32_t arg, ...)
static void lpc17_txtimeout_expiry(int argc, uint32_t arg, ...)
{
struct lpc17_driver_s *priv = (struct lpc17_driver_s *)arg;
/* Increment statistics and dump debug info */
/* Disable further Tx interrupts. Tx interrupts may be re-enabled again
* depending upon the actions of lpc17_poll_process()
*/
EMAC_STAT(priv, tx_timeouts);
if (priv->lp_ifup)
priv->lp_inten &= ~ETH_TXINTS;
lpc17_putreg(priv->lp_inten, LPC17_ETH_INTEN);
#ifdef CONFIG_NET_NOINTS
/* Is the single TX work structure available? If not, then there is
* pending TX work to be done this must be a false alarm TX timeout.
*/
if (work_available(&priv->lp_txwork))
{
/* Then reset the hardware. ifup() will reset the interface, then bring
* it back up.
*/
/* Schedule to perform the interrupt processing on the worker thread. */
(void)lpc17_ifup(&priv->lp_dev);
/* Then poll uIP for new XMIT data */
(void)devif_poll(&priv->lp_dev, lpc17_txpoll);
work_queue(HPWORK, &priv->lp_txwork, lpc17_poll_work, priv, 0);
}
#else
/* Process the timeout now */
lpc17_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: lpc17_polltimer
* Function: lpc17_poll_process
*
* Description:
* Periodic timer handler. Called from the timer interrupt handler.
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* argc - The number of available arguments
* arg - The first argument
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static void lpc17_polltimer(int argc, uint32_t arg, ...)
static void lpc17_poll_process(FAR struct lpc17_driver_s *priv)
{
struct lpc17_driver_s *priv = (struct lpc17_driver_s *)arg;
unsigned int prodidx;
unsigned int considx;
@ -1393,9 +1541,9 @@ static void lpc17_polltimer(int argc, uint32_t arg, ...)
if (lpc17_txdesc(priv) == OK)
{
/* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm..
* might be bug here. Does this mean if there is a transmit in progress,
* we will missing TCP time state updates?
/* If so, update TCP timing states and poll the network layer for new
* XMIT data. Hmmm.. might be bug here. Does this mean if there is a
* transmit in progress, we will missing TCP time state updates?
*/
(void)devif_timer(&priv->lp_dev, lpc17_txpoll, LPC17_POLLHSEC);
@ -1412,20 +1560,103 @@ static void lpc17_polltimer(int argc, uint32_t arg, ...)
if (considx != prodidx)
{
#if CONFIG_NET_WORKER_THREAD
work_queue(HPWORK, &priv->irqwork_rxdone,
(worker_t)lpc17_eth_irqworker_rxdone,
#if CONFIG_NET_NOINTS
work_queue(HPWORK, &priv->lp_rxwork,
(worker_t)lpc17_rxdone_work,
(FAR void *)priv, 0);
#else /*CONFIG_NET_WORKER_THREAD*/
lpc17_rxdone(priv);
#else /* CONFIG_NET_NOINTS */
lpc17_rxdone_process(priv);
#endif /*CONFIG_NET_WORKER_THREAD*/
#endif /* CONFIG_NET_NOINTS */
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->lp_txpoll, LPC17_WDDELAY, lpc17_polltimer, 1, arg);
(void)wd_start(priv->lp_txpoll, LPC17_WDDELAY, lpc17_poll_expiry, 1, priv);
}
/****************************************************************************
* Function: lpc17_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:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc17_poll_work(FAR void *arg)
{
FAR struct lpc17_driver_s *priv = (FAR struct lpc17_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
lpc17_poll_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: lpc17_poll_expiry
*
* Description:
* Periodic timer handler. Called from the timer interrupt handler.
*
* 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 lpc17_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct lpc17_driver_s *priv = (FAR struct lpc17_driver_s *)arg;
DEBUGASSERT(arg);
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
if (work_available(&priv->lpc17_poll_work))
{
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(HPWORK, &priv->lpc17_poll_work, lpc17_poll_work, priv, 0);
}
else
{
/* No.. Just re-start the watchdog poll timer, missing one polling
* cycle.
*/
(void)wd_start(priv->lp_txpoll, LPC17_WDDELAY, lpc17_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
lpc17_poll_process(priv);
#endif
}
/****************************************************************************
@ -1661,7 +1892,7 @@ static int lpc17_ifup(struct net_driver_s *dev)
/* Set and activate a timer process */
(void)wd_start(priv->lp_txpoll, LPC17_WDDELAY, lpc17_polltimer, 1,
(void)wd_start(priv->lp_txpoll, LPC17_WDDELAY, lpc17_poll_expiry, 1,
(uint32_t)priv);
/* Finally, make the interface up and enable the Ethernet interrupt at
@ -1716,6 +1947,74 @@ static int lpc17_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: lpc17_txavail_process
*
* Description:
* Perform an out-of-cycle poll.
*
* Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called in normal user mode
*
****************************************************************************/
static inline void lpc17_txavail_process(FAR struct lpc17_driver_s *priv)
{
net_lock_t state;
/* Ignore the notification if the interface is not yet up */
state = net_lock();
if (priv->lp_ifup)
{
/* Check if there is room in the hardware to hold another outgoing packet. */
if (lpc17_txdesc(priv) == OK)
{
/* If so, then poll the network layer for new XMIT data */
(void)devif_poll(&priv->lp_dev, lpc17_txpoll);
}
}
net_unlock(state);
return OK;
}
/****************************************************************************
* Function: lpc17_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 lpc17_txavail_work(FAR void *arg)
{
FAR struct lpc17_driver_s *priv = (FAR struct lpc17_driver_s *)arg;
/* Perform the poll */
lpc17_txavail_process(priv);
}
#endif
/****************************************************************************
* Function: lpc17_txavail
*
@ -1737,36 +2036,29 @@ static int lpc17_ifdown(struct net_driver_s *dev)
static int lpc17_txavail(struct net_driver_s *dev)
{
struct lpc17_driver_s *priv = (struct lpc17_driver_s *)dev->d_private;
#ifndef CONFIG_NET_WORKER_THREAD
irqstate_t flags;
#endif /*CONFIG_NET_WORKER_THREAD*/
FAR struct lpc17_driver_s *priv = (FAR struct lpc17_driver_s *)dev->d_private;
/* Disable interrupts because this function may be called from interrupt
* level processing.
#ifdef CONFIG_NET_NOINTS
/* Is our single poll work structure available? It may not be if there
* are pending polling actions and we will have to ignore the Tx
* availability action (which is okay because all poll actions have,
* ultimately, the same effect.
*/
#ifndef CONFIG_NET_WORKER_THREAD
flags = irqsave();
#endif /*CONFIG_NET_WORKER_THREAD*/
/* Ignore the notification if the interface is not yet up */
if (priv->lp_ifup)
if (work_available(&priv->sk_work))
{
/* Check if there is room in the hardware to hold another outgoing packet. */
/* Schedule to serialize the poll on the worker thread. */
if (lpc17_txdesc(priv) == OK)
{
/* If so, then poll uIP for new XMIT data */
(void)devif_poll(&priv->lp_dev, lpc17_txpoll);
}
work_queue(HPWORK, &priv->sk_work, lpc17_txavail_work, priv, 0);
}
#ifndef CONFIG_NET_WORKER_THREAD
irqrestore(flags);
#endif /*CONFIG_NET_WORKER_THREAD*/
#else
/* Perform the out-of-cycle poll now */
lpc17_txavail_process(priv);
#endif
return OK;
}

View File

@ -598,9 +598,6 @@ static int skel_interrupt(int irq, FAR void *context)
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void skel_txtimeout_process(FAR struct skel_driver_s *priv)