Kinetis enet: buffer management update
This patch manages the packet buffer used by the upper layers by making sure it is always set to a valid transmit buffer that can be used by the MAC-NET core. The only exception to this is when the upper layer re-uses a receive buffer to send a response. In this case, the updated receive buffer is swapped with an empty transmit buffer. If there is no empty transmit buffer available, the packet will be dropped. Signed-off-by: Andrew Webster <awebster@arcx.com> Kinetis enet: add support for DBSWP Signed-off-by: Andrew Webster <awebster@arcx.com>
This commit is contained in:
parent
64a0f54767
commit
d3238e6f95
@ -196,7 +196,7 @@ static struct kinetis_driver_s g_enet[CONFIG_ENET_NETHIFS];
|
||||
****************************************************************************/
|
||||
/* Utility functions */
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
#ifndef KINETIS_BUFFERS_SWAP
|
||||
# define kinesis_swap32(value) (value)
|
||||
# define kinesis_swap16(value) (value)
|
||||
#else
|
||||
@ -346,6 +346,7 @@ static int kinetis_transmit(FAR struct kinetis_driver_s *priv)
|
||||
{
|
||||
struct enet_desc_s *txdesc;
|
||||
uint32_t regval;
|
||||
uint8_t *buf;
|
||||
|
||||
/* Since this can be called from kinetis_receive, it is possible that
|
||||
* the transmit queue is full, so check for that now. If this is the
|
||||
@ -388,6 +389,22 @@ static int kinetis_transmit(FAR struct kinetis_driver_s *priv)
|
||||
#endif
|
||||
txdesc->status1 |= (TXDESC_R | TXDESC_L | TXDESC_TC);
|
||||
|
||||
buf = (uint8_t*)kinesis_swap32((uint32_t)priv->dev.d_buf);
|
||||
if (priv->rxdesc[priv->rxtail].data == buf)
|
||||
{
|
||||
struct enet_desc_s *rxdesc = &priv->rxdesc[priv->rxtail];
|
||||
|
||||
/* Data was written into the RX buffer, so swap the TX and RX buffers */
|
||||
|
||||
DEBUGASSERT((rxdesc->status1 & RXDESC_E) == 0);
|
||||
rxdesc->data = txdesc->data;
|
||||
txdesc->data = buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(txdesc->data == buf);
|
||||
}
|
||||
|
||||
/* Start the TX transfer (if it was not already waiting for buffers) */
|
||||
|
||||
putreg32(ENET_TDAR, KINETIS_ENET_TDAR);
|
||||
@ -463,6 +480,7 @@ static int kinetis_txpoll(struct net_driver_s *dev)
|
||||
/* Send the packet */
|
||||
|
||||
kinetis_transmit(priv);
|
||||
priv->dev.d_buf = (uint8_t*)kinesis_swap32((uint32_t)priv->txdesc[priv->txhead].data);
|
||||
|
||||
/* Check if there is room in the device to hold another packet. If not,
|
||||
* return a non-zero value to terminate the poll.
|
||||
@ -515,22 +533,6 @@ static void kinetis_receive(FAR struct kinetis_driver_s *priv)
|
||||
priv->dev.d_len = kinesis_swap16(priv->rxdesc[priv->rxtail].length);
|
||||
priv->dev.d_buf = (uint8_t *)kinesis_swap32((uint32_t)priv->rxdesc[priv->rxtail].data);
|
||||
|
||||
/* Doing this here could cause corruption! */
|
||||
|
||||
priv->rxdesc[priv->rxtail].status1 |= RXDESC_E;
|
||||
|
||||
/* Update the index to the next descriptor */
|
||||
|
||||
priv->rxtail++;
|
||||
if (priv->rxtail >= CONFIG_ENET_NTXBUFFERS)
|
||||
{
|
||||
priv->rxtail = 0;
|
||||
}
|
||||
|
||||
/* Indicate that there have been empty receive buffers produced */
|
||||
|
||||
putreg32(ENET_RDAR, KINETIS_ENET_RDAR);
|
||||
|
||||
#ifdef CONFIG_NET_PKT
|
||||
/* When packet sockets are enabled, feed the frame into the packet tap */
|
||||
|
||||
@ -639,6 +641,27 @@ static void kinetis_receive(FAR struct kinetis_driver_s *priv)
|
||||
{
|
||||
NETDEV_RXDROPPED(&priv->dev);
|
||||
}
|
||||
|
||||
/* Point the packet buffer back to the next TX buffer, which will be used during
|
||||
* the next write. If the write queue is full, then this will point at an active
|
||||
* buffer, which must not be written to. This is OK because devif_poll won't be
|
||||
* called unless the queue is not full.
|
||||
*/
|
||||
|
||||
priv->dev.d_buf = (uint8_t*)kinesis_swap32((uint32_t)priv->txdesc[priv->txhead].data);
|
||||
priv->rxdesc[priv->rxtail].status1 |= RXDESC_E;
|
||||
|
||||
/* Update the index to the next descriptor */
|
||||
|
||||
priv->rxtail++;
|
||||
if (priv->rxtail >= CONFIG_ENET_NRXBUFFERS)
|
||||
{
|
||||
priv->rxtail = 0;
|
||||
}
|
||||
|
||||
/* Indicate that there have been empty receive buffers produced */
|
||||
|
||||
putreg32(ENET_RDAR, KINETIS_ENET_RDAR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -942,7 +965,11 @@ static int kinetis_ifup(struct net_driver_s *dev)
|
||||
/* And enable the MAC itself */
|
||||
|
||||
regval = getreg32(KINETIS_ENET_ECR);
|
||||
regval |= ENET_ECR_ETHEREN;
|
||||
regval |= ENET_ECR_ETHEREN
|
||||
#ifdef KINETIS_USE_DBSWAP
|
||||
| ENET_ECR_DBSWP
|
||||
#endif
|
||||
;
|
||||
putreg32(regval, KINETIS_ENET_ECR);
|
||||
|
||||
/* Indicate that there have been empty receive buffers produced */
|
||||
@ -1453,6 +1480,10 @@ static void kinetis_initbuffers(struct kinetis_driver_s *priv)
|
||||
priv->txtail = 0;
|
||||
priv->txhead = 0;
|
||||
priv->rxtail = 0;
|
||||
|
||||
/* Initialize the packet buffer, which is used when sending */
|
||||
|
||||
priv->dev.d_buf = (uint8_t*)kinesis_swap32((uint32_t)priv->txdesc[priv->txhead].data);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -195,7 +195,10 @@
|
||||
/* Bit 5: Reserved */
|
||||
#define ENET_ECR_DBGEN (1 << 6) /* Bit 6: Debug enable */
|
||||
#define ENET_ECR_STOPEN (1 << 7) /* Bit 7: STOPEN Signal Control */
|
||||
/* Bits 8-31: Reserved */
|
||||
#ifdef KINETIS_ENET_HAS_DBSWAP
|
||||
#define ENET_ECR_DBSWP (1 << 8) /* Bit 8: Swap bytes */
|
||||
#endif
|
||||
/* Bits 9-31: Reserved */
|
||||
/* MII Management Frame Register */
|
||||
|
||||
#define ENET_MMFR_DATA_SHIFT (0) /* Bits 0-15: Management frame data */
|
||||
@ -454,7 +457,17 @@
|
||||
* the underlying hardware writes the data in big-endian byte order.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
#ifdef KINETIS_ENET_HAS_DBSWAP
|
||||
# ifndef CONFIG_ENDIAN_BIG
|
||||
# define KINETIS_USE_DBSWAP
|
||||
# endif
|
||||
#else
|
||||
# ifndef CONFIG_ENDIAN_BIG
|
||||
# define KINETIS_BUFFERS_SWAP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef KINETIS_BUFFERS_SWAP
|
||||
# define TXDESC_ABC (1 << 9) /* Legacy */
|
||||
# define TXDESC_TC (1 << 10) /* Common */
|
||||
# define TXDESC_L (1 << 11) /* Common */
|
||||
@ -474,7 +487,7 @@
|
||||
|
||||
/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
#ifndef KINETIS_BUFFERS_SWAP
|
||||
# define TXDESC_TSE (1 << 8)
|
||||
# define TXDESC_OE (1 << 9)
|
||||
# define TXDESC_LCE (1 << 10)
|
||||
@ -508,7 +521,7 @@
|
||||
|
||||
/* Legacy (and Common) RX Buffer Descriptor Bit Definitions */
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
#ifndef KINETIS_BUFFERS_SWAP
|
||||
# define RXDESC_TR (1 << 0)
|
||||
# define RXDESC_OV (1 << 1)
|
||||
# define RXDESC_CR (1 << 2)
|
||||
@ -540,7 +553,7 @@
|
||||
|
||||
/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
#ifndef KINETIS_BUFFERS_SWAP
|
||||
# define RXDESC_FRAG (1 << 0)
|
||||
# define RXDESC_IPV6 (1 << 1)
|
||||
# define RXDESC_VLAN (1 << 2)
|
||||
@ -575,6 +588,26 @@
|
||||
/* Legacy Buffer Descriptor */
|
||||
|
||||
#ifdef CONFIG_ENET_ENHANCEDBD
|
||||
#ifdef KINETIS_USE_DBSWAP
|
||||
/* When DBSWP is used to swap the bytes in hardware, it is done 32-bits
|
||||
* at a time. Therefore, all 16 bit elements need to be swapped to
|
||||
* compensate.
|
||||
*/
|
||||
|
||||
struct enet_desc_s
|
||||
{
|
||||
uint16_t length; /* Data length */
|
||||
uint16_t status1; /* Control and status */
|
||||
uint8_t *data; /* Buffer address */
|
||||
uint32_t status2; /* Extended status */
|
||||
uint16_t checksum; /* Payload checksum */
|
||||
uint16_t lenproto; /* Header length + Protocol type */
|
||||
uint32_t bdu; /* BDU */
|
||||
uint32_t timestamp; /* Time stamp */
|
||||
uint32_t reserved1; /* unused */
|
||||
uint32_t reserved2; /* unused */
|
||||
};
|
||||
#else
|
||||
struct enet_desc_s
|
||||
{
|
||||
uint16_t status1; /* Control and status */
|
||||
@ -587,7 +620,16 @@ struct enet_desc_s
|
||||
uint32_t timestamp; /* Time stamp */
|
||||
uint32_t reserved1; /* unused */
|
||||
uint32_t reserved2; /* unused */
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
#ifdef KINETIS_USE_DBSWAP
|
||||
struct enet_desc_s
|
||||
{
|
||||
uint16_t length; /* Data length */
|
||||
uint16_t status1; /* Control and status */
|
||||
uint8_t *data; /* Buffer address */
|
||||
};
|
||||
#else
|
||||
struct enet_desc_s
|
||||
{
|
||||
@ -596,6 +638,7 @@ struct enet_desc_s
|
||||
uint8_t *data; /* Buffer address */
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/********************************************************************************************
|
||||
* Public Data
|
||||
|
Loading…
Reference in New Issue
Block a user