From 80dfdd5a6f57b8b3fb2f447ab092429ef3262cab Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Thu, 30 Aug 2018 13:06:27 -0700 Subject: [PATCH 1/7] qcacmn: Fix NULL pointer dereference in pno & regulatory In target_if_pno_start, target_if_pno_stop, tgt_reg_chan_list_update_handler, tgt_reg_11d_new_cc_handler & tgt_reg_ch_avoid_event_handler wmi_handle is derived & dereferenced with out a NULL check. Add a NULL check for wmi_handle before it is dereferenced. Change-Id: I4b4afa5bb74a2c97d921af2672eb285f7c34062a CRs-Fixed: 2305512 --- target_if/regulatory/src/target_if_reg.c | 33 +++++++++++++++++++----- target_if/scan/src/target_if_scan.c | 24 +++++++++++++---- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/target_if/regulatory/src/target_if_reg.c b/target_if/regulatory/src/target_if_reg.c index 04bfbd7382d9..9a1371bb29cc 100644 --- a/target_if/regulatory/src/target_if_reg.c +++ b/target_if/regulatory/src/target_if_reg.c @@ -99,6 +99,7 @@ static int tgt_reg_chan_list_update_handler(ol_scn_t handle, struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; struct cur_regulatory_info *reg_info; QDF_STATUS status; + struct wmi_unified *wmi_handle; TARGET_IF_ENTER(); @@ -125,7 +126,13 @@ static int tgt_reg_chan_list_update_handler(ol_scn_t handle, return -ENOMEM; } - if (wmi_extract_reg_chan_list_update_event(GET_WMI_HDL_FROM_PSOC(psoc), + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return -EINVAL; + } + + if (wmi_extract_reg_chan_list_update_event(wmi_handle, event_buf, reg_info, len) != QDF_STATUS_SUCCESS) { @@ -163,6 +170,7 @@ static int tgt_reg_11d_new_cc_handler(ol_scn_t handle, struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; struct reg_11d_new_country reg_11d_new_cc; QDF_STATUS status; + struct wmi_unified *wmi_handle; TARGET_IF_ENTER(); @@ -179,9 +187,14 @@ static int tgt_reg_11d_new_cc_handler(ol_scn_t handle, return -EINVAL; } - if (wmi_extract_reg_11d_new_cc_event(GET_WMI_HDL_FROM_PSOC(psoc), - event_buf, ®_11d_new_cc, len) != - QDF_STATUS_SUCCESS) { + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return -EINVAL; + } + if (wmi_extract_reg_11d_new_cc_event(wmi_handle, event_buf, + ®_11d_new_cc, len) + != QDF_STATUS_SUCCESS) { target_if_err("Extraction of new country event failed"); return -EFAULT; @@ -205,6 +218,7 @@ static int tgt_reg_ch_avoid_event_handler(ol_scn_t handle, struct wlan_lmac_if_reg_rx_ops *reg_rx_ops; struct ch_avoid_ind_type ch_avoid_event; QDF_STATUS status; + struct wmi_unified *wmi_handle; TARGET_IF_ENTER(); @@ -221,9 +235,14 @@ static int tgt_reg_ch_avoid_event_handler(ol_scn_t handle, return -EINVAL; } - if (wmi_extract_reg_ch_avoid_event(GET_WMI_HDL_FROM_PSOC(psoc), - event_buf, &ch_avoid_event, len) != - QDF_STATUS_SUCCESS) { + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return -EINVAL; + } + if (wmi_extract_reg_ch_avoid_event(wmi_handle, event_buf, + &ch_avoid_event, len) + != QDF_STATUS_SUCCESS) { target_if_err("Extraction of CH avoid event failed"); return -EFAULT; diff --git a/target_if/scan/src/target_if_scan.c b/target_if/scan/src/target_if_scan.c index 2b7f6eb12274..7c1407174f0f 100644 --- a/target_if/scan/src/target_if_scan.c +++ b/target_if/scan/src/target_if_scan.c @@ -244,13 +244,19 @@ target_if_pno_start(struct wlan_objmgr_psoc *psoc, struct pno_scan_req_params *req) { QDF_STATUS status; + struct wmi_unified *wmi_handle; - status = wmi_unified_pno_start_cmd(GET_WMI_HDL_FROM_PSOC(psoc), req); + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } + + status = wmi_unified_pno_start_cmd(wmi_handle, req); if (status == QDF_STATUS_SUCCESS) { if (req->mawc_params.enable) - status = wmi_unified_nlo_mawc_cmd( - GET_WMI_HDL_FROM_PSOC(psoc), - &req->mawc_params); + status = wmi_unified_nlo_mawc_cmd(wmi_handle, + &req->mawc_params); } return status; @@ -260,7 +266,15 @@ static QDF_STATUS target_if_pno_stop(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) { - return wmi_unified_pno_stop_cmd(GET_WMI_HDL_FROM_PSOC(psoc), vdev_id); + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } + + return wmi_unified_pno_stop_cmd(wmi_handle, vdev_id); } #else From a9307520d35056a1b47f60678977f487275284bd Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Thu, 30 Aug 2018 13:26:21 -0700 Subject: [PATCH 2/7] qcacmn: Fix NULL pointer dereference in tdls In target_if_tdls_update_fw_state, target_if_tdls_set_offchan_mode, & target_if_tdls_set_uapsd wmi_handle is derived & dereferenced with out a NULL check. Add a NULL check for wmi_handle before it is dereferenced. Change-Id: If741f69773a712cebcd1be889ca09d01eee97fae CRs-Fixed: 2305520 --- target_if/tdls/src/target_if_tdls.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/target_if/tdls/src/target_if_tdls.c b/target_if/tdls/src/target_if_tdls.c index bbb3c32cf096..f6b248e93d53 100644 --- a/target_if/tdls/src/target_if_tdls.c +++ b/target_if/tdls/src/target_if_tdls.c @@ -82,6 +82,13 @@ target_if_tdls_update_fw_state(struct wlan_objmgr_psoc *psoc, { QDF_STATUS status; uint8_t tdls_state; + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } if (TDLS_SUPPORT_EXP_TRIG_ONLY == param->tdls_state) tdls_state = WMI_TDLS_ENABLE_PASSIVE; @@ -91,7 +98,7 @@ target_if_tdls_update_fw_state(struct wlan_objmgr_psoc *psoc, else tdls_state = WMI_TDLS_DISABLE; - status = wmi_unified_update_fw_tdls_state_cmd(GET_WMI_HDL_FROM_PSOC(psoc), + status = wmi_unified_update_fw_tdls_state_cmd(wmi_handle, param, tdls_state); target_if_debug("vdev_id %d", param->vdev_id); @@ -110,8 +117,14 @@ target_if_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc, struct tdls_channel_switch_params *params) { QDF_STATUS status; + struct wmi_unified *wmi_handle; - status = wmi_unified_set_tdls_offchan_mode_cmd(GET_WMI_HDL_FROM_PSOC(psoc), + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } + status = wmi_unified_set_tdls_offchan_mode_cmd(wmi_handle, params); return status; @@ -122,8 +135,13 @@ target_if_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc, struct sta_uapsd_trig_params *params) { QDF_STATUS ret; - wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + struct wmi_unified *wmi_handle; + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } if (!wmi_service_enabled(wmi_handle, wmi_sta_uapsd_basic_auto_trig) || !wmi_service_enabled(wmi_handle, @@ -132,7 +150,7 @@ target_if_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc, params->vdevid); return QDF_STATUS_SUCCESS; } - ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(GET_WMI_HDL_FROM_PSOC(psoc), + ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_handle, params); if (QDF_IS_STATUS_ERROR(ret)) From 9b8cfb0ebfbfc661cf2aab778fac27167efb5037 Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Thu, 30 Aug 2018 11:54:19 -0700 Subject: [PATCH 3/7] qcacmn: Fix NULL pointer dereference in ftm In target_if_ftm_process_utf_event is derived & dereferenced with out a NULL check. Add a NULL check for wmi_handle before it is dereferenced. Change-Id: Id3c1ae4df9aa7b0cfc12fbf9288bec2ae72c6de6 CRs-Fixed: 2305506 --- target_if/ftm/src/target_if_ftm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/target_if/ftm/src/target_if_ftm.c b/target_if/ftm/src/target_if_ftm.c index c27f074357f7..0e4e76563233 100644 --- a/target_if/ftm/src/target_if_ftm.c +++ b/target_if/ftm/src/target_if_ftm.c @@ -44,6 +44,7 @@ target_if_ftm_process_utf_event(ol_scn_t sc, uint8_t *event_buf, uint32_t len) struct wlan_lmac_if_ftm_rx_ops *ftm_rx_ops; QDF_STATUS status = QDF_STATUS_E_FAILURE; uint32_t pdev_id; + struct wmi_unified *wmi_handle; psoc = target_if_get_psoc_from_scn_hdl(sc); if (!psoc) { @@ -58,8 +59,16 @@ target_if_ftm_process_utf_event(ol_scn_t sc, uint8_t *event_buf, uint32_t len) } event.datalen = len; - if (wmi_extract_pdev_utf_event(GET_WMI_HDL_FROM_PSOC(psoc), - event_buf, &event) != QDF_STATUS_SUCCESS) { + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + ftm_err("Invalid WMI handle"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); + return QDF_STATUS_E_INVAL; + } + + if (wmi_extract_pdev_utf_event(wmi_handle, event_buf, &event) + != QDF_STATUS_SUCCESS) { ftm_err("Extracting utf event failed"); wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); return QDF_STATUS_E_INVAL; From b7b7b36900e4e4b17a8a618bb25154ef13d0465d Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Mon, 3 Sep 2018 18:53:38 +0530 Subject: [PATCH 4/7] qcacmn: Add mgmt_txrx api to drain packets specific to peer At peer deletion corresponding mgmt packets needs to be cleaned up. So add mgmt_txrx api to drain all the mgmt packets specific to a peer. Change-Id: I6a7f5efa665a1da009e594248e88002df35ae9ff CRs-Fixed: 2299964 --- .../dispatcher/inc/wlan_mgmt_txrx_utils_api.h | 27 ++++++++++ .../dispatcher/src/wlan_mgmt_txrx_utils_api.c | 52 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h index be50315facb4..159fd7fbb1cc 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h +++ b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h @@ -745,6 +745,19 @@ typedef QDF_STATUS (*mgmt_frame_fill_peer_cb)( struct wlan_objmgr_peer *peer, qdf_nbuf_t buf); +/** + * mgmt_frame_nbuf_op - Function pointer for any nbuf ops + * @peer: peer + * @buf: buffer + * + * This is the function pointer to be called during drain at peer + * peer deletion + * + * Return: None + */ +typedef void (*mgmt_frame_nbuf_op)(struct wlan_objmgr_peer *peer, + qdf_nbuf_t buf); + /** * struct mgmt_txrx_mgmt_frame_cb_info - frm and corresponding rx cb info * @frm_type: mgmt frm type @@ -847,6 +860,20 @@ QDF_STATUS wlan_mgmt_txrx_register_rx_cb( struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info, uint8_t num_entries); +/** + * wlan_mgmt_txrx_peer_drain() - Function to drain all mgmt packets + * specific to a peer + * @peer: peer context + * @mgmt_nbuf_op: callback func to UMAC for nbuf related operation + * + * This function drains all mgmt packets of a peer at the time of + * peer deletion. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS wlan_mgmt_txrx_peer_drain(struct wlan_objmgr_peer *peer, + mgmt_frame_nbuf_op mgmt_nbuf_op); + /** * wlan_mgmt_txrx_vdev_drain() - Function to drain all mgmt packets * specific to a vdev diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c index 4dc065d25b43..8850f6580660 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c @@ -770,6 +770,58 @@ QDF_STATUS wlan_mgmt_txrx_pdev_close(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_SUCCESS; } +QDF_STATUS wlan_mgmt_txrx_peer_drain(struct wlan_objmgr_peer *peer, + mgmt_frame_nbuf_op mgmt_nbuf_op) +{ + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_vdev *vdev; + struct mgmt_txrx_priv_pdev_context *mgmt_txrx_ctx; + struct mgmt_txrx_desc_elem_t *mgmt_desc; + struct wlan_objmgr_peer *des_peer; + uint32_t pool_size; + int i; + + vdev = wlan_peer_get_vdev(peer); + if (!vdev) { + mgmt_txrx_err("vdev context is NULL"); + return QDF_STATUS_E_INVAL; + } + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + mgmt_txrx_err("pdev context is NULL"); + return QDF_STATUS_E_INVAL; + } + + mgmt_txrx_ctx = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_MGMT_TXRX); + if (!mgmt_txrx_ctx) { + mgmt_txrx_err("mgmt txrx context is NULL"); + return QDF_STATUS_E_FAILURE; + } + + pool_size = mgmt_txrx_ctx->mgmt_desc_pool.free_list.max_size; + if (!pool_size) { + mgmt_txrx_err("pool size is 0"); + return QDF_STATUS_E_FAILURE; + } + + for (i = 0; i < pool_size; i++) { + if (mgmt_txrx_ctx->mgmt_desc_pool.pool[i].in_use) { + mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[i]; + des_peer = mgmt_txrx_get_peer(pdev, mgmt_desc->desc_id); + if (peer == des_peer) { + if (mgmt_nbuf_op) + mgmt_nbuf_op(peer, mgmt_desc->nbuf); + mgmt_txrx_tx_completion_handler(pdev, + mgmt_desc->desc_id, 0, 0); + } + } + } + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS wlan_mgmt_txrx_vdev_drain(struct wlan_objmgr_vdev *vdev, mgmt_frame_fill_peer_cb mgmt_fill_peer_cb, void *status) From 39bb395e2e4be142fb2649c48310a959d4f07122 Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Mon, 27 Aug 2018 17:09:14 -0700 Subject: [PATCH 5/7] qcacmn: Add scheduler history To help triage issues where the scheduler thread is processing slowly, add a scheduler processing history for offline analysis. This can also be useful in determining if a processing delay in some operation is attributed to the scheduler thread or not. Change-Id: Icfea17efc34b2a23d4f8b2baebe08db4e2f6ce8b CRs-Fixed: 2307252 --- qdf/inc/qdf_time.h | 10 ++++++++ scheduler/src/scheduler_core.c | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/qdf/inc/qdf_time.h b/qdf/inc/qdf_time.h index 3f3dbb9fffff..fd151dabe38d 100644 --- a/qdf/inc/qdf_time.h +++ b/qdf/inc/qdf_time.h @@ -306,6 +306,16 @@ static inline uint64_t qdf_get_log_timestamp(void) return __qdf_get_log_timestamp(); } +/** + * qdf_get_log_timestamp_usecs() - get time stamp for logging in microseconds + * + * Return: The current logging timestamp normalized to microsecond precision + */ +static inline uint64_t qdf_get_log_timestamp_usecs(void) +{ + return qdf_log_timestamp_to_usecs(qdf_get_log_timestamp()); +} + /** * qdf_get_monotonic_boottime - get monotonic kernel boot time * This API is similar to qdf_get_system_boottime but it includes diff --git a/scheduler/src/scheduler_core.c b/scheduler/src/scheduler_core.c index 9031532721be..fca63056470f 100644 --- a/scheduler/src/scheduler_core.c +++ b/scheduler/src/scheduler_core.c @@ -30,6 +30,46 @@ static struct scheduler_ctx *gp_sched_ctx; DEFINE_QDF_FLEX_MEM_POOL(sched_pool, sizeof(struct scheduler_msg), WLAN_SCHED_REDUCTION_LIMIT); +#ifdef WLAN_SCHED_HISTORY_SIZE + +struct sched_history_item { + void *callback; + uint32_t type_id; + uint64_t start_us; + uint64_t duration_us; +}; + +static struct sched_history_item sched_history[WLAN_SCHED_HISTORY_SIZE]; +static uint32_t sched_history_index; + +static void sched_history_start(struct scheduler_msg *msg) +{ + struct sched_history_item hist = { + .callback = msg->callback, + .type_id = msg->type, + .start_us = qdf_get_log_timestamp_usecs(), + }; + + sched_history[sched_history_index] = hist; +} + +static void sched_history_stop(void) +{ + struct sched_history_item *hist = &sched_history[sched_history_index]; + + hist->duration_us = qdf_get_log_timestamp_usecs() - hist->start_us; + + sched_history_index++; + sched_history_index %= WLAN_SCHED_HISTORY_SIZE; +} + +#else /* WLAN_SCHED_HISTORY_SIZE */ + +static inline void sched_history_start(struct scheduler_msg *msg) { } +static inline void sched_history_stop(void) { } + +#endif /* WLAN_SCHED_HISTORY_SIZE */ + QDF_STATUS scheduler_create_ctx(void) { qdf_flex_mem_init(&sched_pool); @@ -266,11 +306,14 @@ static void scheduler_thread_process_queues(struct scheduler_ctx *sch_ctx, if (sch_ctx->queue_ctx.scheduler_msg_process_fn[i]) { sch_ctx->watchdog_msg_type = msg->type; sch_ctx->watchdog_callback = msg->callback; + + sched_history_start(msg); qdf_timer_start(&sch_ctx->watchdog_timer, SCHEDULER_WATCHDOG_TIMEOUT); status = sch_ctx->queue_ctx. scheduler_msg_process_fn[i](msg); qdf_timer_stop(&sch_ctx->watchdog_timer); + sched_history_stop(); if (QDF_IS_STATUS_ERROR(status)) sched_err("Failed processing Qid[%d] message", From 7d991b3f72812cccc36b83bd90c8a8081da15f6b Mon Sep 17 00:00:00 2001 From: Aniruddha Paul Date: Mon, 3 Sep 2018 17:40:00 +0530 Subject: [PATCH 6/7] qcacmn: Increase the WBM2SW ring size to 8191 from 4096 Increase the WBM2SW ring size to 8191 from 4096 for NSS offload radios Change-Id: Iad8c0beb811a57bc6ee6136231c6199e9e67bd13 --- wlan_cfg/cfg_dp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wlan_cfg/cfg_dp.h b/wlan_cfg/cfg_dp.h index 0d775a9bbc0e..7f7a26920007 100644 --- a/wlan_cfg/cfg_dp.h +++ b/wlan_cfg/cfg_dp.h @@ -145,9 +145,9 @@ #define WLAN_CFG_INT_TIMER_THRESHOLD_OTHER_MIN 8 #define WLAN_CFG_INT_TIMER_THRESHOLD_OTHER_MAX 1000 -#define WLAN_CFG_NSS_TX_COMP_RING_SIZE 0x1000 -#define WLAN_CFG_NSS_TX_COMP_RING_SIZE_MIN 0x1000 -#define WLAN_CFG_NSS_TX_COMP_RING_SIZE_MAX 0x1000 +#define WLAN_CFG_NSS_TX_COMP_RING_SIZE 0x2000 +#define WLAN_CFG_NSS_TX_COMP_RING_SIZE_MIN 0x2000 +#define WLAN_CFG_NSS_TX_COMP_RING_SIZE_MAX 0x2000 #ifdef QCA_LL_TX_FLOW_CONTROL_V2 From 287dee3f437c10595b2788bec98676067917fab6 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Fri, 24 Aug 2018 20:07:31 -0700 Subject: [PATCH 7/7] qcacmn: Disable CE-IRQ interrupt before cleaning up the tasklets Current driver calls ce_tasklet_kill API which does tasklet_disable() first and then does tasklet_kill which invites race condition as follows. 1) Lets say CPU-0 is executing ce_tasklet_kill() API for CE1 (in process ctx) to kill any tasklets associated with CE1-IRQ 2) t1 time- CPU-1 has scheduled the tasklet as part of rescheduled API ce_schedule_tasklet(), so this tasklet goes to be scheduled list of kernel. 3) t2 time- CPU-0 executes tasklet_disable() and about to execute tasklet_kill() 4) t3 time - kernel got a chance and wants to run the tasklet which was scheduled at t1 time but it can't because t2 time, tasklet has been disable. 5) t5 time- CPU-0 now executes tasklet_kill which checks if any tasklet which is in "SCHEDULE" state to go to "RUNNING" state and finish and tasklet on CPU-1 can't go to "RUNNING" state due to tasklet_disable(), driver is stuck waiting for it to finish. Fix the situation by removing tasklet_disable() Change-Id: I3ac56975dc1f6538962060dd20e881c43e7516ca CRs-Fixed: 2301368 --- hif/src/ce/ce_tasklet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c index e49c3f10c841..09d4f66bdc84 100644 --- a/hif/src/ce/ce_tasklet.c +++ b/hif/src/ce/ce_tasklet.c @@ -239,7 +239,7 @@ void ce_tasklet_kill(struct hif_softc *scn) work_initialized = false; - for (i = 0; i < CE_COUNT_MAX; i++) + for (i = 0; i < CE_COUNT_MAX; i++) { if (hif_ce_state->tasklets[i].inited) { hif_ce_state->tasklets[i].inited = false; /* @@ -251,9 +251,9 @@ void ce_tasklet_kill(struct hif_softc *scn) * tasklet_disable() will take care of that. */ cancel_work_sync(&tasklet_workers[i].work); - tasklet_disable(&hif_ce_state->tasklets[i].intr_tq); tasklet_kill(&hif_ce_state->tasklets[i].intr_tq); } + } qdf_atomic_set(&scn->active_tasklet_cnt, 0); }