Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6ea26a7 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cnss2: Allow WLAN driver register after cold boot calibration"

parents 80660953 f6efedba
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -71,8 +71,8 @@ static int cnss_stats_show_state(struct seq_file *s,
		case CNSS_FW_READY:
			seq_puts(s, "FW_READY");
			continue;
		case CNSS_COLD_BOOT_CAL:
			seq_puts(s, "COLD_BOOT_CAL");
		case CNSS_IN_COLD_BOOT_CAL:
			seq_puts(s, "IN_COLD_BOOT_CAL");
			continue;
		case CNSS_DRIVER_LOADING:
			seq_puts(s, "DRIVER_LOADING");
@@ -113,6 +113,9 @@ static int cnss_stats_show_state(struct seq_file *s,
		case CNSS_IN_REBOOT:
			seq_puts(s, "IN_REBOOT");
			continue;
		case CNSS_COLD_BOOT_CAL_DONE:
			seq_puts(s, "COLD_BOOT_CAL_DONE");
			continue;
		}

		seq_printf(s, "UNKNOWN-%d", i);
+29 −11
Original line number Diff line number Diff line
@@ -390,6 +390,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
	if (!plat_priv)
		return -ENODEV;

	cnss_pr_dbg("Processing FW Init Done..\n");
	del_timer(&plat_priv->fw_boot_timer);
	set_bit(CNSS_FW_READY, &plat_priv->driver_state);
	clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
@@ -402,7 +403,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
	if (test_bit(ENABLE_WALTEST, &plat_priv->ctrl_params.quirks)) {
		ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
						    CNSS_WALTEST);
	} else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) {
	} else if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
		cnss_request_antenna_sharing(plat_priv);
		ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
						    CNSS_CALIBRATION);
@@ -1273,19 +1274,30 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
{
	int ret = 0;

	if (test_bit(CNSS_FW_READY, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
		cnss_pr_dbg("Device is already active, ignore calibration\n");
	if (test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state)) {
		cnss_pr_dbg("Calibration complete. Ignore calibration req\n");
		goto out;
	}

	set_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
	if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state) ||
	    test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
		cnss_pr_err("WLAN in mission mode before cold boot calibration\n");
		CNSS_ASSERT(0);
		return -EINVAL;
	}

	set_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
	reinit_completion(&plat_priv->cal_complete);
	ret = cnss_bus_dev_powerup(plat_priv);
	if (ret) {
		complete(&plat_priv->cal_complete);
		clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
		clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
		/* Set CBC done in driver state to mark attempt and note error
		 * since calibration cannot be retried at boot.
		 */
		plat_priv->cal_done = CNSS_CAL_FAILURE;
		set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);
	}

out:
@@ -1297,7 +1309,7 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
{
	struct cnss_cal_info *cal_info = data;

	if (!test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state))
	if (!test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state))
		goto out;

	switch (cal_info->cal_status) {
@@ -1306,7 +1318,9 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
		plat_priv->cal_done = true;
		break;
	case CNSS_CAL_TIMEOUT:
		cnss_pr_dbg("Calibration timed out, force shutdown\n");
	case CNSS_CAL_FAILURE:
		cnss_pr_dbg("Calibration failed. Status: %d, force shutdown\n",
			    cal_info->cal_status);
		break;
	default:
		cnss_pr_err("Unknown calibration status: %u\n",
@@ -1320,7 +1334,8 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
	cnss_bus_dev_shutdown(plat_priv);
	msleep(COLD_BOOT_CAL_SHUTDOWN_DELAY_MS);
	complete(&plat_priv->cal_complete);
	clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
	clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
	set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);

out:
	kfree(data);
@@ -2022,7 +2037,7 @@ static ssize_t fs_ready_store(struct device *dev,
		return count;
	}

	if (fs_ready == FILE_SYSTEM_READY) {
	if (fs_ready == FILE_SYSTEM_READY && plat_priv->cbc_enabled) {
		cnss_driver_event_post(plat_priv,
				       CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
				       0, NULL);
@@ -2179,6 +2194,9 @@ static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
				  "cnss-daemon-support"))
		plat_priv->ctrl_params.quirks |= BIT(ENABLE_DAEMON_SUPPORT);

	plat_priv->cbc_enabled =
		of_property_read_bool(plat_priv->plat_dev->dev.of_node,
				      "qcom,wlan-cbc-enabled");
	plat_priv->ctrl_params.mhi_timeout = CNSS_MHI_TIMEOUT_DEFAULT;
	plat_priv->ctrl_params.mhi_m2_timeout = CNSS_MHI_M2_TIMEOUT_DEFAULT;
	plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT;
+10 −5
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#define CNSS_RDDM_TIMEOUT_MS		20000
#define RECOVERY_TIMEOUT		60000
#define WLAN_WD_TIMEOUT_MS		60000
#define WLAN_COLD_BOOT_CAL_TIMEOUT	60000
#define WLAN_DRIVER_LOAD_TIMEOUT	90000
#define TIME_CLOCK_FREQ_HZ		19200000
#define CNSS_RAMDUMP_MAGIC		0x574C414E
#define CNSS_RAMDUMP_VERSION		0
@@ -218,23 +220,24 @@ enum cnss_driver_event_type {
};

enum cnss_driver_state {
	CNSS_QMI_WLFW_CONNECTED,
	CNSS_QMI_WLFW_CONNECTED = 0,
	CNSS_FW_MEM_READY,
	CNSS_FW_READY,
	CNSS_COLD_BOOT_CAL,
	CNSS_IN_COLD_BOOT_CAL,
	CNSS_DRIVER_LOADING,
	CNSS_DRIVER_UNLOADING,
	CNSS_DRIVER_UNLOADING = 5,
	CNSS_DRIVER_IDLE_RESTART,
	CNSS_DRIVER_IDLE_SHUTDOWN,
	CNSS_DRIVER_PROBED,
	CNSS_DRIVER_RECOVERY,
	CNSS_FW_BOOT_RECOVERY,
	CNSS_FW_BOOT_RECOVERY = 10,
	CNSS_DEV_ERR_NOTIFY,
	CNSS_DRIVER_DEBUG,
	CNSS_COEX_CONNECTED,
	CNSS_IMS_CONNECTED,
	CNSS_IN_SUSPEND_RESUME,
	CNSS_IN_SUSPEND_RESUME = 15,
	CNSS_IN_REBOOT,
	CNSS_COLD_BOOT_CAL_DONE,
};

struct cnss_recovery_data {
@@ -285,6 +288,7 @@ enum cnss_bdf_type {
enum cnss_cal_status {
	CNSS_CAL_DONE,
	CNSS_CAL_TIMEOUT,
	CNSS_CAL_FAILURE,
};

struct cnss_cal_info {
@@ -393,6 +397,7 @@ struct cnss_plat_data {
	u64 dynamic_feature;
	void *get_info_cb_ctx;
	int (*get_info_cb)(void *ctx, void *event, int event_len);
	bool cbc_enabled;
	u8 use_nv_mac;
	u8 set_wlaon_pwr_ctrl;
	struct kobject *shutdown_kobj;
+23 −10
Original line number Diff line number Diff line
@@ -1497,7 +1497,7 @@ int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)

	plat_priv = pci_priv->plat_priv;

	if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
	if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state) ||
	    test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
		cnss_pr_dbg("Skip driver remove\n");
@@ -1843,10 +1843,12 @@ static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv)
		if (ret)
			goto stop_mhi;
	} else if (timeout) {
		if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state))
			timeout = timeout << 1;
		if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state))
			timeout += WLAN_COLD_BOOT_CAL_TIMEOUT;
		else
			timeout += WLAN_DRIVER_LOAD_TIMEOUT;
		mod_timer(&plat_priv->fw_boot_timer,
			  jiffies + msecs_to_jiffies(timeout << 1));
			  jiffies + msecs_to_jiffies(timeout));
	}

	return 0;
@@ -2133,14 +2135,26 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
		return -EEXIST;
	}

	if (!test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state))
	if (!plat_priv->cbc_enabled ||
	    test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state))
		goto register_driver;

	/* If enabled Cold Boot Calibration is the 1st step in init sequence.
	 * CBC is done on file system_ready trigger. Qcacld should be loaded
	 * from init.target.rc after that. Reject qcacld load from
	 * vendor_modprobe.sh at early boot to satisfy this requirement.
	 */
	if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
		cnss_pr_dbg("Start to wait for calibration to complete\n");
	} else {
		cnss_pr_err("Reject WLAN Driver insmod before CBC\n");
		return -EPERM;
	}

	timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev);
	ret = wait_for_completion_timeout(&plat_priv->cal_complete,
					  msecs_to_jiffies(timeout) << 2);
					  WLAN_COLD_BOOT_CAL_TIMEOUT +
					  msecs_to_jiffies(timeout));
	if (!ret) {
		cnss_pr_err("Timeout waiting for calibration to complete\n");
		if (!test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state))
@@ -2156,12 +2170,11 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
				       0, cal_info);
	}

register_driver:
	if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
		cnss_pr_dbg("Reboot or shutdown is in progress, ignore register driver\n");
		return -EINVAL;
	}

register_driver:
	reinit_completion(&plat_priv->power_up_complete);
	ret = cnss_driver_event_post(plat_priv,
				     CNSS_DRIVER_EVENT_REGISTER_DRIVER,
@@ -3222,7 +3235,7 @@ void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
	if (!plat_priv)
		return;

	if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) {
	if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
		cnss_pr_dbg("Ignore FW ready timeout for calibration mode\n");
		return;
	}
+14 −4
Original line number Diff line number Diff line
@@ -78,12 +78,11 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv)

	req->client_id_valid = 1;
	req->client_id = WLFW_CLIENT_ID;
	req->fw_ready_enable_valid = 1;
	req->fw_ready_enable = 1;
	req->request_mem_enable_valid = 1;
	req->request_mem_enable = 1;
	req->fw_mem_ready_enable_valid = 1;
	req->fw_mem_ready_enable = 1;
	/* fw_ready indication is replaced by fw_init_done in HST/HSP */
	req->fw_init_done_enable_valid = 1;
	req->fw_init_done_enable = 1;
	req->pin_connect_result_enable_valid = 1;
@@ -1776,6 +1775,12 @@ static void cnss_wlfw_fw_mem_ready_ind_cb(struct qmi_handle *qmi_wlfw,
			       0, NULL);
}

/**
 * cnss_wlfw_fw_ready_ind_cb: FW ready indication handler (Helium arch)
 *
 * This event is not required for HST/ HSP as FW calibration done is
 * provided in QMI_WLFW_CAL_DONE_IND_V01
 */
static void cnss_wlfw_fw_ready_ind_cb(struct qmi_handle *qmi_wlfw,
				      struct sockaddr_qrtr *sq,
				      struct qmi_txn *txn, const void *data)
@@ -1784,13 +1789,18 @@ static void cnss_wlfw_fw_ready_ind_cb(struct qmi_handle *qmi_wlfw,
		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
	struct cnss_cal_info *cal_info;

	cnss_pr_dbg("Received QMI WLFW FW ready indication\n");

	if (!txn) {
		cnss_pr_err("Spurious indication\n");
		return;
	}

	if (plat_priv->device_id == QCA6390_DEVICE_ID ||
	    plat_priv->device_id == QCA6490_DEVICE_ID) {
		cnss_pr_dbg("Ignore FW Ready Indication for HST/HSP");
		return;
	}

	cnss_pr_dbg("Received QMI WLFW FW ready indication.\n");
	cal_info = kzalloc(sizeof(*cal_info), GFP_KERNEL);
	if (!cal_info)
		return;