drivers/ethernet: Use new net_pkt API for sending and receiving
Use the new API where relevant. Only sam_gmac is left aside for now. This simplifies a lot the code as the caller should only care about allocating net_pkt and its buffer once, and thus will not need to mess with "frags" etc... Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
999b3740b8
commit
c14a5c896f
7 changed files with 59 additions and 130 deletions
|
@ -86,14 +86,14 @@ static void eth_rx(struct device *dev)
|
|||
frm_len -= sizeof(u32_t);
|
||||
}
|
||||
|
||||
pkt = net_pkt_get_reserve_rx(K_NO_WAIT);
|
||||
pkt = net_pkt_rx_alloc_with_buffer(context->iface, frm_len,
|
||||
AF_UNSPEC, 0, K_NO_WAIT);
|
||||
if (!pkt) {
|
||||
LOG_ERR("Failed to obtain RX buffer");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!net_pkt_append_all(pkt, frm_len, (u8_t *)context->rx_buf,
|
||||
K_NO_WAIT)) {
|
||||
if (net_pkt_write_new(pkt, (void *)context->rx_buf, frm_len)) {
|
||||
LOG_ERR("Failed to append RX buffer to context buffer");
|
||||
net_pkt_unref(pkt);
|
||||
goto error;
|
||||
|
|
|
@ -50,19 +50,6 @@ static enum ethernet_hw_caps e1000_caps(struct device *dev)
|
|||
ETHERNET_LINK_1000BASE_T;
|
||||
}
|
||||
|
||||
static size_t e1000_linearize(struct net_pkt *pkt, void *buf, size_t bufsize)
|
||||
{
|
||||
size_t len = 0;
|
||||
struct net_buf *nb;
|
||||
|
||||
for (nb = pkt->frags; nb; nb = nb->frags) {
|
||||
memcpy((u8_t *) buf + len, nb->data, nb->len);
|
||||
len += nb->len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int e1000_tx(struct e1000_dev *dev, void *data, size_t data_len)
|
||||
{
|
||||
dev->tx.addr = POINTER_TO_INT(data);
|
||||
|
@ -83,7 +70,11 @@ static int e1000_tx(struct e1000_dev *dev, void *data, size_t data_len)
|
|||
static int e1000_send(struct device *device, struct net_pkt *pkt)
|
||||
{
|
||||
struct e1000_dev *dev = device->driver_data;
|
||||
size_t len = e1000_linearize(pkt, dev->txb, sizeof(dev->txb));
|
||||
size_t len = net_pkt_get_len(pkt);
|
||||
|
||||
if (net_pkt_read_new(pkt, dev->txb, len)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return e1000_tx(dev, dev->txb, len);
|
||||
}
|
||||
|
@ -99,19 +90,20 @@ static struct net_pkt *e1000_rx(struct e1000_dev *dev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
pkt = net_pkt_get_reserve_rx(K_NO_WAIT);
|
||||
pkt = net_pkt_rx_alloc_with_buffer(dev->iface, dev->rx.len - 4,
|
||||
AF_UNSPEC, 0, K_NO_WAIT);
|
||||
if (!pkt) {
|
||||
LOG_ERR("Out of RX buffers");
|
||||
LOG_ERR("Out of buffers");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!net_pkt_append_all(pkt, dev->rx.len - 4,
|
||||
INT_TO_POINTER((u32_t) dev->rx.addr),
|
||||
K_NO_WAIT)) {
|
||||
if (net_pkt_write_new(pkt, INT_TO_POINTER((u32_t) dev->rx.addr),
|
||||
dev->rx.len - 4)) {
|
||||
LOG_ERR("Out of memory for received frame");
|
||||
net_pkt_unref(pkt);
|
||||
pkt = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
return pkt;
|
||||
}
|
||||
|
|
|
@ -500,7 +500,6 @@ static int eth_enc28j60_rx(struct device *dev)
|
|||
|
||||
do {
|
||||
struct net_buf *pkt_buf = NULL;
|
||||
struct net_buf *last_buf = NULL;
|
||||
u16_t frm_len = 0U;
|
||||
u8_t info[RSV_SIZE];
|
||||
struct net_pkt *pkt;
|
||||
|
@ -538,36 +537,22 @@ static int eth_enc28j60_rx(struct device *dev)
|
|||
lengthfr = frm_len;
|
||||
|
||||
/* Get the frame from the buffer */
|
||||
pkt = net_pkt_get_reserve_rx(config->timeout);
|
||||
pkt = net_pkt_rx_alloc_with_buffer(context->iface, frm_len,
|
||||
AF_UNSPEC, 0,
|
||||
config->timeout);
|
||||
if (!pkt) {
|
||||
LOG_ERR("Could not allocate rx buffer");
|
||||
eth_stats_update_errors_rx(context->iface);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pkt_buf = pkt->buffer;
|
||||
|
||||
do {
|
||||
size_t frag_len;
|
||||
u8_t *data_ptr;
|
||||
size_t spi_frame_len;
|
||||
|
||||
/* Reserve a data frag to receive the frame */
|
||||
pkt_buf = net_pkt_get_frag(pkt, config->timeout);
|
||||
if (!pkt_buf) {
|
||||
LOG_ERR("Could not allocate data buffer");
|
||||
eth_stats_update_errors_rx(context->iface);
|
||||
net_pkt_unref(pkt);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!last_buf) {
|
||||
net_pkt_frag_insert(pkt, pkt_buf);
|
||||
} else {
|
||||
net_buf_frag_insert(last_buf, pkt_buf);
|
||||
}
|
||||
|
||||
last_buf = pkt_buf;
|
||||
|
||||
data_ptr = pkt_buf->data;
|
||||
|
||||
/* Review the space available for the new frag */
|
||||
|
@ -585,6 +570,7 @@ static int eth_enc28j60_rx(struct device *dev)
|
|||
|
||||
/* One fragment has been written via SPI */
|
||||
frm_len -= spi_frame_len;
|
||||
pkt_buf = pkt_buf->frags;
|
||||
} while (frm_len > 0);
|
||||
|
||||
/* Let's pop the useless CRC */
|
||||
|
@ -599,7 +585,9 @@ static int eth_enc28j60_rx(struct device *dev)
|
|||
|
||||
/* Feed buffer frame to IP stack */
|
||||
LOG_DBG("Received packet of length %u", lengthfr);
|
||||
net_recv_data(context->iface, pkt);
|
||||
if (net_recv_data(context->iface, pkt) < 0) {
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
done:
|
||||
/* Free buffer memory and decrement rx counter */
|
||||
eth_enc28j60_set_bank(dev, ENC28J60_REG_ERXRDPTL);
|
||||
|
|
|
@ -490,16 +490,13 @@ static bool eth_get_ptp_data(struct net_if *iface, struct net_pkt *pkt,
|
|||
static int eth_tx(struct device *dev, struct net_pkt *pkt)
|
||||
{
|
||||
struct eth_context *context = dev->driver_data;
|
||||
const struct net_buf *frag;
|
||||
u8_t *dst;
|
||||
u16_t total_len = net_pkt_get_len(pkt);
|
||||
status_t status;
|
||||
unsigned int imask;
|
||||
#if defined(CONFIG_PTP_CLOCK_MCUX)
|
||||
bool timestamped_frame;
|
||||
#endif
|
||||
|
||||
u16_t total_len = net_pkt_get_len(pkt);
|
||||
|
||||
k_sem_take(&context->tx_buf_sem, K_FOREVER);
|
||||
|
||||
/* As context->frame_buf is shared resource used by both eth_tx
|
||||
|
@ -507,13 +504,9 @@ static int eth_tx(struct device *dev, struct net_pkt *pkt)
|
|||
*/
|
||||
imask = irq_lock();
|
||||
|
||||
/* Copy the fragments */
|
||||
dst = context->frame_buf;
|
||||
frag = pkt->frags;
|
||||
while (frag) {
|
||||
memcpy(dst, frag->data, frag->len);
|
||||
dst += frag->len;
|
||||
frag = frag->frags;
|
||||
if (net_pkt_read_new(pkt, context->frame_buf, total_len)) {
|
||||
irq_unlock(imask);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* FIXME: Dirty workaround.
|
||||
|
@ -559,13 +552,11 @@ static int eth_tx(struct device *dev, struct net_pkt *pkt)
|
|||
static void eth_rx(struct device *iface)
|
||||
{
|
||||
struct eth_context *context = iface->driver_data;
|
||||
struct net_buf *prev_buf;
|
||||
struct net_pkt *pkt;
|
||||
const u8_t *src;
|
||||
u16_t vlan_tag = NET_VLAN_TAG_UNSPEC;
|
||||
u32_t frame_length = 0U;
|
||||
struct net_pkt *pkt;
|
||||
status_t status;
|
||||
unsigned int imask;
|
||||
u16_t vlan_tag = NET_VLAN_TAG_UNSPEC;
|
||||
|
||||
#if defined(CONFIG_PTP_CLOCK_MCUX)
|
||||
enet_ptp_time_data_t ptpTimeData;
|
||||
|
@ -588,7 +579,9 @@ static void eth_rx(struct device *iface)
|
|||
goto flush;
|
||||
}
|
||||
|
||||
pkt = net_pkt_get_reserve_rx(K_NO_WAIT);
|
||||
/* Using root iface. It will be updated in net_recv_data() */
|
||||
pkt = net_pkt_rx_alloc_with_buffer(context->iface, frame_length,
|
||||
AF_UNSPEC, 0, K_NO_WAIT);
|
||||
if (!pkt) {
|
||||
goto flush;
|
||||
}
|
||||
|
@ -607,39 +600,12 @@ static void eth_rx(struct device *iface)
|
|||
goto error;
|
||||
}
|
||||
|
||||
src = context->frame_buf;
|
||||
prev_buf = NULL;
|
||||
do {
|
||||
struct net_buf *pkt_buf;
|
||||
size_t frag_len;
|
||||
|
||||
pkt_buf = net_pkt_get_frag(pkt, K_NO_WAIT);
|
||||
if (!pkt_buf) {
|
||||
irq_unlock(imask);
|
||||
LOG_ERR("Failed to get fragment buf");
|
||||
net_pkt_unref(pkt);
|
||||
assert(status == kStatus_Success);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!prev_buf) {
|
||||
net_pkt_frag_insert(pkt, pkt_buf);
|
||||
} else {
|
||||
net_buf_frag_insert(prev_buf, pkt_buf);
|
||||
}
|
||||
|
||||
prev_buf = pkt_buf;
|
||||
|
||||
frag_len = net_buf_tailroom(pkt_buf);
|
||||
if (frag_len > frame_length) {
|
||||
frag_len = frame_length;
|
||||
}
|
||||
|
||||
memcpy(pkt_buf->data, src, frag_len);
|
||||
net_buf_add(pkt_buf, frag_len);
|
||||
src += frag_len;
|
||||
frame_length -= frag_len;
|
||||
} while (frame_length > 0);
|
||||
if (net_pkt_write_new(pkt, context->frame_buf, frame_length)) {
|
||||
irq_unlock(imask);
|
||||
LOG_ERR("Unable to write frame into the pkt");
|
||||
net_pkt_unref(pkt);
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_VLAN)
|
||||
{
|
||||
|
|
|
@ -210,15 +210,12 @@ static void update_gptp(struct net_if *iface, struct net_pkt *pkt,
|
|||
static int eth_send(struct device *dev, struct net_pkt *pkt)
|
||||
{
|
||||
struct eth_context *ctx = dev->driver_data;
|
||||
struct net_buf *frag;
|
||||
int count = 0;
|
||||
int count = net_pkt_get_len(pkt);
|
||||
int ret;
|
||||
|
||||
frag = pkt->frags;
|
||||
while (frag) {
|
||||
memcpy(ctx->send + count, frag->data, frag->len);
|
||||
count += frag->len;
|
||||
frag = frag->frags;
|
||||
ret = net_pkt_read_new(pkt, ctx->send, count);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
update_gptp(net_pkt_iface(pkt), pkt, true);
|
||||
|
@ -269,37 +266,24 @@ static inline struct net_if *get_iface(struct eth_context *ctx,
|
|||
static int read_data(struct eth_context *ctx, int fd)
|
||||
{
|
||||
u16_t vlan_tag = NET_VLAN_TAG_UNSPEC;
|
||||
int count = 0;
|
||||
struct net_if *iface;
|
||||
struct net_pkt *pkt;
|
||||
struct net_buf *frag;
|
||||
u32_t pkt_len;
|
||||
int ret;
|
||||
int count;
|
||||
|
||||
ret = eth_read_data(fd, ctx->recv, sizeof(ctx->recv));
|
||||
if (ret <= 0) {
|
||||
count = eth_read_data(fd, ctx->recv, sizeof(ctx->recv));
|
||||
if (count <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkt = net_pkt_get_reserve_rx(NET_BUF_TIMEOUT);
|
||||
pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, count,
|
||||
AF_UNSPEC, 0, NET_BUF_TIMEOUT);
|
||||
if (!pkt) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
do {
|
||||
frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
|
||||
if (!frag) {
|
||||
net_pkt_unref(pkt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
net_pkt_frag_add(pkt, frag);
|
||||
|
||||
net_buf_add_mem(frag, ctx->recv + count,
|
||||
min(net_buf_tailroom(frag), ret));
|
||||
ret -= frag->len;
|
||||
count += frag->len;
|
||||
} while (ret > 0);
|
||||
if (net_pkt_write_new(pkt, ctx->recv, count)) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_VLAN)
|
||||
{
|
||||
|
@ -325,9 +309,8 @@ static int read_data(struct eth_context *ctx, int fd)
|
|||
#endif
|
||||
|
||||
iface = get_iface(ctx, vlan_tag);
|
||||
pkt_len = net_pkt_get_len(pkt);
|
||||
|
||||
LOG_DBG("Recv pkt %p len %d", pkt, pkt_len);
|
||||
LOG_DBG("Recv pkt %p len %d", pkt, count);
|
||||
|
||||
update_gptp(iface, pkt, false);
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ static int eth_tx(struct device *dev, struct net_pkt *pkt)
|
|||
ETH_HandleTypeDef *heth;
|
||||
u8_t *dma_buffer;
|
||||
int res;
|
||||
struct net_buf *frag;
|
||||
u16_t total_len;
|
||||
__IO ETH_DMADescTypeDef *dma_tx_desc;
|
||||
|
||||
|
@ -88,11 +87,9 @@ static int eth_tx(struct device *dev, struct net_pkt *pkt)
|
|||
|
||||
dma_buffer = (u8_t *)(dma_tx_desc->Buffer1Addr);
|
||||
|
||||
frag = pkt->frags;
|
||||
while (frag) {
|
||||
memcpy(dma_buffer, frag->data, frag->len);
|
||||
dma_buffer += frag->len;
|
||||
frag = frag->frags;
|
||||
if (net_pkt_read_new(pkt, dma_buffer, total_len)) {
|
||||
res = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (HAL_ETH_TransmitFrame(heth, total_len) != HAL_OK) {
|
||||
|
@ -146,13 +143,14 @@ static struct net_pkt *eth_rx(struct device *dev)
|
|||
total_len = heth->RxFrameInfos.length;
|
||||
dma_buffer = (u8_t *)heth->RxFrameInfos.buffer;
|
||||
|
||||
pkt = net_pkt_get_reserve_rx(K_NO_WAIT);
|
||||
pkt = net_pkt_rx_alloc_with_buffer(dev_data->iface, total_len,
|
||||
AF_UNSPEC, 0, K_NO_WAIT);
|
||||
if (!pkt) {
|
||||
LOG_ERR("Failed to obtain RX buffer");
|
||||
goto release_desc;
|
||||
}
|
||||
|
||||
if (!net_pkt_append_all(pkt, total_len, dma_buffer, K_NO_WAIT)) {
|
||||
if (net_pkt_write_new(pkt, dma_buffer, total_len)) {
|
||||
LOG_ERR("Failed to append RX buffer to context buffer");
|
||||
net_pkt_unref(pkt);
|
||||
pkt = NULL;
|
||||
|
|
|
@ -559,6 +559,8 @@ static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)
|
|||
goto error;
|
||||
}
|
||||
|
||||
net_pkt_cursor_init(pkt);
|
||||
|
||||
ret = api->send(net_if_get_device(iface), pkt);
|
||||
if (ret != 0) {
|
||||
eth_stats_update_errors_tx(iface);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue