summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMin Liu <minliu@codeaurora.org>2018-05-17 11:51:53 +0800
committernshrivas <nshrivas@codeaurora.org>2018-06-13 16:04:37 -0700
commit0efeb4e5a6d97731e7d004d15eddb6828385696f (patch)
tree9e7c6aa362fd2fc276ec43b294d561acb7e01a0d
parent21dcdf1b905f5b868fca14a446af4aa73e374282 (diff)
qcacld-3.0: Cleanup blocked scan requests
The following memory leak issues of blocked scan requests need to be addressed: 1. Add list for blocked scan requests There could be multiple scan requests are blocked before related callback can be executed. Currently there is only one pointer for such requests. A list is added accordingly. 2. Cleanup blocked scan request when ifdown Scheduled work for blocked scan might not be able to be executed before ifdown. When the work is cancelled, related scan request is not freed and will caused memory leak. Call the relate callback when blocked scan work is cancelled to cleanup the pending scan request. Change-Id: Ifb5fc1b14a043ad67e4ba1d305ce4133b471188c CRs-Fixed: 2166111
-rw-r--r--core/hdd/inc/wlan_hdd_main.h4
-rw-r--r--core/hdd/src/wlan_hdd_main.c12
-rw-r--r--core/hdd/src/wlan_hdd_scan.c92
3 files changed, 73 insertions, 35 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index aba1d43d8dfc..ee03e2118640 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1384,8 +1384,6 @@ struct hdd_adapter_s {
/* 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
@@ -1542,6 +1540,8 @@ struct hdd_adapter_s {
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 5da466658294..c577362fb196 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -517,10 +517,13 @@ static int __hdd_netdev_notifier_call(struct notifier_block *nb,
msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
if (!rc)
hdd_err("Timeout occurred while waiting for abortscan");
- } 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
@@ -4442,6 +4445,9 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
}
INIT_WORK(&adapter->scan_block_work, wlan_hdd_cfg80211_scan_block_cb);
+ qdf_list_create(&adapter->blocked_scan_request_q,
+ CFG_MAX_SCAN_COUNT_MAX);
+ qdf_mutex_create(&adapter->blocked_scan_request_q_lock);
cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
mutex_init(&cfgState->remain_on_chan_ctx_lock);
diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c
index eb81c2208cc1..de093bd68900 100644
--- a/core/hdd/src/wlan_hdd_scan.c
+++ b/core/hdd/src/wlan_hdd_scan.c
@@ -1623,35 +1623,35 @@ static void __wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work)
hdd_adapter_t *adapter = container_of(work,
hdd_adapter_t, scan_block_work);
struct cfg80211_scan_request *request;
- hdd_context_t *hdd_ctx;
+ struct hdd_scan_req *blocked_scan_req;
+ qdf_list_node_t *node = NULL;
if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
hdd_err("HDD adapter context is invalid");
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 hdd_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)
@@ -1916,6 +1916,43 @@ static void wlan_hdd_free_voui(tCsrScanRequest *scan_req)
qdf_mem_free(scan_req->voui);
}
+static int
+wlan_hdd_enqueue_blocked_scan_request(struct net_device *dev,
+ struct cfg80211_scan_request *request,
+ uint8_t source)
+{
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ struct hdd_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->adapter = adapter;
+ 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) <
+ CFG_MAX_SCAN_COUNT_MAX)
+ 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 CDS_SCAN_ATTEMPT_FAILURES
@@ -1983,10 +2020,8 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
conn_info.connState) &&
(!pHddCtx->config->enable_connected_scan)) {
hdd_info("enable_connected_scan is false, Aborting scan");
- if (NL_SCAN == source)
- pAdapter->request = request;
- else
- pAdapter->vendor_request = request;
+ if (wlan_hdd_enqueue_blocked_scan_request(dev, request, source))
+ return -EAGAIN;
schedule_work(&pAdapter->scan_block_work);
return 0;
}
@@ -2043,10 +2078,9 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
* startup.
*/
hdd_err("##In DFS Master mode. Scan aborted");
- if (NL_SCAN == source)
- pAdapter->request = request;
- else
- pAdapter->vendor_request = request;
+ if (wlan_hdd_enqueue_blocked_scan_request(dev, request,
+ source))
+ return -EAGAIN;
schedule_work(&pAdapter->scan_block_work);
return 0;
}
@@ -2147,10 +2181,8 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
if (pAdapter->device_mode == QDF_SAP_MODE &&
wlan_hdd_sap_skip_scan_check(pHddCtx, request)) {
hdd_debug("sap scan skipped");
- if (NL_SCAN == source)
- pAdapter->request = request;
- else
- pAdapter->vendor_request = request;
+ if (wlan_hdd_enqueue_blocked_scan_request(dev, request, source))
+ return -EAGAIN;
schedule_work(&pAdapter->scan_block_work);
return 0;
}