Forráskód Böngészése

qcacld-3.0: Handle SSR Reinit failure gracefully

Presently on the re-init failure when the driver tries
to unregister the wiphy during the re_init failure
SSR timeout happens because the wiphy_unregister
would be waiting on the interface opencount to be set
to 0, it would happen only if the netdevice's are de-registered
with the kernel before wiphy_unregister

De-register the interfaces during the reinit failure so that
upper layer is blocked from accessing the driver and also have
a clean rmmod of the driver.

Change-Id: I3d97df19f6c59fcfd1d423d5cc4eae85040d4a97
CRs-Fixed: 2019989
Ashish Kumar Dhanotiya 8 éve
szülő
commit
aa2b17c8d8

+ 1 - 0
core/cds/src/cds_sched.c

@@ -877,6 +877,7 @@ QDF_STATUS cds_sched_close(void *p_cds_context)
 	unregister_hotcpu_notifier(&cds_cpu_hotplug_notifier);
 	gp_cds_sched_context->cpu_hot_plug_notifier = NULL;
 #endif
+	gp_cds_sched_context = NULL;
 	return QDF_STATUS_SUCCESS;
 } /* cds_sched_close() */
 

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

@@ -2361,4 +2361,12 @@ int wlan_hdd_send_mcc_latency(hdd_adapter_t *adapter, int sval);
  */
 hdd_adapter_t *wlan_hdd_get_adapter_from_vdev(struct wlan_objmgr_psoc
 					*psoc, uint8_t vdev_id);
+/**
+ * hdd_unregister_notifiers()- unregister kernel notifiers
+ * @hdd_ctx: Hdd Context
+ *
+ * Unregister netdev notifiers like Netdevice,IPv4 and IPv6.
+ *
+ */
+void hdd_unregister_notifiers(hdd_context_t *hdd_ctx);
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 18 - 18
core/hdd/src/wlan_hdd_main.c

@@ -5098,7 +5098,7 @@ out:
  *
  * Return: None.
  */
-static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
+void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
 {
 	hdd_wlan_unregister_ip6_notifier(hdd_ctx);
 
@@ -5378,9 +5378,9 @@ static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
 	}
 
 	/*
-	 * Close the scheduler before calling cds_close to make sure no thread
-	 * is scheduled after the each module close is called i.e after all the
-	 * data structures are freed.
+	 * Close the scheduler before calling cds_close to make sure
+	 * no thread is scheduled after the each module close is
+	 * is called i.e after all the data structures are freed.
 	 */
 	qdf_status = cds_sched_close(p_cds_context);
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
@@ -5413,10 +5413,15 @@ static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
 
 	wlansap_global_deinit();
 	wlan_hdd_deinit_chan_info(hdd_ctx);
-	wiphy_unregister(wiphy);
-	wlan_hdd_cfg80211_deinit(wiphy);
-
-	hdd_lpass_notify_stop(hdd_ctx);
+	/*
+	 * If there is re_init failure wiphy would have already de-registered
+	 * check the wiphy status before un-registering again
+	 */
+	if (!wiphy && wiphy->registered) {
+		wiphy_unregister(wiphy);
+		wlan_hdd_cfg80211_deinit(wiphy);
+		hdd_lpass_notify_stop(hdd_ctx);
+	}
 
 	hdd_exit_netlink_services(hdd_ctx);
 	mutex_destroy(&hdd_ctx->iface_change_lock);
@@ -6113,10 +6118,11 @@ static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
  */
 void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
 {
-	if (hdd_ctx->hdd_txrx_hist) {
-		qdf_mem_free(hdd_ctx->hdd_txrx_hist);
-		hdd_ctx->hdd_txrx_hist = NULL;
-	}
+	if (!hdd_ctx || hdd_ctx->hdd_txrx_hist == NULL)
+		return;
+
+	qdf_mem_free(hdd_ctx->hdd_txrx_hist);
+	hdd_ctx->hdd_txrx_hist = NULL;
 }
 
 static uint8_t *convert_level_to_string(uint32_t level)
@@ -8810,7 +8816,6 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
 	qdf_device_t qdf_ctx;
 	QDF_STATUS qdf_status;
 	int ret = 0;
-	p_cds_sched_context cds_sched_context = NULL;
 	bool is_idle_stop = !cds_is_driver_unloading() &&
 		!cds_is_driver_recovering();
 	int active_threads;
@@ -8825,11 +8830,6 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
 		return -EINVAL;
 	}
 
-	cds_sched_context = get_cds_sched_ctxt();
-	if (!cds_sched_context) {
-		hdd_err("cds scheduler context NULL");
-		return -EINVAL;
-	}
 	mutex_lock(&hdd_ctx->iface_change_lock);
 	hdd_ctx->stop_modules_in_progress = true;
 

+ 10 - 6
core/hdd/src/wlan_hdd_power.c

@@ -1432,21 +1432,25 @@ err_cds_disable:
 	hdd_wlan_stop_modules(pHddCtx, false);
 
 err_wiphy_unregister:
+	if (bug_on_reinit_failure)
+		QDF_BUG(0);
+
 	if (pHddCtx) {
-		/* Unregister the Net Device Notifier */
-		unregister_netdevice_notifier(&hdd_netdev_notifier);
+		/* Unregister the Notifier's */
+		hdd_unregister_notifiers(pHddCtx);
 		ptt_sock_deactivate_svc();
 		nl_srv_exit();
 
-		/* Free up dynamically allocated members inside HDD Adapter */
-		qdf_mem_free(pHddCtx->config);
-		pHddCtx->config = NULL;
+		hdd_close_all_adapters(pHddCtx, false);
+		wlan_hdd_cfg80211_deinit(pHddCtx->wiphy);
+		hdd_lpass_notify_stop(pHddCtx);
 		wlan_hdd_deinit_tx_rx_histogram(pHddCtx);
 		wiphy_unregister(pHddCtx->wiphy);
-		wiphy_free(pHddCtx->wiphy);
+
 	}
 
 err_re_init:
+	hdd_ssr_timer_del();
 	/* Allow the phone to go to sleep */
 	hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
 	if (bug_on_reinit_failure)