From c34d4a335248756804b88726da41e36a16eae5d7 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Wed, 12 Jul 2017 16:20:27 +0530 Subject: [PATCH] qcacld-3.0: Set timer expiry on queued HDD scan requests In certain cases HDD fails to receive callbacks for the scan requests queued to SME. Kernel may free up these scan requests due to timeout. During driver shutdown and exit if scan done is performed on these stale scan requests, kernel crash may occur. Set a timer of 60 seconds on queued scan requests, after expiry BUG_ON for debugging purposes. Change-Id: I6db155b17a8a5ae87208ec84eaab221a53623a63 CRs-Fixed: 2070594 --- core/hdd/inc/wlan_hdd_main.h | 2 ++ core/hdd/src/wlan_hdd_scan.c | 51 ++++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_scan.h | 6 +++++ 3 files changed, 59 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 14acff08ce77..f6519fe0d9c7 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -603,6 +603,8 @@ struct hdd_scan_req { uint32_t scan_id; uint8_t source; uint32_t timestamp; + qdf_timer_t hdd_scan_inactivity_timer; + uint32_t scan_req_flags; }; enum p2p_action_frame_state { diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index 695fe50e35ee..911ce09a07cd 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -184,6 +184,40 @@ static bool wlan_hdd_is_scan_pending(hdd_adapter_t *adapter) return false; } +/** + * hdd_scan_inactivity_timer_handler() - Function invoked when hdd inactivity + * timer expires + * @scan_req: void pointer to scan request + * + * This function is invoked when the scan request enqueued by hdd expires the + * given timeout, it shall BUG_ON to provide further details for debugging. + * + * Return: void + */ +static void hdd_scan_inactivity_timer_handler(void *scan_req) +{ + struct hdd_scan_req *hdd_scan_req = scan_req; + + hdd_debug("scan_id %d, enqueue timestamp %u, flags 0x%X", + hdd_scan_req->scan_id, hdd_scan_req->timestamp, + hdd_scan_req->scan_req_flags); + + if (cds_is_load_or_unload_in_progress()) + hdd_err("%s: Module (un)loading; Ignore hdd scan req timeout", + __func__); + else if (cds_is_driver_recovering()) + hdd_err("%s: Module recovering; Ignore hdd scan req timeout", + __func__); + else if (cds_is_driver_in_bad_state()) + hdd_err("%s: Module in bad state; Ignore hdd scan req timeout", + __func__); + else if (cds_is_self_recovery_enabled()) + cds_trigger_recovery(false); + else + QDF_BUG(0); + +} + /** * wlan_hdd_scan_request_enqueue() - enqueue Scan Request * @adapter: Pointer to the adapter @@ -215,6 +249,10 @@ static int wlan_hdd_scan_request_enqueue(hdd_adapter_t *adapter, hdd_scan_req->source = source; hdd_scan_req->scan_id = scan_id; hdd_scan_req->timestamp = timestamp; + if (scan_req != NULL) + hdd_scan_req->scan_req_flags = scan_req->flags; + else + hdd_scan_req->scan_req_flags = 0; qdf_spin_lock(&hdd_ctx->hdd_scan_req_q_lock); status = qdf_list_insert_back(&hdd_ctx->hdd_scan_req_q, @@ -226,6 +264,13 @@ static int wlan_hdd_scan_request_enqueue(hdd_adapter_t *adapter, qdf_mem_free(hdd_scan_req); return -EINVAL; } + + qdf_timer_init(NULL, &hdd_scan_req->hdd_scan_inactivity_timer, + hdd_scan_inactivity_timer_handler, hdd_scan_req, + QDF_TIMER_TYPE_SW); + qdf_timer_start(&hdd_scan_req->hdd_scan_inactivity_timer, + HDD_SCAN_INACTIVITY_TIMEOUT); + EXIT(); return 0; } @@ -274,6 +319,12 @@ static QDF_STATUS wlan_hdd_scan_request_dequeue(hdd_context_t *hdd_ctx, status = qdf_list_remove_node(&hdd_ctx->hdd_scan_req_q, pNode); if (status == QDF_STATUS_SUCCESS) { + qdf_timer_stop(&hdd_scan_req-> + hdd_scan_inactivity_timer); + qdf_timer_free(&hdd_scan_req-> + hdd_scan_inactivity_timer); + hdd_debug("Stopping HDD Scan inactivity timer"); + *req = hdd_scan_req->scan_request; *source = hdd_scan_req->source; *timestamp = hdd_scan_req->timestamp; diff --git a/core/hdd/src/wlan_hdd_scan.h b/core/hdd/src/wlan_hdd_scan.h index 9d4ed327d6f3..2e969f88d7ce 100644 --- a/core/hdd/src/wlan_hdd_scan.h +++ b/core/hdd/src/wlan_hdd_scan.h @@ -30,6 +30,7 @@ #define WLAN_HDD_SCAN_H #include "wlan_hdd_main.h" +#include "csr_inside_api.h" #include #define MAX_PENDING_LOG 5 @@ -37,6 +38,11 @@ /* (30 Mins) */ #define MIN_TIME_REQUIRED_FOR_NEXT_BUG_REPORT (30 * 60 * 1000) +/* HDD Scan inactivity timeout set to 10 seconds + * more than the CSR CMD Timeout */ +#define HDD_SCAN_INACTIVITY_TIMEOUT \ + (CSR_ACTIVE_SCAN_LIST_CMD_TIMEOUT + (10*1000)) + int hdd_scan_context_init(hdd_context_t *hdd_ctx); void hdd_scan_context_destroy(hdd_context_t *hdd_ctx);