Browse Source

qcacld-3.0: hdd: Refactor wlan_startup (phase 2)

In HDD, hdd_wlan_startup which is called by probe is beast of a
function to maintain. Over time it has grown to such an extent
that it is almost 800 lines of code with in a single function.
Divide the beast into logical smaller functions.

Make separate function to open the interfaces at probe time.

Change-Id: Ia0044f5b0d0f009950d62556e09928ac578a1d4b
CRs-fixed: 959287
Prashanth Bhatta 9 years ago
parent
commit
59b4c87e27
3 changed files with 190 additions and 140 deletions
  1. 3 3
      core/hdd/inc/wlan_hdd_main.h
  2. 2 2
      core/hdd/src/wlan_hdd_ftm.c
  3. 185 135
      core/hdd/src/wlan_hdd_main.c

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

@@ -1371,10 +1371,10 @@ CDF_STATUS hdd_add_adapter_front(hdd_context_t *pHddCtx,
 
 hdd_adapter_t *hdd_open_adapter(hdd_context_t *pHddCtx, uint8_t session_type,
 				const char *name, tSirMacAddr macAddr,
-				uint8_t rtnl_held);
+				bool rtnl_held);
 CDF_STATUS hdd_close_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
-			     uint8_t rtnl_held);
-CDF_STATUS hdd_close_all_adapters(hdd_context_t *pHddCtx);
+			     bool rtnl_held);
+CDF_STATUS hdd_close_all_adapters(hdd_context_t *pHddCtx, bool rtnl_held);
 CDF_STATUS hdd_stop_all_adapters(hdd_context_t *pHddCtx);
 CDF_STATUS hdd_reset_all_adapters(hdd_context_t *pHddCtx);
 CDF_STATUS hdd_start_all_adapters(hdd_context_t *pHddCtx);

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

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -659,7 +659,7 @@ int wlan_hdd_ftm_close(hdd_context_t *hdd_ctx)
 		wlan_ftm_stop(hdd_ctx);
 	}
 
-	hdd_close_all_adapters(hdd_ctx);
+	hdd_close_all_adapters(hdd_ctx, false);
 
 	cdf_status = cds_sched_close(cds_context);
 	if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {

+ 185 - 135
core/hdd/src/wlan_hdd_main.c

@@ -1939,14 +1939,14 @@ static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
 }
 
 CDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
-				  uint8_t rtnl_lock_held)
+				  bool rtnl_held)
 {
 	struct net_device *pWlanDev = adapter->dev;
 	/* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
 	/* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
 	/* CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; */
 
-	if (rtnl_lock_held) {
+	if (rtnl_held) {
 		if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
 			if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
 				hddLog(CDF_TRACE_LEVEL_ERROR,
@@ -2234,7 +2234,7 @@ void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
 }
 
 void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
-			 uint8_t rtnl_held)
+			 bool rtnl_held)
 {
 	struct net_device *pWlanDev = NULL;
 
@@ -2291,7 +2291,7 @@ CDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
 }
 hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
 				const char *iface_name, tSirMacAddr macAddr,
-				uint8_t rtnl_held)
+				bool rtnl_held)
 {
 	hdd_adapter_t *adapter = NULL;
 	hdd_adapter_list_node_t *pHddAdapterNode = NULL;
@@ -2673,7 +2673,7 @@ err_free_netdev:
 }
 
 CDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
-			     uint8_t rtnl_held)
+			     bool rtnl_held)
 {
 	hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
 	CDF_STATUS status;
@@ -2711,7 +2711,16 @@ CDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
 	return CDF_STATUS_E_FAILURE;
 }
 
-CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx)
+/**
+ * hdd_close_all_adapters - Close all open adapters
+ * @hdd_ctx:	Hdd context
+ * rtnl_held:	True if RTNL lock held
+ *
+ * Close all open adapters.
+ *
+ * Return: CDF status code
+ */
+CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
 {
 	hdd_adapter_list_node_t *pHddAdapterNode;
 	CDF_STATUS status;
@@ -2722,7 +2731,7 @@ CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx)
 		status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
 		if (pHddAdapterNode && CDF_STATUS_SUCCESS == status) {
 			hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
-					    false);
+					    rtnl_held);
 			cdf_mem_free(pHddAdapterNode);
 		}
 	} while (NULL != pHddAdapterNode && CDF_STATUS_E_EMPTY != status);
@@ -3793,7 +3802,7 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx)
 #endif /* WLAN_KD_READY_NOTIFIER */
 	nl_srv_exit();
 
-	hdd_close_all_adapters(hdd_ctx);
+	hdd_close_all_adapters(hdd_ctx, false);
 
 	hdd_ipa_cleanup(hdd_ctx);
 
@@ -5185,6 +5194,152 @@ err_out:
 	return ERR_PTR(ret);
 }
 
+#ifdef WLAN_OPEN_P2P_INTERFACE
+/**
+ * hdd_open_p2p_interface - Open P2P interface
+ * @hdd_ctx:	HDD context
+ * @rtnl_held:	True if RTNL lock held
+ *
+ * Open P2P interface during probe. This function called to open the P2P
+ * interface at probe along with STA interface.
+ *
+ * Return: 0 on success and errno on failure
+ */
+static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
+{
+	hdd_adapter_t *adapter;
+	uint8_t *p2p_dev_addr;
+
+	if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
+	    !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
+		cdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
+			     hdd_ctx->config->intfMacAddr[0].bytes,
+			     sizeof(tSirMacAddr));
+
+		/*
+		 * Generate the P2P Device Address.  This consists of
+		 * the device's primary MAC address with the locally
+		 * administered bit set.
+		 */
+		hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
+	} else {
+		p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
+		if (p2p_dev_addr == NULL) {
+			hdd_alert("Failed to allocate mac_address for p2p_device");
+			return -ENOSPC;
+		}
+
+		cdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
+			     CDF_MAC_ADDR_SIZE);
+	}
+
+	adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
+				   &hdd_ctx->p2pDeviceAddress.bytes[0],
+				   rtnl_held);
+
+	if (NULL == adapter) {
+		hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
+		return -ENOSPC;
+	}
+
+	return 0;
+}
+#else
+static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx,
+					 bool rtnl_held)
+{
+	return 0;
+}
+#endif
+
+/**
+ * hdd_open_interfaces - Open all required interfaces
+ * hdd_ctx:	HDD context
+ * rtnl_held: True if RTNL lock is held
+ *
+ * Open all the interfaces like STA, P2P and OCB based on the configuration.
+ *
+ * Return: Primary adapter on success and PTR_ERR on failure
+ */
+static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
+					  bool rtnl_held)
+{
+	hdd_adapter_t *adapter = NULL;
+	hdd_adapter_t *adapter_11p = NULL;
+	int ret;
+
+	/* Create only 802.11p interface */
+	if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
+		adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d",
+					   wlan_hdd_get_intf_addr(hdd_ctx),
+					   rtnl_held);
+
+		if (adapter == NULL)
+			return ERR_PTR(-ENOSPC);
+
+		return adapter;
+	}
+
+	adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, "wlan%d",
+				   wlan_hdd_get_intf_addr(hdd_ctx),
+				   rtnl_held);
+
+	if (adapter == NULL)
+		return ERR_PTR(-ENOSPC);
+
+	ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
+	if (ret)
+		goto err_close_adapter;
+
+	/* Open 802.11p Interface */
+	if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
+		adapter_11p = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB,
+					       "wlanocb%d",
+					       wlan_hdd_get_intf_addr(hdd_ctx),
+					       rtnl_held);
+		if (adapter_11p == NULL) {
+			hdd_err("Failed to open 802.11p interface");
+			goto err_close_adapter;
+		}
+	}
+
+	return adapter;
+
+err_close_adapter:
+	hdd_close_all_adapters(hdd_ctx, rtnl_held);
+	return ERR_PTR(ret);
+}
+
+#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
+/**
+ * hdd_hold_rtnl_lock - Hold RTNL lock
+ *
+ * Hold RTNL lock
+ *
+ * Return: True if held and false otherwise
+ */
+static inline bool hdd_hold_rtnl_lock(void)
+{
+	rtnl_lock();
+	return true;
+}
+
+/**
+ * hdd_release_rtnl_lock - Release RTNL lock
+ *
+ * Release RTNL lock
+ *
+ * Return: None
+ */
+static inline void hdd_release_rtnl_lock(void)
+{
+	rtnl_unlock();
+}
+#else
+static inline bool hdd_hold_rtnl_lock(void) { return false; }
+static inline void hdd_release_rtnl_lock(void) { }
+#endif
+
 /**
  * hdd_wlan_startup() - HDD init function
  * @dev:	Pointer to the underlying device
@@ -5197,17 +5352,12 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 {
 	CDF_STATUS status;
 	hdd_adapter_t *adapter = NULL;
-#ifdef WLAN_OPEN_P2P_INTERFACE
-	hdd_adapter_t *pP2adapter = NULL;
-#endif
 	hdd_context_t *hdd_ctx = NULL;
 	int ret;
 	unsigned long rc;
 	tSmeThermalParams thermalParam;
 	tSirTxPowerLimit *hddtxlimit;
-	uint8_t rtnl_lock_enable;
-	uint8_t reg_netdev_notifier_done = false;
-	hdd_adapter_t *dot11_adapter = NULL;
+	bool rtnl_held;
 
 	ENTER();
 
@@ -5365,87 +5515,13 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 	cds_pkt_proto_trace_init();
 #endif /* QCA_PKT_PROTO_TRACE */
 
-#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
-	rtnl_lock();
-	rtnl_lock_enable = true;
-#else
-	rtnl_lock_enable = false;
-#endif
-
-	if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
-		/* Create only 802.11p interface */
-		adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d",
-					   wlan_hdd_get_intf_addr(hdd_ctx),
-					   rtnl_lock_enable);
-	else
-		adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION,
-					   "wlan%d",
-					   wlan_hdd_get_intf_addr(hdd_ctx),
-					   rtnl_lock_enable);
-
-#ifdef WLAN_OPEN_P2P_INTERFACE
-	/* Open P2P device interface */
-	if (adapter != NULL) {
-		if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
-		   !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
-			cdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
-				     hdd_ctx->config->intfMacAddr[0].bytes,
-				     sizeof(tSirMacAddr));
-
-			/*
-			 * Generate the P2P Device Address.  This consists of
-			 * the device's primary MAC address with the locally
-			 * administered bit set.
-			 */
-			hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
-		} else {
-			uint8_t *p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
-			if (p2p_dev_addr != NULL) {
-				cdf_mem_copy(&hdd_ctx->p2pDeviceAddress.
-					     bytes[0], p2p_dev_addr,
-					     CDF_MAC_ADDR_SIZE);
-			} else {
-				hddLog(CDF_TRACE_LEVEL_FATAL,
-				       FL(
-					  "Failed to allocate mac_address for p2p_device"
-					 ));
-				goto err_close_adapter;
-			}
-		}
-
-		pP2adapter =
-			hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
-					 &hdd_ctx->p2pDeviceAddress.bytes[0],
-					 rtnl_lock_enable);
-
-		if (NULL == pP2adapter) {
-			hddLog(CDF_TRACE_LEVEL_FATAL,
-			       FL(
-				  "Failed to do hdd_open_adapter for P2P Device Interface"
-				 ));
-			goto err_close_adapter;
-		}
-	}
-#endif
+	rtnl_held = hdd_hold_rtnl_lock();
 
-	if (adapter == NULL) {
-		hddLog(CDF_TRACE_LEVEL_ERROR, FL("hdd_open_adapter failed"));
-		goto err_close_adapter;
-	}
+	adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
 
-	/* Open 802.11p Interface */
-	if (adapter != NULL) {
-		if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
-			dot11_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB,
-						"wlanocb%d",
-						wlan_hdd_get_intf_addr(hdd_ctx),
-						rtnl_lock_enable);
-			if (dot11_adapter == NULL) {
-				hddLog(LOGE,
-				       FL("failed to open 802.11p Interface"));
-				goto err_close_adapter;
-			}
-		}
+	if (IS_ERR(adapter)) {
+		ret = PTR_ERR(adapter);
+		goto err_cds_disable;
 	}
 
 	/*
@@ -5505,21 +5581,11 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 
 	/* FW capabilities received, Set the Dot11 mode */
 	sme_setdef_dot11mode(hdd_ctx->hHal);
-#if !defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
-	/* register net device notifier for device change notification */
-	ret = register_netdevice_notifier(&hdd_netdev_notifier);
 
-	if (ret < 0) {
-		hddLog(CDF_TRACE_LEVEL_ERROR,
-		       FL("register_netdevice_notifier failed"));
-		goto err_free_power_on_lock;
-	}
-	reg_netdev_notifier_done = true;
-#endif
 	/* Initialize the nlink service */
 	if (nl_srv_init() != 0) {
 		hddLog(CDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed"));
-		goto err_reg_netdev;
+		goto err_close_adapter;
 	}
 #ifdef WLAN_KD_READY_NOTIFIER
 	hdd_ctx->kd_nl_init = 1;
@@ -5558,19 +5624,15 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 
 	mutex_init(&hdd_ctx->sap_lock);
 
-#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
-	if (rtnl_lock_enable == true) {
-		rtnl_lock_enable = false;
-		rtnl_unlock();
-	}
+	hdd_release_rtnl_lock();
+	rtnl_held = false;
+
 	ret = register_netdevice_notifier(&hdd_netdev_notifier);
 	if (ret < 0) {
-		hddLog(CDF_TRACE_LEVEL_ERROR,
-		       FL("register_netdevice_notifier failed"));
+		hdd_err("register_netdevice_notifier failed: %d", ret);
 		goto err_nl_srv;
 	}
-	reg_netdev_notifier_done = true;
-#endif
+
 #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
 	/* Initialize the wake lcok */
 	cdf_wake_lock_init(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
@@ -5605,7 +5667,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 	status = cds_init_policy_mgr();
 	if (!CDF_IS_STATUS_SUCCESS(status)) {
 		hdd_err("Policy manager initialization failed");
-		goto err_nl_srv;
+		goto err_unreg_netdev_notifier;
 	}
 
 	/* Thermal Mitigation */
@@ -5648,7 +5710,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 	if (!hddtxlimit) {
 		hddLog(CDF_TRACE_LEVEL_ERROR,
 		       FL("Memory allocation for TxPowerLimit failed!"));
-		goto err_nl_srv;
+		goto err_unreg_netdev_notifier;
 	}
 	hddtxlimit->txPower2g = hdd_ctx->config->TxPower2g;
 	hddtxlimit->txPower5g = hdd_ctx->config->TxPower5g;
@@ -5718,7 +5780,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 		status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
 		if (status != CDF_STATUS_SUCCESS) {
 			hdd_err("Failed to disable dual mac features");
-			goto err_nl_srv;
+			goto err_unreg_netdev_notifier;
 		}
 	}
 
@@ -5728,6 +5790,9 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 
 	goto success;
 
+err_unreg_netdev_notifier:
+	unregister_netdevice_notifier(&hdd_netdev_notifier);
+
 err_nl_srv:
 #ifdef WLAN_KD_READY_NOTIFIER
 	cnss_diag_notify_wlan_close();
@@ -5740,28 +5805,13 @@ err_nl_srv:
 		hdd_err("Failed to destroy hdd_conc_list_lock");
 		/* Proceed and complete the clean up */
 	}
-err_reg_netdev:
-	if (rtnl_lock_enable == true) {
-		rtnl_lock_enable = false;
-		rtnl_unlock();
-	}
-	if (reg_netdev_notifier_done == true) {
-	unregister_netdevice_notifier(&hdd_netdev_notifier);
-		reg_netdev_notifier_done = false;
-	}
-#if !defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
-err_free_power_on_lock:
-#endif
+
 	hdd_debugfs_exit(hdd_ctx);
 
 err_close_adapter:
-#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
-	if (rtnl_lock_enable == true) {
-		rtnl_lock_enable = false;
-		rtnl_unlock();
-	}
-#endif
-	hdd_close_all_adapters(hdd_ctx);
+	hdd_release_rtnl_lock();
+
+	hdd_close_all_adapters(hdd_ctx, false);
 
 err_cds_disable:
 	cds_disable(hdd_ctx->pcds_context);