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:
Ryan Hsu
2018-05-14 12:13:15 -07:00
committed by nshrivas
parent 0342407471
commit b5783cfcb2
2 changed files with 101 additions and 63 deletions

View File

@@ -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;