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 */
|
/* Utility functions */
|
||||||
|
|
||||||
#ifdef CONFIG_ENDIAN_BIG
|
#ifndef KINETIS_BUFFERS_SWAP
|
||||||
# define kinesis_swap32(value) (value)
|
# define kinesis_swap32(value) (value)
|
||||||
# define kinesis_swap16(value) (value)
|
# define kinesis_swap16(value) (value)
|
||||||
#else
|
#else
|
||||||
@ -346,6 +346,7 @@ static int kinetis_transmit(FAR struct kinetis_driver_s *priv)
|
|||||||
{
|
{
|
||||||
struct enet_desc_s *txdesc;
|
struct enet_desc_s *txdesc;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
uint8_t *buf;
|
||||||
|
|
||||||
/* Since this can be called from kinetis_receive, it is possible that
|
/* 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
|
* 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
|
#endif
|
||||||
txdesc->status1 |= (TXDESC_R | TXDESC_L | TXDESC_TC);
|
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) */
|
/* Start the TX transfer (if it was not already waiting for buffers) */
|
||||||
|
|
||||||
putreg32(ENET_TDAR, KINETIS_ENET_TDAR);
|
putreg32(ENET_TDAR, KINETIS_ENET_TDAR);
|
||||||
@ -463,6 +480,7 @@ static int kinetis_txpoll(struct net_driver_s *dev)
|
|||||||
/* Send the packet */
|
/* Send the packet */
|
||||||
|
|
||||||
kinetis_transmit(priv);
|
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,
|
/* Check if there is room in the device to hold another packet. If not,
|
||||||
* return a non-zero value to terminate the poll.
|
* 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_len = kinesis_swap16(priv->rxdesc[priv->rxtail].length);
|
||||||
priv->dev.d_buf = (uint8_t *)kinesis_swap32((uint32_t)priv->rxdesc[priv->rxtail].data);
|
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
|
#ifdef CONFIG_NET_PKT
|
||||||
/* When packet sockets are enabled, feed the frame into the packet tap */
|
/* 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);
|
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 */
|
/* And enable the MAC itself */
|
||||||
|
|
||||||
regval = getreg32(KINETIS_ENET_ECR);
|
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);
|
putreg32(regval, KINETIS_ENET_ECR);
|
||||||
|
|
||||||
/* Indicate that there have been empty receive buffers produced */
|
/* 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->txtail = 0;
|
||||||
priv->txhead = 0;
|
priv->txhead = 0;
|
||||||
priv->rxtail = 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 */
|
/* Bit 5: Reserved */
|
||||||
#define ENET_ECR_DBGEN (1 << 6) /* Bit 6: Debug enable */
|
#define ENET_ECR_DBGEN (1 << 6) /* Bit 6: Debug enable */
|
||||||
#define ENET_ECR_STOPEN (1 << 7) /* Bit 7: STOPEN Signal Control */
|
#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 */
|
/* MII Management Frame Register */
|
||||||
|
|
||||||
#define ENET_MMFR_DATA_SHIFT (0) /* Bits 0-15: Management frame data */
|
#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.
|
* 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_ABC (1 << 9) /* Legacy */
|
||||||
# define TXDESC_TC (1 << 10) /* Common */
|
# define TXDESC_TC (1 << 10) /* Common */
|
||||||
# define TXDESC_L (1 << 11) /* Common */
|
# define TXDESC_L (1 << 11) /* Common */
|
||||||
@ -474,7 +487,7 @@
|
|||||||
|
|
||||||
/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
|
/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
|
||||||
|
|
||||||
#ifdef CONFIG_ENDIAN_BIG
|
#ifndef KINETIS_BUFFERS_SWAP
|
||||||
# define TXDESC_TSE (1 << 8)
|
# define TXDESC_TSE (1 << 8)
|
||||||
# define TXDESC_OE (1 << 9)
|
# define TXDESC_OE (1 << 9)
|
||||||
# define TXDESC_LCE (1 << 10)
|
# define TXDESC_LCE (1 << 10)
|
||||||
@ -508,7 +521,7 @@
|
|||||||
|
|
||||||
/* Legacy (and Common) RX Buffer Descriptor Bit Definitions */
|
/* Legacy (and Common) RX Buffer Descriptor Bit Definitions */
|
||||||
|
|
||||||
#ifdef CONFIG_ENDIAN_BIG
|
#ifndef KINETIS_BUFFERS_SWAP
|
||||||
# define RXDESC_TR (1 << 0)
|
# define RXDESC_TR (1 << 0)
|
||||||
# define RXDESC_OV (1 << 1)
|
# define RXDESC_OV (1 << 1)
|
||||||
# define RXDESC_CR (1 << 2)
|
# define RXDESC_CR (1 << 2)
|
||||||
@ -540,7 +553,7 @@
|
|||||||
|
|
||||||
/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
|
/* Enhanced (only) TX Buffer Descriptor Bit Definitions */
|
||||||
|
|
||||||
#ifdef CONFIG_ENDIAN_BIG
|
#ifndef KINETIS_BUFFERS_SWAP
|
||||||
# define RXDESC_FRAG (1 << 0)
|
# define RXDESC_FRAG (1 << 0)
|
||||||
# define RXDESC_IPV6 (1 << 1)
|
# define RXDESC_IPV6 (1 << 1)
|
||||||
# define RXDESC_VLAN (1 << 2)
|
# define RXDESC_VLAN (1 << 2)
|
||||||
@ -575,6 +588,26 @@
|
|||||||
/* Legacy Buffer Descriptor */
|
/* Legacy Buffer Descriptor */
|
||||||
|
|
||||||
#ifdef CONFIG_ENET_ENHANCEDBD
|
#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
|
struct enet_desc_s
|
||||||
{
|
{
|
||||||
uint16_t status1; /* Control and status */
|
uint16_t status1; /* Control and status */
|
||||||
@ -587,7 +620,16 @@ struct enet_desc_s
|
|||||||
uint32_t timestamp; /* Time stamp */
|
uint32_t timestamp; /* Time stamp */
|
||||||
uint32_t reserved1; /* unused */
|
uint32_t reserved1; /* unused */
|
||||||
uint32_t reserved2; /* 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
|
#else
|
||||||
struct enet_desc_s
|
struct enet_desc_s
|
||||||
{
|
{
|
||||||
@ -596,6 +638,7 @@ struct enet_desc_s
|
|||||||
uint8_t *data; /* Buffer address */
|
uint8_t *data; /* Buffer address */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
|
Loading…
Reference in New Issue
Block a user