diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 81557f3ff156..5d54ce3cd58c 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1197,8 +1197,6 @@ struct hdd_adapter { /* TODO Move this to sta Ctx */ struct wireless_dev wdev; - struct cfg80211_scan_request *request; - struct cfg80211_scan_request *vendor_request; /** ops checks if Opportunistic Power Save is Enable or Not * ctw stores ctWindow value once we receive Opps command from @@ -1333,6 +1331,8 @@ struct hdd_adapter { struct delayed_work acs_pending_work; struct work_struct scan_block_work; + qdf_list_t blocked_scan_request_q; + qdf_mutex_t blocked_scan_request_q_lock; #ifdef MSM_PLATFORM unsigned long prev_rx_packets; unsigned long prev_tx_packets; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 920494d1320c..dac0b32a99ff 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -618,10 +618,13 @@ static int __hdd_netdev_notifier_call(struct notifier_block *nb, SCAN_NOT_IN_PROGRESS) { wlan_abort_scan(hdd_ctx->hdd_pdev, INVAL_PDEV_ID, adapter->session_id, INVALID_SCAN_ID, true); - } else { - cds_flush_work(&adapter->scan_block_work); - hdd_debug("Scan is not Pending from user"); } + cds_flush_work(&adapter->scan_block_work); + /* Need to clean up blocked scan request */ + wlan_hdd_cfg80211_scan_block_cb(&adapter->scan_block_work); + qdf_list_destroy(&adapter->blocked_scan_request_q); + qdf_mutex_destroy(&adapter->blocked_scan_request_q_lock); + hdd_debug("Scan is not Pending from user"); /* * After NETDEV_GOING_DOWN, kernel calls hdd_stop.Irrespective * of return status of hdd_stop call, kernel resets the IFF_UP @@ -4770,6 +4773,8 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio } INIT_WORK(&adapter->scan_block_work, wlan_hdd_cfg80211_scan_block_cb); + qdf_list_create(&adapter->blocked_scan_request_q, WLAN_MAX_SCAN_COUNT); + qdf_mutex_create(&adapter->blocked_scan_request_q_lock); if (QDF_STATUS_SUCCESS == status) { /* Add it to the hdd's session list. */ diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 368179377544..9a6c693ae976 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -283,7 +283,8 @@ static void __wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work) { struct hdd_adapter *adapter; struct cfg80211_scan_request *request; - struct hdd_context *hdd_ctx; + struct scan_req *blocked_scan_req; + qdf_list_node_t *node = NULL; adapter = container_of(work, struct hdd_adapter, scan_block_work); if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { @@ -291,28 +292,27 @@ static void __wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work) return; } - hdd_ctx = WLAN_HDD_GET_CTX(adapter); - if (0 != wlan_hdd_validate_context(hdd_ctx)) - return; + qdf_mutex_acquire(&adapter->blocked_scan_request_q_lock); - request = adapter->request; - if (request) { + while (!qdf_list_empty(&adapter->blocked_scan_request_q)) { + qdf_list_remove_front(&adapter->blocked_scan_request_q, + &node); + blocked_scan_req = qdf_container_of(node, struct scan_req, + node); + request = blocked_scan_req->scan_request; request->n_ssids = 0; request->n_channels = 0; - - hdd_err("##In DFS Master mode. Scan aborted. Null result sent"); - hdd_cfg80211_scan_done(adapter, request, true); - adapter->request = NULL; + if (blocked_scan_req->source == NL_SCAN) { + hdd_err("Scan aborted. Null result sent"); + hdd_cfg80211_scan_done(adapter, request, true); + } else { + hdd_err("Vendor scan aborted. Null result sent"); + hdd_vendor_scan_callback(adapter, request, true); + } + qdf_mem_free(blocked_scan_req); } - request = adapter->vendor_request; - if (request) { - request->n_ssids = 0; - request->n_channels = 0; - hdd_err("In DFS Master mode. Scan aborted. Null result sent"); - hdd_vendor_scan_callback(adapter, request, true); - adapter->vendor_request = NULL; - } + qdf_mutex_release(&adapter->blocked_scan_request_q_lock); } void wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work) @@ -387,6 +387,43 @@ static int wlan_hdd_update_scan_ies(struct hdd_adapter *adapter, return 0; } +static int +wlan_hdd_enqueue_blocked_scan_request(struct net_device *dev, + struct cfg80211_scan_request *request, + uint8_t source) +{ + struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct scan_req *blocked_scan_req = + qdf_mem_malloc(sizeof(*blocked_scan_req)); + int ret = 0; + + if (!blocked_scan_req) { + hdd_err("Failed to allocate scan_req"); + return -EINVAL; + } + + blocked_scan_req->dev = dev; + blocked_scan_req->scan_request = request; + blocked_scan_req->source = source; + blocked_scan_req->scan_id = 0; + + qdf_mutex_acquire(&adapter->blocked_scan_request_q_lock); + if (qdf_list_size(&adapter->blocked_scan_request_q) < + WLAN_MAX_SCAN_COUNT) + qdf_list_insert_back(&adapter->blocked_scan_request_q, + &blocked_scan_req->node); + else + ret = -EINVAL; + qdf_mutex_release(&adapter->blocked_scan_request_q_lock); + + if (ret) { + hdd_err("Maximum number of block scan request reached!"); + qdf_mem_free(blocked_scan_req); + } + + return ret; +} + /* Define short name to use in cds_trigger_recovery */ #define SCAN_FAILURE QDF_SCAN_ATTEMPT_FAILURES @@ -452,10 +489,8 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, conn_info.connState) && (!hdd_ctx->config->enable_connected_scan)) { hdd_info("enable_connected_scan is false, Aborting scan"); - if (NL_SCAN == source) - adapter->request = request; - else - adapter->vendor_request = request; + if (wlan_hdd_enqueue_blocked_scan_request(dev, request, source)) + return -EAGAIN; schedule_work(&adapter->scan_block_work); return 0; } @@ -505,11 +540,9 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, * startup. */ hdd_err("##In DFS Master mode. Scan aborted"); - if (NL_SCAN == source) - adapter->request = request; - else - adapter->vendor_request = request; - + if (wlan_hdd_enqueue_blocked_scan_request(dev, request, + source)) + return -EAGAIN; schedule_work(&adapter->scan_block_work); return 0; } @@ -563,10 +596,8 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, if (adapter->device_mode == QDF_SAP_MODE && wlan_hdd_sap_skip_scan_check(hdd_ctx, request)) { hdd_debug("sap scan skipped"); - if (NL_SCAN == source) - adapter->request = request; - else - adapter->vendor_request = request; + if (wlan_hdd_enqueue_blocked_scan_request(dev, request, source)) + return -EAGAIN; schedule_work(&adapter->scan_block_work); return 0; }