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:
parent
d879e8482f
commit
86385590c2
1 changed files with 20 additions and 10 deletions
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue