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
|
help
|
||||||
Enable this configuration to disable priority window for scan
|
Enable this configuration to disable priority window for scan
|
||||||
in the case of coexistence with Short Range radio.
|
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
|
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_TCP |
|
||||||
ETHERNET_CHECKSUM_SUPPORT_UDP;
|
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
|
#endif
|
||||||
ret = 0;
|
ret = 0;
|
||||||
unlock:
|
unlock:
|
||||||
|
|
|
@ -268,6 +268,9 @@ struct nwb {
|
||||||
void (*cleanup_cb)();
|
void (*cleanup_cb)();
|
||||||
unsigned char priority;
|
unsigned char priority;
|
||||||
bool chksum_done;
|
bool chksum_done;
|
||||||
|
#ifdef CONFIG_NRF_WIFI_ZERO_COPY_TX
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *zep_shim_nbuf_alloc(unsigned int size)
|
static void *zep_shim_nbuf_alloc(unsigned int size)
|
||||||
|
@ -301,6 +304,12 @@ static void zep_shim_nbuf_free(void *nbuf)
|
||||||
if (!nbuf) {
|
if (!nbuf) {
|
||||||
return;
|
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(((struct nwb *)nbuf)->priv);
|
||||||
zep_shim_data_mem_free(nbuf);
|
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/ethernet.h>
|
||||||
#include <zephyr/net/net_core.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)
|
void *net_pkt_to_nbuf(struct net_pkt *pkt)
|
||||||
{
|
{
|
||||||
struct nwb *nbuff;
|
struct nwb *nbuff;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
unsigned int len;
|
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);
|
len = net_pkt_get_len(pkt);
|
||||||
|
|
||||||
nbuff = zep_shim_nbuf_alloc(len + 100);
|
nbuff = zep_shim_nbuf_alloc(len + 100);
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <zephyr/drivers/gpio.h>
|
#include <zephyr/drivers/gpio.h>
|
||||||
#include <zephyr/net/net_pkt.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
|
* struct zep_shim_bus_qspi_priv - Structure to hold context information for the Linux OS
|
||||||
* shim.
|
* shim.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue