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);