Skip to content

Commit

Permalink
nrf_wifi: Fix TX de-init crash
Browse files Browse the repository at this point in the history
If interface is de-initialized during active traffic, then the HAL RX
lock still doesn't protect the full de-initialization path, there is a
race after TX de-init, lock is released and before the FMAC context is
de-initialized the NULL checks elsewhere pass and can lead to crashes.

Add an atomic API that does both de-initialization and removal by taking
the HAL RX lock for both operations, this way FMAC context is freed and
NULL checks should avoid any crashes.

Fixes SHEL-2463.

Signed-off-by: Chaitanya Tata <[email protected]>
  • Loading branch information
krish2718 committed Apr 1, 2024
1 parent 1b6570a commit 9b5bcdc
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 1 deletion.
19 changes: 19 additions & 0 deletions nrf_wifi/fw_if/umac_if/inc/default/fmac_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,7 @@ enum nrf_wifi_status nrf_wifi_fmac_get_conn_info(void *fmac_dev_ctx,
* driver. It does the following:
* - De-initializes the HAL layer.
* - Frees the context for the UMAC IF layer.
* Note: Should be called with appropriate locks held.
*
* @return None
*/
Expand All @@ -901,10 +902,28 @@ void nrf_wifi_fmac_deinit(struct nrf_wifi_fmac_priv *fpriv);
* This is a wrapper function which frees the memory for
* an RPU instance at the UMAC layer.
*
* Note: Should be called with appropriate locks held.
*
* @return None.
*/
void nrf_wifi_fmac_dev_rem(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx);

/**
* @brief De-initializes and removes a RPU instance.
* @param fmac_dev_ctx Pointer to the context of the RPU instance to be removed.
*
* This function de-initializes and removes the firmware of an RPU instance.
* It does the following:
* - RPU UMAC deinitialization command is executed
* - RX and TX is deallocated for firmware via UMAC command
* - Frees the context for the RPU instance
* It is a combination of nrf_wifi_fmac_dev_deinit and nrf_wifi_fmac_dev_rem,
* handy in atomic deinit and remove of RPU instance.
*
* @return None.
*/
void nrf_wifi_fmac_dev_deinit_rem(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx);


/**
* @brief Initializes a RPU instance.
Expand Down
20 changes: 20 additions & 0 deletions nrf_wifi/fw_if/umac_if/inc/radio_test/fmac_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ enum nrf_wifi_status nrf_wifi_fmac_rf_test_compute_xo(struct nrf_wifi_fmac_dev_c
* - De-initializes the HAL layer.
* - Frees the context for the UMAC IF layer.
*
* Note: Should be called with appropriate locks held.
*
* @return None
*/
void nrf_wifi_fmac_deinit_rt(struct nrf_wifi_fmac_priv *fpriv);
Expand All @@ -223,10 +225,28 @@ void nrf_wifi_fmac_deinit_rt(struct nrf_wifi_fmac_priv *fpriv);
*
* This function handles the removal of an RPU instance at the UMAC IF layer.
*
* Note: Should be called with appropriate locks held.
*
* @return None.
*/
void nrf_wifi_fmac_dev_rem_rt(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx);

/**
* @brief De-initializes and removes a RPU instance.
* @param fmac_dev_ctx Pointer to the context of the RPU instance to be removed.
*
* This function de-initializes and removes the firmware of an RPU instance.
* It does the following:
* - RPU UMAC deinitialization command is executed
* - RX and TX is deallocated for firmware via UMAC command
* - Frees the context for the RPU instance
* It is a combination of nrf_wifi_fmac_dev_deinit_rt and nrf_wifi_fmac_dev_rem_rt,
* handy in atomic deinit and remove of RPU instance.
*
* @return None.
*/
void nrf_wifi_fmac_dev_deinit_rem_rt(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx);


/**
* @brief Initializes a RPU instance.
Expand Down
8 changes: 7 additions & 1 deletion nrf_wifi/fw_if/umac_if/src/default/fmac_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,16 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_init(struct nrf_wifi_fmac_dev_ctx *fmac_d

void nrf_wifi_fmac_dev_deinit(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
{
nrf_wifi_hal_lock_rx(fmac_dev_ctx->hal_dev_ctx);
nrf_wifi_fmac_fw_deinit(fmac_dev_ctx);
nrf_wifi_osal_mem_free(fmac_dev_ctx->fpriv->opriv,
fmac_dev_ctx->tx_pwr_ceil_params);
}

void nrf_wifi_fmac_dev_deinit_rem(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
{
nrf_wifi_hal_lock_rx(fmac_dev_ctx->hal_dev_ctx);
nrf_wifi_fmac_dev_deinit(fmac_dev_ctx);
nrf_wifi_fmac_dev_rem(fmac_dev_ctx);
nrf_wifi_hal_unlock_rx(fmac_dev_ctx->hal_dev_ctx);
}

Expand Down
8 changes: 8 additions & 0 deletions nrf_wifi/fw_if/umac_if/src/radio_test/fmac_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ void nrf_wifi_fmac_dev_deinit_rt(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
nrf_wifi_fmac_fw_deinit_rt(fmac_dev_ctx);
}

void nrf_wifi_fmac_dev_deinit_rem_rt(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
{
nrf_wifi_hal_lock_rx(fmac_dev_ctx->hal_dev_ctx);
nrf_wifi_fmac_dev_deinit_rt(fmac_dev_ctx);
nrf_wifi_fmac_dev_rem_rt(fmac_dev_ctx);
nrf_wifi_hal_unlock_rx(fmac_dev_ctx->hal_dev_ctx);
}

struct nrf_wifi_fmac_priv *nrf_wifi_fmac_init_rt(void)
{
struct nrf_wifi_osal_priv *opriv = NULL;
Expand Down

0 comments on commit 9b5bcdc

Please sign in to comment.