diff --git a/arch/arm/src/tiva/tm4c_ethernet.c b/arch/arm/src/tiva/tm4c_ethernet.c index 8ef82c0e193..98efdb2ea3a 100644 --- a/arch/arm/src/tiva/tm4c_ethernet.c +++ b/arch/arm/src/tiva/tm4c_ethernet.c @@ -726,6 +726,10 @@ static void tiva_poll_expiry(int argc, uint32_t arg, ...); static int tiva_ifup(struct net_driver_s *dev); static int tiva_ifdown(struct net_driver_s *dev); +static inline void tiva_txavail_process(FAR struct tiva_ethmac_s *priv); +#ifdef CONFIG_NET_NOINTS +static void tiva_txavail_work(FAR void *arg); +#endif static int tiva_txavail(struct net_driver_s *dev); #ifdef CONFIG_NET_IGMP static int tiva_addmac(struct net_driver_s *dev, FAR const uint8_t *mac); @@ -1820,7 +1824,7 @@ static void tiva_receive(FAR struct tiva_ethmac_s *priv) static void tiva_freeframe(FAR struct tiva_ethmac_s *priv) { - struct emac_txdesc_s *txdesc; + FAR struct emac_txdesc_s *txdesc; int i; nvdbg("txhead: %p txtail: %p inflight: %d\n", @@ -1916,11 +1920,15 @@ static void tiva_freeframe(FAR struct tiva_ethmac_s *priv) static void tiva_txdone(FAR struct tiva_ethmac_s *priv) { + FAR struct net_driver_s *dev = &priv->dev; + DEBUGASSERT(priv->txtail != NULL); /* Scan the TX descriptor change, returning buffers to free list */ tiva_freeframe(priv); + dev->d_buf = NULL; + dev->d_len = 0; /* If no further xmits are pending, then cancel the TX timeout */ @@ -2501,6 +2509,65 @@ static int tiva_ifdown(struct net_driver_s *dev) return OK; } +/**************************************************************************** + * Function: tiva_txavail_process + * + * Description: + * Perform an out-of-cycle poll. + * + * Parameters: + * priv - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static inline void tiva_txavail_process(FAR struct tiva_ethmac_s *priv) +{ + nvdbg("ifup: %d\n", priv->ifup); + + /* Ignore the notification if the interface is not yet up */ + + if (priv->ifup) + { + /* Poll uIP for new XMIT data */ + + tiva_dopoll(priv); + } +} + +/**************************************************************************** + * Function: tiva_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 tiva_txavail_work(FAR void *arg) +{ + FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg; + + /* Perform the poll */ + + tiva_txavail_process(priv); +} +#endif + /**************************************************************************** * Function: tiva_txavail * @@ -2523,9 +2590,22 @@ static int tiva_ifdown(struct net_driver_s *dev) static int tiva_txavail(struct net_driver_s *dev) { FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)dev->d_private; - irqstate_t flags; - nvdbg("ifup: %d\n", priv->ifup); +#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->work)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &priv->work, tiva_txavail_work, priv, 0); + } + +#else + irqstate_t flags; /* Disable interrupts because this function may be called from interrupt * level processing. @@ -2533,16 +2613,12 @@ static int tiva_txavail(struct net_driver_s *dev) flags = irqsave(); - /* Ignore the notification if the interface is not yet up */ - - if (priv->ifup) - { - /* Poll uIP for new XMIT data */ - - tiva_dopoll(priv); - } + /* Perform the out-of-cycle poll now */ + tiva_txavail_process(priv); irqrestore(flags); +#endif + return OK; }