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:
Tomasz Bursztyka 2018-11-27 20:16:42 +01:00 committed by Jukka Rissanen
commit c14a5c896f
7 changed files with 59 additions and 130 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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,40 +600,13 @@ 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) {
if (net_pkt_write_new(pkt, context->frame_buf, frame_length)) {
irq_unlock(imask);
LOG_ERR("Failed to get fragment buf");
LOG_ERR("Unable to write frame into the pkt");
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 defined(CONFIG_NET_VLAN)
{
struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);

View file

@ -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,38 +266,25 @@ 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;
if (net_pkt_write_new(pkt, ctx->recv, count)) {
return -ENOBUFS;
}
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 defined(CONFIG_NET_VLAN)
{
struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);
@ -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);

View file

@ -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;

View file

@ -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);