From 016a1aca3a465efa0b532fcd4de4fbc9c4e1514b Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Sun, 16 Sep 2018 09:55:50 +0530 Subject: [PATCH] qcacld-3.0: In nud_reset_tracking, flush NUD work based on flag Race condition occurs when NUD failure happens and NUD work is scheduled and at the same time within driver csr disconnect issued because of Roam Sync failure. Disable flush of NUD work in hdd_nud_reset_tracking during hdd_dis_connect_handler() Change-Id: I3d24073c5c8047fad42309e878f3741c7a2d268e CRs-Fixed: 2315973 --- core/hdd/src/wlan_hdd_main.c | 4 +++- core/hdd/src/wlan_hdd_nud_tracking.c | 31 ++++++++++++++++------------ core/hdd/src/wlan_hdd_nud_tracking.h | 13 ++++++++++++ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index d1af2152f74b..0fb8c55c090d 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5099,6 +5099,7 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx, hdd_nud_ignore_tracking(adapter, true); hdd_nud_reset_tracking(adapter); + hdd_nud_flush_work(adapter); hdd_debug("Disabling queues"); wlan_hdd_netif_queue_control(adapter, @@ -5483,8 +5484,9 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx) } } - hdd_nud_reset_tracking(adapter); hdd_nud_ignore_tracking(adapter, true); + hdd_nud_reset_tracking(adapter); + hdd_nud_flush_work(adapter); hdd_set_disconnect_status(adapter, false); hdd_softap_deinit_tx_rx(adapter); diff --git a/core/hdd/src/wlan_hdd_nud_tracking.c b/core/hdd/src/wlan_hdd_nud_tracking.c index c691ed4c2a61..aae1f6797f5b 100644 --- a/core/hdd/src/wlan_hdd_nud_tracking.c +++ b/core/hdd/src/wlan_hdd_nud_tracking.c @@ -42,16 +42,17 @@ void hdd_nud_incr_gw_rx_pkt_cnt(struct hdd_adapter *adapter, ->nud_tracking.tx_rx_stats.gw_rx_packets); } -/** - * hdd_nud_flush_work() - flush pending nud work - * @adapter: Pointer to hdd adapter - * - * Return: None - */ -static inline void -hdd_nud_flush_work(struct hdd_adapter *adapter) +void hdd_nud_flush_work(struct hdd_adapter *adapter) { - qdf_disable_work(&adapter->nud_tracking.nud_event_work); + struct hdd_context *hdd_ctx; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (adapter->device_mode == QDF_STA_MODE && + hdd_ctx->config->enable_nud_tracking) { + hdd_debug("Flush the NUD work"); + qdf_disable_work(&adapter->nud_tracking.nud_event_work); + } } void hdd_nud_deinit_tracking(struct hdd_adapter *adapter) @@ -88,8 +89,6 @@ void hdd_nud_reset_tracking(struct hdd_adapter *adapter) adapter->nud_tracking.curr_state = NUD_NONE; qdf_atomic_set(&adapter ->nud_tracking.tx_rx_stats.gw_rx_packets, 0); - - hdd_nud_flush_work(adapter); } } @@ -236,6 +235,10 @@ static void __hdd_nud_failure_work(void *data) hdd_debug("Not in Connected State"); return; } + if (adapter->nud_tracking.curr_state != NUD_FAILED) { + hdd_debug("Not in NUD_FAILED state"); + return; + } qdf_mutex_acquire(&adapter->disconnection_status_lock); if (adapter->disconnection_in_progress) { @@ -309,11 +312,13 @@ static void hdd_nud_process_failure_event(struct hdd_adapter *adapter) curr_state = adapter->nud_tracking.curr_state; if (curr_state == NUD_PROBE || curr_state == NUD_INCOMPLETE) { hdd_nud_capture_stats(adapter, NUD_FAILED); - if (hdd_nud_honour_failure(adapter)) + if (hdd_nud_honour_failure(adapter)) { + adapter->nud_tracking.curr_state = NUD_FAILED; qdf_sched_work(0, &adapter ->nud_tracking.nud_event_work); - else + } else { hdd_nud_set_tracking(adapter, NUD_NONE, false); + } } else { hdd_debug("NUD FAILED -> Current State [0x%x]", curr_state); } diff --git a/core/hdd/src/wlan_hdd_nud_tracking.h b/core/hdd/src/wlan_hdd_nud_tracking.h index efd3dd96fa90..584cf9b0560e 100644 --- a/core/hdd/src/wlan_hdd_nud_tracking.h +++ b/core/hdd/src/wlan_hdd_nud_tracking.h @@ -139,6 +139,14 @@ int hdd_nud_register_netevent_notifier(struct hdd_context *hdd_ctx); */ void hdd_nud_unregister_netevent_notifier(struct hdd_context *hdd_ctx); +/** + * hdd_nud_flush_work() - flush pending nud work + * @adapter: Pointer to hdd adapter + * + * Return: None + */ +void hdd_nud_flush_work(struct hdd_adapter *adapter); + #else static inline void hdd_nud_set_gateway_addr(struct hdd_adapter *adapter, struct qdf_mac_addr gw_mac_addr) @@ -177,5 +185,10 @@ static inline void hdd_nud_unregister_netevent_notifier(struct hdd_context *hdd_ctx) { } + +static inline void +hdd_nud_flush_work(struct hdd_adapter *adapter) +{ +} #endif /* WLAN_NUD_TRACKING */ #endif /* end of _WLAN_NUD_TRACKING_H_ */