diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-12-31 06:37:14 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-12-31 06:37:14 -0600 |
commit | cc1340f6ba00bc2295d8ebb64a59a2c7ff2989e1 (patch) | |
tree | 53f6323e851997f1161c4d886b0333e54bb9c189 | |
parent | 38e156745d164c33298c128ea71a7adfef3ee469 (diff) | |
download | px4-nuttx-cc1340f6ba00bc2295d8ebb64a59a2c7ff2989e1.tar.gz px4-nuttx-cc1340f6ba00bc2295d8ebb64a59a2c7ff2989e1.tar.bz2 px4-nuttx-cc1340f6ba00bc2295d8ebb64a59a2c7ff2989e1.zip |
Update drivers/net/skeleton.c
-rw-r--r-- | nuttx/drivers/net/skeleton.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/nuttx/drivers/net/skeleton.c b/nuttx/drivers/net/skeleton.c index 5d012811d..28d2a3f6d 100644 --- a/nuttx/drivers/net/skeleton.c +++ b/nuttx/drivers/net/skeleton.c @@ -106,7 +106,7 @@ struct skel_driver_s WDOG_ID sk_txpoll; /* TX poll timer */ WDOG_ID sk_txtimeout; /* TX timeout timer */ #ifdef CONFIG_NET_NOINTS - struct work_s work; /* For deferring work to the work queue */ + struct work_s sk_work; /* For deferring work to the work queue */ #endif /* This holds the information visible to uIP/NuttX */ @@ -397,7 +397,7 @@ static inline void skel_interrupt_process(FAR struct skel_driver_s *skel) * Perform interrupt related work from the worker thread * * Parameters: - * arg - The argument passed when work_queue() as called. + * arg - The argument passed when work_queue() was called. * * Returned Value: * OK on success @@ -442,14 +442,18 @@ static int skel_interrupt(int irq, FAR void *context) FAR struct skel_driver_s *skel = &g_skel[0]; #ifdef CONFIG_NET_NOINTS - /* TODO: Disable further Ethernet interrupts */ - - /* Schedule to perform the interrupt processing on the worker thread. - * TODO: Assure that no timeouts can occur. + /* TODO: Disable further Ethernet interrupts. Because Ethernet interrupts + * are also disabled if the TX timeout event occurs, there can be no race + * condition here. */ - DEBUGASSERT(work_available(&skel->work); - work_queue(HPWORK, &skel->work, skel_interrupt_work, skel, 0); + /* Cancel any pending poll work */ + + work_cancel(HPWORK, skel->sk_work); + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(HPWORK, &skel->sk_work, skel_interrupt_work, skel, 0); #else /* Process the interrupt now */ @@ -542,14 +546,22 @@ static void skel_txtimeout(int argc, uint32_t arg, ...) FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg; #ifdef CONFIG_NET_NOINTS - /* TODO: Disable further Ethernet interrupts */ + /* TODO: Disable further Ethernet 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. + */ + + /* Cancel any pending poll or interrupt work. This will have not effect + * on work that has already been started. + */ + + work_cancel(HPWORK, skel->sk_work); /* Schedule to perform the TX timeout processing on the worker thread. * TODO: Assure that no there is not pending interrupt or poll work. */ - DEBUGASSERT(work_available(&skel->work); - work_queue(HPWORK, &skel->work, skel_txtimeout_work, skel, 0); + work_queue(HPWORK, &skel->sk_work, skel_txtimeout_work, skel, 0); #else /* Process the interrupt now */ @@ -643,12 +655,27 @@ static void skel_polltimer(int argc, uint32_t arg, ...) FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg; #ifdef CONFIG_NET_NOINTS - /* Schedule to perform the interrupt processing on the worker thread. - * TODO: Make sure that there can be no pending interrupt work. + /* Is our single work structure available? It may not be if there are + * pending interrupt actions. */ - DEBUGASSERT(work_available(&skel->work); - work_queue(HPWORK, &skel->work, skel_poll_work, skel, 0); + if (work_available(&skel->sk_work) + { + /* Schedule to perform the interrupt processing on the worker thread. + * TODO: Make sure that there can be no pending interrupt work. + */ + + work_queue(HPWORK, &skel->sk_work, skel_poll_work, skel, 0); + } + else + { + /* No.. Just re-start the watchdog poll timer, missing one polling + * cycle. + */ + + (void)wd_start(skel->sk_txpoll, skeleton_WDDELAY, skel_polltimer, 1, arg); + } + #else /* Process the interrupt now */ |