summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-01-17 11:00:29 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-01-17 11:00:29 -0600
commit2f175018846a885fd571cf2e119a5d3b2578007b (patch)
tree9d23684cda8b1bfe665e593944898a2d5ff8570f
parentf8df646dc75e62be61822713419d9447aac2419f (diff)
parenteebc384e9ba10466185c9d4e7955ce819838463d (diff)
downloadnuttx-2f175018846a885fd571cf2e119a5d3b2578007b.tar.gz
nuttx-2f175018846a885fd571cf2e119a5d3b2578007b.tar.bz2
nuttx-2f175018846a885fd571cf2e119a5d3b2578007b.zip
Merge remote-tracking branch 'origin/master' into ipv6
-rw-r--r--nuttx/arch/arm/src/tiva/tm4c_ethernet.c121
-rw-r--r--nuttx/drivers/net/skeleton.c104
2 files changed, 190 insertions, 35 deletions
diff --git a/nuttx/arch/arm/src/tiva/tm4c_ethernet.c b/nuttx/arch/arm/src/tiva/tm4c_ethernet.c
index 14acdab76..98efdb2ea 100644
--- a/nuttx/arch/arm/src/tiva/tm4c_ethernet.c
+++ b/nuttx/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);
@@ -1665,7 +1669,12 @@ static void tiva_receive(FAR struct tiva_ethmac_s *priv)
* flasher leaves the hardware in a bad state(?).
*/
- DEBUGASSERT(dev->d_buf != NULL);
+ // DEBUGASSERT(dev->d_buf != NULL);
+ if (dev->d_buf == NULL)
+ {
+ nlldbg("ERROR: Ignoring NULL I/O buffer\n");
+ return;
+ }
/* Loop while while tiva_recvframe() successfully retrieves valid
* Ethernet frames.
@@ -1815,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",
@@ -1852,7 +1861,7 @@ static void tiva_freeframe(FAR struct tiva_ethmac_s *priv)
txdesc->tdes2 = 0;
- /* Check if this is the last segement of a TX frame */
+ /* Check if this is the last segment of a TX frame */
if ((txdesc->tdes0 & EMAC_TDES0_LS) != 0)
{
@@ -1911,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 desciptor change, returning buffers to free list */
+ /* 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 */
@@ -2009,13 +2022,13 @@ static inline void tiva_interrupt_process(FAR struct tiva_ethmac_s *priv)
#ifdef CONFIG_DEBUG_NET
- /* Check if there are pending "anormal" interrupts */
+ /* Check if there are pending "abnormal" interrupts */
if ((dmaris & EMAC_DMAINT_AIS) != 0)
{
/* Just let the user know what happened */
- nlldbg("Abormal event(s): %08x\n", dmaris);
+ nlldbg("Abnormal event(s): %08x\n", dmaris);
/* Clear all pending abnormal events */
@@ -2196,7 +2209,7 @@ static inline void tiva_txtimeout_process(FAR struct tiva_ethmac_s *priv)
#ifdef CONFIG_NET_NOINTS
static void tiva_txtimeout_work(FAR void *arg)
{
- FAR struct tiva_ethmac_s *priv = ( FAR struct tiva_ethmac_s *)arg;
+ FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg;
/* Process pending Ethernet interrupts */
@@ -2497,6 +2510,65 @@ static int tiva_ifdown(struct net_driver_s *dev)
}
/****************************************************************************
+ * 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
*
* Description:
@@ -2518,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.
@@ -2528,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;
}
@@ -2616,7 +2697,7 @@ static int tiva_addmac(struct net_driver_s *dev, FAR const uint8_t *mac)
/* Add the MAC address to the hardware multicast hash table */
- crc = tiva_calcethcrc( mac, 6 );
+ crc = tiva_calcethcrc(mac, 6);
hashindex = (crc >> 26) & 0x3F;
@@ -2673,7 +2754,7 @@ static int tiva_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac)
/* Remove the MAC address to the hardware multicast hash table */
- crc = tiva_calcethcrc( mac, 6 );
+ crc = tiva_calcethcrc(mac, 6);
hashindex = (crc >> 26) & 0x3F;
@@ -2693,7 +2774,7 @@ static int tiva_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac)
/* If there is no address registered any more, delete multicast filtering */
- if (tiva_getreg(TIVA_EMAC_HASHTBLH ) == 0 &&
+ if (tiva_getreg(TIVA_EMAC_HASHTBLH) == 0 &&
tiva_getreg(TIVA_EMAC_HASHTBLL) == 0)
{
temp = tiva_getreg(TIVA_EMAC_FRAMEFLTR);
diff --git a/nuttx/drivers/net/skeleton.c b/nuttx/drivers/net/skeleton.c
index 1a932c056..86f1f83a1 100644
--- a/nuttx/drivers/net/skeleton.c
+++ b/nuttx/drivers/net/skeleton.c
@@ -155,12 +155,16 @@ static void skel_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
-static int skel_ifup(struct net_driver_s *dev);
-static int skel_ifdown(struct net_driver_s *dev);
-static int skel_txavail(struct net_driver_s *dev);
+static int skel_ifup(FAR struct net_driver_s *dev);
+static int skel_ifdown(FAR 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
-static int skel_addmac(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_addmac(FAR 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
/****************************************************************************
@@ -827,6 +831,67 @@ static int skel_ifdown(struct net_driver_s *dev)
}
/****************************************************************************
+ * 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
*
* Description:
@@ -848,6 +913,21 @@ static int skel_ifdown(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;
+
+#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;
/* 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();
- /* 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);
- }
+ /* Perform the out-of-cycle poll now */
+ skel_poll_process(skel);
irqrestore(flags);
+#endif
+
return OK;
}