From aaa3f8871c7779965ef2a6b503f04f3025e6ad93 Mon Sep 17 00:00:00 2001 From: Hanumanth Reddy Pothula Date: Thu, 5 Oct 2017 17:45:00 +0530 Subject: [PATCH] qcacld-3.0: Fix CPU soft lock up during workqueue cancellation Propagation from qcacld-2.0 to qcacld-3.0 ipv4 and ipv6 workqueues are initialized in open adapter for STA and P2P modes but not for AP mode. The workqueues are cancelled in stop adapter. The cancel_work_sync may be called on AP adapter workqueue also, if just in time, the AP adapter mode has changed to STA mode, for example during hostapd stop etc. This can cause the cancel_work_sync to continuously loop since INIT_WORK has not been called, finally raising CPU stuck. There is no harm in calling INIT_WORK on any workqueue since it only makes sure that in cases as above there is no undeterministic behaviour. Fix cancel_work_sync issues by initializing ipv4 and ipv6 workqueues. CRs-Fixed: 2121723 Change-Id: Ief8dd0c797dd1492fa30ca4e41da9e583548e21d --- core/hdd/src/wlan_hdd_main.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 68986305cf30..5f63cb9c1734 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4074,6 +4074,22 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio wlan_hdd_netif_queue_control(adapter, WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH); + + /* + * Workqueue which gets scheduled in IPv4 notification + * callback + */ + INIT_WORK(&adapter->ipv4NotifierWorkQueue, + hdd_ipv4_notifier_work_queue); + +#ifdef WLAN_NS_OFFLOAD + /* + * Workqueue which gets scheduled in IPv6 + * notification callback. + */ + INIT_WORK(&adapter->ipv6NotifierWorkQueue, + hdd_ipv6_notifier_work_queue); +#endif break; case QDF_FTM_MODE: adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr, @@ -4485,6 +4501,16 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *ada if (true == bCloseSession) hdd_vdev_destroy(adapter); mutex_unlock(&hdd_ctx->sap_lock); + +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&adapter->ipv4NotifierWorkQueue); +#endif + +#ifdef WLAN_NS_OFFLOAD +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&adapter->ipv6NotifierWorkQueue); +#endif +#endif break; case QDF_OCB_MODE: cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),