Browse Source

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
Alok Kumar 6 years ago
parent
commit
016a1aca3a

+ 3 - 1
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_ignore_tracking(adapter, true);
 	hdd_nud_reset_tracking(adapter);
 	hdd_nud_reset_tracking(adapter);
+	hdd_nud_flush_work(adapter);
 
 
 	hdd_debug("Disabling queues");
 	hdd_debug("Disabling queues");
 	wlan_hdd_netif_queue_control(adapter,
 	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_ignore_tracking(adapter, true);
+		hdd_nud_reset_tracking(adapter);
+		hdd_nud_flush_work(adapter);
 		hdd_set_disconnect_status(adapter, false);
 		hdd_set_disconnect_status(adapter, false);
 
 
 		hdd_softap_deinit_tx_rx(adapter);
 		hdd_softap_deinit_tx_rx(adapter);

+ 18 - 13
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);
 			       ->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)
 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;
 		adapter->nud_tracking.curr_state = NUD_NONE;
 		qdf_atomic_set(&adapter
 		qdf_atomic_set(&adapter
 			       ->nud_tracking.tx_rx_stats.gw_rx_packets, 0);
 			       ->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");
 		hdd_debug("Not in Connected State");
 		return;
 		return;
 	}
 	}
+	if (adapter->nud_tracking.curr_state != NUD_FAILED) {
+		hdd_debug("Not in NUD_FAILED state");
+		return;
+	}
 
 
 	qdf_mutex_acquire(&adapter->disconnection_status_lock);
 	qdf_mutex_acquire(&adapter->disconnection_status_lock);
 	if (adapter->disconnection_in_progress) {
 	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;
 	curr_state = adapter->nud_tracking.curr_state;
 	if (curr_state == NUD_PROBE || curr_state == NUD_INCOMPLETE) {
 	if (curr_state == NUD_PROBE || curr_state == NUD_INCOMPLETE) {
 		hdd_nud_capture_stats(adapter, NUD_FAILED);
 		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
 			qdf_sched_work(0, &adapter
 					->nud_tracking.nud_event_work);
 					->nud_tracking.nud_event_work);
-		else
+		} else {
 			hdd_nud_set_tracking(adapter, NUD_NONE, false);
 			hdd_nud_set_tracking(adapter, NUD_NONE, false);
+		}
 	} else {
 	} else {
 		hdd_debug("NUD FAILED -> Current State [0x%x]", curr_state);
 		hdd_debug("NUD FAILED -> Current State [0x%x]", curr_state);
 	}
 	}

+ 13 - 0
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);
 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
 #else
 static inline void hdd_nud_set_gateway_addr(struct hdd_adapter *adapter,
 static inline void hdd_nud_set_gateway_addr(struct hdd_adapter *adapter,
 					    struct qdf_mac_addr gw_mac_addr)
 					    struct qdf_mac_addr gw_mac_addr)
@@ -177,5 +185,10 @@ static inline void
 hdd_nud_unregister_netevent_notifier(struct hdd_context *hdd_ctx)
 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 /* WLAN_NUD_TRACKING */
 #endif /* end  of _WLAN_NUD_TRACKING_H_ */
 #endif /* end  of _WLAN_NUD_TRACKING_H_ */