Преглед изворни кода

qcacld-3.0: Handle cleanup during error in add interface

Presently if there is an error during the add interface, closing of adapter
and the stopping of the modules is not handled.

So, close adapter during the failure adding the new virtual interface
and if there are no interfaces running start the interface change
timer callback.

Change-Id: I807bc5b295a7faf369e8a9f1e0958eac869f189f
CRs-Fixed: 1097312
Ashish Kumar Dhanotiya пре 8 година
родитељ
комит
486c13a3fa
3 измењених фајлова са 55 додато и 20 уклоњено
  1. 10 0
      core/hdd/inc/wlan_hdd_main.h
  2. 22 17
      core/hdd/src/wlan_hdd_main.c
  3. 23 3
      core/hdd/src/wlan_hdd_p2p.c

+ 10 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -2199,4 +2199,14 @@ void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx);
  */
 void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx);
 void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit);
+/**
+ * hdd_check_for_opened_interfaces()- Check for interface up
+ * @hdd_ctx: HDD context
+ *
+ * check  if there are any wlan interfaces before starting the timer
+ * to close the modules
+ *
+ * Return: 0 if interface was opened else false
+ */
+bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx);
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 22 - 17
core/hdd/src/wlan_hdd_main.c

@@ -2091,10 +2091,7 @@ static int __hdd_stop(struct net_device *dev)
 {
 	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
 	int ret;
-	bool close_modules = true;
-	QDF_STATUS status;
 
 	ENTER_DEV(dev);
 
@@ -2155,20 +2152,7 @@ static int __hdd_stop(struct net_device *dev)
 	 * Find if any iface is up. If any iface is up then can't put device to
 	 * sleep/power save mode
 	 */
-	status = hdd_get_front_adapter(hdd_ctx, &adapternode);
-	while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
-		if (test_bit(DEVICE_IFACE_OPENED,
-			     &adapternode->pAdapter->event_flags)) {
-			hdd_info("Still other ifaces are up cannot close modules");
-			close_modules = false;
-			break;
-		}
-		status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
-		adapternode = next;
-
-	}
-
-	if (close_modules) {
+	if (hdd_check_for_opened_interfaces(hdd_ctx)) {
 		hdd_info("Closing all modules from the hdd_stop");
 		qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
 				   hdd_ctx->config->iface_change_wait_time
@@ -3999,6 +3983,27 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
 	return QDF_STATUS_SUCCESS;
 }
 
+bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
+{
+	hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
+	QDF_STATUS status;
+	bool close_modules = true;
+
+	status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
+	while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
+		if (test_bit(DEVICE_IFACE_OPENED,
+		    &adapter_node->pAdapter->event_flags)) {
+			hdd_info("Still other ifaces are up cannot close modules");
+			close_modules = false;
+			break;
+		}
+		status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
+		adapter_node = next;
+	}
+
+	return close_modules;
+}
+
 /**
  * hdd_is_interface_up()- Checkfor interface up before ssr
  * @hdd_ctx: HDD context

+ 23 - 3
core/hdd/src/wlan_hdd_p2p.c

@@ -2138,8 +2138,10 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 	 * open the modules.
 	 */
 	ret = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
-	if (ret)
-		return ERR_PTR(ret);
+	if (ret) {
+		hdd_err("Failed to start the wlan_modules");
+		goto close_adapter;
+	}
 
 	/*
 	 * Once the support for session creation/deletion from
@@ -2150,7 +2152,7 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 		ret = hdd_start_adapter(pAdapter);
 		if (ret) {
 			hdd_err("Failed to start %s", name);
-			return ERR_PTR(-EINVAL);
+			goto stop_modules;
 		}
 	}
 
@@ -2159,6 +2161,24 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 
 	EXIT();
 	return pAdapter->dev->ieee80211_ptr;
+
+stop_modules:
+	/*
+	 * Find if any iface is up. If there is not iface which is up
+	 * start the timer to close the modules
+	 */
+	if (hdd_check_for_opened_interfaces(pHddCtx)) {
+		hdd_info("Closing all modules from the add_virt_iface");
+		qdf_mc_timer_start(&pHddCtx->iface_change_timer,
+				   pHddCtx->config->iface_change_wait_time
+				   * 50000);
+	} else
+		hdd_info("Other interfaces are still up dont close modules!");
+
+close_adapter:
+	hdd_close_adapter(pHddCtx, pAdapter, false);
+
+	return ERR_PTR(-EINVAL);
 }
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS)