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;
|
qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
|
||||||
int i;
|
int i;
|
||||||
QDF_STATUS status;
|
QDF_STATUS status;
|
||||||
|
uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
|
||||||
|
|
||||||
ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d",
|
ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d",
|
||||||
net_dev->name, type, mac_addr, sta_id);
|
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;
|
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.
|
* 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 */
|
/* Enable IPA UC Data PIPEs when first STA connected */
|
||||||
if (ipa_ctx->sap_num_connected_sta == 0 &&
|
if (ipa_ctx->sap_num_connected_sta == 0 &&
|
||||||
ipa_ctx->uc_loaded == true) {
|
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) &&
|
if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
|
||||||
ipa_ctx->sta_connected) {
|
ipa_ctx->sta_connected) {
|
||||||
qdf_mutex_release(&ipa_ctx->event_lock);
|
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,
|
wlan_ipa_uc_offload_enable_disable(ipa_ctx,
|
||||||
SIR_STA_RX_DATA_OFFLOAD,
|
SIR_STA_RX_DATA_OFFLOAD,
|
||||||
sta_session_id, true);
|
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->config) &&
|
||||||
ipa_ctx->sta_connected) {
|
ipa_ctx->sta_connected) {
|
||||||
qdf_mutex_release(&ipa_ctx->event_lock);
|
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(
|
wlan_ipa_uc_offload_enable_disable(
|
||||||
ipa_ctx,
|
ipa_ctx,
|
||||||
SIR_STA_RX_DATA_OFFLOAD,
|
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) &&
|
if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
|
||||||
ipa_ctx->sta_connected) {
|
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);
|
qdf_mutex_release(&ipa_ctx->event_lock);
|
||||||
wlan_ipa_uc_offload_enable_disable(ipa_ctx,
|
wlan_ipa_uc_offload_enable_disable(ipa_ctx,
|
||||||
SIR_STA_RX_DATA_OFFLOAD,
|
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
|
* wlan_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
|
||||||
* @ipa_ctx: IPA context
|
* @ipa_ctx: IPA context
|
||||||
*
|
*
|
||||||
* Return: QDF_STATUS
|
* 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;
|
int i;
|
||||||
uint32_t max_desc_cnt;
|
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);
|
qdf_spin_lock_bh(&ipa_ctx->q_lock);
|
||||||
for (i = 0; i < max_desc_cnt; i++) {
|
for (i = 0; i < max_desc_cnt; i++) {
|
||||||
tmp_desc = qdf_mem_malloc(sizeof(*tmp_desc));
|
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->id = i;
|
||||||
tmp_desc->ipa_tx_desc_ptr = NULL;
|
tmp_desc->ipa_tx_desc_ptr = NULL;
|
||||||
qdf_list_insert_back(&ipa_ctx->tx_desc_list,
|
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);
|
qdf_spin_unlock_bh(&ipa_ctx->q_lock);
|
||||||
|
|
||||||
return QDF_STATUS_SUCCESS;
|
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
|
#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;
|
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
|
* wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
|
||||||
* @ipa_ctx: Global IPA IPA context
|
* @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)
|
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;
|
uint32_t desc_fifo_sz;
|
||||||
|
|
||||||
/* The maximum number of descriptors that can be provided to a BAM at
|
/* 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;
|
return ret;
|
||||||
|
|
||||||
setup_sys_pipe_fail:
|
setup_sys_pipe_fail:
|
||||||
|
wlan_ipa_teardown_sys_pipe(ipa_ctx);
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
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
|
#ifndef QCA_LL_TX_FLOW_CONTROL_V2
|
||||||
QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
|
QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
|
||||||
bool mcc_mode)
|
bool mcc_mode)
|
||||||
@@ -2294,7 +2310,7 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
|
|||||||
if (status == QDF_STATUS_E_BUSY)
|
if (status == QDF_STATUS_E_BUSY)
|
||||||
status = wlan_ipa_uc_send_wdi_control_msg(false);
|
status = wlan_ipa_uc_send_wdi_control_msg(false);
|
||||||
if (status != QDF_STATUS_SUCCESS) {
|
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;
|
goto fail_create_sys_pipe;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -2442,6 +2458,12 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
|
|||||||
QDF_STATUS status;
|
QDF_STATUS status;
|
||||||
|
|
||||||
ipa_info("UC READY");
|
ipa_info("UC READY");
|
||||||
|
|
||||||
|
if (!qdf_dev) {
|
||||||
|
ipa_err("qdf device is NULL!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (true == ipa_ctx->uc_loaded) {
|
if (true == ipa_ctx->uc_loaded) {
|
||||||
ipa_info("UC already loaded");
|
ipa_info("UC already loaded");
|
||||||
return;
|
return;
|
||||||
|
@@ -126,6 +126,12 @@ QDF_STATUS ol_txrx_ipa_uc_get_resource(struct cdp_pdev *ppdev)
|
|||||||
struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource;
|
struct ol_txrx_ipa_resources *ipa_res = &pdev->ipa_resource;
|
||||||
qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||||
|
|
||||||
|
if (!osdev) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: qdf device is null!", __func__);
|
||||||
|
return QDF_STATUS_E_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
htt_ipa_uc_get_resource(pdev->htt_pdev,
|
htt_ipa_uc_get_resource(pdev->htt_pdev,
|
||||||
&ipa_res->ce_sr,
|
&ipa_res->ce_sr,
|
||||||
&ipa_res->tx_comp_ring,
|
&ipa_res->tx_comp_ring,
|
||||||
@@ -414,6 +420,12 @@ static inline void ol_txrx_ipa_wdi_tx_params(
|
|||||||
{
|
{
|
||||||
qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||||
|
|
||||||
|
if (!osdev) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: qdf device is null!", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
|
QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
|
||||||
QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
|
QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
|
||||||
qdf_mem_get_dma_addr(osdev,
|
qdf_mem_get_dma_addr(osdev,
|
||||||
@@ -496,8 +508,12 @@ QDF_STATUS ol_txrx_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb,
|
|||||||
uint32_t tx_comp_db_dmaaddr = 0, rx_rdy_db_dmaaddr = 0;
|
uint32_t tx_comp_db_dmaaddr = 0, rx_rdy_db_dmaaddr = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
qdf_mem_zero(&tx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
|
if (!osdev) {
|
||||||
qdf_mem_zero(&rx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
|
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: qdf device is null!", __func__);
|
||||||
|
return QDF_STATUS_E_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
qdf_mem_zero(&pipe_in, sizeof(pipe_in));
|
qdf_mem_zero(&pipe_in, sizeof(pipe_in));
|
||||||
qdf_mem_zero(&pipe_out, sizeof(pipe_out));
|
qdf_mem_zero(&pipe_out, sizeof(pipe_out));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user