Browse Source

cnss2: Refactor calibration timeout handling

WLAN driver register requires calibration to complete if enabled.
Calibration timeout can happen due to FW or file system mount delay.

Update driver to assert only for calibration timeout due to FW.

In some cases file system mount may take longer if file system repair
is attempted. Thus update cnss platform driver to wait for this
operation to complete and only log the time elapsed.

Change-Id: Iacd4d4565fb05ae1557c94c574c0153b5995b226
Manikandan Mohan 3 years ago
parent
commit
11e6daf9bf
4 changed files with 39 additions and 8 deletions
  1. 5 0
      cnss2/debug.c
  2. 15 5
      cnss2/main.c
  3. 1 0
      cnss2/main.h
  4. 18 3
      cnss2/pci.c

+ 5 - 0
cnss2/debug.c

@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */
+
 
 #include <linux/err.h>
 #include <linux/seq_file.h>
@@ -134,6 +136,9 @@ static int cnss_stats_show_state(struct seq_file *s,
 		case CNSS_PCI_PROBE_DONE:
 			seq_puts(s, "PCI PROBE DONE");
 			continue;
+		case CNSS_DRIVER_REGISTER:
+			seq_puts(s, "DRIVER REGISTERED");
+			continue;
 		}
 
 		seq_printf(s, "UNKNOWN-%d", i);

+ 15 - 5
cnss2/main.c

@@ -1899,7 +1899,7 @@ EXPORT_SYMBOL(cnss_qmi_send);
 static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
 {
 	int ret = 0;
-	u32 retry = 0;
+	u32 retry = 0, timeout;
 
 	if (test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state)) {
 		cnss_pr_dbg("Calibration complete. Ignore calibration req\n");
@@ -1931,6 +1931,15 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
 	}
 
 	set_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
+	if (test_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state)) {
+		timeout = cnss_get_timeout(plat_priv,
+					   CNSS_TIMEOUT_CALIBRATION);
+		cnss_pr_dbg("Restarting calibration %ds timeout\n",
+			    timeout / 1000);
+		if (cancel_delayed_work_sync(&plat_priv->wlan_reg_driver_work))
+			schedule_delayed_work(&plat_priv->wlan_reg_driver_work,
+					      msecs_to_jiffies(timeout));
+	}
 	reinit_completion(&plat_priv->cal_complete);
 	ret = cnss_bus_dev_powerup(plat_priv);
 mark_cal_fail:
@@ -1984,12 +1993,13 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
 
 	if (cal_info->cal_status == CNSS_CAL_DONE) {
 		cnss_cal_mem_upload_to_file(plat_priv);
-		if (cancel_delayed_work_sync(&plat_priv->wlan_reg_driver_work)
-		   ) {
-			cnss_pr_dbg("Schedule WLAN driver load\n");
+		if (!test_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state))
+			goto out;
+
+		cnss_pr_dbg("Schedule WLAN driver load\n");
+		if (cancel_delayed_work_sync(&plat_priv->wlan_reg_driver_work))
 			schedule_delayed_work(&plat_priv->wlan_reg_driver_work,
 					      0);
-		}
 	}
 out:
 	kfree(data);

+ 1 - 0
cnss2/main.h

@@ -314,6 +314,7 @@ enum cnss_driver_state {
 	CNSS_QMI_DMS_CONNECTED = 20,
 	CNSS_DAEMON_CONNECTED,
 	CNSS_PCI_PROBE_DONE,
+	CNSS_DRIVER_REGISTER,
 };
 
 struct cnss_recovery_data {

+ 18 - 3
cnss2/pci.c

@@ -3191,18 +3191,32 @@ static void cnss_wlan_reg_driver_work(struct work_struct *work)
 	container_of(work, struct cnss_plat_data, wlan_reg_driver_work.work);
 	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
 	struct cnss_cal_info *cal_info;
+	unsigned int timeout;
 
 	if (test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state)) {
 		goto reg_driver;
 	} else {
-		cnss_pr_err("Timeout waiting for calibration to complete\n");
-		del_timer(&plat_priv->fw_boot_timer);
 		if (plat_priv->charger_mode) {
 			cnss_pr_err("Ignore calibration timeout in charger mode\n");
 			return;
 		}
-		if (!test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state))
+		if (!test_bit(CNSS_IN_COLD_BOOT_CAL,
+			      &plat_priv->driver_state)) {
+			timeout = cnss_get_timeout(plat_priv,
+						   CNSS_TIMEOUT_CALIBRATION);
+			cnss_pr_dbg("File system not ready to start calibration. Wait for %ds..\n",
+				    timeout / 1000);
+			schedule_delayed_work(&plat_priv->wlan_reg_driver_work,
+					      msecs_to_jiffies(timeout));
+			return;
+		}
+
+		del_timer(&plat_priv->fw_boot_timer);
+		if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state) &&
+		    !test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
+			cnss_pr_err("Timeout waiting for calibration to complete\n");
 			CNSS_ASSERT(0);
+		}
 		cal_info = kzalloc(sizeof(*cal_info), GFP_KERNEL);
 		if (!cal_info)
 			return;
@@ -3274,6 +3288,7 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
 			    plat_priv->device_version.major_version);
 		return -ENODEV;
 	}
+	set_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state);
 
 	if (!plat_priv->cbc_enabled ||
 	    test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state))