Tive Ethernet: Fix some race conditions in the driver that become apparent when debug is enabled
This commit is contained in:
parent
26499b440b
commit
b7c0bfebd5
@ -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_ifup(struct net_driver_s *dev);
|
||||||
static int tiva_ifdown(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);
|
static int tiva_txavail(struct net_driver_s *dev);
|
||||||
#ifdef CONFIG_NET_IGMP
|
#ifdef CONFIG_NET_IGMP
|
||||||
static int tiva_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
|
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)
|
static void tiva_freeframe(FAR struct tiva_ethmac_s *priv)
|
||||||
{
|
{
|
||||||
struct emac_txdesc_s *txdesc;
|
FAR struct emac_txdesc_s *txdesc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
nvdbg("txhead: %p txtail: %p inflight: %d\n",
|
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)
|
static void tiva_txdone(FAR struct tiva_ethmac_s *priv)
|
||||||
{
|
{
|
||||||
|
FAR struct net_driver_s *dev = &priv->dev;
|
||||||
|
|
||||||
DEBUGASSERT(priv->txtail != NULL);
|
DEBUGASSERT(priv->txtail != NULL);
|
||||||
|
|
||||||
/* Scan the TX descriptor change, returning buffers to free list */
|
/* Scan the TX descriptor change, returning buffers to free list */
|
||||||
|
|
||||||
tiva_freeframe(priv);
|
tiva_freeframe(priv);
|
||||||
|
dev->d_buf = NULL;
|
||||||
|
dev->d_len = 0;
|
||||||
|
|
||||||
/* If no further xmits are pending, then cancel the TX timeout */
|
/* 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;
|
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
|
* 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)
|
static int tiva_txavail(struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)dev->d_private;
|
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
|
/* Disable interrupts because this function may be called from interrupt
|
||||||
* level processing.
|
* level processing.
|
||||||
@ -2533,16 +2613,12 @@ static int tiva_txavail(struct net_driver_s *dev)
|
|||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
|
||||||
/* Ignore the notification if the interface is not yet up */
|
/* Perform the out-of-cycle poll now */
|
||||||
|
|
||||||
if (priv->ifup)
|
|
||||||
{
|
|
||||||
/* Poll uIP for new XMIT data */
|
|
||||||
|
|
||||||
tiva_dopoll(priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
tiva_txavail_process(priv);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,12 +155,16 @@ static void skel_poll_expiry(int argc, uint32_t arg, ...);
|
|||||||
|
|
||||||
/* NuttX callback functions */
|
/* NuttX callback functions */
|
||||||
|
|
||||||
static int skel_ifup(struct net_driver_s *dev);
|
static int skel_ifup(FAR struct net_driver_s *dev);
|
||||||
static int skel_ifdown(struct net_driver_s *dev);
|
static int skel_ifdown(FAR struct net_driver_s *dev);
|
||||||
static int skel_txavail(struct net_driver_s *dev);
|
static inline int skel_txavail_process(FAR struct skel_driver_s *skel);
|
||||||
|
#ifdef CONFIG_NET_NOINTS
|
||||||
|
static void skel_txavail_work(FAR void *arg);
|
||||||
|
#endif
|
||||||
|
static int skel_txavail(FAR struct net_driver_s *dev);
|
||||||
#ifdef CONFIG_NET_IGMP
|
#ifdef CONFIG_NET_IGMP
|
||||||
static int skel_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
|
static int skel_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac);
|
||||||
static int skel_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
|
static int skel_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -826,6 +830,67 @@ static int skel_ifdown(struct net_driver_s *dev)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: skel_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 int inline skel_txavail_process(FAR struct skel_driver_s *skel)
|
||||||
|
{
|
||||||
|
/* Ignore the notification if the interface is not yet up */
|
||||||
|
|
||||||
|
if (skel->sk_bifup)
|
||||||
|
{
|
||||||
|
/* Check if there is room in the hardware to hold another outgoing packet. */
|
||||||
|
|
||||||
|
/* If so, then poll uIP for new XMIT data */
|
||||||
|
|
||||||
|
(void)devif_poll(&skel->sk_dev, skel_txpoll);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: skel_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 skel_txavail_work(FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg;
|
||||||
|
|
||||||
|
/* Perform the poll */
|
||||||
|
|
||||||
|
skel_txavail_process(skel);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: skel_txavail
|
* Function: skel_txavail
|
||||||
*
|
*
|
||||||
@ -848,6 +913,21 @@ static int skel_ifdown(struct net_driver_s *dev)
|
|||||||
static int skel_txavail(struct net_driver_s *dev)
|
static int skel_txavail(struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)dev->d_private;
|
FAR struct skel_driver_s *skel = (FAR struct skel_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(&skel->sk_work))
|
||||||
|
{
|
||||||
|
/* Schedule to serialize the poll on the worker thread. */
|
||||||
|
|
||||||
|
work_queue(HPWORK, &skel->sk_work, skel_txavail_work, skel, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
/* Disable interrupts because this function may be called from interrupt
|
/* Disable interrupts because this function may be called from interrupt
|
||||||
@ -856,18 +936,12 @@ static int skel_txavail(struct net_driver_s *dev)
|
|||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
|
||||||
/* Ignore the notification if the interface is not yet up */
|
/* Perform the out-of-cycle poll now */
|
||||||
|
|
||||||
if (skel->sk_bifup)
|
|
||||||
{
|
|
||||||
/* Check if there is room in the hardware to hold another outgoing packet. */
|
|
||||||
|
|
||||||
/* If so, then poll uIP for new XMIT data */
|
|
||||||
|
|
||||||
(void)devif_poll(&skel->sk_dev, skel_txpoll);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
skel_poll_process(skel);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user