qcacld-3.0: clean up to avoid NULL pointer dereference IPA
Fix a few things in one shot. - clean up some code to avoid potential NULL pointer dereference. - add a helper function - wlan_ipa_free_tx_desc_list() to avoid duplication. - rearrage wlan_ipa_teardown_sys_pipe() to allow others' reference Change-Id: I9d6391a7f20ae427bf59f07958bd13f349e61d83 CRs-Fixed: 2233867
This commit is contained in:
@@ -1360,6 +1360,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
|
||||
qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
|
||||
int i;
|
||||
QDF_STATUS status;
|
||||
uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
|
||||
|
||||
ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d",
|
||||
net_dev->name, type, mac_addr, sta_id);
|
||||
@@ -1373,6 +1374,14 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (ipa_ctx->sta_connected) {
|
||||
iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
|
||||
if (iface_ctx)
|
||||
sta_session_id = iface_ctx->session_id;
|
||||
else
|
||||
ipa_err("sta iface_ctx is NULL");
|
||||
}
|
||||
|
||||
/*
|
||||
* During IPA UC resource loading/unloading new events can be issued.
|
||||
*/
|
||||
@@ -1644,14 +1653,10 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
|
||||
/* Enable IPA UC Data PIPEs when first STA connected */
|
||||
if (ipa_ctx->sap_num_connected_sta == 0 &&
|
||||
ipa_ctx->uc_loaded == true) {
|
||||
struct wlan_ipa_iface_context *iface_ctx;
|
||||
uint8_t sta_session_id;
|
||||
|
||||
if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
|
||||
ipa_ctx->sta_connected) {
|
||||
qdf_mutex_release(&ipa_ctx->event_lock);
|
||||
iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
|
||||
sta_session_id = iface_ctx->session_id;
|
||||
wlan_ipa_uc_offload_enable_disable(ipa_ctx,
|
||||
SIR_STA_RX_DATA_OFFLOAD,
|
||||
sta_session_id, true);
|
||||
@@ -1667,9 +1672,6 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
|
||||
ipa_ctx->config) &&
|
||||
ipa_ctx->sta_connected) {
|
||||
qdf_mutex_release(&ipa_ctx->event_lock);
|
||||
iface_ctx = wlan_ipa_get_iface(ipa_ctx,
|
||||
QDF_STA_MODE);
|
||||
sta_session_id = iface_ctx->session_id;
|
||||
wlan_ipa_uc_offload_enable_disable(
|
||||
ipa_ctx,
|
||||
SIR_STA_RX_DATA_OFFLOAD,
|
||||
@@ -1760,13 +1762,6 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
|
||||
|
||||
if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
|
||||
ipa_ctx->sta_connected) {
|
||||
struct wlan_ipa_iface_context *iface_ctx;
|
||||
uint8_t sta_session_id;
|
||||
|
||||
iface_ctx = wlan_ipa_get_iface(ipa_ctx,
|
||||
QDF_STA_MODE);
|
||||
sta_session_id = iface_ctx->session_id;
|
||||
|
||||
qdf_mutex_release(&ipa_ctx->event_lock);
|
||||
wlan_ipa_uc_offload_enable_disable(ipa_ctx,
|
||||
SIR_STA_RX_DATA_OFFLOAD,
|
||||
@@ -1925,13 +1920,39 @@ wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
|
||||
* @ipa_ctx: IPA context
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
|
||||
{
|
||||
struct wlan_ipa_tx_desc *tmp_desc;
|
||||
qdf_ipa_rx_data_t *ipa_tx_desc;
|
||||
qdf_list_node_t *node;
|
||||
|
||||
while (qdf_list_remove_front(&ipa_ctx->tx_desc_list, &node) ==
|
||||
QDF_STATUS_SUCCESS) {
|
||||
tmp_desc = qdf_container_of(node, struct wlan_ipa_tx_desc,
|
||||
node);
|
||||
|
||||
ipa_tx_desc = tmp_desc->ipa_tx_desc_ptr;
|
||||
if (ipa_tx_desc)
|
||||
qdf_ipa_free_skb(ipa_tx_desc);
|
||||
|
||||
qdf_mem_free(tmp_desc);
|
||||
tmp_desc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
|
||||
* @ipa_ctx: IPA context
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static int wlan_ipa_alloc_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
|
||||
static QDF_STATUS wlan_ipa_alloc_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
|
||||
{
|
||||
int i;
|
||||
uint32_t max_desc_cnt;
|
||||
@@ -1944,6 +1965,12 @@ static int wlan_ipa_alloc_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
|
||||
qdf_spin_lock_bh(&ipa_ctx->q_lock);
|
||||
for (i = 0; i < max_desc_cnt; i++) {
|
||||
tmp_desc = qdf_mem_malloc(sizeof(*tmp_desc));
|
||||
|
||||
if (!tmp_desc) {
|
||||
qdf_spin_unlock_bh(&ipa_ctx->q_lock);
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
tmp_desc->id = i;
|
||||
tmp_desc->ipa_tx_desc_ptr = NULL;
|
||||
qdf_list_insert_back(&ipa_ctx->tx_desc_list,
|
||||
@@ -1957,6 +1984,11 @@ static int wlan_ipa_alloc_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
|
||||
qdf_spin_unlock_bh(&ipa_ctx->q_lock);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
alloc_fail:
|
||||
wlan_ipa_free_tx_desc_list(ipa_ctx);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
||||
}
|
||||
|
||||
#ifndef QCA_LL_TX_FLOW_CONTROL_V2
|
||||
@@ -2068,6 +2100,33 @@ static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
|
||||
* @ipa_ctx: Global IPA IPA context
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (!ipa_ctx)
|
||||
return;
|
||||
|
||||
for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
|
||||
if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
|
||||
ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
|
||||
ipa_ctx->sys_pipe[i].conn_hdl);
|
||||
if (ret)
|
||||
ipa_err("Failed:%d", ret);
|
||||
|
||||
ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
wlan_ipa_free_tx_desc_list(ipa_ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
|
||||
* @ipa_ctx: Global IPA IPA context
|
||||
@@ -2076,7 +2135,7 @@ static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
|
||||
*/
|
||||
static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
|
||||
{
|
||||
int i = WLAN_IPA_MAX_IFACE, ret = 0;
|
||||
int ret = 0;
|
||||
uint32_t desc_fifo_sz;
|
||||
|
||||
/* The maximum number of descriptors that can be provided to a BAM at
|
||||
@@ -2113,54 +2172,11 @@ static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
|
||||
return ret;
|
||||
|
||||
setup_sys_pipe_fail:
|
||||
|
||||
for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
|
||||
if (ipa_ctx->sys_pipe[i].conn_hdl_valid)
|
||||
qdf_ipa_teardown_sys_pipe(
|
||||
ipa_ctx->sys_pipe[i].conn_hdl);
|
||||
qdf_mem_zero(&ipa_ctx->sys_pipe[i],
|
||||
sizeof(struct wlan_ipa_sys_pipe));
|
||||
}
|
||||
wlan_ipa_teardown_sys_pipe(ipa_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
|
||||
* @ipa_ctx: Global IPA IPA context
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
|
||||
{
|
||||
int ret = 0, i;
|
||||
struct wlan_ipa_tx_desc *tmp_desc;
|
||||
qdf_ipa_rx_data_t *ipa_tx_desc;
|
||||
qdf_list_node_t *node;
|
||||
|
||||
for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
|
||||
if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
|
||||
ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
|
||||
ipa_ctx->sys_pipe[i].conn_hdl);
|
||||
if (ret)
|
||||
ipa_err("Failed:%d", ret);
|
||||
|
||||
ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (qdf_list_remove_front(&ipa_ctx->tx_desc_list, &node) ==
|
||||
QDF_STATUS_SUCCESS) {
|
||||
tmp_desc = qdf_container_of(node, struct wlan_ipa_tx_desc,
|
||||
node);
|
||||
ipa_tx_desc = tmp_desc->ipa_tx_desc_ptr;
|
||||
if (ipa_tx_desc)
|
||||
qdf_ipa_free_skb(ipa_tx_desc);
|
||||
|
||||
qdf_mem_free(tmp_desc);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QCA_LL_TX_FLOW_CONTROL_V2
|
||||
QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
|
||||
bool mcc_mode)
|
||||
@@ -2294,7 +2310,7 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
|
||||
if (status == QDF_STATUS_E_BUSY)
|
||||
status = wlan_ipa_uc_send_wdi_control_msg(false);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
ipa_err("IPA WDI init failed: ret=%d", ret);
|
||||
ipa_err("IPA WDI init failed: ret=%d", status);
|
||||
goto fail_create_sys_pipe;
|
||||
}
|
||||
} else {
|
||||
@@ -2442,6 +2458,12 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
|
||||
QDF_STATUS status;
|
||||
|
||||
ipa_info("UC READY");
|
||||
|
||||
if (!qdf_dev) {
|
||||
ipa_err("qdf device is NULL!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (true == ipa_ctx->uc_loaded) {
|
||||
ipa_info("UC already loaded");
|
||||
return;
|
||||
|
Reference in New Issue
Block a user