wifi: nrf_wifi: net_if: allocate memory before mutex

Allocate the memory in `nrf_wifi_if_send` *before* taking the nrf70
global mutex. This prevents the function from deadlocking the
application if attempting to send under memory-pressure, since many of
the memory release paths also happen under the global mutex.

Signed-off-by: Jordan Yates <jordan@embeint.com>
This commit is contained in:
Jordan Yates 2025-04-18 14:27:15 +10:00 committed by Benjamin Cabé
commit 86385590c2

View file

@ -358,6 +358,7 @@ int nrf_wifi_if_send(const struct device *dev,
struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL; struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
struct rpu_host_stats *host_stats = NULL; struct rpu_host_stats *host_stats = NULL;
void *nbuf = NULL; void *nbuf = NULL;
bool locked = false;
if (!dev || !pkt) { if (!dev || !pkt) {
LOG_ERR("%s: vif_ctx_zep is NULL", __func__); LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
@ -371,24 +372,27 @@ int nrf_wifi_if_send(const struct device *dev,
goto out; goto out;
} }
/* Allocate packet before locking mutex (blocks until allocation success) */
nbuf = net_pkt_to_nbuf(pkt);
ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER); ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
if (ret != 0) { if (ret != 0) {
LOG_ERR("%s: Failed to lock vif_lock", __func__); LOG_ERR("%s: Failed to lock vif_lock", __func__);
goto out; goto drop;
} }
locked = true;
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) { if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
goto unlock; goto drop;
} }
sys_dev_ctx = wifi_dev_priv(rpu_ctx_zep->rpu_ctx); sys_dev_ctx = wifi_dev_priv(rpu_ctx_zep->rpu_ctx);
host_stats = &sys_dev_ctx->host_stats; host_stats = &sys_dev_ctx->host_stats;
nbuf = net_pkt_to_nbuf(pkt);
if (!nbuf) { if (nbuf == NULL) {
LOG_DBG("Failed to allocate net_pkt"); LOG_ERR("%s: allocation failed", __func__);
host_stats->total_tx_drop_pkts++; goto drop;
goto out;
} }
#ifdef CONFIG_NRF70_RAW_DATA_TX #ifdef CONFIG_NRF70_RAW_DATA_TX
@ -415,10 +419,16 @@ int nrf_wifi_if_send(const struct device *dev,
#endif /* CONFIG_NRF70_RAW_DATA_TX */ #endif /* CONFIG_NRF70_RAW_DATA_TX */
goto unlock; goto unlock;
drop: drop:
host_stats->total_tx_drop_pkts++; if (host_stats != NULL) {
nrf_wifi_osal_nbuf_free(nbuf); host_stats->total_tx_drop_pkts++;
}
if (nbuf != NULL) {
nrf_wifi_osal_nbuf_free(nbuf);
}
unlock: unlock:
k_mutex_unlock(&vif_ctx_zep->vif_lock); if (locked) {
k_mutex_unlock(&vif_ctx_zep->vif_lock);
}
#else #else
ARG_UNUSED(dev); ARG_UNUSED(dev);
ARG_UNUSED(pkt); ARG_UNUSED(pkt);