arch/arm/src/lpc54xx: Fix a few more Ethernet issues related to buffer management and address filtering.

This commit is contained in:
Gregory Nutt 2018-01-01 08:54:31 -06:00
parent fd10eaf1fb
commit 3c65be8c1a
3 changed files with 97 additions and 64 deletions

View File

@ -47,7 +47,7 @@
* 2. Multi-queuing not fully; supported. The second queue is intended to
* support QVLAN, AVB type packets which have an 18-byte IEEE 802.1q
* Ethernet header. That implies that we would need to support two
* devices intstances: One with a standard Ethernet header and one with
* devices instances: One with a standard Ethernet header and one with
* an IEEE 802.1q Ethernet header.
*
* 3. Multicast address filtering. Unlike other hardware, this Ethernet
@ -292,7 +292,7 @@ struct lpc54_ethdriver_s
uint8_t eth_rxdiscard : 1; /* 1:Discarding Rx data */
WDOG_ID eth_txpoll; /* TX poll timer */
WDOG_ID eth_txtimeout; /* TX timeout timer */
struct work_s eth_irqwork; /* For deferring interupt work to the work queue */
struct work_s eth_irqwork; /* For deferring interrupt work to the work queue */
struct work_s eth_pollwork; /* For deferring poll work to the work queue */
struct work_s eth_timeoutwork; /* For deferring timeout work to the work queue */
struct sq_queue_s eth_freebuf; /* Free packet buffers */
@ -340,7 +340,7 @@ static struct enet_txdesc_s g_ch1_txdesc[CONFIG_LPC54_ETH_NTXDESC1];
static uint32_t g_prealloc_buffers[LPC54_NBUFFERS * LPC54_BUFFER_WORDS];
/* Packet buffers assigned to Rx and Tx descriptors. The packet buffer
* addresses are lost in the DMA due to write-back from the DMA harware.
* addresses are lost in the DMA due to write-back from the DMA hardware.
* So we have to remember the buffer assignments explicitly.
*
* REVISIT: According to the User manual, buffer1 and buffer2 addresses
@ -571,7 +571,7 @@ static void lpc54_putreg(uint32_t val, uintptr_t addr)
* OK on success; a negated errno on failure
*
* Assumptions:
* The network must be locked.
* The network is locked.
*
****************************************************************************/
@ -745,8 +745,7 @@ static unsigned int lpc54_eth_getring(struct lpc54_ethdriver_s *priv)
* OK on success; a negated errno on failure
*
* Assumptions:
* May or may not be called from an interrupt handler. In either case,
* the network is locked.
* The network is locked.
*
****************************************************************************/
@ -993,6 +992,21 @@ static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv)
{
NETDEV_RXDROPPED(&priv->eth_dev);
}
/* On entry, d_buf refers to the receive buffer as set by logic in
* lpc54_eth_receive(). If lpc54_eth_transmit() was called to respond
* with an outgoing packet, then that packet was removed for transmission
* and d_buf was nullified. Otherwise, d_buf still holds the stale
* receive buffer and we will need to dispose of it here.
*/
if (priv->eth_dev.d_buf != NULL)
{
lpc54_pktbuf_free(priv, (uint32_t *)priv->eth_dev.d_buf);
}
priv->eth_dev.d_buf = NULL;
priv->eth_dev.d_len = 0;
}
/****************************************************************************
@ -1097,32 +1111,32 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
lpc54_eth_rxdisptch(priv);
/* Allocate a new Rx buffer and update the Rx buffer
* descriptor.
*/
/* Allocate a new Rx buffer and update the Rx buffer
* descriptor.
*/
rxdesc->buffer1 = (uint32_t)lpc54_pktbuf_alloc(priv);
DEBUGASSERT(rxdesc->buffer1 != 0);
(rxring->rr_buffers)[supply] = (uint32_t *)rxdesc->buffer1;
rxdesc->buffer1 = (uint32_t)lpc54_pktbuf_alloc(priv);
DEBUGASSERT(rxdesc->buffer1 != 0);
(rxring->rr_buffers)[supply] = (uint32_t *)rxdesc->buffer1;
#if LPC54_BUFFER_SIZE > LPC54_BUFFER_MAX
rxdesc->buffer2 = rxdesc->buffer1 + LPC54_BUFFER_MAX;
rxdesc->buffer2 = rxdesc->buffer1 + LPC54_BUFFER_MAX;
#else
/* The second buffer is not used */
/* The second buffer is not used */
rxdesc->buffer2 = 0;
rxdesc->buffer2 = 0;
#endif
rxdesc->reserved = 0;
rxdesc->reserved = 0;
/* Buffer1 (and maybe 2) valid, interrupt on completion,
* owned by DMA.
*/
/* Buffer1 (and maybe 2) valid, interrupt on completion,
* owned by DMA.
*/
regval = ETH_RXDES3_BUF1V | ETH_RXDES3_IOC | ETH_RXDES3_OWN;
regval = ETH_RXDES3_BUF1V | ETH_RXDES3_IOC | ETH_RXDES3_OWN;
#if LPC54_BUFFER_SIZE > LPC54_BUFFER_MAX
regval |= ETH_RXDES3_BUF2V;
regval |= ETH_RXDES3_BUF2V;
#endif
rxdesc->ctrl = regval;
rxdesc->ctrl = regval;
}
}
}
@ -1134,13 +1148,13 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
* Rx descriptors. We cannot support that in this design. We
* would like to:
*
* 1. Accumate the data in yet another Rx buffer,
* 1. Accumulate the data in yet another Rx buffer,
* 2. Accumulate the size in the 'pktlen' local variable, then
* 3. Dispatch that extra Rx buffer when the last frame is
* encountered.
*
* The assumption here is that this will never happen if our MTU
* properaly advertised.
* properly advertised.
*/
NETDEV_RXDROPPED(&priv->eth_dev);
@ -1148,7 +1162,7 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
}
}
/* Restart the recevier if it was suspended. */
/* Restart the receiver if it was suspended. */
if (suspend)
{
@ -1334,7 +1348,7 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
/* Handle the Tx completion event. Reclaim the completed Tx
* descriptors, free packet buffers, and check if we can start a new
* transmissin.
* transmission.
*/
lpc54_eth_txdone(priv, chan);
@ -1363,7 +1377,7 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
* OK on success
*
* Assumptions:
* The network is locked.
* Runs on a worker thread.
*
****************************************************************************/
@ -1409,7 +1423,8 @@ static void lpc54_eth_interrupt_work(void *arg)
* context - Interrupt register state save info (architecture-specific)
*
* Returned Value:
* OK on success
* Runs in the context of a the Ethernet interrupt handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -1448,7 +1463,8 @@ static int lpc54_eth_interrupt(int irq, void *context, void *arg)
* context - Interrupt register state save info (architecture-specific)
*
* Returned Value:
* OK on success
* Runs in the context of a the Ethernet PMT interrupt handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -1470,7 +1486,8 @@ static int lpc54_pmt_interrupt(int irq, void *context, void *arg)
* context - Interrupt register state save info (architecture-specific)
*
* Returned Value:
* OK on success
* Runs in the context of a the Ethernet MAC handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -1494,7 +1511,7 @@ static int lpc54_mac_interrupt(int irq, void *context, void *arg)
* OK on success
*
* Assumptions:
* The network is locked.
* Runs on a worker thread.
*
****************************************************************************/
@ -1542,7 +1559,8 @@ static void lpc54_eth_txtimeout_work(void *arg)
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
* Runs in the context of a the timer interrupt handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -1710,7 +1728,7 @@ static void lpc54_eth_dopoll(struct lpc54_ethdriver_s *priv)
* OK on success
*
* Assumptions:
* The network is locked.
* Run on a work queue thread.
*
****************************************************************************/
@ -1751,7 +1769,8 @@ static void lpc54_eth_poll_work(void *arg)
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
* Runs in the context of a the timer interrupt handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -1778,6 +1797,7 @@ static void lpc54_eth_poll_expiry(int argc, wdparm_t arg, ...)
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
@ -1916,16 +1936,16 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
#endif
/* Initialize the Ethernet MAC ********************************************/
/* Instantiate the MAC address that appliation logic should have set in the
/* Instantiate the MAC address that application logic should have set in the
* device structure:
*/
mptr = (uint8_t *)priv->eth_dev.d_mac.ether.ether_addr_octet;
regval = ((uint32_t)mptr[3] << 24) | ((uint32_t)mptr[2] << 16) |
((uint32_t)mptr[1] << 8) | ((uint32_t)mptr[0]);
regval = ((uint32_t)mptr[2] << 24) | ((uint32_t)mptr[3] << 16) |
((uint32_t)mptr[4] << 8) | ((uint32_t)mptr[5]);
lpc54_putreg(regval, LPC54_ETH_MAC_ADDR_LOW);
regval = ((uint32_t)mptr[5] << 8) | ((uint32_t)mptr[4]);
regval = ((uint32_t)mptr[0] << 8) | ((uint32_t)mptr[1]);
lpc54_putreg(regval, LPC54_ETH_MAC_ADDR_HIGH);
/* Set the receive address filter */
@ -2055,6 +2075,7 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
@ -2130,7 +2151,7 @@ static int lpc54_eth_ifdown(struct net_driver_s *dev)
* None
*
* Assumptions:
* Called on the higher priority worker thread.
* Runs on a work queue thread.
*
****************************************************************************/
@ -2173,7 +2194,7 @@ static void lpc54_eth_txavail_work(void *arg)
* None
*
* Assumptions:
* Called in normal user mode
* The network is locked.
*
****************************************************************************/
@ -2267,6 +2288,7 @@ static int lpc54_eth_rmmac(struct net_driver_s *dev, const uint8_t *mac)
* OK on success; Negated errno on failure.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
@ -2742,7 +2764,7 @@ static int lpc54_phy_autonegotiate(struct lpc54_ethdriver_s *priv)
volatile int32_t timeout;
uint16_t phyval;
/* Advertise our cabilities. */
/* Advertise our capabilities. */
phyval = (MII_ADVERTISE_CSMA | MII_ADVERTISE_10BASETXHALF |
MII_ADVERTISE_10BASETXFULL | MII_ADVERTISE_100BASETXHALF |
@ -2878,6 +2900,7 @@ static int lpc54_phy_reset(struct lpc54_ethdriver_s *priv)
* OK on success; Negated errno on failure.
*
* Assumptions:
* Called early in initialization before multi-tasking is initiated.
*
****************************************************************************/
@ -2937,7 +2960,7 @@ int up_netinitialize(int intf)
#endif
priv->eth_dev.d_private = (void *)&g_ethdriver; /* Used to recover private state from dev */
/* Create a watchdog for timing polling for and timing of transmisstions */
/* Create a watchdog for timing polling for and timing of transmissions */
priv->eth_txpoll = wd_create(); /* Create periodic poll timer */
priv->eth_txtimeout = wd_create(); /* Create TX timeout timer */

View File

@ -253,7 +253,7 @@ Configurations
Configures the NuttShell (nsh) application located at examples/nsh.
This configuration was used to bring up the board support and, hence,
is focused on low level, command-line driver testing. It has no
network.
network and no graphics capability.
NOTES:

View File

@ -38,7 +38,6 @@
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_skeleton)
#include <stdint.h>
#include <stdbool.h>
@ -61,6 +60,8 @@
# include <nuttx/net/pkt.h>
#endif
#ifdef CONFIG_NET_skeleton
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -110,7 +111,7 @@ struct skel_driver_s
bool sk_bifup; /* true:ifup false:ifdown */
WDOG_ID sk_txpoll; /* TX poll timer */
WDOG_ID sk_txtimeout; /* TX timeout timer */
struct work_s sk_irqwork; /* For deferring interupt work to the work queue */
struct work_s sk_irqwork; /* For deferring interrupt work to the work queue */
struct work_s sk_pollwork; /* For deferring poll work to the work queue */
/* This holds the information visible to the NuttX network */
@ -122,17 +123,20 @@ struct skel_driver_s
* Private Data
****************************************************************************/
/* These statically allocated structur eswould mean that only a single
/* These statically allocated structures would mean that only a single
* instance of the device could be supported. In order to support multiple
* devices instances, this data would have to be allocated dynamically.
*/
/* A single packet buffer per device is used here. There might be multiple
* packet buffers in a more complex, pipelined design.
/* A single packet buffer per device is used in this example. There might
* be multiple packet buffers in a more complex, pipelined design. Many
* contemporary Ethernet interfaces, for example, use multiple, linked DMA
* descriptors in rings to implement such a pipeline. This example assumes
* much simpler hardware that simply handles one packet at a time.
*
* NOTE that if CONFIG_skeleton_NINTERFACES were greater than 1, you would
* need a minimum on one packetbuffer per instance. Much better to be
* allocated dynamically.
* need a minimum on one packet buffer per instance. Much better to be
* allocated dynamically in cases where more than one are needed.
*/
static uint8_t g_pktbuf[MAX_NET_DEV_MTU + CONFIG_NET_GUARDSIZE];
@ -208,8 +212,7 @@ static int skel_ioctl(FAR struct net_driver_s *dev, int cmd,
* OK on success; a negated errno on failure
*
* Assumptions:
* May or may not be called from an interrupt handler. In either case,
* the network is locked.
* The network is locked.
*
****************************************************************************/
@ -254,8 +257,7 @@ static int skel_transmit(FAR struct skel_driver_s *priv)
* OK on success; a negated errno on failure
*
* Assumptions:
* May or may not be called from an interrupt handler. In either case,
* the network is locked.
* The network is locked.
*
****************************************************************************/
@ -501,6 +503,9 @@ static void skel_txdone(FAR struct skel_driver_s *priv)
* Returned Value:
* OK on success
*
* Assumptions:
* Runs on a worker thread.
*
****************************************************************************/
static void skel_interrupt_work(FAR void *arg)
@ -552,6 +557,8 @@ static void skel_interrupt_work(FAR void *arg)
* OK on success
*
* Assumptions:
* Runs in the context of a the Ethernet interrupt handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -597,9 +604,6 @@ static int skel_interrupt(int irq, FAR void *context, FAR void *arg)
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static void skel_txtimeout_work(FAR void *arg)
@ -641,7 +645,8 @@ static void skel_txtimeout_work(FAR void *arg)
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
* Runs in the context of a the timer interrupt handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -674,7 +679,7 @@ static void skel_txtimeout_expiry(int argc, wdparm_t arg, ...)
* OK on success
*
* Assumptions:
* The network is locked.
* Run on a work queue thread.
*
****************************************************************************/
@ -724,7 +729,8 @@ static void skel_poll_work(FAR void *arg)
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
* Runs in the context of a the timer interrupt handler. Local
* interrupts are disabled by the interrupt logic.
*
****************************************************************************/
@ -751,6 +757,7 @@ static void skel_poll_expiry(int argc, wdparm_t arg, ...)
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
@ -805,6 +812,7 @@ static int skel_ifup(FAR struct net_driver_s *dev)
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
@ -848,7 +856,7 @@ static int skel_ifdown(FAR struct net_driver_s *dev)
* None
*
* Assumptions:
* Called on the higher priority worker thread.
* Runs on a work queue thread.
*
****************************************************************************/
@ -893,7 +901,7 @@ static void skel_txavail_work(FAR void *arg)
* None
*
* Assumptions:
* Called in normal user mode
* The network is locked.
*
****************************************************************************/
@ -1057,6 +1065,7 @@ static void skel_ipv6multicast(FAR struct skel_driver_s *priv)
* OK on success; Negated errno on failure.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
@ -1100,6 +1109,7 @@ static int skel_ioctl(FAR struct net_driver_s *dev, int cmd,
* OK on success; Negated errno on failure.
*
* Assumptions:
* Called early in initialization before multi-tasking is initiated.
*
****************************************************************************/
@ -1139,7 +1149,7 @@ int skel_initialize(int intf)
#endif
priv->sk_dev.d_private = (FAR void *)g_skel; /* Used to recover private state from dev */
/* Create a watchdog for timing polling for and timing of transmisstions */
/* Create a watchdog for timing polling for and timing of transmissions */
priv->sk_txpoll = wd_create(); /* Create periodic poll timer */
priv->sk_txtimeout = wd_create(); /* Create TX timeout timer */
@ -1160,4 +1170,4 @@ int skel_initialize(int intf)
return OK;
}
#endif /* CONFIG_NET && CONFIG_NET_skeleton */
#endif /* CONFIG_NET_skeleton */