Eliminate CONFIG_NO_NOINTS. Lots of files changed -> lots of testing needed.

This commit is contained in:
Gregory Nutt
2016-12-03 16:28:19 -06:00
parent bdb8275824
commit 7467329a98
180 changed files with 1481 additions and 5157 deletions
+67 -228
View File
@@ -59,11 +59,7 @@
#include <nuttx/wdog.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -84,13 +80,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE)
#endif
#else
/* Use the low priority work queue if possible */
/* Use the low priority work queue if possible */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_C5471_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_C5471_LPWORK)
@@ -317,9 +312,7 @@ struct c5471_driver_s
bool c_bifup; /* true:ifup false:ifdown */
WDOG_ID c_txpoll; /* TX poll timer */
WDOG_ID c_txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s c_work; /* For deferring work to the work queue */
#endif
/* Note: According to the C547x documentation: "The software has to maintain
* two pointers to the current RX-CPU and TX-CPU descriptors. At init time,
@@ -407,25 +400,15 @@ static void c5471_txstatus(struct c5471_driver_s *priv);
#endif
static void c5471_txdone(struct c5471_driver_s *priv);
static inline void c5471_interrupt_process(FAR struct c5471_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void c5471_interrupt_work(FAR void *arg);
#endif
static int c5471_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void c5471_txtimeout_process(FAR struct c5471_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void c5471_txtimeout_work(FAR void *arg);
#endif
static void c5471_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void c5471_poll_process(FAR struct c5471_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void c5471_poll_work(FAR void *arg);
#endif
static void c5471_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -433,10 +416,7 @@ static void c5471_poll_expiry(int argc, uint32_t arg, ...);
static int c5471_ifup(struct net_driver_s *dev);
static int c5471_ifdown(struct net_driver_s *dev);
static inline void c5471_txavail_process(FAR struct c5471_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void c5471_txavail_work(FAR void *arg);
#endif
static int c5471_txavail(struct net_driver_s *dev);
#ifdef CONFIG_NET_IGMP
@@ -1558,25 +1538,30 @@ static void c5471_txdone(struct c5471_driver_s *priv)
}
/****************************************************************************
* Function: c5471_interrupt_process
* Function: c5471_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void c5471_interrupt_process(FAR struct c5471_driver_s *priv)
static void c5471_interrupt_work(FAR void *arg)
{
FAR struct c5471_driver_s *priv = (FAR struct c5471_driver_s *)arg;
/* Process pending Ethernet interrupts */
net_lock();
/* Get and clear interrupt status bits */
priv->c_eimstatus = getreg32(EIM_STATUS);
@@ -1624,42 +1609,13 @@ static inline void c5471_interrupt_process(FAR struct c5471_driver_s *priv)
c5471_txdone(priv);
}
}
/****************************************************************************
* Function: c5471_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void c5471_interrupt_work(FAR void *arg)
{
FAR struct c5471_driver_s *priv = (FAR struct c5471_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
c5471_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
up_enable_irq(C5471_IRQ_ETHER);
}
#endif
/****************************************************************************
* Function: c5471_interrupt
@@ -1686,7 +1642,6 @@ static int c5471_interrupt(int irq, FAR void *context)
# error "Additional logic needed to support multiple interfaces"
#endif
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
@@ -1712,52 +1667,9 @@ static int c5471_interrupt(int irq, FAR void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->c_work, c5471_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
c5471_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: c5471_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void c5471_txtimeout_process(FAR struct c5471_driver_s *priv)
{
/* Increment statistics */
#ifdef CONFIG_C5471_NET_STATS
priv->c_txtimeouts++;
ninfo("c_txtimeouts: %d\n", priv->c_txtimeouts);
#endif
/* Then try to restart the hardware */
c5471_ifdown(&priv->c_dev);
c5471_ifup(&priv->c_dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->c_dev, c5471_txpoll);
}
/****************************************************************************
* Function: c5471_txtimeout_work
*
@@ -1775,20 +1687,29 @@ static inline void c5471_txtimeout_process(FAR struct c5471_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void c5471_txtimeout_work(FAR void *arg)
{
FAR struct c5471_driver_s *priv = (FAR struct c5471_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Increment statistics */
state = net_lock();
c5471_txtimeout_process(priv);
net_unlock(state);
}
net_lock();
#ifdef CONFIG_C5471_NET_STATS
priv->c_txtimeouts++;
ninfo("c_txtimeouts: %d\n", priv->c_txtimeouts);
#endif
/* Then try to restart the hardware */
c5471_ifdown(&priv->c_dev);
c5471_ifup(&priv->c_dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->c_dev, c5471_txpoll);
net_unlock();
}
/****************************************************************************
* Function: c5471_txtimeout_expiry
*
@@ -1812,7 +1733,6 @@ static void c5471_txtimeout_expiry(int argc, wdparm_t arg, ...)
{
struct c5471_driver_s *priv = (struct c5471_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -1829,47 +1749,6 @@ static void c5471_txtimeout_expiry(int argc, wdparm_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->c_work, c5471_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
c5471_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: c5471_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void c5471_poll_process(FAR struct c5471_driver_s *priv)
{
/* Check if the ESM has let go of the RX descriptor giving us access rights
* to submit another Ethernet frame.
*/
if ((EIM_TXDESC_OWN_HOST & getreg32(priv->c_rxcpudesc)) == 0)
{
/* If so, update TCP timing states and poll the network for new XMIT data */
(void)devif_timer(&priv->c_dev, c5471_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->c_txpoll, C5471_WDDELAY, c5471_poll_expiry, 1,
(wdparm_t)priv);
}
/****************************************************************************
@@ -1889,19 +1768,28 @@ static inline void c5471_poll_process(FAR struct c5471_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void c5471_poll_work(FAR void *arg)
{
FAR struct c5471_driver_s *priv = (FAR struct c5471_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Check if the ESM has let go of the RX descriptor giving us access rights
* to submit another Ethernet frame.
*/
state = net_lock();
c5471_poll_process(priv);
net_unlock(state);
net_lock();
if ((EIM_TXDESC_OWN_HOST & getreg32(priv->c_rxcpudesc)) == 0)
{
/* If so, update TCP timing states and poll the network for new XMIT data */
(void)devif_timer(&priv->c_dev, c5471_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->c_txpoll, C5471_WDDELAY, c5471_poll_expiry, 1,
(wdparm_t)priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: c5471_poll_expiry
@@ -1925,7 +1813,6 @@ static void c5471_poll_expiry(int argc, wdparm_t arg, ...)
{
struct c5471_driver_s *priv = (struct c5471_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -1945,12 +1832,6 @@ static void c5471_poll_expiry(int argc, wdparm_t arg, ...)
(void)wd_start(priv->c_txpoll, C5471_WDDELAY, c5471_poll_expiry,
1, arg);
}
#else
/* Process the interrupt now */
c5471_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2071,44 +1952,6 @@ static int c5471_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: c5471_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 inline void c5471_txavail_process(FAR struct c5471_driver_s *priv)
{
ninfo("Polling\n");
/* Ignore the notification if the interface is not yet up */
if (priv->c_bifup)
{
/* Check if the ESM has let go of the RX descriptor giving us access
* rights to submit another Ethernet frame.
*/
if ((EIM_TXDESC_OWN_HOST & getreg32(priv->c_rxcpudesc)) == 0)
{
/* If so, then poll the network for new XMIT data */
(void)devif_poll(&priv->c_dev, c5471_txpoll);
}
}
}
/****************************************************************************
* Function: c5471_txavail_work
*
@@ -2126,19 +1969,31 @@ static inline void c5471_txavail_process(FAR struct c5471_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void c5471_txavail_work(FAR void *arg)
{
FAR struct c5471_driver_s *priv = (FAR struct c5471_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("Polling\n");
state = net_lock();
c5471_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->c_bifup)
{
/* Check if the ESM has let go of the RX descriptor giving us access
* rights to submit another Ethernet frame.
*/
if ((EIM_TXDESC_OWN_HOST & getreg32(priv->c_rxcpudesc)) == 0)
{
/* If so, then poll the network for new XMIT data */
(void)devif_poll(&priv->c_dev, c5471_txpoll);
}
}
net_unlock();
}
#endif
/****************************************************************************
* Function: c5471_txavail
@@ -2163,7 +2018,6 @@ static int c5471_txavail(FAR struct net_driver_s *dev)
{
struct c5471_driver_s *priv = (struct c5471_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.
@@ -2176,21 +2030,6 @@ static int c5471_txavail(FAR struct net_driver_s *dev)
work_queue(ETHWORK, &priv->c_work, c5471_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
c5471_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+68 -221
View File
@@ -53,14 +53,11 @@
#include <nuttx/wdog.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#ifdef CONFIG_NET_PKT
# include <nuttx/net/pkt.h>
#endif
@@ -84,13 +81,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_KINETIS_EMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_KINETIS_EMAC_LPWORK)
@@ -219,9 +215,7 @@ struct kinetis_driver_s
uint8_t phyaddr; /* Selected PHY address */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
struct enet_desc_s *txdesc; /* A pointer to the list of TX descriptor */
struct enet_desc_s *rxdesc; /* A pointer to the list of RX descriptors */
@@ -279,24 +273,15 @@ static int kinetis_txpoll(struct net_driver_s *dev);
static void kinetis_receive(FAR struct kinetis_driver_s *priv);
static void kinetis_txdone(FAR struct kinetis_driver_s *priv);
static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_interrupt_work(FAR void *arg);
#endif
static int kinetis_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_txtimeout_work(FAR void *arg);
#endif
static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_poll_work(FAR void *arg);
#endif
static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -304,10 +289,7 @@ static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...);
static int kinetis_ifup(struct net_driver_s *dev);
static int kinetis_ifdown(struct net_driver_s *dev);
static inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_txavail_work(FAR void *arg);
#endif
static int kinetis_txavail(struct net_driver_s *dev);
#ifdef CONFIG_NET_IGMP
@@ -824,27 +806,31 @@ static void kinetis_txdone(FAR struct kinetis_driver_s *priv)
}
/****************************************************************************
* Function: kinetis_interrupt_process
* Function: kinetis_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv)
static void kinetis_interrupt_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
uint32_t pending;
/* Process pending Ethernet interrupts */
net_lock();
/* Get the set of unmasked, pending interrupt. */
pending = getreg32(KINETIS_ENET_EIR) & getreg32(KINETIS_ENET_EIMR);
@@ -892,36 +878,8 @@ static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv)
putreg32(ENET_RDAR, KINETIS_ENET_RDAR);
}
}
/****************************************************************************
* Function: kinetis_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_interrupt_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
kinetis_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
@@ -932,7 +890,6 @@ static void kinetis_interrupt_work(FAR void *arg)
up_enable_irq(KINETIS_IRQ_EMACRX);
up_enable_irq(KINETIS_IRQ_EMACMISC);
}
#endif
/****************************************************************************
* Function: kinetis_interrupt
@@ -958,7 +915,6 @@ static int kinetis_interrupt(int irq, FAR void *context)
{
register FAR struct kinetis_driver_s *priv = &g_enet[0];
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
@@ -987,51 +943,9 @@ static int kinetis_interrupt(int irq, FAR void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->work, kinetis_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
kinetis_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: kinetis_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv)
{
/* Increment statistics and dump debug info */
NETDEV_TXTIMEOUTS(&priv->dev);
/* Take the interface down and bring it back up. The is the most agressive
* hardware reset.
*/
(void)kinetis_ifdown(&priv->dev);
(void)kinetis_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
/****************************************************************************
* Function: kinetis_txtimeout_work
*
@@ -1049,19 +963,27 @@ static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_txtimeout_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Increment statistics and dump debug info */
state = net_lock();
kinetis_txtimeout_process(priv);
net_unlock(state);
net_lock();
NETDEV_TXTIMEOUTS(&priv->dev);
/* Take the interface down and bring it back up. The is the most agressive
* hardware reset.
*/
(void)kinetis_ifdown(&priv->dev);
(void)kinetis_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->dev, kinetis_txpoll);
net_unlock();
}
#endif
/****************************************************************************
* Function: kinetis_txtimeout_expiry
@@ -1086,7 +1008,6 @@ static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -1106,50 +1027,6 @@ static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, kinetis_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
kinetis_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: kinetis_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv)
{
/* Check if there is there is a transmission in progress. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
if (!kinetics_txringfull(priv))
{
/* If so, update TCP timing states and poll the network for new XMIT data. Hmmm..
* might be bug here. Does this mean if there is a transmit in progress,
* we will missing TCP time state updates?
*/
(void)devif_timer(&priv->dev, kinetis_txpoll);
}
/* Setup the watchdog poll timer again in any case */
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)priv);
}
/****************************************************************************
@@ -1169,19 +1046,31 @@ static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_poll_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Check if there is there is a transmission in progress. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
state = net_lock();
kinetis_poll_process(priv);
net_unlock(state);
net_lock();
if (!kinetics_txringfull(priv))
{
/* If so, update TCP timing states and poll the network for new XMIT data. Hmmm..
* might be bug here. Does this mean if there is a transmit in progress,
* we will missing TCP time state updates?
*/
(void)devif_timer(&priv->dev, kinetis_txpoll);
}
/* Setup the watchdog poll timer again in any case */
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: kinetis_polltimer_expiry
@@ -1205,7 +1094,6 @@ static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -1225,12 +1113,6 @@ static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)arg);
}
#else
/* Process the interrupt now */
kinetis_poll_process(priv);
#endif
}
/****************************************************************************
@@ -1416,49 +1298,6 @@ static int kinetis_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: kinetis_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 inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv)
{
net_lock_t state;
/* Ignore the notification if the interface is not yet up */
state = net_lock();
if (priv->bifup)
{
/* Check if there is room in the hardware to hold another outgoing
* packet.
*/
if (!kinetics_txringfull(priv))
{
/* No, there is space for another transfer. Poll the network for new
* XMIT data.
*/
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
}
net_unlock(state);
}
/****************************************************************************
* Function: kinetis_txavail_work
*
@@ -1476,16 +1315,31 @@ static inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_txavail_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up */
kinetis_txavail_process(priv);
net_lock();
if (priv->bifup)
{
/* Check if there is room in the hardware to hold another outgoing
* packet.
*/
if (!kinetics_txringfull(priv))
{
/* No, there is space for another transfer. Poll the network for new
* XMIT data.
*/
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
}
net_unlock();
}
#endif
/****************************************************************************
* Function: kinetis_txavail
@@ -1511,7 +1365,6 @@ static int kinetis_txavail(struct net_driver_s *dev)
FAR struct kinetis_driver_s *priv =
(FAR struct kinetis_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.
@@ -1524,12 +1377,6 @@ static int kinetis_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, kinetis_txavail_work, priv, 0);
}
#else
/* Perform the out-of-cycle poll now */
kinetis_txavail_process(priv);
#endif
return OK;
}
File diff suppressed because it is too large Load Diff
+48 -216
View File
@@ -53,11 +53,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -87,13 +83,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_LPC43_ETHERNET_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_LPC43_ETHERNET_LPWORK)
@@ -524,9 +519,7 @@ struct lpc43_ethmac_s
uint8_t fduplex : 1; /* Full (vs. half) duplex */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -599,34 +592,26 @@ static int lpc43_recvframe(FAR struct lpc43_ethmac_s *priv);
static void lpc43_receive(FAR struct lpc43_ethmac_s *priv);
static void lpc43_freeframe(FAR struct lpc43_ethmac_s *priv);
static void lpc43_txdone(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_interrupt_work(FAR void *arg);
#endif
static int lpc43_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_txtimeout_work(FAR void *arg);
#endif
static void lpc43_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_poll_work(FAR void *arg);
#endif
static void lpc43_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
static int lpc43_ifup(struct net_driver_s *dev);
static int lpc43_ifdown(struct net_driver_s *dev);
static inline void lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_txavail_work(FAR void *arg);
#endif
static int lpc43_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int lpc43_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
#endif
@@ -1900,29 +1885,32 @@ static void lpc43_txdone(FAR struct lpc43_ethmac_s *priv)
}
/****************************************************************************
* Function: lpc43_interrupt_process
* Function: lpc43_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void lpc43_interrupt_process(FAR struct lpc43_ethmac_s *priv)
static void lpc43_interrupt_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
uint32_t dmasr;
DEBUGASSERT(priv);
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
net_lock();
dmasr = lpc43_getreg(LPC43_ETH_DMASTAT);
/* Mask only enabled interrupts. This depends on the fact that the interrupt
@@ -1974,7 +1962,6 @@ static inline void lpc43_interrupt_process(FAR struct lpc43_ethmac_s *priv)
/* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */
#ifdef CONFIG_DEBUG_NET
/* Check if there are pending "abnormal" interrupts */
if ((dmasr & ETH_DMAINT_AIS) != 0)
@@ -1991,45 +1978,13 @@ static inline void lpc43_interrupt_process(FAR struct lpc43_ethmac_s *priv)
lpc43_putreg(ETH_DMAINT_AIS, LPC43_ETH_DMASTAT);
}
#endif
}
/****************************************************************************
* Function: lpc43_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_interrupt_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
state = net_lock();
lpc43_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts at the NVIC */
up_enable_irq(LPC43M4_IRQ_ETHERNET);
}
#endif
/****************************************************************************
* Function: lpc43_interrupt
@@ -2051,8 +2006,6 @@ static void lpc43_interrupt_work(FAR void *arg)
static int lpc43_interrupt(int irq, FAR void *context)
{
FAR struct lpc43_ethmac_s *priv = &g_lpc43ethmac;
#ifdef CONFIG_NET_NOINTS
uint32_t dmasr;
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
@@ -2088,49 +2041,9 @@ static int lpc43_interrupt(int irq, FAR void *context)
work_queue(ETHWORK, &priv->work, lpc43_interrupt_work, priv, 0);
}
#else
/* Process the interrupt now */
lpc43_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: lpc43_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv)
{
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
lpc43_ifdown(&priv->dev);
lpc43_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
lpc43_dopoll(priv);
}
/****************************************************************************
* Function: lpc43_txtimeout_work
*
@@ -2148,19 +2061,23 @@ static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_txtimeout_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
state = net_lock();
lpc43_txtimeout_process(priv);
net_unlock(state);
net_lock();
lpc43_ifdown(&priv->dev);
lpc43_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
lpc43_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: lpc43_txtimeout_expiry
@@ -2187,7 +2104,6 @@ static void lpc43_txtimeout_expiry(int argc, uint32_t arg, ...)
ninfo("Timeout!\n");
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2206,33 +2122,28 @@ static void lpc43_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, lpc43_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
lpc43_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: lpc43_poll_process
* Function: lpc43_poll_work
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
* Perform periodic polling from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv)
static void lpc43_poll_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
FAR struct net_driver_s *dev = &priv->dev;
/* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We
@@ -2246,6 +2157,7 @@ static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv)
* CONFIG_LPC43_ETH_NTXDESC).
*/
net_lock();
if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 &&
priv->txhead->tdes2 == 0)
{
@@ -2281,39 +2193,9 @@ static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv)
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, LPC43_WDDELAY, lpc43_poll_expiry, 1, priv);
net_unlock();
}
/****************************************************************************
* Function: lpc43_poll_work
*
* Description:
* Perform periodic polling from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_poll_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
lpc43_poll_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: lpc43_poll_expiry
*
@@ -2336,7 +2218,6 @@ static void lpc43_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2356,12 +2237,6 @@ static void lpc43_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, LPC43_WDDELAY, lpc43_poll_expiry, 1,
(uint32_t)priv);
}
#else
/* Process the interrupt now */
lpc43_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2467,37 +2342,6 @@ static int lpc43_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: lpc43_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 lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll for new XMIT data */
lpc43_dopoll(priv);
}
}
/****************************************************************************
* Function: lpc43_txavail_work
*
@@ -2515,19 +2359,23 @@ static inline void lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_txavail_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up */
state = net_lock();
lpc43_txavail_process(priv);
net_unlock(state);
net_lock();
ninfo("ifup: %d\n", priv->ifup);
if (priv->ifup)
{
/* Poll for new XMIT data */
lpc43_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: lpc43_txavail
@@ -2552,7 +2400,6 @@ static int lpc43_txavail(struct net_driver_s *dev)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_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.
@@ -2565,21 +2412,6 @@ static int lpc43_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, lpc43_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
lpc43_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+57 -221
View File
@@ -64,11 +64,7 @@
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include <nuttx/kmalloc.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -101,13 +97,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_SAM34_EMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_SAM34_EMAC_LPWORK)
@@ -275,9 +270,7 @@ struct sam_emac_s
uint8_t ifup : 1; /* true:ifup false:ifdown */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -386,24 +379,16 @@ static void sam_dopoll(struct sam_emac_s *priv);
static int sam_recvframe(struct sam_emac_s *priv);
static void sam_receive(struct sam_emac_s *priv);
static void sam_txdone(struct sam_emac_s *priv);
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg);
#endif
static int sam_emac_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg);
#endif
static void sam_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void sam_poll_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg);
#endif
static void sam_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -411,10 +396,7 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...);
static int sam_ifup(struct net_driver_s *dev);
static int sam_ifdown(struct net_driver_s *dev);
static inline void sam_txavail_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg);
#endif
static int sam_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
@@ -465,6 +447,7 @@ static int sam_emac_configure(struct sam_emac_s *priv);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sam_checkreg
*
@@ -1421,25 +1404,25 @@ static void sam_txdone(struct sam_emac_s *priv)
}
/****************************************************************************
* Function: sam_interrupt_process
* Function: sam_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
uint32_t isr;
uint32_t rsr;
uint32_t tsr;
@@ -1448,6 +1431,9 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
uint32_t pending;
uint32_t clrbits;
/* Process pending Ethernet interrupts */
net_lock();
isr = sam_getreg(priv, SAM_EMAC_ISR);
rsr = sam_getreg(priv, SAM_EMAC_RSR);
tsr = sam_getreg(priv, SAM_EMAC_TSR);
@@ -1603,42 +1589,13 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
nwarn("WARNING: Pause TO!\n");
}
#endif
}
/****************************************************************************
* Function: sam_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
sam_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
up_enable_irq(SAM_IRQ_EMAC);
}
#endif
/****************************************************************************
* Function: sam_emac_interrupt
@@ -1661,7 +1618,6 @@ static int sam_emac_interrupt(int irq, void *context)
{
struct sam_emac_s *priv = &g_emac;
#ifdef CONFIG_NET_NOINTS
uint32_t tsr;
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
@@ -1705,52 +1661,9 @@ static int sam_emac_interrupt(int irq, void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
sam_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: sam_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
{
nerr("ERROR: Timeout!\n");
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
}
/****************************************************************************
* Function: sam_txtimeout_work
*
@@ -1768,19 +1681,25 @@ static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
nerr("ERROR: Timeout!\n");
state = net_lock();
sam_txtimeout_process(priv);
net_unlock(state);
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
net_lock();
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txtimeout_expiry
@@ -1805,7 +1724,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -1822,48 +1740,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
sam_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: sam_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void sam_poll_process(FAR struct sam_emac_s *priv)
{
struct net_driver_s *dev = &priv->dev;
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
}
/****************************************************************************
@@ -1883,19 +1759,28 @@ static inline void sam_poll_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
struct net_driver_s *dev = &priv->dev;
/* Perform the poll */
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
state = net_lock();
sam_poll_process(priv);
net_unlock(state);
net_lock();
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_poll_expiry
@@ -1919,7 +1804,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -1938,12 +1822,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
sam_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2070,37 +1948,6 @@ static int sam_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: sam_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 inline void sam_txavail_process(FAR struct sam_emac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
}
/****************************************************************************
* Function: sam_txavail_work
*
@@ -2118,19 +1965,24 @@ static inline void sam_txavail_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
sam_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txavail
@@ -2155,7 +2007,6 @@ static int sam_txavail(struct net_driver_s *dev)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_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.
@@ -2168,21 +2019,6 @@ static int sam_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, sam_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
sam_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+54 -219
View File
@@ -65,11 +65,7 @@
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/kmalloc.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -103,13 +99,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_SAMA5_EMACA_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_SAMA5_EMACA_LPWORK)
@@ -280,9 +275,7 @@ struct sam_emac_s
uint8_t ifup : 1; /* true:ifup false:ifdown */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -391,24 +384,16 @@ static void sam_dopoll(struct sam_emac_s *priv);
static int sam_recvframe(struct sam_emac_s *priv);
static void sam_receive(struct sam_emac_s *priv);
static void sam_txdone(struct sam_emac_s *priv);
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg);
#endif
static int sam_emac_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg);
#endif
static void sam_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void sam_poll_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg);
#endif
static void sam_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -416,10 +401,7 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...);
static int sam_ifup(struct net_driver_s *dev);
static int sam_ifdown(struct net_driver_s *dev);
static inline void sam_txavail_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg);
#endif
static int sam_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
@@ -1462,25 +1444,25 @@ static void sam_txdone(struct sam_emac_s *priv)
}
/****************************************************************************
* Function: sam_interrupt_process
* Function: sam_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
uint32_t isr;
uint32_t rsr;
uint32_t tsr;
@@ -1489,6 +1471,9 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
uint32_t pending;
uint32_t clrbits;
/* Process pending Ethernet interrupts */
net_lock();
isr = sam_getreg(priv, SAM_EMAC_ISR);
rsr = sam_getreg(priv, SAM_EMAC_RSR);
tsr = sam_getreg(priv, SAM_EMAC_TSR);
@@ -1643,42 +1628,13 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
nwarn("WARNING: Pause TO!\n");
}
#endif
}
/****************************************************************************
* Function: sam_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
sam_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
up_enable_irq(SAM_IRQ_EMAC);
}
#endif
/****************************************************************************
* Function: sam_emac_interrupt
@@ -1700,7 +1656,6 @@ static void sam_interrupt_work(FAR void *arg)
static int sam_emac_interrupt(int irq, void *context)
{
struct sam_emac_s *priv = &g_emac;
#ifdef CONFIG_NET_NOINTS
uint32_t tsr;
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
@@ -1744,50 +1699,9 @@ static int sam_emac_interrupt(int irq, void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
sam_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: sam_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
{
nerr("ERROR: Timeout!\n");
/* Reset the hardware. Just take the interface down, then back up again. */
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
}
/****************************************************************************
* Function: sam_txtimeout_work
*
@@ -1805,19 +1719,23 @@ static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
nerr("ERROR: Timeout!\n");
state = net_lock();
sam_txtimeout_process(priv);
net_unlock(state);
/* Reset the hardware. Just take the interface down, then back up again. */
net_lock();
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txtimeout_expiry
@@ -1842,7 +1760,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -1859,48 +1776,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
sam_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: sam_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void sam_poll_process(FAR struct sam_emac_s *priv)
{
struct net_driver_s *dev = &priv->dev;
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
}
/****************************************************************************
@@ -1920,19 +1795,28 @@ static inline void sam_poll_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
struct net_driver_s *dev = &priv->dev;
/* Perform the poll */
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
state = net_lock();
sam_poll_process(priv);
net_unlock(state);
net_lock();
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_poll_expiry
@@ -1956,7 +1840,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -1975,12 +1858,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
sam_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2107,37 +1984,6 @@ static int sam_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: sam_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 inline void sam_txavail_process(FAR struct sam_emac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
}
/****************************************************************************
* Function: sam_txavail_work
*
@@ -2155,19 +2001,24 @@ static inline void sam_txavail_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
sam_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txavail
@@ -2192,7 +2043,6 @@ static int sam_txavail(struct net_driver_s *dev)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_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.
@@ -2205,21 +2055,6 @@ static int sam_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, sam_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
sam_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+54 -219
View File
@@ -79,11 +79,7 @@
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include <nuttx/kmalloc.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -117,13 +113,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_SAMA5_EMACB_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_SAMA5_EMACB_LPWORK)
@@ -418,9 +413,7 @@ struct sam_emac_s
uint8_t ifup : 1; /* true:ifup false:ifdown */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -486,10 +479,8 @@ static void sam_dopoll(struct sam_emac_s *priv);
static int sam_recvframe(struct sam_emac_s *priv);
static void sam_receive(struct sam_emac_s *priv);
static void sam_txdone(struct sam_emac_s *priv);
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg);
#endif
static int sam_emac_interrupt(struct sam_emac_s *priv);
#ifdef CONFIG_SAMA5_EMAC0
static int sam_emac0_interrupt(int irq, void *context);
@@ -500,16 +491,10 @@ static int sam_emac1_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg);
#endif
static void sam_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void sam_poll_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg);
#endif
static void sam_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -517,10 +502,7 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...);
static int sam_ifup(struct net_driver_s *dev);
static int sam_ifdown(struct net_driver_s *dev);
static inline void sam_txavail_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg);
#endif
static int sam_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
@@ -1830,25 +1812,25 @@ static void sam_txdone(struct sam_emac_s *priv)
}
/****************************************************************************
* Function: sam_interrupt_process
* Function: sam_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
uint32_t isr;
uint32_t rsr;
uint32_t tsr;
@@ -1857,6 +1839,9 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
uint32_t pending;
uint32_t clrbits;
/* Process pending Ethernet interrupts */
net_lock();
isr = sam_getreg(priv, SAM_EMAC_ISR_OFFSET);
rsr = sam_getreg(priv, SAM_EMAC_RSR_OFFSET);
tsr = sam_getreg(priv, SAM_EMAC_TSR_OFFSET);
@@ -2012,42 +1997,13 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv)
nwarn("WARNING: Pause TO!\n");
}
#endif
}
/****************************************************************************
* Function: sam_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
sam_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
up_enable_irq(priv->attr->irq);
}
#endif
/****************************************************************************
* Function: sam_emac_interrupt
@@ -2067,7 +2023,6 @@ static void sam_interrupt_work(FAR void *arg)
static int sam_emac_interrupt(struct sam_emac_s *priv)
{
#ifdef CONFIG_NET_NOINTS
uint32_t tsr;
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
@@ -2111,13 +2066,6 @@ static int sam_emac_interrupt(struct sam_emac_s *priv)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
sam_interrupt_process(priv);
#endif
return OK;
}
@@ -2152,40 +2100,6 @@ static int sam_emac1_interrupt(int irq, void *context)
}
#endif
/****************************************************************************
* Function: sam_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
{
nerr("ERROR: Timeout!\n");
/* Reset the hardware. Just take the interface down, then back up again. */
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
}
/****************************************************************************
* Function: sam_txtimeout_work
*
@@ -2203,19 +2117,23 @@ static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
nerr("ERROR: Timeout!\n");
state = net_lock();
sam_txtimeout_process(priv);
net_unlock(state);
/* Reset the hardware. Just take the interface down, then back up again. */
net_lock();
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txtimeout_expiry
@@ -2240,7 +2158,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2257,48 +2174,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
sam_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: sam_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void sam_poll_process(FAR struct sam_emac_s *priv)
{
struct net_driver_s *dev = &priv->dev;
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
}
/****************************************************************************
@@ -2318,19 +2193,28 @@ static inline void sam_poll_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
struct net_driver_s *dev = &priv->dev;
/* Perform the poll */
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
state = net_lock();
sam_poll_process(priv);
net_unlock(state);
net_lock();
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_poll_expiry
@@ -2354,7 +2238,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2373,12 +2256,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
sam_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2513,37 +2390,6 @@ static int sam_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: sam_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 inline void sam_txavail_process(FAR struct sam_emac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
}
/****************************************************************************
* Function: sam_txavail_work
*
@@ -2561,19 +2407,24 @@ static inline void sam_txavail_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
sam_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txavail
@@ -2598,7 +2449,6 @@ static int sam_txavail(struct net_driver_s *dev)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_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.
@@ -2611,21 +2461,6 @@ static int sam_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, sam_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
sam_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+54 -219
View File
@@ -62,11 +62,7 @@
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include <nuttx/kmalloc.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/gmii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -100,13 +96,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_SAMA5_GMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_SAMA5_GMAC_LPWORK)
@@ -206,9 +201,7 @@ struct sam_gmac_s
uint8_t ifup : 1; /* true:ifup false:ifdown */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -316,24 +309,16 @@ static void sam_dopoll(struct sam_gmac_s *priv);
static int sam_recvframe(struct sam_gmac_s *priv);
static void sam_receive(struct sam_gmac_s *priv);
static void sam_txdone(struct sam_gmac_s *priv);
static inline void sam_interrupt_process(FAR struct sam_gmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg);
#endif
static int sam_gmac_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void sam_txtimeout_process(FAR struct sam_gmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg);
#endif
static void sam_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void sam_poll_process(FAR struct sam_gmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg);
#endif
static void sam_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -341,10 +326,7 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...);
static int sam_ifup(struct net_driver_s *dev);
static int sam_ifdown(struct net_driver_s *dev);
static inline void sam_txavail_process(FAR struct sam_gmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg);
#endif
static int sam_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
@@ -1390,25 +1372,25 @@ static void sam_txdone(struct sam_gmac_s *priv)
}
/****************************************************************************
* Function: sam_interrupt_process
* Function: sam_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void sam_interrupt_process(FAR struct sam_gmac_s *priv)
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg;
uint32_t isr;
uint32_t rsr;
uint32_t tsr;
@@ -1417,6 +1399,9 @@ static inline void sam_interrupt_process(FAR struct sam_gmac_s *priv)
uint32_t pending;
uint32_t clrbits;
/* Process pending Ethernet interrupts */
net_lock();
isr = sam_getreg(priv, SAM_GMAC_ISR);
rsr = sam_getreg(priv, SAM_GMAC_RSR);
tsr = sam_getreg(priv, SAM_GMAC_TSR);
@@ -1595,42 +1580,13 @@ static inline void sam_interrupt_process(FAR struct sam_gmac_s *priv)
nwarn("WARNING: Pause TO!\n");
}
#endif
}
/****************************************************************************
* Function: sam_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
sam_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
up_enable_irq(SAM_IRQ_GMAC);
}
#endif
/****************************************************************************
* Function: sam_gmac_interrupt
@@ -1652,7 +1608,6 @@ static void sam_interrupt_work(FAR void *arg)
static int sam_gmac_interrupt(int irq, void *context)
{
struct sam_gmac_s *priv = &g_gmac;
#ifdef CONFIG_NET_NOINTS
uint32_t tsr;
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
@@ -1696,50 +1651,9 @@ static int sam_gmac_interrupt(int irq, void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
sam_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: sam_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void sam_txtimeout_process(FAR struct sam_gmac_s *priv)
{
nerr("ERROR: Timeout!\n");
/* Reset the hardware. Just take the interface down, then back up again. */
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
}
/****************************************************************************
* Function: sam_txtimeout_work
*
@@ -1757,19 +1671,23 @@ static inline void sam_txtimeout_process(FAR struct sam_gmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
nerr("ERROR: Timeout!\n");
state = net_lock();
sam_txtimeout_process(priv);
net_unlock(state);
/* Reset the hardware. Just take the interface down, then back up again. */
net_lock();
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txtimeout_expiry
@@ -1794,7 +1712,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -1811,48 +1728,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
sam_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: sam_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void sam_poll_process(FAR struct sam_gmac_s *priv)
{
struct net_driver_s *dev = &priv->dev;
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
}
/****************************************************************************
@@ -1872,19 +1747,28 @@ static inline void sam_poll_process(FAR struct sam_gmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg;
net_lock_t state;
struct net_driver_s *dev = &priv->dev;
/* Perform the poll */
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
state = net_lock();
sam_poll_process(priv);
net_unlock(state);
net_lock();
if (sam_txfree(priv) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_poll_expiry
@@ -1908,7 +1792,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -1927,12 +1810,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
sam_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2062,37 +1939,6 @@ static int sam_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: sam_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 inline void sam_txavail_process(FAR struct sam_gmac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
}
/****************************************************************************
* Function: sam_txavail_work
*
@@ -2110,19 +1956,24 @@ static inline void sam_txavail_process(FAR struct sam_gmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
sam_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txavail
@@ -2147,7 +1998,6 @@ static int sam_txavail(struct net_driver_s *dev)
{
FAR struct sam_gmac_s *priv = (FAR struct sam_gmac_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.
@@ -2160,21 +2010,6 @@ static int sam_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, sam_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
sam_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+57 -222
View File
@@ -69,11 +69,7 @@
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include <nuttx/kmalloc.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -107,13 +103,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_SAMV7_EMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_SAMV7_EMAC_LPWORK)
@@ -523,9 +518,7 @@ struct sam_emac_s
uint8_t ifup : 1; /* true:ifup false:ifdown */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -588,11 +581,8 @@ static int sam_recvframe(struct sam_emac_s *priv, int qid);
static void sam_receive(struct sam_emac_s *priv, int qid);
static void sam_txdone(struct sam_emac_s *priv, int qid);
static void sam_txerr_interrupt(FAR struct sam_emac_s *priv, int qid);
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv,
int qid);
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg);
#endif
static int sam_emac_interrupt(struct sam_emac_s *priv);
#ifdef CONFIG_SAMV7_EMAC0
static int sam_emac0_interrupt(int irq, void *context);
@@ -603,16 +593,10 @@ static int sam_emac1_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg);
#endif
static void sam_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void sam_poll_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg);
#endif
static void sam_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -620,10 +604,7 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...);
static int sam_ifup(struct net_driver_s *dev);
static int sam_ifdown(struct net_driver_s *dev);
static inline void sam_txavail_process(FAR struct sam_emac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg);
#endif
static int sam_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
@@ -2272,26 +2253,25 @@ static void sam_txerr_interrupt(FAR struct sam_emac_s *priv, int qid)
}
/****************************************************************************
* Function: sam_interrupt_process
* Function: sam_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* quid - Index of the transfer queue that generated the interrupt
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void sam_interrupt_process(FAR struct sam_emac_s *priv, int qid)
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
uint32_t isr;
uint32_t rsr;
uint32_t tsr;
@@ -2300,6 +2280,10 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv, int qid)
uint32_t pending;
uint32_t clrbits;
/* Process pending Ethernet interrupts */
net_lock();
/* Read the interrupt status, RX status, and TX status registers.
* NOTE that the interrupt status register is cleared by this read.
*/
@@ -2458,42 +2442,13 @@ static inline void sam_interrupt_process(FAR struct sam_emac_s *priv, int qid)
ninfo("Pause TO!\n");
}
#endif
}
/****************************************************************************
* Function: sam_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_interrupt_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
sam_interrupt_process(priv, EMAC_QUEUE_0);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
up_enable_irq(priv->attr->irq);
}
#endif
/****************************************************************************
* Function: sam_emac_interrupt
@@ -2513,7 +2468,6 @@ static void sam_interrupt_work(FAR void *arg)
static int sam_emac_interrupt(struct sam_emac_s *priv)
{
#ifdef CONFIG_NET_NOINTS
uint32_t tsr;
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
@@ -2557,13 +2511,6 @@ static int sam_emac_interrupt(struct sam_emac_s *priv)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
sam_interrupt_process(priv, EMAC_QUEUE_0);
#endif
return OK;
}
@@ -2598,41 +2545,6 @@ static int sam_emac1_interrupt(int irq, void *context)
}
#endif
/****************************************************************************
* Function: sam_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
{
nerr("ERROR: Timeout!\n");
NETDEV_TXTIMEOUTS(&priv->dev);
/* Reset the hardware. Just take the interface down, then back up again. */
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv, EMAC_QUEUE_0);
}
/****************************************************************************
* Function: sam_txtimeout_work
*
@@ -2650,19 +2562,25 @@ static inline void sam_txtimeout_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txtimeout_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
nerr("ERROR: Timeout!\n");
state = net_lock();
sam_txtimeout_process(priv);
net_unlock(state);
net_lock();
NETDEV_TXTIMEOUTS(&priv->dev);
/* Reset the hardware. Just take the interface down, then back up again. */
sam_ifdown(&priv->dev);
sam_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
sam_dopoll(priv, EMAC_QUEUE_0);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txtimeout_expiry
@@ -2687,7 +2605,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2704,48 +2621,6 @@ static void sam_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, sam_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
sam_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: sam_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void sam_poll_process(FAR struct sam_emac_s *priv)
{
struct net_driver_s *dev = &priv->dev;
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
if (sam_txfree(priv, EMAC_QUEUE_0) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
}
/****************************************************************************
@@ -2765,19 +2640,28 @@ static inline void sam_poll_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_poll_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
struct net_driver_s *dev = &priv->dev;
/* Perform the poll */
/* Check if the there are any free TX descriptors. We cannot perform the
* TX poll if we do not have buffering for another packet.
*/
state = net_lock();
sam_poll_process(priv);
net_unlock(state);
net_lock();
if (sam_txfree(priv, EMAC_QUEUE_0) > 0)
{
/* Update TCP timing states and poll the network for new XMIT data. */
(void)devif_timer(dev, sam_txpoll);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_poll_expiry
@@ -2801,7 +2685,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2820,12 +2703,6 @@ static void sam_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, SAM_WDDELAY, sam_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
sam_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2963,37 +2840,6 @@ static int sam_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: sam_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 inline void sam_txavail_process(FAR struct sam_emac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv, EMAC_QUEUE_0);
}
}
/****************************************************************************
* Function: sam_txavail_work
*
@@ -3011,19 +2857,24 @@ static inline void sam_txavail_process(FAR struct sam_emac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void sam_txavail_work(FAR void *arg)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
sam_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
sam_dopoll(priv, EMAC_QUEUE_0);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: sam_txavail
@@ -3048,7 +2899,6 @@ static int sam_txavail(struct net_driver_s *dev)
{
FAR struct sam_emac_s *priv = (FAR struct sam_emac_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.
@@ -3061,21 +2911,6 @@ static int sam_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, sam_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
sam_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+52 -215
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/stm32/stm32_eth.c
*
* Copyright (C) 2011-2012, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012, 2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -53,14 +53,11 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
#if defined(CONFIG_NET_PKT)
# include <nuttx/net/pkt.h>
#endif
@@ -97,13 +94,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_STM32_ETHMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_STM32_ETHMAC_LPWORK)
@@ -587,9 +583,7 @@ struct stm32_ethmac_s
uint8_t fduplex : 1; /* Full (vs. half) duplex */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -662,34 +656,26 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv);
static void stm32_receive(FAR struct stm32_ethmac_s *priv);
static void stm32_freeframe(FAR struct stm32_ethmac_s *priv);
static void stm32_txdone(FAR struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_interrupt_work(FAR void *arg);
#endif
static int stm32_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void stm32_txtimeout_process(FAR struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_txtimeout_work(FAR void *arg);
#endif
static void stm32_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void stm32_poll_process(FAR struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_poll_work(FAR void *arg);
#endif
static void stm32_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
static int stm32_ifup(struct net_driver_s *dev);
static int stm32_ifdown(struct net_driver_s *dev);
static inline void stm32_txavail_process(FAR struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_txavail_work(FAR void *arg);
#endif
static int stm32_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int stm32_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
#endif
@@ -1964,27 +1950,33 @@ static void stm32_txdone(FAR struct stm32_ethmac_s *priv)
}
/****************************************************************************
* Function: stm32_interrupt_process
* Function: stm32_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void stm32_interrupt_process(FAR struct stm32_ethmac_s *priv)
static void stm32_interrupt_work(FAR void *arg)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
uint32_t dmasr;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
net_lock();
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
dmasr = stm32_getreg(STM32_ETH_DMASR);
@@ -2056,44 +2048,13 @@ static inline void stm32_interrupt_process(FAR struct stm32_ethmac_s *priv)
stm32_putreg(ETH_DMAINT_AIS, STM32_ETH_DMASR);
}
#endif
}
/****************************************************************************
* Function: stm32_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_interrupt_work(FAR void *arg)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
net_lock_t state;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
state = net_lock();
stm32_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts at the NVIC */
up_enable_irq(STM32_IRQ_ETH);
}
#endif
/****************************************************************************
* Function: stm32_interrupt
@@ -2115,8 +2076,6 @@ static void stm32_interrupt_work(FAR void *arg)
static int stm32_interrupt(int irq, FAR void *context)
{
FAR struct stm32_ethmac_s *priv = &g_stm32ethmac[0];
#ifdef CONFIG_NET_NOINTS
uint32_t dmasr;
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
@@ -2152,49 +2111,9 @@ static int stm32_interrupt(int irq, FAR void *context)
work_queue(ETHWORK, &priv->work, stm32_interrupt_work, priv, 0);
}
#else
/* Process the interrupt now */
stm32_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: stm32_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void stm32_txtimeout_process(FAR struct stm32_ethmac_s *priv)
{
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
stm32_ifdown(&priv->dev);
stm32_ifup(&priv->dev);
/* Then poll for new XMIT data */
stm32_dopoll(priv);
}
/****************************************************************************
* Function: stm32_txtimeout_work
*
@@ -2212,19 +2131,21 @@ static inline void stm32_txtimeout_process(FAR struct stm32_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_txtimeout_work(FAR void *arg)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Reset the hardware. Just take the interface down, then back up again. */
state = net_lock();
stm32_txtimeout_process(priv);
net_unlock(state);
net_lock();
stm32_ifdown(&priv->dev);
stm32_ifup(&priv->dev);
/* Then poll for new XMIT data */
stm32_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: stm32_txtimeout_expiry
@@ -2251,7 +2172,6 @@ static void stm32_txtimeout_expiry(int argc, uint32_t arg, ...)
nerr("ERROR: Timeout!\n");
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2270,33 +2190,28 @@ static void stm32_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, stm32_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
stm32_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: stm32_poll_process
* Function: stm32_poll_work
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
* Perform periodic polling from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void stm32_poll_process(FAR struct stm32_ethmac_s *priv)
static void stm32_poll_work(FAR void *arg)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
FAR struct net_driver_s *dev = &priv->dev;
/* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We
@@ -2310,6 +2225,7 @@ static inline void stm32_poll_process(FAR struct stm32_ethmac_s *priv)
* CONFIG_STM32_ETH_NTXDESC).
*/
net_lock();
if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 &&
priv->txhead->tdes2 == 0)
{
@@ -2345,39 +2261,9 @@ static inline void stm32_poll_process(FAR struct stm32_ethmac_s *priv)
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_poll_expiry, 1, priv);
net_unlock();
}
/****************************************************************************
* Function: stm32_poll_work
*
* Description:
* Perform periodic polling from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_poll_work(FAR void *arg)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
stm32_poll_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: stm32_poll_expiry
*
@@ -2400,7 +2286,6 @@ static void stm32_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2419,12 +2304,6 @@ static void stm32_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_poll_expiry, 1, (uint32_t)priv);
}
#else
/* Process the interrupt now */
stm32_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2529,37 +2408,6 @@ static int stm32_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: stm32_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 stm32_txavail_process(FAR struct stm32_ethmac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
stm32_dopoll(priv);
}
}
/****************************************************************************
* Function: stm32_txavail_work
*
@@ -2577,19 +2425,24 @@ static inline void stm32_txavail_process(FAR struct stm32_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_txavail_work(FAR void *arg)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
stm32_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
stm32_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: stm32_txavail
@@ -2614,7 +2467,6 @@ static int stm32_txavail(struct net_driver_s *dev)
{
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_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.
@@ -2627,21 +2479,6 @@ static int stm32_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, stm32_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
stm32_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+52 -217
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/stm32f7/stm32_ethernet.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -52,14 +52,11 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
#if defined(CONFIG_NET_PKT)
# include <nuttx/net/pkt.h>
#endif
@@ -98,13 +95,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_STM32F7_ETHMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_STM32F7_ETHMAC_LPWORK)
@@ -611,9 +607,7 @@ struct stm32_ethmac_s
uint8_t intf; /* Ethernet interface number */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -705,35 +699,26 @@ static int stm32_recvframe(struct stm32_ethmac_s *priv);
static void stm32_receive(struct stm32_ethmac_s *priv);
static void stm32_freeframe(struct stm32_ethmac_s *priv);
static void stm32_txdone(struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_interrupt_work(void *arg);
#endif
static int stm32_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void stm32_txtimeout_process(struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_txtimeout_work(void *arg);
#endif
static void stm32_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void stm32_poll_process(struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_poll_work(void *arg);
#endif
static void stm32_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
static int stm32_ifup(struct net_driver_s *dev);
static int stm32_ifdown(struct net_driver_s *dev);
static int stm32_ifdown(struct net_driver_s *dev);
static inline void stm32_txavail_process(struct stm32_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void stm32_txavail_work(void *arg);
#endif
static int stm32_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int stm32_addmac(struct net_driver_s *dev, const uint8_t *mac);
#endif
@@ -2078,27 +2063,33 @@ static void stm32_txdone(struct stm32_ethmac_s *priv)
}
/****************************************************************************
* Function: stm32_interrupt_process
* Function: stm32_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void stm32_interrupt_process(struct stm32_ethmac_s *priv)
static void stm32_interrupt_work(void *arg)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
uint32_t dmasr;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
net_lock();
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
dmasr = stm32_getreg(STM32_ETH_DMASR);
@@ -2169,44 +2160,13 @@ static inline void stm32_interrupt_process(struct stm32_ethmac_s *priv)
stm32_putreg(ETH_DMAINT_AIS, STM32_ETH_DMASR);
}
#endif
}
/****************************************************************************
* Function: stm32_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_interrupt_work(void *arg)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
net_lock_t state;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
state = net_lock();
stm32_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts at the NVIC */
up_enable_irq(STM32_IRQ_ETH);
}
#endif
/****************************************************************************
* Function: stm32_interrupt
@@ -2228,8 +2188,6 @@ static void stm32_interrupt_work(void *arg)
static int stm32_interrupt(int irq, void *context)
{
struct stm32_ethmac_s *priv = &g_stm32ethmac[0];
#ifdef CONFIG_NET_NOINTS
uint32_t dmasr;
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
@@ -2265,49 +2223,9 @@ static int stm32_interrupt(int irq, void *context)
work_queue(ETHWORK, &priv->work, stm32_interrupt_work, priv, 0);
}
#else
/* Process the interrupt now */
stm32_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: stm32_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void stm32_txtimeout_process(struct stm32_ethmac_s *priv)
{
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
stm32_ifdown(&priv->dev);
stm32_ifup(&priv->dev);
/* Then poll for new XMIT data */
stm32_dopoll(priv);
}
/****************************************************************************
* Function: stm32_txtimeout_work
*
@@ -2325,19 +2243,21 @@ static inline void stm32_txtimeout_process(struct stm32_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_txtimeout_work(void *arg)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Reset the hardware. Just take the interface down, then back up again. */
state = net_lock();
stm32_txtimeout_process(priv);
net_unlock(state);
net_lock();
stm32_ifdown(&priv->dev);
stm32_ifup(&priv->dev);
/* Then poll for new XMIT data */
stm32_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: stm32_txtimeout_expiry
@@ -2364,7 +2284,6 @@ static void stm32_txtimeout_expiry(int argc, uint32_t arg, ...)
nerr("ERROR: Timeout!\n");
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2383,33 +2302,28 @@ static void stm32_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, stm32_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
stm32_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: stm32_poll_process
* Function: stm32_poll_work
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
* Perform periodic polling from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void stm32_poll_process(struct stm32_ethmac_s *priv)
static void stm32_poll_work(void *arg)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
struct net_driver_s *dev = &priv->dev;
/* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We
@@ -2423,6 +2337,7 @@ static inline void stm32_poll_process(struct stm32_ethmac_s *priv)
* CONFIG_STM32F7_ETH_NTXDESC).
*/
net_lock();
if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 &&
priv->txhead->tdes2 == 0)
{
@@ -2458,39 +2373,9 @@ static inline void stm32_poll_process(struct stm32_ethmac_s *priv)
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_poll_expiry, 1, priv);
net_unlock();
}
/****************************************************************************
* Function: stm32_poll_work
*
* Description:
* Perform periodic polling from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_poll_work(void *arg)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
stm32_poll_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: stm32_poll_expiry
*
@@ -2513,7 +2398,6 @@ static void stm32_poll_expiry(int argc, uint32_t arg, ...)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2532,12 +2416,6 @@ static void stm32_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, STM32_WDDELAY, stm32_poll_expiry, 1, (uint32_t)priv);
}
#else
/* Process the interrupt now */
stm32_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2642,38 +2520,6 @@ static int stm32_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: stm32_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 stm32_txavail_process(struct stm32_ethmac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
stm32_dopoll(priv);
}
}
/****************************************************************************
* Function: stm32_txavail_work
*
@@ -2691,19 +2537,24 @@ static inline void stm32_txavail_process(struct stm32_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void stm32_txavail_work(void *arg)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
stm32_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
stm32_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: stm32_txavail
@@ -2728,7 +2579,6 @@ static int stm32_txavail(struct net_driver_s *dev)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_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.
@@ -2741,21 +2591,6 @@ static int stm32_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, stm32_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
stm32_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+71 -231
View File
@@ -52,10 +52,7 @@
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/irq.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <arch/board/board.h>
#include <nuttx/net/arp.h>
@@ -80,13 +77,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE)
#endif
#else
/* Use the low priority work queue if possible */
/* Use the low priority work queue if possible */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_TIVA_ETHERNET_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_TIVA_ETHERNET_LPWORK)
@@ -206,9 +202,7 @@ struct tiva_driver_s
bool ld_bifup; /* true:ifup false:ifdown */
WDOG_ID ld_txpoll; /* TX poll timer */
WDOG_ID ld_txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s ld_work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -256,24 +250,15 @@ static int tiva_txpoll(struct net_driver_s *dev);
static void tiva_receive(struct tiva_driver_s *priv);
static void tiva_txdone(struct tiva_driver_s *priv);
static inline void tiva_interrupt_process(struct tiva_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void tiva_interrupt_work(void *arg);
#endif
static int tiva_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void tiva_txtimeout_process(struct tiva_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void tiva_txtimeout_work(void *arg);
#endif
static void tiva_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void tiva_poll_process(struct tiva_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void tiva_poll_work(void *arg);
#endif
static void tiva_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -281,11 +266,7 @@ 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(struct tiva_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void tiva_txavail_work(void *arg);
#endif
static int tiva_txavail(struct net_driver_s *dev);
#ifdef CONFIG_NET_IGMP
@@ -963,27 +944,31 @@ static void tiva_txdone(struct tiva_driver_s *priv)
}
/****************************************************************************
* Function: tiva_interrupt_process
* Function: tiva_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void tiva_interrupt_process(struct tiva_driver_s *priv)
static void tiva_interrupt_work(void *arg)
{
struct tiva_driver_s *priv = (struct tiva_driver_s *)arg;
uint32_t ris;
/* Process pending Ethernet interrupts */
net_lock();
/* Read the raw interrupt status register */
ris = tiva_ethin(priv, TIVA_MAC_RIS_OFFSET);
@@ -1038,36 +1023,8 @@ static inline void tiva_interrupt_process(struct tiva_driver_s *priv)
tiva_txdone(priv);
}
}
/****************************************************************************
* Function: tiva_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void tiva_interrupt_work(void *arg)
{
struct tiva_driver_s *priv = (struct tiva_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
tiva_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
@@ -1077,7 +1034,6 @@ static void tiva_interrupt_work(void *arg)
up_disable_irq(TIVA_IRQ_ETHCON);
#endif
}
#endif
/****************************************************************************
* Function: tiva_interrupt
@@ -1107,7 +1063,6 @@ static int tiva_interrupt(int irq, void *context)
priv = &g_lm3sdev[0];
#endif
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
@@ -1145,51 +1100,9 @@ static int tiva_interrupt(int irq, void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->ld_work, tiva_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
tiva_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: tiva_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void tiva_txtimeout_process(struct tiva_driver_s *priv)
{
/* Increment statistics */
nerr("ERROR: Tx timeout\n");
NETDEV_TXTIMEOUTS(&priv->ld_dev);
/* Then reset the hardware */
DEBUGASSERT(priv->ld_bifup);
tiva_ifdown(&priv->ld_dev);
tiva_ifup(&priv->ld_dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->ld_dev, tiva_txpoll);
}
/****************************************************************************
* Function: tiva_txtimeout_work
*
@@ -1207,19 +1120,27 @@ static inline void tiva_txtimeout_process(struct tiva_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void tiva_txtimeout_work(void *arg)
{
struct tiva_driver_s *priv = (struct tiva_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Increment statistics */
state = net_lock();
tiva_txtimeout_process(priv);
net_unlock(state);
net_lock();
nerr("ERROR: Tx timeout\n");
NETDEV_TXTIMEOUTS(&priv->ld_dev);
/* Then reset the hardware */
DEBUGASSERT(priv->ld_bifup);
tiva_ifdown(&priv->ld_dev);
tiva_ifup(&priv->ld_dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->ld_dev, tiva_txpoll);
net_unlock();
}
#endif
/****************************************************************************
* Function: tiva_txtimeout_expiry
@@ -1244,7 +1165,6 @@ static void tiva_txtimeout_expiry(int argc, wdparm_t arg, ...)
{
struct tiva_driver_s *priv = (struct tiva_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -1265,53 +1185,6 @@ static void tiva_txtimeout_expiry(int argc, wdparm_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->ld_work, tiva_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
tiva_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: tiva_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void tiva_poll_process(struct tiva_driver_s *priv)
{
/* Check if we can send another Tx packet now. The NEWTX bit initiates an
* Ethernet transmission once the packet has been placed in the TX FIFO.
* This bit is cleared once the transmission has been completed.
*
* NOTE: This can cause missing poll cycles and, hence, some timing
* inaccuracies.
*/
if ((tiva_ethin(priv, TIVA_MAC_TR_OFFSET) & MAC_TR_NEWTX) == 0)
{
/* If so, update TCP timing states and poll the network for new XMIT
* data.
*/
(void)devif_timer(&priv->ld_dev, tiva_txpoll);
/* Setup the watchdog poll timer again */
(void)wd_start(priv->ld_txpoll, TIVA_WDDELAY, tiva_poll_expiry,
1, priv);
}
}
/****************************************************************************
@@ -1331,19 +1204,35 @@ static inline void tiva_poll_process(struct tiva_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void tiva_poll_work(void *arg)
{
struct tiva_driver_s *priv = (struct tiva_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Check if we can send another Tx packet now. The NEWTX bit initiates an
* Ethernet transmission once the packet has been placed in the TX FIFO.
* This bit is cleared once the transmission has been completed.
*
* NOTE: This can cause missing poll cycles and, hence, some timing
* inaccuracies.
*/
state = net_lock();
tiva_poll_process(priv);
net_unlock(state);
net_lock();
if ((tiva_ethin(priv, TIVA_MAC_TR_OFFSET) & MAC_TR_NEWTX) == 0)
{
/* If so, update TCP timing states and poll the network for new XMIT
* data.
*/
(void)devif_timer(&priv->ld_dev, tiva_txpoll);
/* Setup the watchdog poll timer again */
(void)wd_start(priv->ld_txpoll, TIVA_WDDELAY, tiva_poll_expiry,
1, priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: tiva_poll_expiry
@@ -1367,7 +1256,6 @@ static void tiva_poll_expiry(int argc, wdparm_t arg, ...)
{
struct tiva_driver_s *priv = (struct tiva_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -1386,12 +1274,6 @@ static void tiva_poll_expiry(int argc, wdparm_t arg, ...)
(void)wd_start(priv->ld_txpoll, TIVA_WDDELAY, tiva_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
tiva_poll_process(priv);
#endif
}
/****************************************************************************
@@ -1633,43 +1515,6 @@ static int tiva_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: tiva_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 inline void tiva_txavail_process(struct tiva_driver_s *priv)
{
/* Ignore the notification if the interface is not yet up or if the Tx FIFO
* hardware is not available at this time. The NEWTX bit initiates an
* Ethernet transmission once the packet has been placed in the TX FIFO.
* This bit is cleared once the transmission has been completed. When the
* transmission completes, tiva_txdone() will be called and the Tx polling
* will occur at that time.
*/
if (priv->ld_bifup && (tiva_ethin(priv, TIVA_MAC_TR_OFFSET) & MAC_TR_NEWTX) == 0)
{
/* If the interface is up and we can use the Tx FIFO, then poll the network
* for new Tx data
*/
(void)devif_poll(&priv->ld_dev, tiva_txpoll);
}
}
/****************************************************************************
* Function: tiva_txavail_work
*
@@ -1687,19 +1532,30 @@ static inline void tiva_txavail_process(struct tiva_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void tiva_txavail_work(void *arg)
{
struct tiva_driver_s *priv = (struct tiva_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up or if the Tx FIFO
* hardware is not available at this time. The NEWTX bit initiates an
* Ethernet transmission once the packet has been placed in the TX FIFO.
* This bit is cleared once the transmission has been completed. When the
* transmission completes, tiva_txdone() will be called and the Tx polling
* will occur at that time.
*/
state = net_lock();
tiva_txavail_process(priv);
net_unlock(state);
net_lock();
if (priv->ld_bifup && (tiva_ethin(priv, TIVA_MAC_TR_OFFSET) & MAC_TR_NEWTX) == 0)
{
/* If the interface is up and we can use the Tx FIFO, then poll the network
* for new Tx data
*/
(void)devif_poll(&priv->ld_dev, tiva_txpoll);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: tiva_txavail
@@ -1724,7 +1580,6 @@ static int tiva_txavail(struct net_driver_s *dev)
{
struct tiva_driver_s *priv = (struct tiva_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.
@@ -1737,21 +1592,6 @@ static int tiva_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->ld_work, tiva_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
tiva_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+50 -213
View File
@@ -53,11 +53,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -102,13 +98,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_TIVA_ETHERNET_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_TIVA_ETHERNET_LPWORK)
@@ -631,9 +626,7 @@ struct tiva_ethmac_s
uint8_t fduplex : 1; /* Full (vs. half) duplex */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
#ifdef CONFIG_TIVA_PHY_INTERRUPTS
xcpt_t handler; /* Attached PHY interrupt handler */
#endif
@@ -709,35 +702,26 @@ static int tiva_recvframe(FAR struct tiva_ethmac_s *priv);
static void tiva_receive(FAR struct tiva_ethmac_s *priv);
static void tiva_freeframe(FAR struct tiva_ethmac_s *priv);
static void tiva_txdone(FAR struct tiva_ethmac_s *priv);
static inline void tiva_interrupt_process(FAR struct tiva_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void tiva_interrupt_work(FAR void *arg);
#endif
static int tiva_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void tiva_txtimeout_process(FAR struct tiva_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void tiva_txtimeout_work(FAR void *arg);
#endif
static void tiva_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void tiva_poll_process(FAR struct tiva_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void tiva_poll_work(FAR void *arg);
#endif
static void tiva_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
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);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int tiva_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
#endif
@@ -1994,27 +1978,33 @@ static void tiva_txdone(FAR struct tiva_ethmac_s *priv)
}
/****************************************************************************
* Function: tiva_interrupt_process
* Function: tiva_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void tiva_interrupt_process(FAR struct tiva_ethmac_s *priv)
static void tiva_interrupt_work(FAR void *arg)
{
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg;
uint32_t dmaris;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
net_lock();
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
dmaris = tiva_getreg(TIVA_EMAC_DMARIS);
@@ -2086,44 +2076,13 @@ static inline void tiva_interrupt_process(FAR struct tiva_ethmac_s *priv)
tiva_putreg(EMAC_DMAINT_AIS, TIVA_EMAC_DMARIS);
}
#endif
}
/****************************************************************************
* Function: tiva_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void tiva_interrupt_work(FAR void *arg)
{
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg;
net_lock_t state;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
state = net_lock();
tiva_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts at the NVIC */
up_enable_irq(TIVA_IRQ_ETHCON);
}
#endif
/****************************************************************************
* Function: tiva_interrupt
@@ -2145,8 +2104,6 @@ static void tiva_interrupt_work(FAR void *arg)
static int tiva_interrupt(int irq, FAR void *context)
{
FAR struct tiva_ethmac_s *priv = &g_tiva_ethmac[0];
#ifdef CONFIG_NET_NOINTS
uint32_t dmaris;
/* Get the raw interrupt status. */
@@ -2182,12 +2139,6 @@ static int tiva_interrupt(int irq, FAR void *context)
work_queue(ETHWORK, &priv->work, tiva_interrupt_work, priv, 0);
}
#else
/* Process the interrupt now */
tiva_interrupt_process(priv);
#endif
#ifdef CONFIG_TIVA_PHY_INTERRUPTS
/* Check for pending PHY interrupts */
@@ -2209,38 +2160,6 @@ static int tiva_interrupt(int irq, FAR void *context)
return OK;
}
/****************************************************************************
* Function: tiva_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void tiva_txtimeout_process(FAR struct tiva_ethmac_s *priv)
{
/* Reset the hardware. Just take the interface down, then back up again. */
tiva_ifdown(&priv->dev);
tiva_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
tiva_dopoll(priv);
}
/****************************************************************************
* Function: tiva_txtimeout_work
*
@@ -2258,19 +2177,21 @@ 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;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Reset the hardware. Just take the interface down, then back up again. */
state = net_lock();
tiva_txtimeout_process(priv);
net_unlock(state);
net_lock();
tiva_ifdown(&priv->dev);
tiva_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
tiva_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: tiva_txtimeout_expiry
@@ -2297,7 +2218,6 @@ static void tiva_txtimeout_expiry(int argc, uint32_t arg, ...)
nerr("ERROR: Timeout!\n");
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2316,33 +2236,28 @@ static void tiva_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, tiva_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
tiva_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: tiva_poll_process
* Function: tiva_poll_work
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
* Perform periodic polling from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void tiva_poll_process(FAR struct tiva_ethmac_s *priv)
static void tiva_poll_work(FAR void *arg)
{
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg;
FAR struct net_driver_s *dev = &priv->dev;
/* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We
@@ -2356,6 +2271,7 @@ static inline void tiva_poll_process(FAR struct tiva_ethmac_s *priv)
* CONFIG_TIVA_EMAC_NTXDESC).
*/
net_lock();
if ((priv->txhead->tdes0 & EMAC_TDES0_OWN) == 0 &&
priv->txhead->tdes2 == 0)
{
@@ -2391,39 +2307,9 @@ static inline void tiva_poll_process(FAR struct tiva_ethmac_s *priv)
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, TIVA_WDDELAY, tiva_poll_expiry, 1, (uint32_t)priv);
net_unlock();
}
/****************************************************************************
* Function: tiva_poll_work
*
* Description:
* Perform periodic polling from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void tiva_poll_work(FAR void *arg)
{
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
tiva_poll_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: tiva_poll_expiry
*
@@ -2446,7 +2332,6 @@ static void tiva_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2465,12 +2350,6 @@ static void tiva_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, TIVA_WDDELAY, tiva_poll_expiry, 1, (uint32_t)priv);
}
#else
/* Process the interrupt now */
tiva_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2575,37 +2454,6 @@ 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)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll the network for new XMIT data */
tiva_dopoll(priv);
}
}
/****************************************************************************
* Function: tiva_txavail_work
*
@@ -2623,19 +2471,24 @@ static inline void tiva_txavail_process(FAR struct tiva_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void tiva_txavail_work(FAR void *arg)
{
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
ninfo("ifup: %d\n", priv->ifup);
state = net_lock();
tiva_txavail_process(priv);
net_unlock(state);
/* Ignore the notification if the interface is not yet up */
net_lock();
if (priv->ifup)
{
/* Poll the network for new XMIT data */
tiva_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: tiva_txavail
@@ -2660,7 +2513,6 @@ static int tiva_txavail(struct net_driver_s *dev)
{
FAR struct tiva_ethmac_s *priv = (FAR struct tiva_ethmac_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.
@@ -2673,21 +2525,6 @@ static int tiva_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, tiva_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
tiva_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+70 -231
View File
@@ -55,11 +55,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/arp.h>
@@ -90,13 +86,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE)
#endif
#else
/* Use the low priority work queue if possible */
/* Use the low priority work queue if possible */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_PIC32MX_ETHERNET_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_PIC32MX_ETHERNET_LPWORK)
@@ -326,9 +321,7 @@ struct pic32mx_driver_s
uint32_t pd_inten; /* Shadow copy of INTEN register */
WDOG_ID pd_txpoll; /* TX poll timer */
WDOG_ID pd_txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s pd_work; /* For deferring work to the work queue */
#endif
sq_queue_t pd_freebuffers; /* The free buffer list */
@@ -401,24 +394,15 @@ static void pic32mx_response(struct pic32mx_driver_s *priv);
static void pic32mx_rxdone(struct pic32mx_driver_s *priv);
static void pic32mx_txdone(struct pic32mx_driver_s *priv);
static inline void pic32mx_interrupt_process(struct pic32mx_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mx_interrupt_work(void *arg);
#endif
static int pic32mx_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void pic32mx_txtimeout_process(struct pic32mx_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mx_txtimeout_work(void *arg);
#endif
static void pic32mx_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void pic32mx_poll_process(struct pic32mx_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mx_poll_work(void *arg);
#endif
static void pic32mx_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -426,10 +410,7 @@ static void pic32mx_poll_expiry(int argc, uint32_t arg, ...);
static int pic32mx_ifup(struct net_driver_s *dev);
static int pic32mx_ifdown(struct net_driver_s *dev);
static inline void pic32mx_txavail_process(struct pic32mx_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mx_txavail_work(void *arg);
#endif
static int pic32mx_txavail(struct net_driver_s *dev);
#ifdef CONFIG_NET_IGMP
@@ -1682,27 +1663,31 @@ static void pic32mx_txdone(struct pic32mx_driver_s *priv)
}
/****************************************************************************
* Function: pic32mx_interrupt_process
* Function: pic32mx_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void pic32mx_interrupt_process(struct pic32mx_driver_s *priv)
static void pic32mx_interrupt_work(void *arg)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
uint32_t status;
/* Process pending Ethernet interrupts */
net_lock();
/* Get the interrupt status (zero means no interrupts pending). */
status = pic32mx_getreg(PIC32MX_ETH_IRQ);
@@ -1840,36 +1825,7 @@ static inline void pic32mx_interrupt_process(struct pic32mx_driver_s *priv)
#else
up_clrpend_irq(PIC32MX_IRQSRC_ETH);
#endif
}
/****************************************************************************
* Function: pic32mx_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mx_interrupt_work(void *arg)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
pic32mx_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
@@ -1879,7 +1835,6 @@ static void pic32mx_interrupt_work(void *arg)
up_enable_irq(PIC32MX_IRQSRC_ETH);
#endif
}
#endif
/****************************************************************************
* Function: pic32mx_interrupt
@@ -1909,7 +1864,6 @@ static int pic32mx_interrupt(int irq, void *context)
priv = &g_ethdrvr[0];
#endif
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
@@ -1944,54 +1898,9 @@ static int pic32mx_interrupt(int irq, void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->pd_work, pic32mx_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
pic32mx_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: pic32mx_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void pic32mx_txtimeout_process(struct pic32mx_driver_s *priv)
{
/* Increment statistics and dump debug info */
NETDEV_TXTIMEOUTS(&priv->pd_dev);
if (priv->pd_ifup)
{
/* Then reset the hardware. ifup() will reset the interface, then bring
* it back up.
*/
(void)pic32mx_ifup(&priv->pd_dev);
/* Then poll the network for new XMIT data (We are guaranteed to have
* a free buffer here).
*/
pic32mx_poll(priv);
}
}
/****************************************************************************
* Function: pic32mx_txtimeout_work
*
@@ -2009,19 +1918,31 @@ static inline void pic32mx_txtimeout_process(struct pic32mx_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mx_txtimeout_work(void *arg)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Increment statistics and dump debug info */
state = net_lock();
pic32mx_txtimeout_process(priv);
net_unlock(state);
net_lock();
NETDEV_TXTIMEOUTS(&priv->pd_dev);
if (priv->pd_ifup)
{
/* Then reset the hardware. ifup() will reset the interface, then bring
* it back up.
*/
(void)pic32mx_ifup(&priv->pd_dev);
/* Then poll the network for new XMIT data (We are guaranteed to have
* a free buffer here).
*/
pic32mx_poll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: pic32mx_txtimeout_expiry
@@ -2046,7 +1967,6 @@ static void pic32mx_txtimeout_expiry(int argc, wdparm_t arg, ...)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2067,50 +1987,6 @@ static void pic32mx_txtimeout_expiry(int argc, wdparm_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->pd_work, pic32mx_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
pic32mx_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: pic32mx_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void pic32mx_poll_process(struct pic32mx_driver_s *priv)
{
/* Check if the next Tx descriptor is available. We cannot perform the Tx
* poll if we are unable to accept another packet for transmission.
*/
if (pic32mx_txdesc(priv) != NULL)
{
/* If so, update TCP timing states and poll the network for new XMIT data. Hmmm..
* might be bug here. Does this mean if there is a transmit in progress,
* we will missing TCP time state updates?
*/
pic32mx_timerpoll(priv);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->pd_txpoll, PIC32MX_WDDELAY, pic32mx_poll_expiry,
1, priv);
}
/****************************************************************************
@@ -2130,19 +2006,31 @@ static inline void pic32mx_poll_process(struct pic32mx_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mx_poll_work(void *arg)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Check if the next Tx descriptor is available. We cannot perform the Tx
* poll if we are unable to accept another packet for transmission.
*/
state = net_lock();
pic32mx_poll_process(priv);
net_unlock(state);
net_lock();
if (pic32mx_txdesc(priv) != NULL)
{
/* If so, update TCP timing states and poll the network for new XMIT data. Hmmm..
* might be bug here. Does this mean if there is a transmit in progress,
* we will missing TCP time state updates?
*/
pic32mx_timerpoll(priv);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->pd_txpoll, PIC32MX_WDDELAY, pic32mx_poll_expiry,
1, priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: pic32mx_poll_expiry
@@ -2166,7 +2054,6 @@ static void pic32mx_poll_expiry(int argc, wdparm_t arg, ...)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2186,12 +2073,6 @@ static void pic32mx_poll_expiry(int argc, wdparm_t arg, ...)
(void)wd_start(priv->pd_txpoll, PIC32MX_WDDELAY, pic32mx_poll_expiry,
1, arg);
}
#else
/* Process the interrupt now */
pic32mx_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2541,42 +2422,6 @@ static int pic32mx_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: pic32mx_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 inline void pic32mx_txavail_process(struct pic32mx_driver_s *priv)
{
/* Ignore the notification if the interface is not yet up */
if (priv->pd_ifup)
{
/* Check if the next Tx descriptor is available. */
if (pic32mx_txdesc(priv) != NULL)
{
/* If so, then poll the network for new XMIT data. First allocate a buffer
* to perform the poll
*/
pic32mx_poll(priv);
}
}
}
/****************************************************************************
* Function: pic32mx_txavail_work
*
@@ -2594,19 +2439,29 @@ static inline void pic32mx_txavail_process(struct pic32mx_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mx_txavail_work(void *arg)
{
struct pic32mx_driver_s *priv = (struct pic32mx_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up */
state = net_lock();
pic32mx_txavail_process(priv);
net_unlock(state);
net_lock();
if (priv->pd_ifup)
{
/* Check if the next Tx descriptor is available. */
if (pic32mx_txdesc(priv) != NULL)
{
/* If so, then poll the network for new XMIT data. First allocate a buffer
* to perform the poll
*/
pic32mx_poll(priv);
}
}
net_unlock();
}
#endif
/****************************************************************************
* Function: pic32mx_txavail
@@ -2631,7 +2486,6 @@ static int pic32mx_txavail(struct net_driver_s *dev)
{
struct pic32mx_driver_s *priv = (struct pic32mx_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.
@@ -2644,21 +2498,6 @@ static int pic32mx_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->pd_work, pic32mx_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
pic32mx_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+70 -231
View File
@@ -55,11 +55,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/arp.h>
@@ -90,13 +86,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE)
#endif
#else
/* Use the low priority work queue if possible */
/* Use the low priority work queue if possible */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_PIC32MZ_ETHERNET_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_PIC32MZ_ETHERNET_LPWORK)
@@ -353,9 +348,7 @@ struct pic32mz_driver_s
uint32_t pd_inten; /* Shadow copy of INTEN register */
WDOG_ID pd_txpoll; /* TX poll timer */
WDOG_ID pd_txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s pd_work; /* For deferring work to the work queue */
#endif
sq_queue_t pd_freebuffers; /* The free buffer list */
@@ -428,24 +421,15 @@ static void pic32mz_response(struct pic32mz_driver_s *priv);
static void pic32mz_rxdone(struct pic32mz_driver_s *priv);
static void pic32mz_txdone(struct pic32mz_driver_s *priv);
static inline void pic32mz_interrupt_process(struct pic32mz_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mz_interrupt_work(void *arg);
#endif
static int pic32mz_interrupt(int irq, void *context);
/* Watchdog timer expirations */
static inline void pic32mz_txtimeout_process(struct pic32mz_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mz_txtimeout_work(void *arg);
#endif
static void pic32mz_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void pic32mz_poll_process(struct pic32mz_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mz_poll_work(void *arg);
#endif
static void pic32mz_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -453,10 +437,7 @@ static void pic32mz_poll_expiry(int argc, uint32_t arg, ...);
static int pic32mz_ifup(struct net_driver_s *dev);
static int pic32mz_ifdown(struct net_driver_s *dev);
static inline void pic32mz_txavail_process(struct pic32mz_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void pic32mz_txavail_work(void *arg);
#endif
static int pic32mz_txavail(struct net_driver_s *dev);
#ifdef CONFIG_NET_IGMP
@@ -1709,27 +1690,31 @@ static void pic32mz_txdone(struct pic32mz_driver_s *priv)
}
/****************************************************************************
* Function: pic32mz_interrupt_process
* Function: pic32mz_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void pic32mz_interrupt_process(struct pic32mz_driver_s *priv)
static void pic32mz_interrupt_work(void *arg)
{
struct pic32mz_driver_s *priv = (struct pic32mz_driver_s *)arg;
uint32_t status;
/* Process pending Ethernet interrupts */
net_lock();
/* Get the interrupt status (zero means no interrupts pending). */
status = pic32mz_getreg(PIC32MZ_ETH_IRQ);
@@ -1867,36 +1852,7 @@ static inline void pic32mz_interrupt_process(struct pic32mz_driver_s *priv)
#else
up_clrpend_irq(PIC32MZ_IRQ_ETH);
#endif
}
/****************************************************************************
* Function: pic32mz_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mz_interrupt_work(void *arg)
{
struct pic32mz_driver_s *priv = (struct pic32mz_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
pic32mz_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
@@ -1906,7 +1862,6 @@ static void pic32mz_interrupt_work(void *arg)
up_enable_irq(PIC32MZ_IRQ_ETH);
#endif
}
#endif
/****************************************************************************
* Function: pic32mz_interrupt
@@ -1936,7 +1891,6 @@ static int pic32mz_interrupt(int irq, void *context)
priv = &g_ethdrvr[0];
#endif
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
@@ -1971,54 +1925,9 @@ static int pic32mz_interrupt(int irq, void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->pd_work, pic32mz_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
pic32mz_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: pic32mz_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void pic32mz_txtimeout_process(struct pic32mz_driver_s *priv)
{
/* Increment statistics and dump debug info */
NETDEV_TXTIMEOUTS(&priv->pd_dev);
if (priv->pd_ifup)
{
/* Then reset the hardware. ifup() will reset the interface, then bring
* it back up.
*/
(void)pic32mz_ifup(&priv->pd_dev);
/* Then poll the network for new XMIT data (We are guaranteed to have a free
* buffer here).
*/
pic32mz_poll(priv);
}
}
/****************************************************************************
* Function: pic32mz_txtimeout_work
*
@@ -2036,19 +1945,31 @@ static inline void pic32mz_txtimeout_process(struct pic32mz_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mz_txtimeout_work(void *arg)
{
struct pic32mz_driver_s *priv = (struct pic32mz_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Increment statistics and dump debug info */
state = net_lock();
pic32mz_txtimeout_process(priv);
net_unlock(state);
net_lock();
NETDEV_TXTIMEOUTS(&priv->pd_dev);
if (priv->pd_ifup)
{
/* Then reset the hardware. ifup() will reset the interface, then bring
* it back up.
*/
(void)pic32mz_ifup(&priv->pd_dev);
/* Then poll the network for new XMIT data (We are guaranteed to have a free
* buffer here).
*/
pic32mz_poll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: pic32mz_txtimeout_expiry
@@ -2073,7 +1994,6 @@ static void pic32mz_txtimeout_expiry(int argc, wdparm_t arg, ...)
{
struct pic32mz_driver_s *priv = (struct pic32mz_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -2094,50 +2014,6 @@ static void pic32mz_txtimeout_expiry(int argc, wdparm_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->pd_work, pic32mz_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
pic32mz_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: pic32mz_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void pic32mz_poll_process(struct pic32mz_driver_s *priv)
{
/* Check if the next Tx descriptor is available. We cannot perform the Tx
* poll if we are unable to accept another packet for transmission.
*/
if (pic32mz_txdesc(priv) != NULL)
{
/* If so, update TCP timing states and poll the network for new XMIT
* data. Hmmm.. might be bug here. Does this mean if there is a
* transmit in progress, we will missing TCP time state updates?
*/
pic32mz_timerpoll(priv);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->pd_txpoll, PIC32MZ_WDDELAY, pic32mz_poll_expiry,
1, priv);
}
/****************************************************************************
@@ -2157,19 +2033,31 @@ static inline void pic32mz_poll_process(struct pic32mz_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mz_poll_work(void *arg)
{
struct pic32mz_driver_s *priv = (struct pic32mz_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Check if the next Tx descriptor is available. We cannot perform the Tx
* poll if we are unable to accept another packet for transmission.
*/
state = net_lock();
pic32mz_poll_process(priv);
net_unlock(state);
net_lock();
if (pic32mz_txdesc(priv) != NULL)
{
/* If so, update TCP timing states and poll the network for new XMIT
* data. Hmmm.. might be bug here. Does this mean if there is a
* transmit in progress, we will missing TCP time state updates?
*/
pic32mz_timerpoll(priv);
}
/* Setup the watchdog poll timer again */
(void)wd_start(priv->pd_txpoll, PIC32MZ_WDDELAY, pic32mz_poll_expiry,
1, priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: pic32mz_poll_expiry
@@ -2193,7 +2081,6 @@ static void pic32mz_poll_expiry(int argc, wdparm_t arg, ...)
{
struct pic32mz_driver_s *priv = (struct pic32mz_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2212,12 +2099,6 @@ static void pic32mz_poll_expiry(int argc, wdparm_t arg, ...)
(void)wd_start(priv->pd_txpoll, PIC32MZ_WDDELAY, pic32mz_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
pic32mz_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2573,42 +2454,6 @@ static int pic32mz_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: pic32mz_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 inline void pic32mz_txavail_process(struct pic32mz_driver_s *priv)
{
/* Ignore the notification if the interface is not yet up */
if (priv->pd_ifup)
{
/* Check if the next Tx descriptor is available. */
if (pic32mz_txdesc(priv) != NULL)
{
/* If so, then poll the network for new XMIT data. First allocate a buffer
* to perform the poll
*/
pic32mz_poll(priv);
}
}
}
/****************************************************************************
* Function: pic32mz_txavail_work
*
@@ -2626,19 +2471,29 @@ static inline void pic32mz_txavail_process(struct pic32mz_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void pic32mz_txavail_work(void *arg)
{
struct pic32mz_driver_s *priv = (struct pic32mz_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up */
state = net_lock();
pic32mz_txavail_process(priv);
net_unlock(state);
net_lock();
if (priv->pd_ifup)
{
/* Check if the next Tx descriptor is available. */
if (pic32mz_txdesc(priv) != NULL)
{
/* If so, then poll the network for new XMIT data. First allocate a buffer
* to perform the poll
*/
pic32mz_poll(priv);
}
}
net_unlock();
}
#endif
/****************************************************************************
* Function: pic32mz_txavail
@@ -2663,7 +2518,6 @@ static int pic32mz_txavail(struct net_driver_s *dev)
{
struct pic32mz_driver_s *priv = (struct pic32mz_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.
@@ -2676,21 +2530,6 @@ static int pic32mz_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->pd_work, pic32mz_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
pic32mz_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
+63 -217
View File
@@ -54,20 +54,18 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include <nuttx/wqueue.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
#include <arch/board/board.h>
#include <arch/board/generated/csr.h>
#include "chip.h"
#include "hw/flags.h"
#include "hw/ethmac_mem.h"
#include "misoc.h"
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#ifdef CONFIG_NET_PKT
# include <nuttx/net/pkt.h>
#endif
@@ -80,8 +78,8 @@
* work queue support is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_HPWORK)
/* REVISIT: The low priority work queue would be preferred if it is avaiable */
#if !defined(CONFIG_SCHED_HPWORK)
/* REVISIT: The low priority work queue would be preferred if it is avaiable */
# error High priority work queue support is required
#endif
@@ -119,9 +117,7 @@ struct misoc_net_driver_s
bool misoc_net_bifup; /* true:ifup false:ifdown */
WDOG_ID misoc_net_txpoll; /* TX poll timer */
WDOG_ID misoc_net_txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s misoc_net_work; /* For deferring work to the work queue */
#endif
uint8_t *rx0_buf; /* 2 RX and 2 TX buffer */
uint8_t *rx1_buf;
@@ -163,35 +159,26 @@ static int misoc_net_txpoll(FAR struct net_driver_s *dev);
static void misoc_net_receive(FAR struct misoc_net_driver_s *priv);
static void misoc_net_txdone(FAR struct misoc_net_driver_s *priv);
static inline void misoc_net_interrupt_process(FAR struct misoc_net_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void misoc_net_interrupt_work(FAR void *arg);
#endif
static int misoc_net_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void misoc_net_txtimeout_process(FAR struct misoc_net_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void misoc_net_txtimeout_work(FAR void *arg);
#endif
static void misoc_net_txtimeout_expiry(int argc, wdparm_t arg, ...);
static inline void misoc_net_poll_process(FAR struct misoc_net_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void misoc_net_poll_work(FAR void *arg);
#endif
static void misoc_net_poll_expiry(int argc, wdparm_t arg, ...);
/* NuttX callback functions */
static int misoc_net_ifup(FAR struct net_driver_s *dev);
static int misoc_net_ifdown(FAR struct net_driver_s *dev);
static inline void misoc_net_txavail_process(FAR struct misoc_net_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void misoc_net_txavail_work(FAR void *arg);
#endif
static int misoc_net_txavail(FAR struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int misoc_net_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac);
#ifdef CONFIG_NET_IGMP
@@ -586,28 +573,29 @@ static void misoc_net_txdone(FAR struct misoc_net_driver_s *priv)
}
/****************************************************************************
* Function: misoc_net_interrupt_process
* Function: misoc_net_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void misoc_net_interrupt_process(FAR struct misoc_net_driver_s *priv)
static void misoc_net_interrupt_work(FAR void *arg)
{
/* Get and clear interrupt status bits */
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_driver_s *)arg;
/* Handle interrupts according to status bit settings */
/* Process pending Ethernet interrupts */
net_lock();
/* Check if we received an incoming packet, if so, call misoc_net_receive() */
@@ -626,42 +614,13 @@ static inline void misoc_net_interrupt_process(FAR struct misoc_net_driver_s *pr
misoc_net_txdone(priv);
ethmac_sram_reader_ev_pending_write(1);
}
}
/****************************************************************************
* Function: misoc_net_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void misoc_net_interrupt_work(FAR void *arg)
{
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
misoc_net_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
up_enable_irq(ETHMAC_INTERRUPT);
}
#endif
/****************************************************************************
* Function: misoc_net_interrupt
@@ -684,7 +643,6 @@ static int misoc_net_interrupt(int irq, FAR void *context)
{
FAR struct misoc_net_driver_s *priv = &g_misoc_net[0];
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
@@ -709,47 +667,9 @@ static int misoc_net_interrupt(int irq, FAR void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(HPWORK, &priv->misoc_net_work, misoc_net_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
misoc_net_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: misoc_net_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void misoc_net_txtimeout_process(FAR struct misoc_net_driver_s *priv)
{
/* Increment statistics and dump debug info */
NETDEV_TXTIMEOUTS(priv->misoc_net_dev);
/* Then reset the hardware */
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->misoc_net_dev, misoc_net_txpoll);
}
/****************************************************************************
* Function: misoc_net_txtimeout_work
*
@@ -767,19 +687,22 @@ static inline void misoc_net_txtimeout_process(FAR struct misoc_net_driver_s *pr
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void misoc_net_txtimeout_work(FAR void *arg)
{
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Increment statistics and dump debug info */
state = net_lock();
misoc_net_txtimeout_process(priv);
net_unlock(state);
net_lock();
NETDEV_TXTIMEOUTS(priv->misoc_net_dev);
/* Then reset the hardware */
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->misoc_net_dev, misoc_net_txpoll);
net_unlock();
}
#endif
/****************************************************************************
* Function: misoc_net_txtimeout_expiry
@@ -804,7 +727,6 @@ static void misoc_net_txtimeout_expiry(int argc, wdparm_t arg, ...)
{
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* 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.
@@ -821,47 +743,6 @@ static void misoc_net_txtimeout_expiry(int argc, wdparm_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(HPWORK, &priv->misoc_net_work, misoc_net_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
misoc_net_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: misoc_net_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void misoc_net_poll_process(FAR struct misoc_net_driver_s *priv)
{
/* Check if there is room in the send another TX packet. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
/* If so, update TCP timing states and poll the network for new XMIT data.
* Hmmm.. might be bug here. Does this mean if there is a transmit in
* progress, we will missing TCP time state updates?
*/
(void)devif_timer(&priv->misoc_net_dev, misoc_net_txpoll);
/* Setup the watchdog poll timer again */
(void)wd_start(priv->misoc_net_txpoll, MISOC_NET_WDDELAY, misoc_net_poll_expiry, 1,
(wdparm_t)priv);
}
/****************************************************************************
@@ -881,19 +762,32 @@ static inline void misoc_net_poll_process(FAR struct misoc_net_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void misoc_net_poll_work(FAR void *arg)
{
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
misoc_net_poll_process(priv);
net_unlock(state);
net_lock();
/* Check if there is room in the send another TX packet. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
/* If so, update TCP timing states and poll the network for new XMIT data.
* Hmmm.. might be bug here. Does this mean if there is a transmit in
* progress, we will missing TCP time state updates?
*/
(void)devif_timer(&priv->misoc_net_dev, misoc_net_txpoll);
/* Setup the watchdog poll timer again */
(void)wd_start(priv->misoc_net_txpoll, MISOC_NET_WDDELAY, misoc_net_poll_expiry, 1,
(wdparm_t)priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: misoc_net_poll_expiry
@@ -917,7 +811,6 @@ static void misoc_net_poll_expiry(int argc, wdparm_t arg, ...)
{
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -934,14 +827,9 @@ static void misoc_net_poll_expiry(int argc, wdparm_t arg, ...)
* cycle.
*/
(void)wd_start(priv->misoc_net_txpoll, MISOC_NET_WDDELAY, misoc_net_poll_expiry, 1, arg);
(void)wd_start(priv->misoc_net_txpoll, MISOC_NET_WDDELAY,
misoc_net_poll_expiry, 1, arg);
}
#else
/* Process the interrupt now */
misoc_net_poll_process(priv);
#endif
}
/****************************************************************************
@@ -1044,40 +932,6 @@ static int misoc_net_ifdown(FAR struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: misoc_net_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 inline void misoc_net_txavail_process(FAR struct misoc_net_driver_s *priv)
{
/* Ignore the notification if the interface is not yet up */
if (priv->misoc_net_bifup)
{
/* Check if there is room in the hardware to hold another outgoing packet. */
if (!ethmac_sram_reader_ready_read())
{
/* If so, then poll the network for new XMIT data */
(void)devif_poll(&priv->misoc_net_dev, misoc_net_txpoll);
}
}
}
/****************************************************************************
* Function: misoc_net_txavail_work
*
@@ -1095,19 +949,27 @@ static inline void misoc_net_txavail_process(FAR struct misoc_net_driver_s *priv
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void misoc_net_txavail_work(FAR void *arg)
{
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up */
state = net_lock();
misoc_net_txavail_process(priv);
net_unlock(state);
net_lock();
if (priv->misoc_net_bifup)
{
/* Check if there is room in the hardware to hold another outgoing packet. */
if (!ethmac_sram_reader_ready_read())
{
/* If so, then poll the network for new XMIT data */
(void)devif_poll(&priv->misoc_net_dev, misoc_net_txpoll);
}
}
net_unlock();
}
#endif
/****************************************************************************
* Function: misoc_net_txavail
@@ -1132,7 +994,6 @@ static int misoc_net_txavail(FAR struct net_driver_s *dev)
{
FAR struct misoc_net_driver_s *priv = (FAR struct misoc_net_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.
@@ -1145,21 +1006,6 @@ static int misoc_net_txavail(FAR struct net_driver_s *dev)
work_queue(HPWORK, &priv->misoc_net_work, misoc_net_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
misoc_net_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
File diff suppressed because it is too large Load Diff
-1
View File
@@ -477,7 +477,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -470,7 +470,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -478,7 +478,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -915,7 +915,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
# CONFIG_NET_NOINTS is not set
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -226,7 +226,6 @@ Networking Support
Networking Support
CONFIG_NET=y : Enable Neworking
CONFIG_NET_ETHERNET=y : Support Ethernet data link
CONFIG_NET_NOINTS=y : Should operative at non-interrupt level
CONFIG_NET_SOCKOPTS=y : Enable socket operations
CONFIG_NET_ETH_MTU=590 : Maximum packet size (MTU) 1518 is more standard
CONFIG_NET_ETH_TCP_RECVWNDO=536 : Should be the same as CONFIG_NET_ETH_MTU
-1
View File
@@ -676,7 +676,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -678,7 +678,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -609,7 +609,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -601,7 +601,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -643,7 +643,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -597,7 +597,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -632,7 +632,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -500,7 +500,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -509,7 +509,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -501,7 +501,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -512,7 +512,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -511,7 +511,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -971,7 +971,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -193,7 +193,6 @@ Networking Support
Networking Support
CONFIG_NET=y : Enable Neworking
CONFIG_NET_ETHERNET=y : Support Ethernet data link
CONFIG_NET_NOINTS=y : Should operative at non-interrupt level
CONFIG_NET_SOCKOPTS=y : Enable socket operations
CONFIG_NET_ETH_MTU=590 : Maximum packet size (MTU) 1518 is more standard
CONFIG_NET_ETH_TCP_RECVWNDO=536 : Should be the same as CONFIG_NET_ETH_MTU
-1
View File
@@ -644,7 +644,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -623,7 +623,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -602,7 +602,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -623,7 +623,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -637,7 +637,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -637,7 +637,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -607,7 +607,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -647,7 +647,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
@@ -591,7 +591,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -663,7 +663,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
@@ -594,7 +594,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -481,7 +481,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
CONFIG_ARCH_HAVE_PHY=y
CONFIG_NET=y
# CONFIG_NET_NOINTS is not set
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -514,7 +514,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#
-1
View File
@@ -509,7 +509,6 @@ CONFIG_SYSLOG_CONSOLE=y
CONFIG_ARCH_HAVE_NET=y
# CONFIG_ARCH_HAVE_PHY is not set
CONFIG_NET=y
CONFIG_NET_NOINTS=y
# CONFIG_NET_PROMISCUOUS is not set
#

Some files were not shown because too many files have changed in this diff Show More