Parcourir la source

qcacld-3.0: Integrate DSC (vdev create/destroy)

The Driver Synchronization Core (DSC) is a set of synchronization
primitives for use by the driver's orchestration layer. It provides APIs
for ensuring safe state transitions (including bring up and tear down)
of major driver objects: a single driver, associated psocs, and their
associated vdevs.

As part of integrating the DSC APIs into HDD, protect vdev create and
destroy.

Change-Id: I005589da96ed0cdd5f9026ad86dc18a4898b7cdf
CRs-Fixed: 2388123
Dustin Brown il y a 6 ans
Parent
commit
693b535094
3 fichiers modifiés avec 218 ajouts et 186 suppressions
  1. 2 1
      core/hdd/src/wlan_hdd_dsc.c
  2. 160 137
      core/hdd/src/wlan_hdd_main.c
  3. 56 48
      core/hdd/src/wlan_hdd_p2p.c

+ 2 - 1
core/hdd/src/wlan_hdd_dsc.c

@@ -212,7 +212,8 @@ struct hdd_vdev_sync *hdd_vdev_sync_unregister(struct net_device *net_dev)
 
 	hdd_vdev_sync_lock();
 	vdev_sync = hdd_vdev_sync_lookup(net_dev);
-	vdev_sync->net_dev = NULL;
+	if (vdev_sync)
+		vdev_sync->net_dev = NULL;
 	hdd_vdev_sync_unlock();
 
 	return vdev_sync;

+ 160 - 137
core/hdd/src/wlan_hdd_main.c

@@ -5274,13 +5274,21 @@ void hdd_close_adapter(struct hdd_context *hdd_ctx,
 void hdd_close_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held)
 {
 	struct hdd_adapter *adapter;
+	struct hdd_vdev_sync *vdev_sync;
 
 	hdd_enter();
 
 	while (QDF_IS_STATUS_SUCCESS(hdd_remove_front_adapter(hdd_ctx,
 							      &adapter))) {
+		vdev_sync = hdd_vdev_sync_unregister(adapter->dev);
+		if (vdev_sync)
+			hdd_vdev_sync_wait_for_ops(vdev_sync);
+
 		wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes);
 		__hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
+
+		if (vdev_sync)
+			hdd_vdev_sync_destroy(vdev_sync);
 	}
 
 	hdd_exit();
@@ -9284,21 +9292,14 @@ static void hdd_psoc_idle_shutdown(struct hdd_context *hdd_ctx)
 int hdd_psoc_idle_restart(struct hdd_context *hdd_ctx)
 {
 	struct hdd_psoc *hdd_psoc = hdd_ctx->hdd_psoc;
-	QDF_STATUS status;
 	int errno;
 
-	status = dsc_psoc_trans_start_wait(hdd_psoc->dsc_psoc, "idle restart");
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_info("unable to start 'idle restart'; status:%u", status);
-		return qdf_status_to_os_return(status);
-	}
+	QDF_BUG(rtnl_is_locked());
 
 	errno = hdd_wlan_start_modules(hdd_ctx, false);
 	if (!errno)
 		hdd_psoc->state = psoc_state_active;
 
-	dsc_psoc_trans_stop(hdd_psoc->dsc_psoc);
-
 	return errno;
 }
 
@@ -9610,114 +9611,6 @@ err_out:
 	return ERR_PTR(ret);
 }
 
-#ifdef WLAN_OPEN_P2P_INTERFACE
-/**
- * hdd_open_p2p_interface - Open P2P interface
- * @hdd_ctx: HDD context
- *
- * Return: QDF_STATUS
- */
-static QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx)
-{
-	struct hdd_adapter *adapter;
-	bool p2p_dev_addr_admin;
-	bool is_p2p_locally_administered = false;
-
-	cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin);
-
-	if (p2p_dev_addr_admin) {
-		if (hdd_ctx->num_provisioned_addr &&
-		    !(hdd_ctx->provisioned_mac_addr[0].bytes[0] & 0x02)) {
-			hdd_ctx->p2p_device_address =
-					hdd_ctx->provisioned_mac_addr[0];
-
-			/*
-			 * Generate the P2P Device Address.  This consists of
-			 * the device's primary MAC address with the locally
-			 * administered bit set.
-			 */
-
-			hdd_ctx->p2p_device_address.bytes[0] |= 0x02;
-			is_p2p_locally_administered = true;
-		} else if (!(hdd_ctx->derived_mac_addr[0].bytes[0] & 0x02)) {
-			hdd_ctx->p2p_device_address =
-						hdd_ctx->derived_mac_addr[0];
-			/*
-			 * Generate the P2P Device Address.  This consists of
-			 * the device's primary MAC address with the locally
-			 * administered bit set.
-			 */
-			hdd_ctx->p2p_device_address.bytes[0] |= 0x02;
-			is_p2p_locally_administered = true;
-		}
-	}
-	if (!is_p2p_locally_administered) {
-		uint8_t *p2p_dev_addr;
-
-		p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx,
-						      QDF_P2P_DEVICE_MODE);
-		if (!p2p_dev_addr) {
-			hdd_err("Failed to get MAC address for new p2p device");
-			return QDF_STATUS_E_INVAL;
-		}
-
-		qdf_mem_copy(hdd_ctx->p2p_device_address.bytes,
-			     p2p_dev_addr, QDF_MAC_ADDR_SIZE);
-	}
-
-	adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
-				   hdd_ctx->p2p_device_address.bytes,
-				   NET_NAME_UNKNOWN, true);
-	if (!adapter) {
-		hdd_err("Failed to open p2p interface");
-		return QDF_STATUS_E_INVAL;
-	}
-
-	return QDF_STATUS_SUCCESS;
-}
-#else
-static inline QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx)
-{
-	return QDF_STATUS_SUCCESS;
-}
-#endif
-
-static QDF_STATUS hdd_open_ocb_interface(struct hdd_context *hdd_ctx)
-{
-	struct hdd_adapter *adapter;
-
-	adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
-				   wlan_hdd_get_intf_addr(hdd_ctx,
-							  QDF_OCB_MODE),
-				   NET_NAME_UNKNOWN, true);
-	if (!adapter) {
-		hdd_err("Failed to open 802.11p interface");
-		return QDF_STATUS_E_INVAL;
-	}
-
-	return QDF_STATUS_SUCCESS;
-}
-
-static QDF_STATUS hdd_open_concurrent_interface(struct hdd_context *hdd_ctx)
-{
-	struct hdd_adapter *adapter;
-
-	if (qdf_str_eq(hdd_ctx->config->enable_concurrent_sta, ""))
-		return QDF_STATUS_SUCCESS;
-
-	adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE,
-				   hdd_ctx->config->enable_concurrent_sta,
-				   wlan_hdd_get_intf_addr(hdd_ctx,
-							  QDF_STA_MODE),
-				   NET_NAME_UNKNOWN, true);
-	if (!adapter) {
-		hdd_err("Failed to open concurrent station interface");
-		return QDF_STATUS_E_INVAL;
-	}
-
-	return QDF_STATUS_SUCCESS;
-}
-
 /**
  * hdd_start_station_adapter()- Start the Station Adapter
  * @adapter: HDD adapter
@@ -11747,12 +11640,151 @@ static QDF_STATUS wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx)
 }
 #endif
 
+static QDF_STATUS hdd_open_adapter_no_trans(struct hdd_context *hdd_ctx,
+					    enum QDF_OPMODE op_mode,
+					    const char *iface_name,
+					    uint8_t *mac_addr_bytes)
+{
+	struct hdd_vdev_sync *vdev_sync;
+	struct hdd_adapter *adapter;
+	QDF_STATUS status;
+	int errno;
+
+	QDF_BUG(rtnl_is_locked());
+	dsc_psoc_assert_trans_protected(hdd_ctx->hdd_psoc->dsc_psoc);
+
+	errno = hdd_vdev_sync_create(hdd_ctx->wiphy, &vdev_sync);
+	if (errno)
+		return qdf_status_from_os_return(errno);
+
+	adapter = hdd_open_adapter(hdd_ctx, op_mode, iface_name,
+				   mac_addr_bytes, NET_NAME_UNKNOWN, true);
+	if (!adapter) {
+		status = QDF_STATUS_E_INVAL;
+		goto destroy_sync;
+	}
+
+	hdd_vdev_sync_register(adapter->dev, vdev_sync);
+
+	return QDF_STATUS_SUCCESS;
+
+destroy_sync:
+	hdd_vdev_sync_destroy(vdev_sync);
+
+	return status;
+}
+
+#ifdef WLAN_OPEN_P2P_INTERFACE
+/**
+ * hdd_open_p2p_interface - Open P2P interface
+ * @hdd_ctx: HDD context
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx)
+{
+	QDF_STATUS status;
+	bool p2p_dev_addr_admin;
+	bool is_p2p_locally_administered = false;
+
+	cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin);
+
+	if (p2p_dev_addr_admin) {
+		if (hdd_ctx->num_provisioned_addr &&
+		    !(hdd_ctx->provisioned_mac_addr[0].bytes[0] & 0x02)) {
+			hdd_ctx->p2p_device_address =
+					hdd_ctx->provisioned_mac_addr[0];
+
+			/*
+			 * Generate the P2P Device Address.  This consists of
+			 * the device's primary MAC address with the locally
+			 * administered bit set.
+			 */
+
+			hdd_ctx->p2p_device_address.bytes[0] |= 0x02;
+			is_p2p_locally_administered = true;
+		} else if (!(hdd_ctx->derived_mac_addr[0].bytes[0] & 0x02)) {
+			hdd_ctx->p2p_device_address =
+						hdd_ctx->derived_mac_addr[0];
+			/*
+			 * Generate the P2P Device Address.  This consists of
+			 * the device's primary MAC address with the locally
+			 * administered bit set.
+			 */
+			hdd_ctx->p2p_device_address.bytes[0] |= 0x02;
+			is_p2p_locally_administered = true;
+		}
+	}
+	if (!is_p2p_locally_administered) {
+		uint8_t *p2p_dev_addr;
+
+		p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx,
+						      QDF_P2P_DEVICE_MODE);
+		if (!p2p_dev_addr) {
+			hdd_err("Failed to get MAC address for new p2p device");
+			return QDF_STATUS_E_INVAL;
+		}
+
+		qdf_mem_copy(hdd_ctx->p2p_device_address.bytes,
+			     p2p_dev_addr, QDF_MAC_ADDR_SIZE);
+	}
+
+	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_P2P_DEVICE_MODE,
+					   "p2p%d",
+					   hdd_ctx->p2p_device_address.bytes);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to open p2p interface");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static inline QDF_STATUS hdd_open_p2p_interface(struct hdd_context *hdd_ctx)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+static QDF_STATUS hdd_open_ocb_interface(struct hdd_context *hdd_ctx)
+{
+	QDF_STATUS status;
+	uint8_t *mac_addr;
+
+	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_OCB_MODE);
+	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_OCB_MODE,
+					   "wlanocb%d", mac_addr);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Failed to open 802.11p interface");
+
+	return status;
+}
+
+static QDF_STATUS hdd_open_concurrent_interface(struct hdd_context *hdd_ctx)
+{
+	QDF_STATUS status;
+	const char *iface_name;
+	uint8_t *mac_addr;
+
+	if (qdf_str_eq(hdd_ctx->config->enable_concurrent_sta, ""))
+		return QDF_STATUS_SUCCESS;
+
+	iface_name = hdd_ctx->config->enable_concurrent_sta;
+	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE);
+	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE,
+					   iface_name, mac_addr);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Failed to open concurrent station interface");
+
+	return status;
+}
+
 static QDF_STATUS
 hdd_open_adapters_for_mission_mode(struct hdd_context *hdd_ctx)
 {
-	struct hdd_adapter *adapter;
 	enum dot11p_mode dot11p_mode;
 	QDF_STATUS status;
+	uint8_t *mac_addr;
 
 	ucfg_mlme_get_dot11p_mode(hdd_ctx->psoc, &dot11p_mode);
 
@@ -11760,12 +11792,11 @@ hdd_open_adapters_for_mission_mode(struct hdd_context *hdd_ctx)
 	if (dot11p_mode == CFG_11P_STANDALONE)
 		return hdd_open_ocb_interface(hdd_ctx);
 
-	adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
-				   wlan_hdd_get_intf_addr(hdd_ctx,
-							  QDF_STA_MODE),
-				   NET_NAME_UNKNOWN, true);
-	if (!adapter)
-		return QDF_STATUS_E_INVAL;
+	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE);
+	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE,
+					   "wlan%d", mac_addr);
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
 
 	/* opening concurrent STA is best effort, continue on error */
 	hdd_open_concurrent_interface(hdd_ctx);
@@ -11791,27 +11822,19 @@ err_close_adapters:
 
 static QDF_STATUS hdd_open_adapters_for_ftm_mode(struct hdd_context *hdd_ctx)
 {
-	struct hdd_adapter *adapter;
+	uint8_t *mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_FTM_MODE);
 
-	adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
-				   wlan_hdd_get_intf_addr(hdd_ctx,
-							  QDF_FTM_MODE),
-				   NET_NAME_UNKNOWN, true);
-
-	return adapter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL;
+	return hdd_open_adapter_no_trans(hdd_ctx, QDF_FTM_MODE,
+					 "wlan%d", mac_addr);
 }
 
 static QDF_STATUS
 hdd_open_adapters_for_monitor_mode(struct hdd_context *hdd_ctx)
 {
-	struct hdd_adapter *adapter;
-
-	adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
-				   wlan_hdd_get_intf_addr(hdd_ctx,
-							  QDF_MONITOR_MODE),
-				   NET_NAME_UNKNOWN, true);
+	uint8_t *mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_MONITOR_MODE);
 
-	return adapter ? QDF_STATUS_SUCCESS : QDF_STATUS_E_INVAL;
+	return hdd_open_adapter_no_trans(hdd_ctx, QDF_MONITOR_MODE,
+					 "wlan%d", mac_addr);
 }
 
 static QDF_STATUS hdd_open_adapters_for_epping_mode(struct hdd_context *hdd_ctx)

+ 56 - 48
core/hdd/src/wlan_hdd_p2p.c

@@ -24,6 +24,7 @@
  *
  */
 
+#include "wlan_hdd_dsc.h"
 #include <wlan_hdd_includes.h>
 #include <wlan_hdd_hostapd.h>
 #include <net/cfg80211.h>
@@ -739,34 +740,53 @@ close_adapter:
 	return ERR_PTR(-EINVAL);
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
-struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
-					       const char *name,
-					       unsigned char name_assign_type,
-					       enum nl80211_iftype type,
-					       struct vif_params *params)
+static struct wireless_dev *
+_wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
+			   const char *name,
+			   unsigned char name_assign_type,
+			   enum nl80211_iftype type,
+			   u32 *flags,
+			   struct vif_params *params)
 {
 	struct wireless_dev *wdev;
+	struct hdd_vdev_sync *vdev_sync;
+	int errno;
+
+	errno = hdd_vdev_sync_create_with_trans(wiphy, &vdev_sync);
+	if (errno)
+		return ERR_PTR(errno);
 
 	cds_ssr_protect(__func__);
 	wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
-					   type, &params->flags, params);
+					   type, flags, params);
 	cds_ssr_unprotect(__func__);
 
+	if (IS_ERR_OR_NULL(wdev))
+		goto destroy_sync;
+
+	hdd_vdev_sync_register(wdev->netdev, vdev_sync);
+	hdd_vdev_sync_trans_stop(vdev_sync);
+
+	return wdev;
+
+destroy_sync:
+	hdd_vdev_sync_trans_stop(vdev_sync);
+	hdd_vdev_sync_destroy(vdev_sync);
+
 	return wdev;
 }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
+					       const char *name,
+					       unsigned char name_assign_type,
+					       enum nl80211_iftype type,
+					       struct vif_params *params)
+{
+	return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
+					  type, &params->flags, params);
+}
 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS)
-/**
- * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
- * @wiphy: wiphy pointer
- * @name: User-visible name of the interface
- * @name_assign_type: the name of assign type of the netdev
- * @nl80211_iftype: (virtual) interface types
- * @flags: monitor mode configuration flags (not used)
- * @vif_params: virtual interface parameters (not used)
- *
- * Return: the pointer of wireless dev, otherwise ERR_PTR.
- */
 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 					       const char *name,
 					       unsigned char name_assign_type,
@@ -774,41 +794,18 @@ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 					       u32 *flags,
 					       struct vif_params *params)
 {
-	struct wireless_dev *wdev;
-
-	cds_ssr_protect(__func__);
-	wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
-					   type, flags, params);
-	cds_ssr_unprotect(__func__);
-	return wdev;
-
+	return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
+					  type, flags, params);
 }
 #else
-/**
- * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
- * @wiphy: wiphy pointer
- * @name: User-visible name of the interface
- * @nl80211_iftype: (virtual) interface types
- * @flags: monitor mode configuration flags (not used)
- * @vif_params: virtual interface parameters (not used)
- *
- * Return: the pointer of wireless dev, otherwise ERR_PTR.
- */
 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 					       const char *name,
 					       enum nl80211_iftype type,
 					       u32 *flags,
 					       struct vif_params *params)
 {
-	struct wireless_dev *wdev;
-	unsigned char name_assign_type = 0;
-
-	cds_ssr_protect(__func__);
-	wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
-					   type, flags, params);
-	cds_ssr_unprotect(__func__);
-	return wdev;
-
+	return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
+					  type, flags, params);
 }
 #endif
 
@@ -866,13 +863,24 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 
 int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
-	int ret;
+	int errno;
+	struct hdd_vdev_sync *vdev_sync;
+
+	errno = hdd_vdev_sync_trans_start_wait(wdev->netdev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	hdd_vdev_sync_unregister(wdev->netdev);
+	hdd_vdev_sync_wait_for_ops(vdev_sync);
 
 	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
+	errno = __wlan_hdd_del_virtual_intf(wiphy, wdev);
 	cds_ssr_unprotect(__func__);
 
-	return ret;
+	hdd_vdev_sync_trans_stop(vdev_sync);
+	hdd_vdev_sync_destroy(vdev_sync);
+
+	return errno;
 }
 
 /**