Bladeren bron

qcacld-3.0: Do netif_tx_stop_all_queues() instead of netif_tx_disable()

Race condition is happening when tx traffic is running and simulataneously
suspend is going on. hdd_hard_start_xmit() is called under txq->__xmit_lock
and in case of low descriptor scenario, it goes to pause the netif queues
and trying to take adapter->pause_map_lock for doing so which is already
acquired by another thread. In another thread, suspend indication is being
preocessed and as a result is trying to pause netif queues with
netif_action WLAN_NETIF_TX_DISABLE which takes adapter->pause_map_lock and
then calls netif_tx_disable() which is trying to take txq->__xmit_lock
already taken by the thread executing hdd_hard_start_xmit(). This leads to
a deadlock situation.

Replace netif_tx_disable() with netif_tx_stop_all_queues() as
netif_tx_stop_all_queues() is doing the same thing as netif_tx_disable()
only without taking the txq->__xmit_lock which prevents this deadlock.

Change-Id: I5afafe6435707bd8f0e87972a740f908d06ce847
CRs-Fixed: 2030933
Himanshu Agarwal 8 jaren geleden
bovenliggende
commit
865201d99d

+ 1 - 1
core/dp/txrx/ol_tx_queue.c

@@ -1839,7 +1839,7 @@ void ol_txrx_vdev_pause(struct cdp_vdev *pvdev, uint32_t reason)
 	if (netif_reason == WLAN_REASON_TYPE_MAX)
 		return;
 
-	pdev->pause_cb(vdev->vdev_id, WLAN_NETIF_TX_DISABLE, netif_reason);
+	pdev->pause_cb(vdev->vdev_id, WLAN_STOP_ALL_NETIF_QUEUE, netif_reason);
 }
 
 /**

+ 9 - 8
core/hdd/src/wlan_hdd_assoc.c

@@ -1553,8 +1553,9 @@ static QDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter,
 	}
 	/* notify apps that we can't pass traffic anymore */
 	hdd_notice("Disabling queues");
-	wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
-				   WLAN_CONTROL_PATH);
+	wlan_hdd_netif_queue_control(pAdapter,
+				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+				     WLAN_CONTROL_PATH);
 
 	if (hdd_ipa_is_enabled(pHddCtx))
 		hdd_ipa_wlan_evt(pAdapter, pHddStaCtx->conn_info.staId[0],
@@ -2986,7 +2987,7 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
 
 		hdd_info("Disabling queues");
 		wlan_hdd_netif_queue_control(pAdapter,
-					   WLAN_NETIF_TX_DISABLE_N_CARRIER,
+					   WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 					   WLAN_CONTROL_PATH);
 	}
 
@@ -3493,7 +3494,7 @@ roam_roam_connect_status_update_handler(hdd_adapter_t *pAdapter,
 		/* Stop only when we are inactive */
 		hdd_info("Disabling queues");
 		wlan_hdd_netif_queue_control(pAdapter,
-					   WLAN_NETIF_TX_DISABLE_N_CARRIER,
+					   WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 					   WLAN_CONTROL_PATH);
 		hdd_conn_set_connection_state(pAdapter,
 					      eConnectionState_NotConnected);
@@ -4781,7 +4782,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
 		hdd_debug("Roam Synch Ind: NAPI Serialize ON");
 		hdd_napi_serialize(1);
 		wlan_hdd_netif_queue_control(pAdapter,
-				WLAN_NETIF_TX_DISABLE,
+				WLAN_STOP_ALL_NETIF_QUEUE,
 				WLAN_CONTROL_PATH);
 		status = hdd_roam_deregister_sta(pAdapter,
 					pHddStaCtx->conn_info.staId[0]);
@@ -4803,7 +4804,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
 		/* notify apps that we can't pass traffic anymore */
 		hdd_debug("Disabling queues");
 		wlan_hdd_netif_queue_control(pAdapter,
-					   WLAN_NETIF_TX_DISABLE,
+					   WLAN_STOP_ALL_NETIF_QUEUE,
 					   WLAN_CONTROL_PATH);
 		if (pHddStaCtx->ft_carrier_on == false) {
 			wlan_hdd_netif_queue_control(pAdapter,
@@ -4816,7 +4817,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
 			hdd_debug("Roaming started due to connection lost");
 			hdd_info("Disabling queues");
 			wlan_hdd_netif_queue_control(pAdapter,
-					WLAN_NETIF_TX_DISABLE_N_CARRIER,
+					WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 					WLAN_CONTROL_PATH);
 			break;
 		}
@@ -5048,7 +5049,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
 	case eCSR_ROAM_START:
 		hdd_debug("Process ROAM_START from firmware");
 		wlan_hdd_netif_queue_control(pAdapter,
-				WLAN_NETIF_TX_DISABLE,
+				WLAN_STOP_ALL_NETIF_QUEUE,
 				WLAN_CONTROL_PATH);
 		hdd_napi_serialize(1);
 		hdd_set_connection_in_progress(true);

+ 1 - 1
core/hdd/src/wlan_hdd_cfg80211.c

@@ -14274,7 +14274,7 @@ static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
 	/* stop tx queues */
 	hdd_debug("Disabling queues");
 	wlan_hdd_netif_queue_control(pAdapter,
-		WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
+		WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
 	hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
 	pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
 	INIT_COMPLETION(pAdapter->disconnect_comp_var);

+ 7 - 5
core/hdd/src/wlan_hdd_hostapd.c

@@ -312,8 +312,9 @@ static int __hdd_hostapd_stop(struct net_device *dev)
 	clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
 	/* Stop all tx queues */
 	hdd_notice("Disabling queues");
-	wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
-				   WLAN_CONTROL_PATH);
+	wlan_hdd_netif_queue_control(adapter,
+				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+				     WLAN_CONTROL_PATH);
 
 	EXIT();
 	return 0;
@@ -2103,8 +2104,8 @@ stopbss:
 		 */
 		hdd_notice("Disabling queues");
 		wlan_hdd_netif_queue_control(pHostapdAdapter,
-					     WLAN_NETIF_TX_DISABLE_N_CARRIER,
-					     WLAN_CONTROL_PATH);
+					WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+					WLAN_CONTROL_PATH);
 
 		/* reclaim all resources allocated to the BSS */
 		qdf_status = hdd_softap_stop_bss(pHostapdAdapter);
@@ -8096,7 +8097,8 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
 						sizeof(struct sap_acs_cfg));
 	/* Stop all tx queues */
 	hdd_notice("Disabling queues");
-	wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
+	wlan_hdd_netif_queue_control(pAdapter,
+				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 				     WLAN_CONTROL_PATH);
 
 	old = pAdapter->sessionCtx.ap.beacon;

+ 14 - 12
core/hdd/src/wlan_hdd_main.c

@@ -2308,8 +2308,9 @@ static int __hdd_stop(struct net_device *dev)
 	 * be called on that interface
 	 */
 	hdd_notice("Disabling queues");
-	wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
-				   WLAN_CONTROL_PATH);
+	wlan_hdd_netif_queue_control(adapter,
+				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+				     WLAN_CONTROL_PATH);
 
 	/*
 	 * NAN data interface is different in some sense. The traffic on NDI is
@@ -3669,8 +3670,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
 		/* Stop the Interface TX queue. */
 		hdd_info("Disabling queues");
 		wlan_hdd_netif_queue_control(adapter,
-					     WLAN_NETIF_TX_DISABLE_N_CARRIER,
-					     WLAN_CONTROL_PATH);
+					WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+					WLAN_CONTROL_PATH);
 		break;
 
 
@@ -3698,8 +3699,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
 		}
 		hdd_info("Disabling queues");
 		wlan_hdd_netif_queue_control(adapter,
-					     WLAN_NETIF_TX_DISABLE_N_CARRIER,
-					     WLAN_CONTROL_PATH);
+					WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+					WLAN_CONTROL_PATH);
 		break;
 	case QDF_FTM_MODE:
 		adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
@@ -3719,8 +3720,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
 		/* Stop the Interface TX queue. */
 		hdd_info("Disabling queues");
 		wlan_hdd_netif_queue_control(adapter,
-					     WLAN_NETIF_TX_DISABLE_N_CARRIER,
-					     WLAN_CONTROL_PATH);
+					WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+					WLAN_CONTROL_PATH);
 		break;
 	default:
 		hdd_err("Invalid session type %d", session_type);
@@ -3930,8 +3931,9 @@ QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
 
 	scan_info = &adapter->scan_info;
 	hdd_notice("Disabling queues");
-	wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
-				   WLAN_CONTROL_PATH);
+	wlan_hdd_netif_queue_control(adapter,
+				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+				     WLAN_CONTROL_PATH);
 	switch (adapter->device_mode) {
 	case QDF_STA_MODE:
 	case QDF_P2P_CLIENT_MODE:
@@ -4163,7 +4165,7 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
 		if (hdd_ctx->config->sap_internal_restart &&
 		    adapter->device_mode == QDF_SAP_MODE) {
 			wlan_hdd_netif_queue_control(adapter,
-						     WLAN_NETIF_TX_DISABLE,
+						     WLAN_STOP_ALL_NETIF_QUEUE,
 						     WLAN_CONTROL_PATH);
 			if (test_bit(SOFTAP_BSS_STARTED,
 						&adapter->event_flags)) {
@@ -4174,7 +4176,7 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
 			clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
 		} else {
 			wlan_hdd_netif_queue_control(adapter,
-					   WLAN_NETIF_TX_DISABLE_N_CARRIER,
+					   WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 					   WLAN_CONTROL_PATH);
 		}
 

+ 1 - 1
core/hdd/src/wlan_hdd_nan_datapath.c

@@ -132,7 +132,7 @@ static int hdd_close_ndi(hdd_adapter_t *adapter)
 		return -EINVAL;
 	}
 	wlan_hdd_netif_queue_control(adapter,
-				     WLAN_NETIF_TX_DISABLE_N_CARRIER,
+				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 				     WLAN_CONTROL_PATH);
 
 #ifdef WLAN_OPEN_SOURCE

+ 3 - 2
core/hdd/src/wlan_hdd_ocb.c

@@ -410,8 +410,9 @@ static int hdd_ocb_set_config_req(hdd_adapter_t *adapter,
 	cookie = hdd_request_cookie(hdd_request);
 
 	hdd_notice("Disabling queues");
-	wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
-		WLAN_CONTROL_PATH);
+	wlan_hdd_netif_queue_control(adapter,
+				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+				     WLAN_CONTROL_PATH);
 
 	/* Call the SME API to set the config */
 	status = sme_ocb_set_config(hdd_ctx->hHal, cookie,

+ 3 - 2
core/hdd/src/wlan_hdd_power.c

@@ -1035,8 +1035,9 @@ hdd_suspend_wlan(void)
 
 		/* stop all TX queues before suspend */
 		hdd_debug("Disabling queues");
-		wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE,
-					   WLAN_CONTROL_PATH);
+		wlan_hdd_netif_queue_control(pAdapter,
+					     WLAN_STOP_ALL_NETIF_QUEUE,
+					     WLAN_CONTROL_PATH);
 
 		/* Configure supported OffLoads */
 		hdd_enable_host_offloads(pAdapter, pmo_apps_suspend);

+ 0 - 27
core/hdd/src/wlan_hdd_tx_rx.c

@@ -1190,8 +1190,6 @@ const char *hdd_action_type_to_string(enum netif_action_type action)
 	CASE_RETURN_STRING(WLAN_WAKE_ALL_NETIF_QUEUE);
 	CASE_RETURN_STRING(WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER);
 	CASE_RETURN_STRING(WLAN_START_ALL_NETIF_QUEUE_N_CARRIER);
-	CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE);
-	CASE_RETURN_STRING(WLAN_NETIF_TX_DISABLE_N_CARRIER);
 	CASE_RETURN_STRING(WLAN_NETIF_CARRIER_ON);
 	CASE_RETURN_STRING(WLAN_NETIF_CARRIER_OFF);
 	default:
@@ -1211,8 +1209,6 @@ static void wlan_hdd_update_queue_oper_stats(hdd_adapter_t *adapter,
 	switch (action) {
 	case WLAN_STOP_ALL_NETIF_QUEUE:
 	case WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER:
-	case WLAN_NETIF_TX_DISABLE:
-	case WLAN_NETIF_TX_DISABLE_N_CARRIER:
 		adapter->queue_oper_stats[reason].pause_count++;
 		break;
 	case WLAN_START_ALL_NETIF_QUEUE:
@@ -1377,29 +1373,6 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
 		spin_unlock_bh(&adapter->pause_map_lock);
 		break;
 
-	case WLAN_NETIF_TX_DISABLE:
-		spin_lock_bh(&adapter->pause_map_lock);
-		if (!adapter->pause_map) {
-			netif_tx_disable(adapter->dev);
-			wlan_hdd_update_txq_timestamp(adapter->dev);
-			wlan_hdd_update_unpause_time(adapter);
-		}
-		adapter->pause_map |= (1 << reason);
-		spin_unlock_bh(&adapter->pause_map_lock);
-		break;
-
-	case WLAN_NETIF_TX_DISABLE_N_CARRIER:
-		spin_lock_bh(&adapter->pause_map_lock);
-		if (!adapter->pause_map) {
-			netif_tx_disable(adapter->dev);
-			wlan_hdd_update_txq_timestamp(adapter->dev);
-			wlan_hdd_update_unpause_time(adapter);
-		}
-		adapter->pause_map |= (1 << reason);
-		netif_carrier_off(adapter->dev);
-		spin_unlock_bh(&adapter->pause_map_lock);
-		break;
-
 	default:
 		hdd_err("unsupported action %d", action);
 	}

+ 1 - 1
core/hdd/src/wlan_hdd_wext.c

@@ -7187,7 +7187,7 @@ static int __iw_set_mlme(struct net_device *dev,
 
 			hdd_notice("Disabling queues");
 			wlan_hdd_netif_queue_control(pAdapter,
-					WLAN_NETIF_TX_DISABLE_N_CARRIER,
+					WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 					WLAN_CONTROL_PATH);
 
 		} else {