drivers: nrf_wifi: Implement TX zero-copy feature
This uses the network packet as is without the need for a copy all the way till the packet is handed over to RPU. Signed-off-by: Chaitanya Tata <Chaitanya.Tata@nordicsemi.no>
This commit is contained in:
parent
5cbae7f2b6
commit
5119f9c379
4 changed files with 87 additions and 0 deletions
|
@ -828,4 +828,25 @@ config NRF_WIFI_COEX_DISABLE_PRIORITY_WINDOW_FOR_SCAN
|
|||
help
|
||||
Enable this configuration to disable priority window for scan
|
||||
in the case of coexistence with Short Range radio.
|
||||
|
||||
if NETWORKING
|
||||
config NRF_WIFI_ZERO_COPY_TX
|
||||
bool "Zero copy Transmit path [EXPERIMENTAL]"
|
||||
select NET_L2_ETHERNET_RESERVE_HEADER
|
||||
select EXPERIMENTAL
|
||||
# 54L has lower RAM
|
||||
default y if SOC_SERIES_NRF54LX
|
||||
help
|
||||
Enable this configuration to use zero copy Transmit path.
|
||||
The driver will use the network buffer directly for transmission
|
||||
without copying the data to the driver's buffer. This reduces the
|
||||
driver heap memory usage without much impact on the performance.
|
||||
|
||||
The application should configure the network buffers to ensure that
|
||||
the whole packet fits in a single buffer, else the driver will fallback
|
||||
to the normal copy path, but the memory requirements would still match
|
||||
to the zero copy path and may be sub-optimal for the normal copy path.
|
||||
|
||||
endif # NETWORKING
|
||||
|
||||
endif # WIFI_NRF70
|
||||
|
|
|
@ -1002,6 +1002,11 @@ int nrf_wifi_if_get_config_zep(const struct device *dev,
|
|||
ETHERNET_CHECKSUM_SUPPORT_TCP |
|
||||
ETHERNET_CHECKSUM_SUPPORT_UDP;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_NRF_WIFI_ZERO_COPY_TX
|
||||
if (type == ETHERNET_CONFIG_TYPE_EXTRA_TX_PKT_HEADROOM) {
|
||||
config->extra_tx_pkt_headroom = NRF_WIFI_EXTRA_TX_HEADROOM;
|
||||
}
|
||||
#endif
|
||||
ret = 0;
|
||||
unlock:
|
||||
|
|
|
@ -268,6 +268,9 @@ struct nwb {
|
|||
void (*cleanup_cb)();
|
||||
unsigned char priority;
|
||||
bool chksum_done;
|
||||
#ifdef CONFIG_NRF_WIFI_ZERO_COPY_TX
|
||||
struct net_pkt *pkt;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void *zep_shim_nbuf_alloc(unsigned int size)
|
||||
|
@ -301,6 +304,12 @@ static void zep_shim_nbuf_free(void *nbuf)
|
|||
if (!nbuf) {
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_NRF_WIFI_ZERO_COPY_TX
|
||||
if (((struct nwb *)nbuf)->pkt) {
|
||||
net_pkt_unref(((struct nwb *)nbuf)->pkt);
|
||||
((struct nwb *)nbuf)->pkt = NULL;
|
||||
}
|
||||
#endif /* CONFIG_NRF_WIFI_ZERO_COPY_TX */
|
||||
|
||||
zep_shim_data_mem_free(((struct nwb *)nbuf)->priv);
|
||||
zep_shim_data_mem_free(nbuf);
|
||||
|
@ -387,12 +396,62 @@ static void zep_shim_nbuf_set_chksum_done(void *nbuf, unsigned char chksum_done)
|
|||
#include <zephyr/net/ethernet.h>
|
||||
#include <zephyr/net/net_core.h>
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_ZERO_COPY_TX
|
||||
void *net_pkt_to_nbuf_zc(struct net_pkt *pkt)
|
||||
{
|
||||
struct nwb *nbuff;
|
||||
|
||||
if (!pkt || !pkt->buffer) {
|
||||
LOG_DBG("Invalid packet, dropping");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if packet has more than one fragment */
|
||||
if (pkt->buffer->frags) {
|
||||
LOG_ERR("Zero-copy only supports single buffer packets");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nbuff = zep_shim_nbuf_alloc(NRF_WIFI_EXTRA_TX_HEADROOM); /* Just for headers */
|
||||
if (!nbuff) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zep_shim_nbuf_headroom_res(nbuff, NRF_WIFI_EXTRA_TX_HEADROOM);
|
||||
|
||||
/* Zero-copy: point to the single data buffer */
|
||||
/* TODO: Use API for proper cursor access? */
|
||||
nbuff->data = pkt->buffer->data;
|
||||
nbuff->len = pkt->buffer->len;
|
||||
|
||||
nbuff->priority = net_pkt_priority(pkt);
|
||||
nbuff->chksum_done = (bool)net_pkt_is_chksum_done(pkt);
|
||||
|
||||
nbuff->pkt = pkt;
|
||||
/* Ref the packet so that it is not freed */
|
||||
net_pkt_ref(pkt);
|
||||
|
||||
return nbuff;
|
||||
}
|
||||
#endif /* CONFIG_NRF_WIFI_ZERO_COPY_TX */
|
||||
|
||||
void *net_pkt_to_nbuf(struct net_pkt *pkt)
|
||||
{
|
||||
struct nwb *nbuff;
|
||||
unsigned char *data;
|
||||
unsigned int len;
|
||||
|
||||
if (!pkt) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_ZERO_COPY_TX
|
||||
/* For zero-copy, check if packet has single buffer */
|
||||
if (pkt->buffer && !pkt->buffer->frags) {
|
||||
return net_pkt_to_nbuf_zc(pkt);
|
||||
}
|
||||
#endif /* CONFIG_NRF_WIFI_ZERO_COPY_TX */
|
||||
|
||||
len = net_pkt_get_len(pkt);
|
||||
|
||||
nbuff = zep_shim_nbuf_alloc(len + 100);
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/net/net_pkt.h>
|
||||
|
||||
#define NRF_WIFI_EXTRA_TX_HEADROOM 100
|
||||
|
||||
/**
|
||||
* struct zep_shim_bus_qspi_priv - Structure to hold context information for the Linux OS
|
||||
* shim.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue