浏览代码

qcacld-3.0: Do SSR cleanup during uevent/shutdown based on context

Currently we have two different cleanup approach for SSR. In case of
Adrastea hardware, cleanup can be done during the receipt of FW_DOWN
uevent while in case of HS/HSP it has to be defered to shutdown.

These two approaches are segregated by different branches and thus did
not need to coexist. But as part of future upgrades, a single component
would be used for both the hardware types.

To enable having both these paths, use the context of execution of the
pld_uevent as the differentiating agent. In case of interrupt context,
go with the deferred cleanup and in case of normal process context,
perform the cleanup in pld_uevent itself.

Change-Id: I554a10cdd99b17a6d3e059ebf7a157b0cddb6226
CRs-Fixed: 2669840
Sourav Mohapatra 5 年之前
父节点
当前提交
a777718385
共有 1 个文件被更改,包括 57 次插入21 次删除
  1. 57 21
      core/hdd/src/wlan_hdd_driver_ops.c

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

@@ -58,6 +58,9 @@
 #define SSR_MAX_FAIL_CNT 3
 static uint8_t re_init_fail_cnt, probe_fail_cnt;
 
+/* An atomic flag to check if SSR cleanup has been done or not */
+static qdf_atomic_t is_recovery_cleanup_done;
+
 /*
  * In BMI Phase we are only sending small chunk (256 bytes) of the FW image at
  * a time, and wait for the completion interrupt to start the next transfer.
@@ -753,13 +756,18 @@ static void hdd_psoc_shutdown_notify(struct hdd_context *hdd_ctx)
 	hdd_wlan_ssr_shutdown_event();
 }
 
-static void __hdd_soc_recovery_shutdown(void)
+/**
+ * hdd_soc_recovery_cleanup() - Perform SSR related cleanup activities.
+ *
+ * This function will perform cleanup activities related to when driver
+ * undergoes SSR. Activities inclues stopping idle timer and invoking shutdown
+ * notifier.
+ *
+ * Return: None
+ */
+static void hdd_soc_recovery_cleanup(void)
 {
 	struct hdd_context *hdd_ctx;
-	void *hif_ctx;
-
-	/* recovery starts via firmware down indication; ensure we got one */
-	QDF_BUG(cds_is_driver_recovering());
 
 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
 	if (!hdd_ctx) {
@@ -782,6 +790,35 @@ static void __hdd_soc_recovery_shutdown(void)
 		return;
 	}
 
+	hdd_psoc_shutdown_notify(hdd_ctx);
+}
+
+static void __hdd_soc_recovery_shutdown(void)
+{
+	struct hdd_context *hdd_ctx;
+	void *hif_ctx;
+
+	/* recovery starts via firmware down indication; ensure we got one */
+	QDF_BUG(cds_is_driver_recovering());
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	if (!hdd_ctx) {
+		hdd_err("hdd_ctx is null");
+		return;
+	}
+
+	/*
+	 * Perform SSR related cleanup if it has not already been done as a
+	 * part of receiving the uevent.
+	 */
+	if (!qdf_atomic_read(&is_recovery_cleanup_done))
+		hdd_soc_recovery_cleanup();
+	else
+		qdf_atomic_set(&is_recovery_cleanup_done, 0);
+
+	if (!hdd_wait_for_debugfs_threads_completion())
+		hdd_err("Debufs threads are still pending, attempting SSR anyway");
+
 	hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
 	if (!hif_ctx) {
 		hdd_err("Failed to get HIF context, ignore SSR shutdown");
@@ -791,11 +828,6 @@ static void __hdd_soc_recovery_shutdown(void)
 	/* mask the host controller interrupts */
 	hif_mask_interrupt_call(hif_ctx);
 
-	hdd_psoc_shutdown_notify(hdd_ctx);
-
-	if (!hdd_wait_for_debugfs_threads_completion())
-		hdd_err("Debufs threads are still pending, attempting SSR anyway");
-
 	if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
 		hif_disable_isr(hif_ctx);
 		hdd_wlan_shutdown();
@@ -1720,21 +1752,24 @@ wlan_hdd_pld_uevent(struct device *dev, struct pld_uevent_data *event_data)
 	case PLD_FW_DOWN:
 		hdd_info("Received firmware down indication");
 
-		/* NOTE! SSR cleanup logic goes in pld shutdown, not here */
-
 		cds_set_target_ready(false);
 		cds_set_recovery_in_progress(true);
 
-		/* SSR cleanup happens in pld shutdown, which is serialized by
-		 * the platform driver. Other operations are also serialized by
-		 * platform driver, such as probe, remove, and reinit. If the
-		 * firmware goes down during one of these operations, the driver
-		 * would normally have to wait for a timeout before shutdown
-		 * could begin. Instead, forcefully complete events waiting on
-		 * firmware with a "reset" status to avoid waiting to time out
-		 * on a firmware we already know is down.
+		/*
+		 * In case of some platforms, uevent will come to the driver in
+		 * process context. In that case, it is safe to complete the
+		 * SSR cleanup activities in the same context. In case of
+		 * other platforms, it will be invoked in interrupt context.
+		 * Performing the cleanup in interrupt context is not ideal,
+		 * thus defer the cleanup to be done during
+		 * hdd_soc_recovery_shutdown
 		 */
-		qdf_complete_wait_events();
+		if (qdf_in_interrupt())
+			break;
+
+		hdd_soc_recovery_cleanup();
+		qdf_atomic_set(&is_recovery_cleanup_done, 1);
+
 		break;
 	case PLD_FW_HANG_EVENT:
 		hdd_info("Received fimrware hang event");
@@ -1760,6 +1795,7 @@ wlan_hdd_pld_uevent(struct device *dev, struct pld_uevent_data *event_data)
 		hdd_send_hang_data(hang_evt_data.hang_data,
 				   QDF_HANG_EVENT_DATA_SIZE);
 		qdf_mem_free(hang_evt_data.hang_data);
+
 		break;
 	default:
 		/* other events intentionally not handled */