Browse Source

Merge 0fcf684c10ff3c1f4bcae162a852bf34c48e246f on remote branch

Change-Id: Id85f57846dd9d3beecc2e5dd13f89e8a08e21d17
Linux Build Service Account 2 years ago
parent
commit
5b2657789c

+ 8 - 0
Kbuild

@@ -70,6 +70,14 @@ ifeq ($(CONFIG_CNSS2_SMMU_DB_SUPPORT),y)
 KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SMMU_DB_SUPPORT
 endif
 
+ifeq ($(CONFIG_CNSS2_ENUM_WITH_LOW_SPEED),y)
+KBUILD_CPPFLAGS += -DCONFIG_CNSS2_ENUM_WITH_LOW_SPEED
+endif
+
+ifeq ($(CONFIG_SLATE_MODULE_ENABLED), y)
+KBUILD_CPPFLAGS += -DSLATE_MODULE_ENABLED
+endif
+
 obj-$(CONFIG_CNSS2) += cnss2/
 obj-$(CONFIG_ICNSS2) += icnss2/
 obj-$(CONFIG_CNSS_GENL) += cnss_genl/

+ 16 - 0
cnss2/Kconfig

@@ -156,3 +156,19 @@ config CNSS_OUT_OF_TREE
 	help
 	  If enabled, CNSS platform driver modules would be able to access
 	  functions from the other modules in the platform driver.
+
+config WCNSS_MEM_PRE_ALLOC
+	tristate "WCNSS pre-alloc memory support"
+	help
+	  Pre-allocate memory for the WLAN driver module.
+	  This feature enable cld wlan driver to use pre allocated memory
+	  for it's internal usage and release it to back to pre allocated pool.
+	  This memory is allocated at the cold boot time.
+
+config CNSS2_ENUM_WITH_LOW_SPEED
+	bool "Enable/Disable enumurate with low speed feature"
+	depends on CNSS2
+	depends on PCI
+	help
+	  Set link target speed to Gen1 before enum, and then restore default
+	  RC speed to re-establish link speed. For Genoa chip, needn't restore.

+ 15 - 0
cnss2/bus.c

@@ -154,6 +154,21 @@ int cnss_bus_load_m3(struct cnss_plat_data *plat_priv)
 	}
 }
 
+int cnss_bus_load_aux(struct cnss_plat_data *plat_priv)
+{
+	if (!plat_priv)
+		return -ENODEV;
+
+	switch (plat_priv->bus_type) {
+	case CNSS_BUS_PCI:
+		return cnss_pci_load_aux(plat_priv->bus_priv);
+	default:
+		cnss_pr_err("Unsupported bus type: %d\n",
+			    plat_priv->bus_type);
+		return -EINVAL;
+	}
+}
+
 int cnss_bus_handle_dev_sol_irq(struct cnss_plat_data *plat_priv)
 {
 	if (!plat_priv)

+ 1 - 0
cnss2/bus.h

@@ -22,6 +22,7 @@ void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
 void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
 				 char *prefix_name, char *name);
 int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
+int cnss_bus_load_aux(struct cnss_plat_data *plat_priv);
 int cnss_bus_handle_dev_sol_irq(struct cnss_plat_data *plat_priv);
 int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv);
 int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv);

+ 103 - 8
cnss2/debug.c

@@ -13,10 +13,33 @@
 
 #define MMIO_REG_ACCESS_MEM_TYPE		0xFF
 #define MMIO_REG_RAW_ACCESS_MEM_TYPE		0xFE
+#define DEFAULT_KERNEL_LOG_LEVEL		INFO_LOG
+#define DEFAULT_IPC_LOG_LEVEL			DEBUG_LOG
+
+enum log_level cnss_kernel_log_level = DEFAULT_KERNEL_LOG_LEVEL;
 
 #if IS_ENABLED(CONFIG_IPC_LOGGING)
 void *cnss_ipc_log_context;
 void *cnss_ipc_log_long_context;
+enum log_level cnss_ipc_log_level = DEFAULT_IPC_LOG_LEVEL;
+
+static int cnss_set_ipc_log_level(u32 val)
+{
+	if (val < MAX_LOG) {
+		cnss_ipc_log_level = val;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static u32 cnss_get_ipc_log_level(void)
+{
+	return cnss_ipc_log_level;
+}
+#else
+static int cnss_set_ipc_log_level(int val) { return -EINVAL; }
+static u32 cnss_get_ipc_log_level(void) { return MAX_LOG; }
 #endif
 
 static int cnss_pin_connect_show(struct seq_file *s, void *data)
@@ -757,7 +780,12 @@ static ssize_t cnss_control_params_debug_write(struct file *fp,
 		plat_priv->ctrl_params.bdf_type = val;
 	else if (strcmp(cmd, "time_sync_period") == 0)
 		plat_priv->ctrl_params.time_sync_period = val;
-	else
+	else if (strcmp(cmd, "kern_log_level") == 0) {
+		if (val < MAX_LOG)
+			cnss_kernel_log_level = val;
+	} else if (strcmp(cmd, "ipc_log_level") == 0) {
+		return cnss_set_ipc_log_level(val) ? -EINVAL : count;
+	} else
 		return -EINVAL;
 
 	return count;
@@ -832,6 +860,7 @@ static int cnss_show_quirks_state(struct seq_file *s,
 static int cnss_control_params_debug_show(struct seq_file *s, void *data)
 {
 	struct cnss_plat_data *cnss_priv = s->private;
+	u32 ipc_log_level;
 
 	seq_puts(s, "\nUsage: echo <params_name> <value> > <debugfs_path>/cnss/control_params\n");
 	seq_puts(s, "<params_name> can be one of below:\n");
@@ -850,6 +879,11 @@ static int cnss_control_params_debug_show(struct seq_file *s, void *data)
 	seq_printf(s, "bdf_type: %u\n", cnss_priv->ctrl_params.bdf_type);
 	seq_printf(s, "time_sync_period: %u\n",
 		   cnss_priv->ctrl_params.time_sync_period);
+	seq_printf(s, "kern_log_level: %u\n", cnss_kernel_log_level);
+
+	ipc_log_level = cnss_get_ipc_log_level();
+	if (ipc_log_level != MAX_LOG)
+		seq_printf(s, "ipc_log_level: %u\n", ipc_log_level);
 
 	return 0;
 }
@@ -1027,7 +1061,8 @@ void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv)
 
 #if IS_ENABLED(CONFIG_IPC_LOGGING)
 void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
-			      const char *log_level, char *fmt, ...)
+			      enum log_level kern_log_level,
+			      enum log_level ipc_log_level, char *fmt, ...)
 {
 	struct va_format vaf;
 	va_list va_args;
@@ -1036,10 +1071,40 @@ void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
 	vaf.fmt = fmt;
 	vaf.va = &va_args;
 
-	if (log_level)
-		printk("%scnss: %pV", log_level, &vaf);
+	if (kern_log_level <= cnss_kernel_log_level) {
+		switch (kern_log_level) {
+		case EMERG_LOG:
+			pr_emerg("cnss: %pV", &vaf);
+			break;
+		case ALERT_LOG:
+			pr_alert("cnss: %pV", &vaf);
+			break;
+		case CRIT_LOG:
+			pr_crit("cnss: %pV", &vaf);
+			break;
+		case ERR_LOG:
+			pr_err("cnss: %pV", &vaf);
+			break;
+		case WARNING_LOG:
+			pr_warn("cnss: %pV", &vaf);
+			break;
+		case NOTICE_LOG:
+			pr_notice("cnss: %pV", &vaf);
+			break;
+		case INFO_LOG:
+			pr_info("cnss: %pV", &vaf);
+			break;
+		case DEBUG_LOG:
+		case DEBUG_HI_LOG:
+			pr_debug("cnss: %pV", &vaf);
+			break;
+		default:
+			break;
+		}
+	}
 
-	ipc_log_string(log_ctx, "[%s] %s: %pV", process, fn, &vaf);
+	if (ipc_log_level <= cnss_ipc_log_level)
+		ipc_log_string(log_ctx, "[%s] %s: %pV", process, fn, &vaf);
 
 	va_end(va_args);
 }
@@ -1080,7 +1145,8 @@ static void cnss_ipc_logging_deinit(void)
 static int cnss_ipc_logging_init(void) { return 0; }
 static void cnss_ipc_logging_deinit(void) {}
 void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
-			      const char *log_level, char *fmt, ...)
+			      enum log_level kern_log_level,
+			      enum log_level ipc_log_level, char *fmt, ...)
 {
 	struct va_format vaf;
 	va_list va_args;
@@ -1089,8 +1155,37 @@ void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
 	vaf.fmt = fmt;
 	vaf.va = &va_args;
 
-	if (log_level)
-		printk("%scnss: %pV", log_level, &vaf);
+	if (kern_log_level <= cnss_kernel_log_level) {
+		switch (kern_log_level) {
+		case EMERG_LOG:
+			pr_emerg("cnss: %pV", &vaf);
+			break;
+		case ALERT_LOG:
+			pr_alert("cnss: %pV", &vaf);
+			break;
+		case CRIT_LOG:
+			pr_crit("cnss: %pV", &vaf);
+			break;
+		case ERR_LOG:
+			pr_err("cnss: %pV", &vaf);
+			break;
+		case WARNING_LOG:
+			pr_warn("cnss: %pV", &vaf);
+			break;
+		case NOTICE_LOG:
+			pr_notice("cnss: %pV", &vaf);
+			break;
+		case INFO_LOG:
+			pr_info("cnss: %pV", &vaf);
+			break;
+		case DEBUG_LOG:
+		case DEBUG_HI_LOG:
+			pr_debug("cnss: %pV", &vaf);
+			break;
+		default:
+			break;
+		}
+	}
 
 	va_end(va_args);
 }

+ 28 - 7
cnss2/debug.h

@@ -1,17 +1,34 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */
 
 #ifndef _CNSS_DEBUG_H
 #define _CNSS_DEBUG_H
 
 #include <linux/printk.h>
 
+enum log_level {
+	EMERG_LOG = 0,
+	ALERT_LOG = 1,
+	CRIT_LOG = 2,
+	ERR_LOG = 3,
+	WARNING_LOG = 4,
+	NOTICE_LOG = 5,
+	INFO_LOG = 6,
+	DEBUG_LOG = 7,
+	DEBUG_HI_LOG = 8,
+	MAX_LOG = 9,
+};
+
+extern enum log_level cnss_kernel_log_level;
+
 #if IS_ENABLED(CONFIG_IPC_LOGGING)
 #include <linux/ipc_logging.h>
 #include <asm/current.h>
 
 extern void *cnss_ipc_log_context;
 extern void *cnss_ipc_log_long_context;
+extern enum log_level cnss_ipc_log_level;
 
 #ifdef CONFIG_CNSS2_DEBUG
 #define CNSS_IPC_LOG_PAGES              100
@@ -35,27 +52,30 @@ extern void *cnss_ipc_log_long_context;
 
 #define cnss_pr_err(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_ERR, _fmt, ##__VA_ARGS__)
+			     ERR_LOG, ERR_LOG, _fmt, ##__VA_ARGS__)
 
 #define cnss_pr_warn(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_WARNING, _fmt, ##__VA_ARGS__)
+			     WARNING_LOG, WARNING_LOG, _fmt, ##__VA_ARGS__)
 
 #define cnss_pr_info(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_INFO, _fmt, ##__VA_ARGS__)
+			     INFO_LOG, INFO_LOG, _fmt, ##__VA_ARGS__)
 
 #define cnss_pr_dbg(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_DEBUG, _fmt, ##__VA_ARGS__)
+			     DEBUG_LOG, DEBUG_LOG, _fmt, ##__VA_ARGS__)
 
 #define cnss_pr_vdbg(_fmt, ...) \
 	cnss_debug_log_long_print(proc_name, __func__, \
-				  KERN_DEBUG, _fmt, ##__VA_ARGS__)
+				  DEBUG_LOG, DEBUG_LOG, _fmt, ##__VA_ARGS__)
 
 #define cnss_pr_buf(_fmt, ...) \
 	cnss_debug_log_long_print(proc_name, __func__, \
-				  NULL, _fmt, ##__VA_ARGS__)
+				  DEBUG_HI_LOG, DEBUG_LOG, _fmt, ##__VA_ARGS__)
+#define cnss_pr_dbg_buf(_fmt, ...) \
+	cnss_debug_log_long_print(proc_name, __func__, \
+				  DEBUG_HI_LOG, DEBUG_HI_LOG, _fmt, ##__VA_ARGS__)
 
 #ifdef CONFIG_CNSS2_DEBUG
 #define CNSS_ASSERT(_condition) do {					\
@@ -83,5 +103,6 @@ void cnss_debug_deinit(void);
 int cnss_debugfs_create(struct cnss_plat_data *plat_priv);
 void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv);
 void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
-			      const char *log_level, char *fmt, ...);
+			      enum log_level kern_log_level,
+			      enum log_level ipc_log_level, char *fmt, ...);
 #endif /* _CNSS_DEBUG_H */

+ 3 - 3
cnss2/genl.c

@@ -95,8 +95,8 @@ static int cnss_genl_send_data(u8 type, char *file_name, u32 total_size,
 	int ret = 0;
 	char filename[CNSS_GENL_STR_LEN_MAX + 1];
 
-	cnss_pr_vdbg("type: %u, file_name %s, total_size: %x, seg_id %u, end %u, data_len %u\n",
-		    type, file_name, total_size, seg_id, end, data_len);
+	cnss_pr_dbg_buf("type: %u, file_name %s, total_size: %x, seg_id %u, end %u, data_len %u\n",
+			type, file_name, total_size, seg_id, end, data_len);
 
 	if (!file_name)
 		strlcpy(filename, "default", sizeof(filename));
@@ -167,7 +167,7 @@ int cnss_genl_send_msg(void *buff, u8 type, char *file_name, u32 total_size)
 	u8 end = 0;
 	u8 retry;
 
-	cnss_pr_vdbg("type: %u, total_size: %x\n", type, total_size);
+	cnss_pr_dbg_buf("type: %u, total_size: %x\n", type, total_size);
 
 	while (remaining) {
 		if (remaining > CNSS_GENL_DATA_LEN_MAX) {

+ 152 - 10
cnss2/main.c

@@ -77,6 +77,7 @@
 #define CNSS_CAL_DB_FILE_NAME "wlfw_cal_db.bin"
 #define CNSS_CAL_START_PROBE_WAIT_RETRY_MAX 100
 #define CNSS_CAL_START_PROBE_WAIT_MS	500
+#define CNSS_TIME_SYNC_PERIOD_INVALID	0xFFFFFFFF
 
 enum cnss_cal_db_op {
 	CNSS_CAL_DB_UPLOAD,
@@ -811,6 +812,23 @@ int cnss_set_pcie_gen_speed(struct device *dev, u8 pcie_gen_speed)
 }
 EXPORT_SYMBOL(cnss_set_pcie_gen_speed);
 
+static bool cnss_is_aux_support_enabled(struct cnss_plat_data *plat_priv)
+{
+	switch (plat_priv->device_id) {
+	case PEACH_DEVICE_ID:
+		if (!plat_priv->fw_aux_uc_support) {
+			cnss_pr_dbg("FW does not support aux uc capability\n");
+			return false;
+		}
+		break;
+	default:
+		cnss_pr_dbg("Host does not support aux uc capability\n");
+		return false;
+	}
+
+	return true;
+}
+
 static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
 {
 	int ret = 0;
@@ -850,6 +868,16 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
 	if (ret)
 		goto out;
 
+	if (cnss_is_aux_support_enabled(plat_priv)) {
+		ret = cnss_bus_load_aux(plat_priv);
+		if (ret)
+			goto out;
+
+		ret = cnss_wlfw_aux_dnld_send_sync(plat_priv);
+		if (ret)
+			goto out;
+	}
+
 	cnss_wlfw_qdss_dnld_send_sync(plat_priv);
 
 	return 0;
@@ -3904,6 +3932,26 @@ static ssize_t time_sync_period_show(struct device *dev,
 			plat_priv->ctrl_params.time_sync_period);
 }
 
+/**
+ * cnss_get_min_time_sync_period_by_vote() - Get minimum time sync period
+ * @plat_priv: Platform data structure
+ *
+ * Result: return minimum time sync period present in vote from wlan and sys
+ */
+uint32_t cnss_get_min_time_sync_period_by_vote(struct cnss_plat_data *plat_priv)
+{
+	unsigned int i, min_time_sync_period = CNSS_TIME_SYNC_PERIOD_INVALID;
+	unsigned int time_sync_period;
+
+	for (i = 0; i < TIME_SYNC_VOTE_MAX; i++) {
+		time_sync_period = plat_priv->ctrl_params.time_sync_period_vote[i];
+		if (min_time_sync_period > time_sync_period)
+			min_time_sync_period = time_sync_period;
+	}
+
+	return min_time_sync_period;
+}
+
 static ssize_t time_sync_period_store(struct device *dev,
 				      struct device_attribute *attr,
 				      const char *buf, size_t count)
@@ -3919,12 +3967,94 @@ static ssize_t time_sync_period_store(struct device *dev,
 		return -EINVAL;
 	}
 
-	if (time_sync_period >= CNSS_MIN_TIME_SYNC_PERIOD)
-		cnss_bus_update_time_sync_period(plat_priv, time_sync_period);
+	if (time_sync_period < CNSS_MIN_TIME_SYNC_PERIOD) {
+		cnss_pr_err("Invalid time sync value\n");
+		return -EINVAL;
+	}
+	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_CNSS] =
+		time_sync_period;
+	time_sync_period = cnss_get_min_time_sync_period_by_vote(plat_priv);
+
+	if (time_sync_period == CNSS_TIME_SYNC_PERIOD_INVALID) {
+		cnss_pr_err("Invalid min time sync value\n");
+		return -EINVAL;
+	}
+
+	cnss_bus_update_time_sync_period(plat_priv, time_sync_period);
 
 	return count;
 }
 
+/**
+ * cnss_update_time_sync_period() - Set time sync period given by driver
+ * @dev: device structure
+ * @time_sync_period: time sync period value
+ *
+ * Update time sync period vote of driver and set minimum of time sync period
+ * from stored vote through wlan and sys config
+ * Result: return 0 for success, error in case of invalid value and no dev
+ */
+int cnss_update_time_sync_period(struct device *dev, uint32_t time_sync_period)
+{
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
+
+	if (!plat_priv)
+		return -ENODEV;
+
+	if (time_sync_period < CNSS_MIN_TIME_SYNC_PERIOD) {
+		cnss_pr_err("Invalid time sync value\n");
+		return -EINVAL;
+	}
+
+	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_WLAN] =
+		time_sync_period;
+	time_sync_period = cnss_get_min_time_sync_period_by_vote(plat_priv);
+
+	if (time_sync_period == CNSS_TIME_SYNC_PERIOD_INVALID) {
+		cnss_pr_err("Invalid min time sync value\n");
+		return -EINVAL;
+	}
+
+	cnss_bus_update_time_sync_period(plat_priv, time_sync_period);
+	return 0;
+}
+EXPORT_SYMBOL(cnss_update_time_sync_period);
+
+/**
+ * cnss_reset_time_sync_period() - Reset time sync period
+ * @dev: device structure
+ *
+ * Update time sync period vote of driver as invalid
+ * and reset minimum of time sync period from
+ * stored vote through wlan and sys config
+ * Result: return 0 for success, error in case of no dev
+ */
+int cnss_reset_time_sync_period(struct device *dev)
+{
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
+	unsigned int time_sync_period = 0;
+
+	if (!plat_priv)
+		return -ENODEV;
+
+	/* Driver vote is set to invalid in case of reset
+	 * In this case, only vote valid to check is sys config
+	 */
+	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_WLAN] =
+		CNSS_TIME_SYNC_PERIOD_INVALID;
+	time_sync_period = cnss_get_min_time_sync_period_by_vote(plat_priv);
+
+	if (time_sync_period == CNSS_TIME_SYNC_PERIOD_INVALID) {
+		cnss_pr_err("Invalid min time sync value\n");
+		return -EINVAL;
+	}
+
+	cnss_bus_update_time_sync_period(plat_priv, time_sync_period);
+
+	return 0;
+}
+EXPORT_SYMBOL(cnss_reset_time_sync_period);
+
 static ssize_t recovery_store(struct device *dev,
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
@@ -4339,12 +4469,6 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
 	timer_setup(&plat_priv->fw_boot_timer,
 		    cnss_bus_fw_boot_timeout_hdlr, 0);
 
-	plat_priv->reboot_nb.notifier_call = cnss_reboot_notifier;
-	ret = register_reboot_notifier(&plat_priv->reboot_nb);
-	if (ret)
-		cnss_pr_err("Failed to register reboot notifier, err = %d\n",
-			    ret);
-
 	ret = device_init_wakeup(&plat_priv->plat_dev->dev, true);
 	if (ret)
 		cnss_pr_err("Failed to init platform device wakeup source, err = %d\n",
@@ -4358,6 +4482,13 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
 	init_completion(&plat_priv->daemon_connected);
 	mutex_init(&plat_priv->dev_lock);
 	mutex_init(&plat_priv->driver_ops_lock);
+
+	plat_priv->reboot_nb.notifier_call = cnss_reboot_notifier;
+	ret = register_reboot_notifier(&plat_priv->reboot_nb);
+	if (ret)
+		cnss_pr_err("Failed to register reboot notifier, err = %d\n",
+			    ret);
+
 	plat_priv->recovery_ws =
 		wakeup_source_register(&plat_priv->plat_dev->dev,
 				       "CNSS_FW_RECOVERY");
@@ -4376,6 +4507,8 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
 	if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
 				  "qcom,rc-ep-short-channel"))
 		cnss_set_feature_list(plat_priv, CNSS_RC_EP_ULTRASHORT_CHANNEL_V01);
+	if (plat_priv->device_id == PEACH_DEVICE_ID)
+		cnss_set_feature_list(plat_priv, CNSS_AUX_UC_SUPPORT_V01);
 
 	return 0;
 }
@@ -4411,6 +4544,14 @@ static void cnss_misc_deinit(struct cnss_plat_data *plat_priv)
 	kfree(plat_priv->on_chip_pmic_board_ids);
 }
 
+static void cnss_init_time_sync_period_default(struct cnss_plat_data *plat_priv)
+{
+	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_WLAN] =
+		CNSS_TIME_SYNC_PERIOD_INVALID;
+	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_CNSS] =
+		CNSS_TIME_SYNC_PERIOD_DEFAULT;
+}
+
 static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
 {
 	plat_priv->ctrl_params.quirks = CNSS_QUIRKS_DEFAULT;
@@ -4424,6 +4565,7 @@ static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
 	plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT;
 	plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT;
 	plat_priv->ctrl_params.time_sync_period = CNSS_TIME_SYNC_PERIOD_DEFAULT;
+	cnss_init_time_sync_period_default(plat_priv);
 	/* Set adsp_pc_enabled default value to true as ADSP pc is always
 	 * enabled by default
 	 */
@@ -4922,8 +5064,8 @@ static int cnss_probe(struct platform_device *plat_dev)
 
 	ret = cnss_get_pld_bus_ops_name(plat_priv);
 	if (ret)
-		cnss_pr_err("Failed to find bus ops name, err = %d\n",
-			    ret);
+		cnss_pr_vdbg("Failed to find bus ops name, err = %d\n",
+			     ret);
 
 	ret = cnss_get_rc_num(plat_priv);
 

+ 16 - 0
cnss2/main.h

@@ -269,6 +269,7 @@ enum cnss_mem_type {
 	CNSS_MEM_M3,
 	CNSS_MEM_CAL_V01,
 	CNSS_MEM_DPD_V01,
+	CNSS_MEM_AUX,
 };
 
 enum cnss_fw_dump_type {
@@ -414,6 +415,18 @@ struct cnss_cal_info {
 	enum cnss_cal_status cal_status;
 };
 
+/**
+ * enum cnss_time_sync_period_vote - to get per vote time sync period
+ * @TIME_SYNC_VOTE_WLAN: WLAN Driver vote
+ * @TIME_SYNC_VOTE_CNSS: sys config vote
+ * @TIME_SYNC_VOTE_MAX
+ */
+enum cnss_time_sync_period_vote {
+	TIME_SYNC_VOTE_WLAN,
+	TIME_SYNC_VOTE_CNSS,
+	TIME_SYNC_VOTE_MAX,
+};
+
 struct cnss_control_params {
 	unsigned long quirks;
 	unsigned int mhi_timeout;
@@ -421,6 +434,7 @@ struct cnss_control_params {
 	unsigned int qmi_timeout;
 	unsigned int bdf_type;
 	unsigned int time_sync_period;
+	unsigned int time_sync_period_vote[TIME_SYNC_VOTE_MAX];
 };
 
 struct cnss_tcs_info {
@@ -535,6 +549,7 @@ struct cnss_plat_data {
 	struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
 	struct cnss_fw_mem m3_mem;
 	struct cnss_fw_mem *cal_mem;
+	struct cnss_fw_mem aux_mem;
 	u64 cal_time;
 	bool cbc_file_download;
 	u32 cal_file_size;
@@ -583,6 +598,7 @@ struct cnss_plat_data {
 	u8 set_wlaon_pwr_ctrl;
 	struct cnss_tcs_info tcs_info;
 	bool fw_pcie_gen_switch;
+	bool fw_aux_uc_support;
 	u64 fw_caps;
 	u8 pcie_gen_speed;
 	struct iommu_domain *audio_iommu_domain;

+ 130 - 6
cnss2/pci.c

@@ -47,6 +47,7 @@
 #define MANGO_PATH_PREFIX		"mango/"
 #define PEACH_PATH_PREFIX		"peach/"
 #define DEFAULT_PHY_M3_FILE_NAME	"m3.bin"
+#define DEFAULT_AUX_FILE_NAME		"aux_ucode.elf"
 #define DEFAULT_PHY_UCODE_FILE_NAME	"phy_ucode.elf"
 #define PHY_UCODE_V2_FILE_NAME		"phy_ucode20.elf"
 #define DEFAULT_FW_FILE_NAME		"amss.bin"
@@ -2210,7 +2211,7 @@ cnss_get_plat_priv_by_driver_ops(struct cnss_wlan_driver *driver_ops)
 		}
 	}
 
-	cnss_pr_err("Invalid cnss driver name from ko %s\n", driver_ops->name);
+	cnss_pr_vdbg("Invalid cnss driver name from ko %s\n", driver_ops->name);
 	/* in the dual wlan card case, the pld_bus_ops_name from dts
 	 * and driver_ops-> name from ko should match, otherwise
 	 * wlanhost driver don't know which plat_env it can use;
@@ -4855,6 +4856,61 @@ void cnss_pci_free_blob_mem(struct cnss_pci_data *pci_priv)
 }
 #endif
 
+int cnss_pci_load_aux(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct cnss_fw_mem *aux_mem = &plat_priv->aux_mem;
+	char filename[MAX_FIRMWARE_NAME_LEN];
+	char *aux_filename = DEFAULT_AUX_FILE_NAME;
+	const struct firmware *fw_entry;
+	int ret = 0;
+
+	if (!aux_mem->va && !aux_mem->size) {
+		cnss_pci_add_fw_prefix_name(pci_priv, filename,
+					    aux_filename);
+
+		ret = firmware_request_nowarn(&fw_entry, filename,
+					      &pci_priv->pci_dev->dev);
+		if (ret) {
+			cnss_pr_err("Failed to load AUX image: %s\n", filename);
+			return ret;
+		}
+
+		aux_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev,
+						fw_entry->size, &aux_mem->pa,
+						GFP_KERNEL);
+		if (!aux_mem->va) {
+			cnss_pr_err("Failed to allocate memory for AUX, size: 0x%zx\n",
+				    fw_entry->size);
+			release_firmware(fw_entry);
+			return -ENOMEM;
+		}
+
+		memcpy(aux_mem->va, fw_entry->data, fw_entry->size);
+		aux_mem->size = fw_entry->size;
+		release_firmware(fw_entry);
+	}
+
+	return 0;
+}
+
+static void cnss_pci_free_aux_mem(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct cnss_fw_mem *aux_mem = &plat_priv->aux_mem;
+
+	if (aux_mem->va && aux_mem->size) {
+		cnss_pr_dbg("Freeing memory for AUX, va: 0x%pK, pa: %pa, size: 0x%zx\n",
+			    aux_mem->va, &aux_mem->pa, aux_mem->size);
+		dma_free_coherent(&pci_priv->pci_dev->dev, aux_mem->size,
+				  aux_mem->va, aux_mem->pa);
+	}
+
+	aux_mem->va = NULL;
+	aux_mem->pa = 0;
+	aux_mem->size = 0;
+}
+
 void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
 {
 	struct cnss_plat_data *plat_priv;
@@ -5540,8 +5596,13 @@ int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
 	if (!test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) ||
 	    test_bit(CNSS_MHI_POWERING_OFF, &pci_priv->mhi_state))
 		return -EINVAL;
-
-	cnss_auto_resume(&pci_priv->pci_dev->dev);
+	/*
+	 * Call pm_runtime_get_sync insteat of auto_resume to get
+	 * reference and make sure runtime_suspend wont get called.
+	 */
+	ret = cnss_pci_pm_runtime_get_sync(pci_priv, RTPM_ID_CNSS);
+	if (ret < 0)
+		goto runtime_pm_put;
 
 	if (!pci_priv->is_smmu_fault)
 		cnss_pci_mhi_reg_dump(pci_priv);
@@ -5550,6 +5611,8 @@ int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
 	ret = cnss_pci_check_link_status(pci_priv);
 	if (ret) {
 		cnss_pci_link_down(&pci_priv->pci_dev->dev);
+		cnss_pci_pm_runtime_mark_last_busy(pci_priv);
+		cnss_pci_pm_runtime_put_autosuspend(pci_priv, RTPM_ID_CNSS);
 		return 0;
 	}
 
@@ -5562,15 +5625,20 @@ int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
 		if (!test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) ||
 		    test_bit(CNSS_MHI_POWERING_OFF, &pci_priv->mhi_state)) {
 			cnss_pr_dbg("MHI is not powered on, ignore RDDM failure\n");
+			cnss_pci_pm_runtime_mark_last_busy(pci_priv);
+			cnss_pci_pm_runtime_put_autosuspend(pci_priv, RTPM_ID_CNSS);
 			return 0;
 		}
 		cnss_fatal_err("Failed to trigger RDDM, err = %d\n", ret);
-		if (!cnss_pci_assert_host_sol(pci_priv))
+		if (!cnss_pci_assert_host_sol(pci_priv)) {
+			cnss_pci_pm_runtime_mark_last_busy(pci_priv);
+			cnss_pci_pm_runtime_put_autosuspend(pci_priv, RTPM_ID_CNSS);
 			return 0;
+		}
 		cnss_pci_dump_debug_reg(pci_priv);
 		cnss_schedule_recovery(&pci_priv->pci_dev->dev,
 				       CNSS_REASON_DEFAULT);
-		return ret;
+		goto runtime_pm_put;
 	}
 
 	if (pci_priv->is_smmu_fault) {
@@ -5583,7 +5651,10 @@ int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
 			  jiffies + msecs_to_jiffies(DEV_RDDM_TIMEOUT));
 	}
 
-	return 0;
+runtime_pm_put:
+	cnss_pci_pm_runtime_mark_last_busy(pci_priv);
+	cnss_pci_pm_runtime_put_autosuspend(pci_priv, RTPM_ID_CNSS);
+	return ret;
 }
 
 static void cnss_pci_add_dump_seg(struct cnss_pci_data *pci_priv,
@@ -6845,6 +6916,54 @@ static void cnss_pci_suspend_pwroff(struct pci_dev *pci_dev)
 	}
 }
 
+#ifdef CONFIG_CNSS2_ENUM_WITH_LOW_SPEED
+static void
+cnss_pci_downgrade_rc_speed(struct cnss_plat_data *plat_priv, u32 rc_num)
+{
+	int ret;
+
+	ret = cnss_pci_set_max_link_speed(plat_priv->bus_priv, rc_num,
+					  PCI_EXP_LNKSTA_CLS_2_5GB);
+	if (ret)
+		cnss_pr_err("Failed to set max PCIe RC%x link speed to Gen1, err = %d\n",
+			     rc_num, ret);
+}
+
+static void
+cnss_pci_restore_rc_speed(struct cnss_pci_data *pci_priv)
+{
+	int ret;
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+	/* if not Genoa, do not restore rc speed */
+	if (pci_priv->device_id != QCN7605_DEVICE_ID) {
+		/* The request 0 will reset maximum GEN speed to default */
+		ret = cnss_pci_set_max_link_speed(pci_priv, plat_priv->rc_num, 0);
+		if (ret)
+			cnss_pr_err("Failed to reset max PCIe RC%x link speed to default, err = %d\n",
+				     plat_priv->rc_num, ret);
+
+		/* suspend/resume will trigger retain to re-establish link speed */
+		ret = cnss_suspend_pci_link(pci_priv);
+		if (ret)
+			cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
+
+		ret = cnss_resume_pci_link(pci_priv);
+		cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
+	}
+}
+#else
+static void
+cnss_pci_downgrade_rc_speed(struct cnss_plat_data *plat_priv, u32 rc_num)
+{
+}
+
+static void
+cnss_pci_restore_rc_speed(struct cnss_pci_data *pci_priv)
+{
+}
+#endif
+
 static int cnss_pci_probe(struct pci_dev *pci_dev,
 			  const struct pci_device_id *id)
 {
@@ -6880,6 +6999,8 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
 	if (plat_priv->use_pm_domain)
 		dev->pm_domain = &cnss_pm_domain;
 
+	cnss_pci_restore_rc_speed(pci_priv);
+
 	ret = cnss_pci_get_dev_cfg_node(plat_priv);
 	if (ret) {
 		cnss_pr_err("Failed to get device cfg node, err = %d\n", ret);
@@ -7001,6 +7122,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
 
 	clear_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state);
 	cnss_pci_unregister_driver_hdlr(pci_priv);
+	cnss_pci_free_aux_mem(pci_priv);
 	cnss_pci_free_m3_mem(pci_priv);
 	cnss_pci_free_fw_mem(pci_priv);
 	cnss_pci_free_qdss_mem(pci_priv);
@@ -7081,6 +7203,8 @@ static int cnss_pci_enumerate(struct cnss_plat_data *plat_priv, u32 rc_num)
 		if (ret && ret != -EPROBE_DEFER)
 			cnss_pr_err("Failed to set max PCIe RC%x link speed to Gen2, err = %d\n",
 				    rc_num, ret);
+	} else {
+		cnss_pci_downgrade_rc_speed(plat_priv, rc_num);
 	}
 
 	cnss_pr_dbg("Trying to enumerate with PCIe RC%x\n", rc_num);

+ 1 - 0
cnss2/pci.h

@@ -255,6 +255,7 @@ int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv);
 void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
 int cnss_pci_load_m3(struct cnss_pci_data *pci_priv);
 void cnss_pci_free_blob_mem(struct cnss_pci_data *pci_priv);
+int cnss_pci_load_aux(struct cnss_pci_data *pci_priv);
 int cnss_pci_handle_dev_sol_irq(struct cnss_pci_data *pci_priv);
 int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv);
 void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);

+ 87 - 6
cnss2/qmi.c

@@ -590,6 +590,10 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
 	if (resp->fw_caps_valid) {
 		plat_priv->fw_pcie_gen_switch =
 			!!(resp->fw_caps & QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01);
+		plat_priv->fw_aux_uc_support =
+			!!(resp->fw_caps & QMI_WLFW_AUX_UC_SUPPORT_V01);
+		cnss_pr_dbg("FW aux uc support capability: %d\n",
+			    plat_priv->fw_aux_uc_support);
 		plat_priv->fw_caps = resp->fw_caps;
 	}
 
@@ -1090,6 +1094,83 @@ out:
 	return ret;
 }
 
+int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv)
+{
+	struct wlfw_aux_uc_info_req_msg_v01 *req;
+	struct wlfw_aux_uc_info_resp_msg_v01 *resp;
+	struct qmi_txn txn;
+	struct cnss_fw_mem *aux_mem = &plat_priv->aux_mem;
+	int ret = 0;
+
+	cnss_pr_dbg("Sending QMI_WLFW_AUX_UC_INFO_REQ_V01 message, state: 0x%lx\n",
+		    plat_priv->driver_state);
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	if (!aux_mem->pa || !aux_mem->size) {
+		cnss_pr_err("Memory for AUX is not available\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cnss_pr_dbg("AUX memory, va: 0x%pK, pa: %pa, size: 0x%zx\n",
+		    aux_mem->va, &aux_mem->pa, aux_mem->size);
+
+	req->addr = plat_priv->aux_mem.pa;
+	req->size = plat_priv->aux_mem.size;
+
+	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
+			   wlfw_aux_uc_info_resp_msg_v01_ei, resp);
+	if (ret < 0) {
+		cnss_pr_err("Failed to initialize txn for QMI_WLFW_AUX_UC_INFO_REQ_V01 request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
+			       QMI_WLFW_AUX_UC_INFO_REQ_V01,
+			       WLFW_AUX_UC_INFO_REQ_MSG_V01_MAX_MSG_LEN,
+			       wlfw_aux_uc_info_req_msg_v01_ei, req);
+	if (ret < 0) {
+		qmi_txn_cancel(&txn);
+		cnss_pr_err("Failed to send QMI_WLFW_AUX_UC_INFO_REQ_V01 request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
+	if (ret < 0) {
+		cnss_pr_err("Failed to wait for response of QMI_WLFW_AUX_UC_INFO_REQ_V01 request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+		cnss_pr_err("QMI_WLFW_AUX_UC_INFO_REQ_V01 request failed, result: %d, err: %d\n",
+			    resp->resp.result, resp->resp.error);
+		ret = -resp->resp.result;
+		goto out;
+	}
+
+	kfree(req);
+	kfree(resp);
+	return 0;
+
+out:
+	CNSS_QMI_ASSERT();
+	kfree(req);
+	kfree(resp);
+	return ret;
+}
+
 int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv,
 				     u8 *mac, u32 mac_len)
 {
@@ -2837,9 +2918,9 @@ static void cnss_wlfw_fw_mem_file_save_ind_cb(struct qmi_handle *qmi_wlfw,
 		cnss_pr_err("Spurious indication\n");
 		return;
 	}
-	cnss_pr_dbg("QMI fw_mem_file_save: source: %d  mem_seg: %d type: %u len: %u\n",
-		    ind_msg->source, ind_msg->mem_seg_valid,
-		    ind_msg->mem_seg[0].type, ind_msg->mem_seg_len);
+	cnss_pr_dbg_buf("QMI fw_mem_file_save: source: %d  mem_seg: %d type: %u len: %u\n",
+			ind_msg->source, ind_msg->mem_seg_valid,
+			ind_msg->mem_seg[0].type, ind_msg->mem_seg_len);
 
 	event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
 	if (!event_data)
@@ -2861,9 +2942,9 @@ static void cnss_wlfw_fw_mem_file_save_ind_cb(struct qmi_handle *qmi_wlfw,
 				cnss_pr_err("FW Mem file save ind cannot have multiple mem types\n");
 				goto free_event_data;
 			}
-			cnss_pr_dbg("seg-%d: addr 0x%llx size 0x%x\n",
-				    i, ind_msg->mem_seg[i].addr,
-				    ind_msg->mem_seg[i].size);
+			cnss_pr_dbg_buf("seg-%d: addr 0x%llx size 0x%x\n",
+					i, ind_msg->mem_seg[i].addr,
+					ind_msg->mem_seg[i].size);
 		}
 	}
 

+ 7 - 1
cnss2/qmi.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 
@@ -45,6 +45,7 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
 				 u32 bdf_type);
 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
+int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
 				  enum cnss_driver_mode mode);
 int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
@@ -145,6 +146,11 @@ static inline int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
 	return 0;
 }
 
+static inline int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
 static inline
 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
 				  enum cnss_driver_mode mode)

+ 18 - 1
cnss_prealloc/cnss_prealloc.c

@@ -85,6 +85,14 @@ static struct cnss_pool cnss_pools_adrastea[] = {
 	{128 * 1024, 2, "cnss-pool-128k", NULL, NULL},
 };
 
+static struct cnss_pool cnss_pools_wcn6750[] = {
+	{8 * 1024, 2, "cnss-pool-8k", NULL, NULL},
+	{16 * 1024, 8, "cnss-pool-16k", NULL, NULL},
+	{32 * 1024, 11, "cnss-pool-32k", NULL, NULL},
+	{64 * 1024, 15, "cnss-pool-64k", NULL, NULL},
+	{128 * 1024, 4, "cnss-pool-128k", NULL, NULL},
+};
+
 struct cnss_pool *cnss_pools;
 unsigned int cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_default);
 
@@ -161,6 +169,9 @@ static void cnss_pool_deinit(void)
 {
 	int i;
 
+	if (!cnss_pools)
+		return;
+
 	for (i = 0; i < cnss_prealloc_pool_size; i++) {
 		pr_info("cnss_prealloc: destroy mempool %s\n",
 			cnss_pools[i].name);
@@ -181,6 +192,9 @@ void cnss_assign_prealloc_pool(unsigned long device_id)
 		cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_adrastea);
 		break;
 	case WCN6750_DEVICE_ID:
+		cnss_pools = cnss_pools_wcn6750;
+		cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_wcn6750);
+		break;
 	case WCN6450_DEVICE_ID:
 	case QCA6390_DEVICE_ID:
 	case QCA6490_DEVICE_ID:
@@ -287,6 +301,9 @@ void *wcnss_prealloc_get(size_t size)
 	gfp_t gfp_mask = __GFP_ZERO;
 	int i;
 
+	if (!cnss_pools)
+		return mem;
+
 	if (in_interrupt() || !preemptible() || rcu_preempt_depth())
 		gfp_mask |= GFP_ATOMIC;
 	else
@@ -326,7 +343,7 @@ int wcnss_prealloc_put(void *mem)
 {
 	int i;
 
-	if (!mem)
+	if (!mem || !cnss_pools)
 		return 0;
 
 	i = cnss_pool_get_index(mem);

+ 12 - 1
cnss_utils/cnss_plat_ipc_qmi.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -26,6 +26,8 @@
 #define QMI_INIT_RETRY_MAX_TIMES 240
 #define QMI_INIT_RETRY_DELAY_MS 250
 #define NUM_LOG_PAGES			10
+#define CNSS_DAEMON_CFG_WAIT_RETRY	200
+#define CNSS_DAEMON_CFG_WAIT_MS	50
 
 /**
  * struct cnss_plat_ipc_file_data: File transfer context data
@@ -591,6 +593,7 @@ cnss_plat_ipc_qmi_init_setup_req_handler(struct qmi_handle *handle,
 	cfg->dms_mac_addr_supported = req_msg->dms_mac_addr_supported;
 	cfg->qdss_hw_trace_override = req_msg->qdss_hw_trace_override;
 	cfg->cal_file_available_bitmask = req_msg->cal_file_available_bitmask;
+	cfg->initialized = 1;
 
 	ret = qmi_send_response
 		(svc->svc_hdl, sq, txn,
@@ -776,6 +779,7 @@ static struct qmi_msg_handler cnss_plat_ipc_qmi_req_handlers[] = {
  */
 struct cnss_plat_ipc_daemon_config *cnss_plat_ipc_qmi_daemon_config(void)
 {
+	int i;
 	struct cnss_plat_ipc_qmi_svc_ctx *svc = &plat_ipc_qmi_svc;
 	struct cnss_plat_ipc_qmi_client_ctx *qmi_client =
 		&svc->qmi_client_ctx[CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01];
@@ -783,6 +787,13 @@ struct cnss_plat_ipc_daemon_config *cnss_plat_ipc_qmi_daemon_config(void)
 	if (!qmi_client->client_connected)
 		return NULL;
 
+	for (i = 0; i < CNSS_DAEMON_CFG_WAIT_RETRY; i++) {
+		if (daemon_cfg.initialized == 1)
+			break;
+
+		msleep(CNSS_DAEMON_CFG_WAIT_MS);
+	}
+
 	return &daemon_cfg;
 }
 EXPORT_SYMBOL(cnss_plat_ipc_qmi_daemon_config);

+ 5 - 1
cnss_utils/cnss_plat_ipc_qmi.h

@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
 
 #ifndef _CNSS_PLAT_IPC_QMI_H
 #define _CNSS_PLAT_IPC_QMI_H
@@ -15,11 +17,13 @@
 
 /**
  * cnss_plat_ipc_daemon_config: Config options provided by cnss-daemon
+ * @initialized: Set when daemon configs are initialized
  * @dms_mac_addr_supported: DMS MAC address provisioning support
  * @qdss_hw_trace_override: QDSS config for HW trace enable
  * @cal_file_available_bitmask: Calibration file available
  */
 struct cnss_plat_ipc_daemon_config {
+	u8 initialized;
 	u8 dms_mac_addr_supported;
 	u8 qdss_hw_trace_override;
 	u32 cal_file_available_bitmask;

+ 181 - 0
cnss_utils/wlan_firmware_service_v01.c

@@ -621,6 +621,46 @@ static struct qmi_elem_info wlfw_host_mlo_chip_info_s_v01_ei[] = {
 	},
 };
 
+static struct qmi_elem_info wlfw_host_mlo_chip_v2_info_s_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct wlfw_host_mlo_chip_info_s_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct
+					   wlfw_host_mlo_chip_v2_info_s_v01,
+					   mlo_chip_info),
+		.ei_array      = wlfw_host_mlo_chip_info_s_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct
+					   wlfw_host_mlo_chip_v2_info_s_v01,
+					   adj_mlo_num_chips),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_WLFW_MAX_NUM_ADJ_MLO_CHIPS_V01,
+		.elem_size      = sizeof(struct wlfw_host_mlo_chip_info_s_v01),
+		.array_type       = STATIC_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct
+					   wlfw_host_mlo_chip_v2_info_s_v01,
+					   adj_mlo_chip_info),
+		.ei_array      = wlfw_host_mlo_chip_info_s_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
 static struct qmi_elem_info wlfw_pmu_param_v01_ei[] = {
 	{
 		.data_type      = QMI_UNSIGNED_1_BYTE,
@@ -2162,6 +2202,46 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = {
 					   wlfw_cap_resp_msg_v01,
 					   rxgainlut_support),
 	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x26,
+		.offset         = offsetof(struct
+					   wlfw_cap_resp_msg_v01,
+					   he_channel_width_cap_valid),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wlfw_he_channel_width_cap_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x26,
+		.offset         = offsetof(struct
+					   wlfw_cap_resp_msg_v01,
+					   he_channel_width_cap),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x27,
+		.offset         = offsetof(struct
+					   wlfw_cap_resp_msg_v01,
+					   phy_qam_cap_valid),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wlfw_phy_qam_cap_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x27,
+		.offset         = offsetof(struct
+					   wlfw_cap_resp_msg_v01,
+					   phy_qam_cap),
+	},
 	{
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
@@ -3961,6 +4041,27 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
 					   wlfw_host_cap_req_msg_v01,
 					   fw_ini_cfg_support),
 	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x2F,
+		.offset         = offsetof(struct
+					   wlfw_host_cap_req_msg_v01,
+					   mlo_chip_v2_info_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_WLFW_MAX_NUM_MLO_V2_CHIPS_V01,
+		.elem_size      = sizeof(struct wlfw_host_mlo_chip_v2_info_s_v01),
+		.array_type       = STATIC_ARRAY,
+		.tlv_type       = 0x2F,
+		.offset         = offsetof(struct
+					   wlfw_host_cap_req_msg_v01,
+					   mlo_chip_v2_info),
+		.ei_array      = wlfw_host_mlo_chip_v2_info_s_v01_ei,
+	},
 	{
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
@@ -6244,6 +6345,26 @@ struct qmi_elem_info wlfw_phy_cap_resp_msg_v01_ei[] = {
 					   wlfw_phy_cap_resp_msg_v01,
 					   board_id),
 	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x12,
+		.offset         = offsetof(struct
+					   wlfw_phy_cap_resp_msg_v01,
+					   mlo_cap_v2_support_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x12,
+		.offset         = offsetof(struct
+					   wlfw_phy_cap_resp_msg_v01,
+					   mlo_cap_v2_support),
+	},
 	{
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
@@ -6389,6 +6510,65 @@ struct qmi_elem_info wlfw_aux_uc_info_resp_msg_v01_ei[] = {
 };
 EXPORT_SYMBOL(wlfw_aux_uc_info_resp_msg_v01_ei);
 
+struct qmi_elem_info wlfw_tme_lite_info_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wlfw_tme_lite_file_type_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct
+					   wlfw_tme_lite_info_req_msg_v01,
+					   tme_file),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct
+					   wlfw_tme_lite_info_req_msg_v01,
+					   addr),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x03,
+		.offset         = offsetof(struct
+					   wlfw_tme_lite_info_req_msg_v01,
+					   size),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_tme_lite_info_req_msg_v01_ei);
+
+struct qmi_elem_info wlfw_tme_lite_info_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct
+					   wlfw_tme_lite_info_resp_msg_v01,
+					   resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_tme_lite_info_resp_msg_v01_ei);
+
 /**
  * wlfw_is_valid_dt_node_found - Check if valid device tree node present
  *
@@ -6419,6 +6599,7 @@ static int __init wlfw_init(void)
 
 	return 0;
 }
+
 module_init(wlfw_init);
 
 MODULE_LICENSE("GPL v2");

+ 60 - 3
cnss_utils/wlan_firmware_service_v01.h

@@ -56,6 +56,7 @@
 #define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025
 #define QMI_WLFW_REJUVENATE_ACK_RESP_V01 0x003A
 #define QMI_WLFW_MSA_INFO_RESP_V01 0x002D
+#define QMI_WLFW_TME_LITE_INFO_RESP_V01 0x005B
 #define QMI_WLFW_SHUTDOWN_REQ_V01 0x0043
 #define QMI_WLFW_VBATT_REQ_V01 0x0032
 #define QMI_WLFW_PCIE_LINK_CTRL_REQ_V01 0x0059
@@ -108,14 +109,17 @@
 #define QMI_WLFW_WLAN_HW_INIT_CFG_RESP_V01 0x0058
 #define QMI_WLFW_INI_FILE_DOWNLOAD_REQ_V01 0x0056
 #define QMI_WLFW_QDSS_TRACE_FREE_IND_V01 0x0046
+#define QMI_WLFW_TME_LITE_INFO_REQ_V01 0x005B
 #define QMI_WLFW_QDSS_MEM_READY_IND_V01 0x0052
 
 #define QMI_WLFW_MAX_NUM_CAL_V01 5
 #define QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 64
 #define QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01 3
+#define QMI_WLFW_MAX_NUM_ADJ_MLO_CHIPS_V01 2
 #define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24
 #define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128
 #define QMI_WLFW_MAX_DEV_MEM_NUM_V01 4
+#define QMI_WLFW_MAX_NUM_MLO_V2_CHIPS_V01 4
 #define QMI_WLFW_MAX_NUM_SHARE_MEM_V01 8
 #define QMI_WLFW_MAX_NUM_MLO_LINKS_PER_CHIP_V01 2
 #define QMI_WLFW_MAX_NUM_SVC_V01 24
@@ -246,6 +250,22 @@ enum wlfw_rd_card_chain_cap_v01 {
 	WLFW_RD_CARD_CHAIN_CAP_MAX_VAL_V01 = INT_MAX,
 };
 
+enum wlfw_he_channel_width_cap_v01 {
+	WLFW_HE_CHANNEL_WIDTH_CAP_MIN_VAL_V01 = INT_MIN,
+	WLFW_PHY_HE_CHANNEL_WIDTH_CAP_UNSPECIFIED_V01 = 0,
+	WLFW_PHY_HE_CHANNEL_WIDTH_CAP_80MHZ_V01 = 1,
+	WLFW_PHY_HE_CHANNEL_WIDTH_CAP_160MHZ_V01 = 2,
+	WLFW_HE_CHANNEL_WIDTH_CAP_MAX_VAL_V01 = INT_MAX,
+};
+
+enum wlfw_phy_qam_cap_v01 {
+	WLFW_PHY_QAM_CAP_MIN_VAL_V01 = INT_MIN,
+	WLFW_PHY_QAM_CAP_UNSPECIFIED_V01 = 0,
+	WLFW_PHY_QAM_CAP_1K_V01 = 1,
+	WLFW_PHY_QAM_CAP_4K_V01 = 2,
+	WLFW_PHY_QAM_CAP_MAX_VAL_V01 = INT_MAX,
+};
+
 enum wlfw_pcie_gen_speed_v01 {
 	WLFW_PCIE_GEN_SPEED_MIN_VAL_V01 = INT_MIN,
 	QMI_PCIE_GEN_SPEED_INVALID_V01 = 0,
@@ -325,6 +345,15 @@ enum wlfw_pcie_link_state_enum_v01 {
 	WLFW_PCIE_LINK_STATE_ENUM_MAX_VAL_V01 = INT_MAX,
 };
 
+enum wlfw_tme_lite_file_type_v01 {
+	WLFW_TME_LITE_FILE_TYPE_MIN_VAL_V01 = INT_MIN,
+	WLFW_TME_LITE_PATCH_FILE_V01 = 0,
+	WLFW_TME_LITE_OEM_FUSE_FILE_V01 = 1,
+	WLFW_TME_LITE_RPR_FILE_V01 = 2,
+	WLFW_TME_LITE_DPR_FILE_V01 = 3,
+	WLFW_TME_LITE_FILE_TYPE_MAX_VAL_V01 = INT_MAX,
+};
+
 #define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
 #define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
 #define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
@@ -448,6 +477,12 @@ struct wlfw_host_mlo_chip_info_s_v01 {
 	u8 valid_mlo_link_id[QMI_WLFW_MAX_NUM_MLO_LINKS_PER_CHIP_V01];
 };
 
+struct wlfw_host_mlo_chip_v2_info_s_v01 {
+	struct wlfw_host_mlo_chip_info_s_v01 mlo_chip_info;
+	u8 adj_mlo_num_chips;
+	struct wlfw_host_mlo_chip_info_s_v01 adj_mlo_chip_info[QMI_WLFW_MAX_NUM_ADJ_MLO_CHIPS_V01];
+};
+
 struct wlfw_pmu_param_v01 {
 	u8 pin_name[QMI_WLFW_PMU_PIN_NAME_MAX_LEN_V01];
 	u32 wake_volt_valid;
@@ -653,8 +688,12 @@ struct wlfw_cap_resp_msg_v01 {
 	u8 regdb_support;
 	u8 rxgainlut_support_valid;
 	u8 rxgainlut_support;
+	u8 he_channel_width_cap_valid;
+	enum wlfw_he_channel_width_cap_v01 he_channel_width_cap;
+	u8 phy_qam_cap_valid;
+	enum wlfw_phy_qam_cap_v01 phy_qam_cap;
 };
-#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 1146
+#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 1160
 extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[];
 
 struct wlfw_bdf_download_req_msg_v01 {
@@ -935,8 +974,10 @@ struct wlfw_host_cap_req_msg_v01 {
 	u32 gpio_info[QMI_WLFW_MAX_NUM_GPIO_INFO_V01];
 	u8 fw_ini_cfg_support_valid;
 	u8 fw_ini_cfg_support;
+	u8 mlo_chip_v2_info_valid;
+	struct wlfw_host_mlo_chip_v2_info_s_v01 mlo_chip_v2_info[QMI_WLFW_MAX_NUM_MLO_V2_CHIPS_V01];
 };
-#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 491
+#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 570
 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
 
 struct wlfw_host_cap_resp_msg_v01 {
@@ -1400,8 +1441,10 @@ struct wlfw_phy_cap_resp_msg_v01 {
 	u8 num_phy;
 	u8 board_id_valid;
 	u32 board_id;
+	u8 mlo_cap_v2_support_valid;
+	u32 mlo_cap_v2_support;
 };
-#define WLFW_PHY_CAP_RESP_MSG_V01_MAX_MSG_LEN 18
+#define WLFW_PHY_CAP_RESP_MSG_V01_MAX_MSG_LEN 25
 extern struct qmi_elem_info wlfw_phy_cap_resp_msg_v01_ei[];
 
 struct wlfw_wlan_hw_init_cfg_req_msg_v01 {
@@ -1442,4 +1485,18 @@ struct wlfw_aux_uc_info_resp_msg_v01 {
 #define WLFW_AUX_UC_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
 extern struct qmi_elem_info wlfw_aux_uc_info_resp_msg_v01_ei[];
 
+struct wlfw_tme_lite_info_req_msg_v01 {
+	enum wlfw_tme_lite_file_type_v01 tme_file;
+	u64 addr;
+	u32 size;
+};
+#define WLFW_TME_LITE_INFO_REQ_MSG_V01_MAX_MSG_LEN 25
+extern struct qmi_elem_info wlfw_tme_lite_info_req_msg_v01_ei[];
+
+struct wlfw_tme_lite_info_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+#define WLFW_TME_LITE_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wlfw_tme_lite_info_resp_msg_v01_ei[];
+
 #endif

+ 15 - 0
icnss2/Kconfig

@@ -36,3 +36,18 @@ config CNSS_QCA6750
 	  CNSS QCA6750 chipset.
 	  These changes are needed to support the new hardware architecture
 	  for CNSS QCA6750 chipset.
+
+config CNSS_OUT_OF_TREE
+	bool "Enable Out of Tree Usage"
+	depends on ICNSS2
+	help
+	  If enabled, ICNSS platform driver modules would be able to access
+	  functions from the other modules in the platform driver.
+
+config WCNSS_MEM_PRE_ALLOC
+	tristate "WCNSS pre-alloc memory support"
+	help
+	  Pre-allocate memory for the WLAN driver module.
+	  This feature enable cld wlan driver to use pre allocated memory
+	  for it's internal usage and release it to back to pre allocated pool.
+	  This memory is allocated at the cold boot time.

+ 3 - 0
icnss2/debug.c

@@ -423,6 +423,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
 		case ICNSS_SLATE_UP:
 			seq_puts(s, "ICNSS SLATE UP");
 			continue;
+		case ICNSS_SLATE_READY:
+			seq_puts(s, "ICNSS SLATE READY");
+			continue;
 		case ICNSS_LOW_POWER:
 			seq_puts(s, "ICNSS LOW POWER");
 		}

+ 125 - 21
icnss2/main.c

@@ -45,7 +45,11 @@
 #include <linux/soc/qcom/pdr.h>
 #include <linux/remoteproc.h>
 #include <trace/hooks/remoteproc.h>
+#ifdef SLATE_MODULE_ENABLED
 #include <linux/soc/qcom/slatecom_interface.h>
+#include <linux/soc/qcom/slate_events_bridge_intf.h>
+#include <uapi/linux/slatecom_interface.h>
+#endif
 #include "main.h"
 #include "qmi.h"
 #include "debug.h"
@@ -837,6 +841,40 @@ static enum wlfw_wlan_rf_subtype_v01 icnss_rf_subtype_value_to_type(u32 val)
 	}
 }
 
+#ifdef SLATE_MODULE_ENABLED
+static void icnss_send_wlan_boot_init(void)
+{
+	send_wlan_state(GMI_MGR_WLAN_BOOT_INIT);
+	icnss_pr_info("sent wlan boot init command\n");
+}
+
+static void icnss_send_wlan_boot_complete(void)
+{
+	send_wlan_state(GMI_MGR_WLAN_BOOT_COMPLETE);
+	icnss_pr_info("sent wlan boot complete command\n");
+}
+
+static void icnss_wait_for_slate_complete(struct icnss_priv *priv)
+{
+	if (!test_bit(ICNSS_SLATE_UP, &priv->state)) {
+		reinit_completion(&priv->slate_boot_complete);
+		icnss_pr_err("Waiting for slate boot up notification, 0x%lx\n",
+			     priv->state);
+		wait_for_completion(&priv->slate_boot_complete);
+	}
+
+	icnss_send_wlan_boot_init();
+}
+#else
+static void icnss_send_wlan_boot_complete(void)
+{
+}
+
+static void icnss_wait_for_slate_complete(struct icnss_priv *priv)
+{
+}
+#endif
+
 static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 						 void *data)
 {
@@ -865,17 +903,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 
 	set_bit(ICNSS_WLFW_CONNECTED, &priv->state);
 
-	if (priv->is_slate_rfa) {
-		if (!test_bit(ICNSS_SLATE_UP, &priv->state)) {
-			reinit_completion(&priv->slate_boot_complete);
-			icnss_pr_dbg("Waiting for slate boot up notification, 0x%lx\n",
-				     priv->state);
-			wait_for_completion(&priv->slate_boot_complete);
-		}
-
-		send_wlan_state(GMI_MGR_WLAN_BOOT_INIT);
-		icnss_pr_info("sent wlan boot init command\n");
-	}
+	if (priv->is_slate_rfa)
+		icnss_wait_for_slate_complete(priv);
 
 	ret = wlfw_ind_register_send_sync_msg(priv);
 	if (ret < 0) {
@@ -1194,10 +1223,8 @@ static int icnss_driver_event_fw_ready_ind(struct icnss_priv *priv, void *data)
 		goto out;
 	}
 
-	if (priv->is_slate_rfa && test_bit(ICNSS_SLATE_UP, &priv->state)) {
-		send_wlan_state(GMI_MGR_WLAN_BOOT_COMPLETE);
-		icnss_pr_info("sent wlan boot complete command\n");
-	}
+	if (priv->is_slate_rfa && test_bit(ICNSS_SLATE_UP, &priv->state))
+		icnss_send_wlan_boot_complete();
 
 	if (test_bit(ICNSS_PD_RESTART, &priv->state)) {
 		ret = icnss_pd_restart_complete(priv);
@@ -2319,6 +2346,57 @@ static int icnss_wpss_ssr_register_notifier(struct icnss_priv *priv)
 	return ret;
 }
 
+#ifdef SLATE_MODULE_ENABLED
+static int icnss_slate_event_notifier_nb(struct notifier_block *nb,
+					 unsigned long event, void *data)
+{
+	icnss_pr_info("Received slate event 0x%x\n", event);
+
+	if (event == SLATE_STATUS) {
+		struct icnss_priv *priv = container_of(nb, struct icnss_priv,
+						       seb_nb);
+		enum boot_status status = *(enum boot_status *)data;
+
+		if (status == SLATE_READY) {
+			icnss_pr_dbg("Slate ready received, state: 0x%lx\n",
+				     priv->state);
+			set_bit(ICNSS_SLATE_READY, &priv->state);
+			set_bit(ICNSS_SLATE_UP, &priv->state);
+			complete(&priv->slate_boot_complete);
+		}
+	}
+
+	return NOTIFY_OK;
+}
+
+static int icnss_register_slate_event_notifier(struct icnss_priv *priv)
+{
+	int ret = 0;
+
+	priv->seb_nb.notifier_call = icnss_slate_event_notifier_nb;
+
+	priv->seb_handle = seb_register_for_slate_event(SLATE_STATUS,
+							&priv->seb_nb);
+	if (IS_ERR_OR_NULL(priv->seb_handle)) {
+		ret = priv->seb_handle ? PTR_ERR(priv->seb_handle) : -EINVAL;
+		icnss_pr_err("SLATE event register notifier failed: %d\n",
+			     ret);
+	}
+
+	return ret;
+}
+
+static int icnss_unregister_slate_event_notifier(struct icnss_priv *priv)
+{
+	int ret = 0;
+
+	ret = seb_unregister_for_slate_event(priv->seb_handle, &priv->seb_nb);
+	if (ret < 0)
+		icnss_pr_err("Slate event unregister failed: %d\n", ret);
+
+	return ret;
+}
+
 static int icnss_slate_notifier_nb(struct notifier_block *nb,
 				   unsigned long code,
 				   void *data)
@@ -2329,7 +2407,8 @@ static int icnss_slate_notifier_nb(struct notifier_block *nb,
 
 	icnss_pr_vdbg("Slate-subsys-notify: event %lu\n", code);
 
-	if (code == QCOM_SSR_AFTER_POWERUP) {
+	if (code == QCOM_SSR_AFTER_POWERUP &&
+	    test_bit(ICNSS_SLATE_READY, &priv->state)) {
 		set_bit(ICNSS_SLATE_UP, &priv->state);
 		complete(&priv->slate_boot_complete);
 		icnss_pr_dbg("Slate boot complete, state: 0x%lx\n",
@@ -2386,6 +2465,27 @@ static int icnss_slate_ssr_unregister_notifier(struct icnss_priv *priv)
 
 	return 0;
 }
+#else
+static int icnss_register_slate_event_notifier(struct icnss_priv *priv)
+{
+	return 0;
+}
+
+static int icnss_unregister_slate_event_notifier(struct icnss_priv *priv)
+{
+	return 0;
+}
+
+static int icnss_slate_ssr_register_notifier(struct icnss_priv *priv)
+{
+	return 0;
+}
+
+static int icnss_slate_ssr_unregister_notifier(struct icnss_priv *priv)
+{
+	return 0;
+}
+#endif
 
 static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv)
 {
@@ -2719,8 +2819,10 @@ static int icnss_enable_recovery(struct icnss_priv *priv)
 
 	icnss_modem_ssr_register_notifier(priv);
 
-	if (priv->is_slate_rfa)
+	if (priv->is_slate_rfa) {
 		icnss_slate_ssr_register_notifier(priv);
+		icnss_register_slate_event_notifier(priv);
+	}
 
 	if (test_bit(SSR_ONLY, &priv->ctrl_params.quirks)) {
 		icnss_pr_dbg("PDR disabled through module parameter\n");
@@ -4593,6 +4695,9 @@ static int icnss_probe(struct platform_device *pdev)
 	INIT_WORK(&priv->event_work, icnss_driver_event_work);
 	INIT_LIST_HEAD(&priv->event_list);
 
+	if (priv->is_slate_rfa)
+		init_completion(&priv->slate_boot_complete);
+
 	ret = icnss_register_fw_service(priv);
 	if (ret < 0) {
 		icnss_pr_err("fw service registration failed: %d\n", ret);
@@ -4614,9 +4719,6 @@ static int icnss_probe(struct platform_device *pdev)
 
 	init_completion(&priv->unblock_shutdown);
 
-	if (priv->is_slate_rfa)
-		init_completion(&priv->slate_boot_complete);
-
 	if (priv->device_id == WCN6750_DEVICE_ID ||
 	    priv->device_id == WCN6450_DEVICE_ID) {
 		priv->soc_wake_wq = alloc_workqueue("icnss_soc_wake_event",
@@ -4727,8 +4829,10 @@ static int icnss_remove(struct platform_device *pdev)
 
 	complete_all(&priv->unblock_shutdown);
 
-	if (priv->is_slate_rfa)
+	if (priv->is_slate_rfa) {
 		icnss_slate_ssr_unregister_notifier(priv);
+		icnss_unregister_slate_event_notifier(priv);
+	}
 
 	icnss_destroy_ramdump_device(priv->msa0_dump_dev);
 

+ 5 - 0
icnss2/main.h

@@ -129,6 +129,7 @@ enum icnss_driver_state {
 	ICNSS_QMI_DMS_CONNECTED,
 	ICNSS_SLATE_SSR_REGISTERED,
 	ICNSS_SLATE_UP,
+	ICNSS_SLATE_READY,
 	ICNSS_LOW_POWER,
 };
 
@@ -505,6 +506,10 @@ struct icnss_priv {
 	u32 rf_subtype;
 	u8 is_slate_rfa;
 	struct completion slate_boot_complete;
+#ifdef SLATE_MODULE_ENABLED
+	struct seb_notif_info *seb_handle;
+	struct notifier_block seb_nb;
+#endif
 	struct timer_list recovery_timer;
 	struct timer_list wpss_ssr_timer;
 	bool wpss_self_recovery_enabled;

+ 4 - 0
inc/cnss2.h

@@ -248,6 +248,7 @@ enum cnss_recovery_reason {
 
 enum cnss_fw_caps {
 	CNSS_FW_CAP_DIRECT_LINK_SUPPORT,
+	CNSS_FW_CAP_AUX_UC_SUPPORT,
 };
 
 enum cnss_remote_mem_type {
@@ -358,4 +359,7 @@ extern void cnss_thermal_cdev_unregister(struct device *dev, int tcdev_id);
 extern int cnss_get_curr_therm_cdev_state(struct device *dev,
 					  unsigned long *thermal_state,
 					  int tcdev_id);
+extern int cnss_update_time_sync_period(struct device *dev,
+					 uint32_t time_sync_period);
+extern int cnss_reset_time_sync_period(struct device *dev);
 #endif /* _NET_CNSS2_H */

+ 8 - 2
wlan_platform_modules.bzl

@@ -67,6 +67,7 @@ def _define_modules_for_target_variant(target, variant):
         deps = [
             "//vendor/qcom/opensource/securemsm-kernel:{}_smcinvoke_dlkm".format(tv),
             ":{}_cnss_utils".format(tv),
+            ":{}_cnss_prealloc".format(tv),
             ":{}_wlan_firmware_service".format(tv),
             ":{}_cnss_plat_ipc_qmi_svc".format(tv),
             "//msm-kernel:all_headers",
@@ -97,6 +98,9 @@ def _define_modules_for_target_variant(target, variant):
         out = "icnss2.ko",
         kernel_build = "//msm-kernel:{}".format(tv),
         deps = [
+            ":{}_cnss_utils".format(tv),
+            ":{}_cnss_prealloc".format(tv),
+            ":{}_wlan_firmware_service".format(tv),
             "//msm-kernel:all_headers",
             ":wlan-platform-headers",
         ],
@@ -119,9 +123,11 @@ def _define_modules_for_target_variant(target, variant):
 
     ddk_module(
         name = "{}_cnss_prealloc".format(tv),
-        srcs = [
+        srcs = native.glob([
             "cnss_prealloc/cnss_prealloc.c",
-        ],
+            "cnss_utils/*.h",
+        ]),
+        includes = ["cnss_utils"],
         kconfig = "cnss_prealloc/Kconfig",
         defconfig = "build/{}_defconfig".format(tv),
         out = "cnss_prealloc.ko",