Просмотр исходного кода

qcacld-3.0: Cancel iface_idle_work before wma_wmi_stop

When interface change timer expires, wma_wmi_service_close() is
called from hdd_iface_change_callback()->hdd_wlan_stop_modules()
->cds_close(). wmi_handle is made null here. At the same time,
if there is a modem reboot, host will receive early
indication from FW. Due to this, icnss driver sent
ICNSS_UEVENT_FW_DOWN event to host and it calls wmi_stop() again
from icnss_call_driver_uevent()->pld_snoc_uevent()->
wlan_hdd_pld_uevent() -> wlan_hdd_set_the_pld_uevent()->
wma_wmi_stop() -> wmi_stop(). As wmi_handle which was marked
null during wlan stop modules, this causes potential NULL
pointer dereference.

Flush iface_idle_work before wma_wmi_stop and add NULL check
before accessing wmi_handle.

Change-Id: I1bfa8ab7329040c0b5ba989c0d7de7bf7228dd35
CRs-Fixed: 2328575
Pragaspathi Thilagaraj 6 лет назад
Родитель
Сommit
bc5a34bba2
2 измененных файлов с 23 добавлено и 4 удалено
  1. 21 2
      core/hdd/src/wlan_hdd_driver_ops.c
  2. 2 2
      core/wma/src/wma_main.c

+ 21 - 2
core/hdd/src/wlan_hdd_driver_ops.c

@@ -1484,8 +1484,6 @@ static void wlan_hdd_purge_notifier(void)
 		return;
 	}
 
-	qdf_cancel_delayed_work(&hdd_ctx->iface_idle_work);
-
 	mutex_lock(&hdd_ctx->iface_change_lock);
 	cds_shutdown_notifier_call();
 	cds_shutdown_notifier_purge();
@@ -1561,6 +1559,25 @@ static void wlan_hdd_handle_the_pld_uevent(struct pld_uevent_data *uevent)
 	}
 }
 
+/**
+ * wlan_hdd_flush_iface_idle_work() - function to flush the interface idle work
+ * event
+ *
+ * Return:  void
+ */
+static void wlan_hdd_flush_iface_idle_work(void)
+{
+	struct hdd_context *hdd_ctx;
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	if (!hdd_ctx) {
+		hdd_err("hdd context is NULL ");
+		return;
+	}
+
+	qdf_cancel_delayed_work(&hdd_ctx->iface_idle_work);
+}
+
 /**
  * wlan_hdd_pld_uevent() - update driver status
  * @dev: device
@@ -1574,7 +1591,9 @@ static void wlan_hdd_pld_uevent(struct device *dev,
 	hdd_enter();
 	hdd_info("pld event %d", uevent->uevent);
 
+	wlan_hdd_flush_iface_idle_work();
 	wma_wmi_stop();
+
 	wlan_hdd_set_the_pld_uevent(uevent);
 	mutex_lock(&hdd_init_deinit_lock);
 	wlan_hdd_handle_the_pld_uevent(uevent);

+ 2 - 2
core/wma/src/wma_main.c

@@ -3044,9 +3044,9 @@ void wma_wmi_stop(void)
 	tp_wma_handle wma_handle;
 
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
-	if (wma_handle == NULL) {
+	if ((!wma_handle) || (!wma_handle->wmi_handle)) {
 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
-			  "wma_handle is NULL\n");
+			  "wma_handle or wmi_handle is NULL\n");
 		return;
 	}
 	wmi_stop(wma_handle->wmi_handle);