Tive Ethernet: Fix some race conditions in the driver that become apparent when debug is enabled

This commit is contained in:
Gregory Nutt
2015-01-17 10:59:45 -06:00
parent f5824701b7
commit 30183a73be
+87 -11
View File
@@ -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;
}