Browse Source

qcacld-3.0: Close FTM vdev leak

When the driver transitions into Factory Test Mode (FTM), the existing
vdev is not properly destroyed. This ultimately leads to a vdev object
leak when the driver is unloaded while in FTM. To close the leak, tear
down the existing station vdev before doing the module stop operation.

Change-Id: I48ca4e6fc5750e593b6afc4e6b44a603570101cc
CRs-Fixed: 2137144
Dustin Brown 7 years ago
parent
commit
db2a8bed51

+ 3 - 6
core/hdd/inc/wlan_hdd_main.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1840,8 +1840,7 @@ QDF_STATUS hdd_close_adapter(struct hdd_context *hdd_ctx,
 			     struct hdd_adapter *adapter,
 			     bool rtnl_held);
 QDF_STATUS hdd_close_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held);
-QDF_STATUS hdd_stop_all_adapters(struct hdd_context *hdd_ctx,
-				 bool close_session);
+QDF_STATUS hdd_stop_all_adapters(struct hdd_context *hdd_ctx);
 void hdd_deinit_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held);
 QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx);
 QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx);
@@ -1862,8 +1861,7 @@ void hdd_deinit_adapter(struct hdd_context *hdd_ctx,
 			struct hdd_adapter *adapter,
 			bool rtnl_held);
 QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
-			    struct hdd_adapter *adapter,
-			    const bool bCloseSession);
+			    struct hdd_adapter *adapter);
 void hdd_set_station_ops(struct net_device *dev);
 uint8_t *wlan_hdd_get_intf_addr(struct hdd_context *hdd_ctx);
 void wlan_hdd_release_intf_addr(struct hdd_context *hdd_ctx,
@@ -2377,7 +2375,6 @@ void hdd_deregister_cb(struct hdd_context *hdd_ctx);
 int hdd_start_station_adapter(struct hdd_adapter *adapter);
 int hdd_start_ap_adapter(struct hdd_adapter *adapter);
 int hdd_configure_cds(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter);
-int hdd_start_ftm_adapter(struct hdd_adapter *adapter);
 int hdd_set_fw_params(struct hdd_adapter *adapter);
 int hdd_wlan_start_modules(struct hdd_context *hdd_ctx,
 			   struct hdd_adapter *adapter,

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

@@ -9718,7 +9718,7 @@ int wlan_hdd_request_pre_cac(uint8_t channel)
 	return 0;
 
 stop_close_pre_cac_adapter:
-	hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
+	hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
 	qdf_mem_free(pre_cac_adapter->session.ap.beacon);
 	pre_cac_adapter->session.ap.beacon = NULL;
 close_pre_cac_adapter:
@@ -14123,7 +14123,7 @@ static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
 	}
 
 	wdev = ndev->ieee80211_ptr;
-	hdd_stop_adapter(hdd_ctx, adapter, true);
+	hdd_stop_adapter(hdd_ctx, adapter);
 	hdd_deinit_adapter(hdd_ctx, adapter, true);
 	wdev->iftype = type;
 	/*Check for sub-string p2p to confirm its a p2p interface */
@@ -14293,7 +14293,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 					(adapter);
 			}
 
-			hdd_stop_adapter(hdd_ctx, adapter, true);
+			hdd_stop_adapter(hdd_ctx, adapter);
 			/* De-init the adapter */
 			hdd_deinit_adapter(hdd_ctx, adapter, true);
 			memset(&adapter->session, 0,

+ 4 - 4
core/hdd/src/wlan_hdd_hostapd.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -515,7 +515,7 @@ static int __hdd_hostapd_stop(struct net_device *dev)
 	 * needs to de-init the sap session here and re-init when
 	 * __hdd_hostapd_open() API
 	 */
-	hdd_stop_adapter(hdd_ctx, adapter, true);
+	hdd_stop_adapter(hdd_ctx, adapter);
 	hdd_deinit_adapter(hdd_ctx, adapter, true);
 	clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
 	/* Stop all tx queues */
@@ -1107,7 +1107,7 @@ static void __wlan_hdd_sap_pre_cac_failure(void *data)
 
 	wlan_hdd_release_intf_addr(hdd_ctx,
 				   adapter->mac_addr.bytes);
-	hdd_stop_adapter(hdd_ctx, adapter, true);
+	hdd_stop_adapter(hdd_ctx, adapter);
 	hdd_close_adapter(hdd_ctx, adapter, false);
 }
 
@@ -1158,7 +1158,7 @@ static void wlan_hdd_sap_pre_cac_success(void *data)
 	cds_ssr_protect(__func__);
 	wlan_hdd_release_intf_addr(hdd_ctx,
 				   adapter->mac_addr.bytes);
-	hdd_stop_adapter(hdd_ctx, adapter, true);
+	hdd_stop_adapter(hdd_ctx, adapter);
 	hdd_close_adapter(hdd_ctx, adapter, false);
 	cds_ssr_unprotect(__func__);
 

+ 26 - 64
core/hdd/src/wlan_hdd_main.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -2099,19 +2099,16 @@ int hdd_start_adapter(struct hdd_adapter *adapter)
 		 * For IBSS interface is initialized as part of
 		 * hdd_init_station_mode()
 		 */
-		return 0;
+		goto exit_with_success;
 	case QDF_FTM_MODE:
-		ret = hdd_start_ftm_adapter(adapter);
-		if (ret)
-			goto err_start_adapter;
-		else
-			goto ftm_complete;
-	break;
+		/* vdevs are dynamically managed by firmware in FTM */
+		goto exit_with_success;
 	default:
 		hdd_err("Invalid session type %d", device_mode);
 		QDF_ASSERT(0);
 		goto err_start_adapter;
 	}
+
 	if (hdd_set_fw_params(adapter))
 		hdd_err("Failed to set the FW params for the adapter!");
 
@@ -2125,9 +2122,11 @@ int hdd_start_adapter(struct hdd_adapter *adapter)
 		goto err_start_adapter;
 	}
 
-ftm_complete:
+exit_with_success:
 	EXIT();
+
 	return 0;
+
 err_start_adapter:
 	return -EINVAL;
 }
@@ -2859,7 +2858,7 @@ static int __hdd_stop(struct net_device *dev)
 	 * Notice that hdd_stop_adapter is requested not to close the session
 	 * That is intentional to be able to scan if it is a STA/P2P interface
 	 */
-	hdd_stop_adapter(hdd_ctx, adapter, true);
+	hdd_stop_adapter(hdd_ctx, adapter);
 
 	/* DeInit the adapter. This ensures datapath cleanup as well */
 	hdd_deinit_adapter(hdd_ctx, adapter, true);
@@ -4554,8 +4553,8 @@ void wlan_hdd_reset_prob_rspies(struct hdd_adapter *adapter)
 	}
 }
 
-QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter,
-			    const bool bCloseSession)
+QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
+			    struct hdd_adapter *adapter)
 {
 	QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
 	struct hdd_wext_state *pWextState =
@@ -4651,19 +4650,14 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *ada
 		if (adapter->device_mode == QDF_STA_MODE)
 			wlan_cfg80211_sched_scan_stop(hdd_ctx->hdd_pdev,
 						      adapter->dev);
-		/*
-		 * It is possible that the caller of this function does not
-		 * wish to close the session
-		 */
-		if (true == bCloseSession) {
-			if (0 != wlan_hdd_try_disconnect(adapter)) {
-				hdd_err("Error: Can't disconnect adapter");
-				return QDF_STATUS_E_FAILURE;
-			}
-			hdd_debug("Destroying adapter: %d",
-				  adapter->session_id);
-			hdd_vdev_destroy(adapter);
+
+		if (wlan_hdd_try_disconnect(adapter)) {
+			hdd_err("Error: Can't disconnect adapter");
+			return QDF_STATUS_E_FAILURE;
 		}
+
+		hdd_vdev_destroy(adapter);
+
 		break;
 
 	case QDF_SAP_MODE:
@@ -4765,11 +4759,9 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *ada
 		cancel_work_sync(&adapter->ipv6_notifier_work);
 #endif
 #endif
-		if (true == bCloseSession) {
-			hdd_debug("Destroying adapter: %d",
-				  adapter->session_id);
-			hdd_vdev_destroy(adapter);
-		}
+
+		hdd_vdev_destroy(adapter);
+
 		mutex_unlock(&hdd_ctx->sap_lock);
 		break;
 	case QDF_OCB_MODE:
@@ -4809,8 +4801,7 @@ void  hdd_deinit_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held)
 	EXIT();
 }
 
-QDF_STATUS hdd_stop_all_adapters(struct hdd_context *hdd_ctx,
-				 bool close_session)
+QDF_STATUS hdd_stop_all_adapters(struct hdd_context *hdd_ctx)
 {
 	struct hdd_adapter *adapter;
 
@@ -4819,7 +4810,7 @@ QDF_STATUS hdd_stop_all_adapters(struct hdd_context *hdd_ctx,
 	cds_flush_work(&hdd_ctx->sap_pre_cac_work);
 
 	hdd_for_each_adapter(hdd_ctx, adapter)
-		hdd_stop_adapter(hdd_ctx, adapter, close_session);
+		hdd_stop_adapter(hdd_ctx, adapter);
 
 	EXIT();
 
@@ -6235,7 +6226,7 @@ static void hdd_wlan_exit(struct hdd_context *hdd_ctx)
 		 */
 		hdd_abort_mac_scan_all_adapters(hdd_ctx);
 		hdd_abort_sched_scan_all_adapters(hdd_ctx);
-		hdd_stop_all_adapters(hdd_ctx, true);
+		hdd_stop_all_adapters(hdd_ctx);
 		hdd_deinit_all_adapters(hdd_ctx, false);
 	}
 
@@ -8396,31 +8387,6 @@ int hdd_start_ap_adapter(struct hdd_adapter *adapter)
 	return 0;
 }
 
-/**
- * hdd_start_ftm_adapter()- Start FTM adapter
- * @adapter: HDD adapter
- *
- * This function initializes the adapter for the FTM mode.
- *
- * Return: 0 on success or errno on failure.
- */
-int hdd_start_ftm_adapter(struct hdd_adapter *adapter)
-{
-	QDF_STATUS qdf_status;
-
-	ENTER_DEV(adapter->dev);
-
-	qdf_status = hdd_init_tx_rx(adapter);
-
-	if (QDF_STATUS_SUCCESS != qdf_status) {
-		hdd_err("Failed to start FTM adapter: %d", qdf_status);
-		return qdf_status_to_os_return(qdf_status);
-	}
-
-	return 0;
-	EXIT();
-}
-
 static int hdd_open_concurrent_interface(struct hdd_context *hdd_ctx,
 								bool rtnl_held)
 {
@@ -11895,9 +11861,8 @@ static void hdd_stop_present_mode(struct hdd_context *hdd_ctx,
 	case QDF_GLOBAL_FTM_MODE:
 		hdd_abort_mac_scan_all_adapters(hdd_ctx);
 		wlan_cfg80211_cleanup_scan_queue(hdd_ctx->hdd_pdev);
+		hdd_stop_all_adapters(hdd_ctx);
 
-		/* re-use the existing session */
-		hdd_stop_all_adapters(hdd_ctx, false);
 		break;
 	default:
 		break;
@@ -12071,16 +12036,13 @@ static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
 		goto reset_flags;
 	}
 
-	if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
-	    con_mode == QDF_GLOBAL_FTM_MODE) {
+	if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
 		if (hdd_start_adapter(adapter)) {
 			hdd_err("Failed to start %s adapter", kmessage);
 			ret = -EINVAL;
 			goto reset_flags;
 		}
-	}
 
-	if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
 		hdd_info("Acquire wakelock for monitor mode!");
 		qdf_wake_lock_acquire(&hdd_ctx->monitor_mode_wakelock,
 				      WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);

+ 2 - 2
core/hdd/src/wlan_hdd_p2p.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -855,7 +855,7 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 	} else {
 		wlan_hdd_release_intf_addr(hdd_ctx,
 					 pVirtAdapter->mac_addr.bytes);
-		hdd_stop_adapter(hdd_ctx, pVirtAdapter, true);
+		hdd_stop_adapter(hdd_ctx, pVirtAdapter);
 		hdd_deinit_adapter(hdd_ctx, pVirtAdapter, true);
 		hdd_close_adapter(hdd_ctx, pVirtAdapter, true);
 	}