Jelajahi Sumber

Merge 0fcf684c10ff3c1f4bcae162a852bf34c48e246f on remote branch

Change-Id: Id85f57846dd9d3beecc2e5dd13f89e8a08e21d17
Linux Build Service Account 2 tahun lalu
induk
melakukan
5b2657789c

+ 8 - 0
Kbuild

@@ -70,6 +70,14 @@ ifeq ($(CONFIG_CNSS2_SMMU_DB_SUPPORT),y)
 KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SMMU_DB_SUPPORT
 KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SMMU_DB_SUPPORT
 endif
 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_CNSS2) += cnss2/
 obj-$(CONFIG_ICNSS2) += icnss2/
 obj-$(CONFIG_ICNSS2) += icnss2/
 obj-$(CONFIG_CNSS_GENL) += cnss_genl/
 obj-$(CONFIG_CNSS_GENL) += cnss_genl/

+ 16 - 0
cnss2/Kconfig

@@ -156,3 +156,19 @@ config CNSS_OUT_OF_TREE
 	help
 	help
 	  If enabled, CNSS platform driver modules would be able to access
 	  If enabled, CNSS platform driver modules would be able to access
 	  functions from the other modules in the platform driver.
 	  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)
 int cnss_bus_handle_dev_sol_irq(struct cnss_plat_data *plat_priv)
 {
 {
 	if (!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,
 void cnss_bus_add_fw_prefix_name(struct cnss_plat_data *plat_priv,
 				 char *prefix_name, char *name);
 				 char *prefix_name, char *name);
 int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
 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_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_fw_mem(struct cnss_plat_data *plat_priv);
 int cnss_bus_alloc_qdss_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_ACCESS_MEM_TYPE		0xFF
 #define MMIO_REG_RAW_ACCESS_MEM_TYPE		0xFE
 #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)
 #if IS_ENABLED(CONFIG_IPC_LOGGING)
 void *cnss_ipc_log_context;
 void *cnss_ipc_log_context;
 void *cnss_ipc_log_long_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
 #endif
 
 
 static int cnss_pin_connect_show(struct seq_file *s, void *data)
 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;
 		plat_priv->ctrl_params.bdf_type = val;
 	else if (strcmp(cmd, "time_sync_period") == 0)
 	else if (strcmp(cmd, "time_sync_period") == 0)
 		plat_priv->ctrl_params.time_sync_period = val;
 		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 -EINVAL;
 
 
 	return count;
 	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)
 static int cnss_control_params_debug_show(struct seq_file *s, void *data)
 {
 {
 	struct cnss_plat_data *cnss_priv = s->private;
 	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, "\nUsage: echo <params_name> <value> > <debugfs_path>/cnss/control_params\n");
 	seq_puts(s, "<params_name> can be one of below:\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, "bdf_type: %u\n", cnss_priv->ctrl_params.bdf_type);
 	seq_printf(s, "time_sync_period: %u\n",
 	seq_printf(s, "time_sync_period: %u\n",
 		   cnss_priv->ctrl_params.time_sync_period);
 		   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;
 	return 0;
 }
 }
@@ -1027,7 +1061,8 @@ void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv)
 
 
 #if IS_ENABLED(CONFIG_IPC_LOGGING)
 #if IS_ENABLED(CONFIG_IPC_LOGGING)
 void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
 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;
 	struct va_format vaf;
 	va_list va_args;
 	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.fmt = fmt;
 	vaf.va = &va_args;
 	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);
 	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 int cnss_ipc_logging_init(void) { return 0; }
 static void cnss_ipc_logging_deinit(void) {}
 static void cnss_ipc_logging_deinit(void) {}
 void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
 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;
 	struct va_format vaf;
 	va_list va_args;
 	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.fmt = fmt;
 	vaf.va = &va_args;
 	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);
 	va_end(va_args);
 }
 }

+ 28 - 7
cnss2/debug.h

@@ -1,17 +1,34 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
 /* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */
 
 
 #ifndef _CNSS_DEBUG_H
 #ifndef _CNSS_DEBUG_H
 #define _CNSS_DEBUG_H
 #define _CNSS_DEBUG_H
 
 
 #include <linux/printk.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)
 #if IS_ENABLED(CONFIG_IPC_LOGGING)
 #include <linux/ipc_logging.h>
 #include <linux/ipc_logging.h>
 #include <asm/current.h>
 #include <asm/current.h>
 
 
 extern void *cnss_ipc_log_context;
 extern void *cnss_ipc_log_context;
 extern void *cnss_ipc_log_long_context;
 extern void *cnss_ipc_log_long_context;
+extern enum log_level cnss_ipc_log_level;
 
 
 #ifdef CONFIG_CNSS2_DEBUG
 #ifdef CONFIG_CNSS2_DEBUG
 #define CNSS_IPC_LOG_PAGES              100
 #define CNSS_IPC_LOG_PAGES              100
@@ -35,27 +52,30 @@ extern void *cnss_ipc_log_long_context;
 
 
 #define cnss_pr_err(_fmt, ...) \
 #define cnss_pr_err(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_ERR, _fmt, ##__VA_ARGS__)
+			     ERR_LOG, ERR_LOG, _fmt, ##__VA_ARGS__)
 
 
 #define cnss_pr_warn(_fmt, ...) \
 #define cnss_pr_warn(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_WARNING, _fmt, ##__VA_ARGS__)
+			     WARNING_LOG, WARNING_LOG, _fmt, ##__VA_ARGS__)
 
 
 #define cnss_pr_info(_fmt, ...) \
 #define cnss_pr_info(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_INFO, _fmt, ##__VA_ARGS__)
+			     INFO_LOG, INFO_LOG, _fmt, ##__VA_ARGS__)
 
 
 #define cnss_pr_dbg(_fmt, ...) \
 #define cnss_pr_dbg(_fmt, ...) \
 	cnss_debug_log_print(proc_name, __func__, \
 	cnss_debug_log_print(proc_name, __func__, \
-			     KERN_DEBUG, _fmt, ##__VA_ARGS__)
+			     DEBUG_LOG, DEBUG_LOG, _fmt, ##__VA_ARGS__)
 
 
 #define cnss_pr_vdbg(_fmt, ...) \
 #define cnss_pr_vdbg(_fmt, ...) \
 	cnss_debug_log_long_print(proc_name, __func__, \
 	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, ...) \
 #define cnss_pr_buf(_fmt, ...) \
 	cnss_debug_log_long_print(proc_name, __func__, \
 	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
 #ifdef CONFIG_CNSS2_DEBUG
 #define CNSS_ASSERT(_condition) do {					\
 #define CNSS_ASSERT(_condition) do {					\
@@ -83,5 +103,6 @@ void cnss_debug_deinit(void);
 int cnss_debugfs_create(struct cnss_plat_data *plat_priv);
 int cnss_debugfs_create(struct cnss_plat_data *plat_priv);
 void cnss_debugfs_destroy(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,
 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 */
 #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;
 	int ret = 0;
 	char filename[CNSS_GENL_STR_LEN_MAX + 1];
 	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)
 	if (!file_name)
 		strlcpy(filename, "default", sizeof(filename));
 		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 end = 0;
 	u8 retry;
 	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) {
 	while (remaining) {
 		if (remaining > CNSS_GENL_DATA_LEN_MAX) {
 		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_DB_FILE_NAME "wlfw_cal_db.bin"
 #define CNSS_CAL_START_PROBE_WAIT_RETRY_MAX 100
 #define CNSS_CAL_START_PROBE_WAIT_RETRY_MAX 100
 #define CNSS_CAL_START_PROBE_WAIT_MS	500
 #define CNSS_CAL_START_PROBE_WAIT_MS	500
+#define CNSS_TIME_SYNC_PERIOD_INVALID	0xFFFFFFFF
 
 
 enum cnss_cal_db_op {
 enum cnss_cal_db_op {
 	CNSS_CAL_DB_UPLOAD,
 	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);
 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)
 static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
 {
 {
 	int ret = 0;
 	int ret = 0;
@@ -850,6 +868,16 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
 	if (ret)
 	if (ret)
 		goto out;
 		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);
 	cnss_wlfw_qdss_dnld_send_sync(plat_priv);
 
 
 	return 0;
 	return 0;
@@ -3904,6 +3932,26 @@ static ssize_t time_sync_period_show(struct device *dev,
 			plat_priv->ctrl_params.time_sync_period);
 			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,
 static ssize_t time_sync_period_store(struct device *dev,
 				      struct device_attribute *attr,
 				      struct device_attribute *attr,
 				      const char *buf, size_t count)
 				      const char *buf, size_t count)
@@ -3919,12 +3967,94 @@ static ssize_t time_sync_period_store(struct device *dev,
 		return -EINVAL;
 		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;
 	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,
 static ssize_t recovery_store(struct device *dev,
 			      struct device_attribute *attr,
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 			      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,
 	timer_setup(&plat_priv->fw_boot_timer,
 		    cnss_bus_fw_boot_timeout_hdlr, 0);
 		    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);
 	ret = device_init_wakeup(&plat_priv->plat_dev->dev, true);
 	if (ret)
 	if (ret)
 		cnss_pr_err("Failed to init platform device wakeup source, err = %d\n",
 		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);
 	init_completion(&plat_priv->daemon_connected);
 	mutex_init(&plat_priv->dev_lock);
 	mutex_init(&plat_priv->dev_lock);
 	mutex_init(&plat_priv->driver_ops_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 =
 	plat_priv->recovery_ws =
 		wakeup_source_register(&plat_priv->plat_dev->dev,
 		wakeup_source_register(&plat_priv->plat_dev->dev,
 				       "CNSS_FW_RECOVERY");
 				       "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,
 	if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
 				  "qcom,rc-ep-short-channel"))
 				  "qcom,rc-ep-short-channel"))
 		cnss_set_feature_list(plat_priv, CNSS_RC_EP_ULTRASHORT_CHANNEL_V01);
 		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;
 	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);
 	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)
 static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
 {
 {
 	plat_priv->ctrl_params.quirks = CNSS_QUIRKS_DEFAULT;
 	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.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT;
 	plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT;
 	plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT;
 	plat_priv->ctrl_params.time_sync_period = CNSS_TIME_SYNC_PERIOD_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
 	/* Set adsp_pc_enabled default value to true as ADSP pc is always
 	 * enabled by default
 	 * 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);
 	ret = cnss_get_pld_bus_ops_name(plat_priv);
 	if (ret)
 	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);
 	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_M3,
 	CNSS_MEM_CAL_V01,
 	CNSS_MEM_CAL_V01,
 	CNSS_MEM_DPD_V01,
 	CNSS_MEM_DPD_V01,
+	CNSS_MEM_AUX,
 };
 };
 
 
 enum cnss_fw_dump_type {
 enum cnss_fw_dump_type {
@@ -414,6 +415,18 @@ struct cnss_cal_info {
 	enum cnss_cal_status cal_status;
 	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 {
 struct cnss_control_params {
 	unsigned long quirks;
 	unsigned long quirks;
 	unsigned int mhi_timeout;
 	unsigned int mhi_timeout;
@@ -421,6 +434,7 @@ struct cnss_control_params {
 	unsigned int qmi_timeout;
 	unsigned int qmi_timeout;
 	unsigned int bdf_type;
 	unsigned int bdf_type;
 	unsigned int time_sync_period;
 	unsigned int time_sync_period;
+	unsigned int time_sync_period_vote[TIME_SYNC_VOTE_MAX];
 };
 };
 
 
 struct cnss_tcs_info {
 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 fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
 	struct cnss_fw_mem m3_mem;
 	struct cnss_fw_mem m3_mem;
 	struct cnss_fw_mem *cal_mem;
 	struct cnss_fw_mem *cal_mem;
+	struct cnss_fw_mem aux_mem;
 	u64 cal_time;
 	u64 cal_time;
 	bool cbc_file_download;
 	bool cbc_file_download;
 	u32 cal_file_size;
 	u32 cal_file_size;
@@ -583,6 +598,7 @@ struct cnss_plat_data {
 	u8 set_wlaon_pwr_ctrl;
 	u8 set_wlaon_pwr_ctrl;
 	struct cnss_tcs_info tcs_info;
 	struct cnss_tcs_info tcs_info;
 	bool fw_pcie_gen_switch;
 	bool fw_pcie_gen_switch;
+	bool fw_aux_uc_support;
 	u64 fw_caps;
 	u64 fw_caps;
 	u8 pcie_gen_speed;
 	u8 pcie_gen_speed;
 	struct iommu_domain *audio_iommu_domain;
 	struct iommu_domain *audio_iommu_domain;

+ 130 - 6
cnss2/pci.c

@@ -47,6 +47,7 @@
 #define MANGO_PATH_PREFIX		"mango/"
 #define MANGO_PATH_PREFIX		"mango/"
 #define PEACH_PATH_PREFIX		"peach/"
 #define PEACH_PATH_PREFIX		"peach/"
 #define DEFAULT_PHY_M3_FILE_NAME	"m3.bin"
 #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 DEFAULT_PHY_UCODE_FILE_NAME	"phy_ucode.elf"
 #define PHY_UCODE_V2_FILE_NAME		"phy_ucode20.elf"
 #define PHY_UCODE_V2_FILE_NAME		"phy_ucode20.elf"
 #define DEFAULT_FW_FILE_NAME		"amss.bin"
 #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
 	/* in the dual wlan card case, the pld_bus_ops_name from dts
 	 * and driver_ops-> name from ko should match, otherwise
 	 * and driver_ops-> name from ko should match, otherwise
 	 * wlanhost driver don't know which plat_env it can use;
 	 * 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
 #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)
 void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
 {
 {
 	struct cnss_plat_data *plat_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) ||
 	if (!test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) ||
 	    test_bit(CNSS_MHI_POWERING_OFF, &pci_priv->mhi_state))
 	    test_bit(CNSS_MHI_POWERING_OFF, &pci_priv->mhi_state))
 		return -EINVAL;
 		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)
 	if (!pci_priv->is_smmu_fault)
 		cnss_pci_mhi_reg_dump(pci_priv);
 		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);
 	ret = cnss_pci_check_link_status(pci_priv);
 	if (ret) {
 	if (ret) {
 		cnss_pci_link_down(&pci_priv->pci_dev->dev);
 		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;
 		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) ||
 		if (!test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) ||
 		    test_bit(CNSS_MHI_POWERING_OFF, &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_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;
 			return 0;
 		}
 		}
 		cnss_fatal_err("Failed to trigger RDDM, err = %d\n", ret);
 		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;
 			return 0;
+		}
 		cnss_pci_dump_debug_reg(pci_priv);
 		cnss_pci_dump_debug_reg(pci_priv);
 		cnss_schedule_recovery(&pci_priv->pci_dev->dev,
 		cnss_schedule_recovery(&pci_priv->pci_dev->dev,
 				       CNSS_REASON_DEFAULT);
 				       CNSS_REASON_DEFAULT);
-		return ret;
+		goto runtime_pm_put;
 	}
 	}
 
 
 	if (pci_priv->is_smmu_fault) {
 	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));
 			  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,
 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,
 static int cnss_pci_probe(struct pci_dev *pci_dev,
 			  const struct pci_device_id *id)
 			  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)
 	if (plat_priv->use_pm_domain)
 		dev->pm_domain = &cnss_pm_domain;
 		dev->pm_domain = &cnss_pm_domain;
 
 
+	cnss_pci_restore_rc_speed(pci_priv);
+
 	ret = cnss_pci_get_dev_cfg_node(plat_priv);
 	ret = cnss_pci_get_dev_cfg_node(plat_priv);
 	if (ret) {
 	if (ret) {
 		cnss_pr_err("Failed to get device cfg node, err = %d\n", 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);
 	clear_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state);
 	cnss_pci_unregister_driver_hdlr(pci_priv);
 	cnss_pci_unregister_driver_hdlr(pci_priv);
+	cnss_pci_free_aux_mem(pci_priv);
 	cnss_pci_free_m3_mem(pci_priv);
 	cnss_pci_free_m3_mem(pci_priv);
 	cnss_pci_free_fw_mem(pci_priv);
 	cnss_pci_free_fw_mem(pci_priv);
 	cnss_pci_free_qdss_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)
 		if (ret && ret != -EPROBE_DEFER)
 			cnss_pr_err("Failed to set max PCIe RC%x link speed to Gen2, err = %d\n",
 			cnss_pr_err("Failed to set max PCIe RC%x link speed to Gen2, err = %d\n",
 				    rc_num, ret);
 				    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);
 	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);
 void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
 int cnss_pci_load_m3(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);
 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_handle_dev_sol_irq(struct cnss_pci_data *pci_priv);
 int cnss_pci_start_mhi(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);
 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) {
 	if (resp->fw_caps_valid) {
 		plat_priv->fw_pcie_gen_switch =
 		plat_priv->fw_pcie_gen_switch =
 			!!(resp->fw_caps & QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01);
 			!!(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;
 		plat_priv->fw_caps = resp->fw_caps;
 	}
 	}
 
 
@@ -1090,6 +1094,83 @@ out:
 	return ret;
 	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,
 int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv,
 				     u8 *mac, u32 mac_len)
 				     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");
 		cnss_pr_err("Spurious indication\n");
 		return;
 		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);
 	event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
 	if (!event_data)
 	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");
 				cnss_pr_err("FW Mem file save ind cannot have multiple mem types\n");
 				goto free_event_data;
 				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 */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  * 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,
 int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
 				 u32 bdf_type);
 				 u32 bdf_type);
 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
 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,
 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
 				  enum cnss_driver_mode mode);
 				  enum cnss_driver_mode mode);
 int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
 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;
 	return 0;
 }
 }
 
 
+static inline int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
 static inline
 static inline
 int cnss_wlfw_wlan_mode_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)
 				  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},
 	{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;
 struct cnss_pool *cnss_pools;
 unsigned int cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_default);
 unsigned int cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_default);
 
 
@@ -161,6 +169,9 @@ static void cnss_pool_deinit(void)
 {
 {
 	int i;
 	int i;
 
 
+	if (!cnss_pools)
+		return;
+
 	for (i = 0; i < cnss_prealloc_pool_size; i++) {
 	for (i = 0; i < cnss_prealloc_pool_size; i++) {
 		pr_info("cnss_prealloc: destroy mempool %s\n",
 		pr_info("cnss_prealloc: destroy mempool %s\n",
 			cnss_pools[i].name);
 			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);
 		cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_adrastea);
 		break;
 		break;
 	case WCN6750_DEVICE_ID:
 	case WCN6750_DEVICE_ID:
+		cnss_pools = cnss_pools_wcn6750;
+		cnss_prealloc_pool_size = ARRAY_SIZE(cnss_pools_wcn6750);
+		break;
 	case WCN6450_DEVICE_ID:
 	case WCN6450_DEVICE_ID:
 	case QCA6390_DEVICE_ID:
 	case QCA6390_DEVICE_ID:
 	case QCA6490_DEVICE_ID:
 	case QCA6490_DEVICE_ID:
@@ -287,6 +301,9 @@ void *wcnss_prealloc_get(size_t size)
 	gfp_t gfp_mask = __GFP_ZERO;
 	gfp_t gfp_mask = __GFP_ZERO;
 	int i;
 	int i;
 
 
+	if (!cnss_pools)
+		return mem;
+
 	if (in_interrupt() || !preemptible() || rcu_preempt_depth())
 	if (in_interrupt() || !preemptible() || rcu_preempt_depth())
 		gfp_mask |= GFP_ATOMIC;
 		gfp_mask |= GFP_ATOMIC;
 	else
 	else
@@ -326,7 +343,7 @@ int wcnss_prealloc_put(void *mem)
 {
 {
 	int i;
 	int i;
 
 
-	if (!mem)
+	if (!mem || !cnss_pools)
 		return 0;
 		return 0;
 
 
 	i = cnss_pool_get_index(mem);
 	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
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  * 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/module.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -26,6 +26,8 @@
 #define QMI_INIT_RETRY_MAX_TIMES 240
 #define QMI_INIT_RETRY_MAX_TIMES 240
 #define QMI_INIT_RETRY_DELAY_MS 250
 #define QMI_INIT_RETRY_DELAY_MS 250
 #define NUM_LOG_PAGES			10
 #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
  * 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->dms_mac_addr_supported = req_msg->dms_mac_addr_supported;
 	cfg->qdss_hw_trace_override = req_msg->qdss_hw_trace_override;
 	cfg->qdss_hw_trace_override = req_msg->qdss_hw_trace_override;
 	cfg->cal_file_available_bitmask = req_msg->cal_file_available_bitmask;
 	cfg->cal_file_available_bitmask = req_msg->cal_file_available_bitmask;
+	cfg->initialized = 1;
 
 
 	ret = qmi_send_response
 	ret = qmi_send_response
 		(svc->svc_hdl, sq, txn,
 		(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)
 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_svc_ctx *svc = &plat_ipc_qmi_svc;
 	struct cnss_plat_ipc_qmi_client_ctx *qmi_client =
 	struct cnss_plat_ipc_qmi_client_ctx *qmi_client =
 		&svc->qmi_client_ctx[CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01];
 		&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)
 	if (!qmi_client->client_connected)
 		return NULL;
 		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;
 	return &daemon_cfg;
 }
 }
 EXPORT_SYMBOL(cnss_plat_ipc_qmi_daemon_config);
 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 */
 /* 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
 #ifndef _CNSS_PLAT_IPC_QMI_H
 #define _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
  * 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
  * @dms_mac_addr_supported: DMS MAC address provisioning support
  * @qdss_hw_trace_override: QDSS config for HW trace enable
  * @qdss_hw_trace_override: QDSS config for HW trace enable
  * @cal_file_available_bitmask: Calibration file available
  * @cal_file_available_bitmask: Calibration file available
  */
  */
 struct cnss_plat_ipc_daemon_config {
 struct cnss_plat_ipc_daemon_config {
+	u8 initialized;
 	u8 dms_mac_addr_supported;
 	u8 dms_mac_addr_supported;
 	u8 qdss_hw_trace_override;
 	u8 qdss_hw_trace_override;
 	u32 cal_file_available_bitmask;
 	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[] = {
 static struct qmi_elem_info wlfw_pmu_param_v01_ei[] = {
 	{
 	{
 		.data_type      = QMI_UNSIGNED_1_BYTE,
 		.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,
 					   wlfw_cap_resp_msg_v01,
 					   rxgainlut_support),
 					   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,
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
 		.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,
 					   wlfw_host_cap_req_msg_v01,
 					   fw_ini_cfg_support),
 					   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,
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
 		.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,
 					   wlfw_phy_cap_resp_msg_v01,
 					   board_id),
 					   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,
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
 		.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);
 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
  * 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;
 	return 0;
 }
 }
+
 module_init(wlfw_init);
 module_init(wlfw_init);
 
 
 MODULE_LICENSE("GPL v2");
 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_BDF_DOWNLOAD_RESP_V01 0x0025
 #define QMI_WLFW_REJUVENATE_ACK_RESP_V01 0x003A
 #define QMI_WLFW_REJUVENATE_ACK_RESP_V01 0x003A
 #define QMI_WLFW_MSA_INFO_RESP_V01 0x002D
 #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_SHUTDOWN_REQ_V01 0x0043
 #define QMI_WLFW_VBATT_REQ_V01 0x0032
 #define QMI_WLFW_VBATT_REQ_V01 0x0032
 #define QMI_WLFW_PCIE_LINK_CTRL_REQ_V01 0x0059
 #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_WLAN_HW_INIT_CFG_RESP_V01 0x0058
 #define QMI_WLFW_INI_FILE_DOWNLOAD_REQ_V01 0x0056
 #define QMI_WLFW_INI_FILE_DOWNLOAD_REQ_V01 0x0056
 #define QMI_WLFW_QDSS_TRACE_FREE_IND_V01 0x0046
 #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_QDSS_MEM_READY_IND_V01 0x0052
 
 
 #define QMI_WLFW_MAX_NUM_CAL_V01 5
 #define QMI_WLFW_MAX_NUM_CAL_V01 5
 #define QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 64
 #define QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 64
 #define QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01 3
 #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_NUM_SHADOW_REG_V01 24
 #define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128
 #define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128
 #define QMI_WLFW_MAX_DEV_MEM_NUM_V01 4
 #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_SHARE_MEM_V01 8
 #define QMI_WLFW_MAX_NUM_MLO_LINKS_PER_CHIP_V01 2
 #define QMI_WLFW_MAX_NUM_MLO_LINKS_PER_CHIP_V01 2
 #define QMI_WLFW_MAX_NUM_SVC_V01 24
 #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,
 	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 {
 enum wlfw_pcie_gen_speed_v01 {
 	WLFW_PCIE_GEN_SPEED_MIN_VAL_V01 = INT_MIN,
 	WLFW_PCIE_GEN_SPEED_MIN_VAL_V01 = INT_MIN,
 	QMI_PCIE_GEN_SPEED_INVALID_V01 = 0,
 	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,
 	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_FLAGS_V01 ((u32)0x00)
 #define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
 #define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
 #define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
 #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];
 	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 {
 struct wlfw_pmu_param_v01 {
 	u8 pin_name[QMI_WLFW_PMU_PIN_NAME_MAX_LEN_V01];
 	u8 pin_name[QMI_WLFW_PMU_PIN_NAME_MAX_LEN_V01];
 	u32 wake_volt_valid;
 	u32 wake_volt_valid;
@@ -653,8 +688,12 @@ struct wlfw_cap_resp_msg_v01 {
 	u8 regdb_support;
 	u8 regdb_support;
 	u8 rxgainlut_support_valid;
 	u8 rxgainlut_support_valid;
 	u8 rxgainlut_support;
 	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[];
 extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[];
 
 
 struct wlfw_bdf_download_req_msg_v01 {
 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];
 	u32 gpio_info[QMI_WLFW_MAX_NUM_GPIO_INFO_V01];
 	u8 fw_ini_cfg_support_valid;
 	u8 fw_ini_cfg_support_valid;
 	u8 fw_ini_cfg_support;
 	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[];
 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
 
 
 struct wlfw_host_cap_resp_msg_v01 {
 struct wlfw_host_cap_resp_msg_v01 {
@@ -1400,8 +1441,10 @@ struct wlfw_phy_cap_resp_msg_v01 {
 	u8 num_phy;
 	u8 num_phy;
 	u8 board_id_valid;
 	u8 board_id_valid;
 	u32 board_id;
 	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[];
 extern struct qmi_elem_info wlfw_phy_cap_resp_msg_v01_ei[];
 
 
 struct wlfw_wlan_hw_init_cfg_req_msg_v01 {
 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
 #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[];
 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
 #endif

+ 15 - 0
icnss2/Kconfig

@@ -36,3 +36,18 @@ config CNSS_QCA6750
 	  CNSS QCA6750 chipset.
 	  CNSS QCA6750 chipset.
 	  These changes are needed to support the new hardware architecture
 	  These changes are needed to support the new hardware architecture
 	  for CNSS QCA6750 chipset.
 	  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:
 		case ICNSS_SLATE_UP:
 			seq_puts(s, "ICNSS SLATE UP");
 			seq_puts(s, "ICNSS SLATE UP");
 			continue;
 			continue;
+		case ICNSS_SLATE_READY:
+			seq_puts(s, "ICNSS SLATE READY");
+			continue;
 		case ICNSS_LOW_POWER:
 		case ICNSS_LOW_POWER:
 			seq_puts(s, "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/soc/qcom/pdr.h>
 #include <linux/remoteproc.h>
 #include <linux/remoteproc.h>
 #include <trace/hooks/remoteproc.h>
 #include <trace/hooks/remoteproc.h>
+#ifdef SLATE_MODULE_ENABLED
 #include <linux/soc/qcom/slatecom_interface.h>
 #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 "main.h"
 #include "qmi.h"
 #include "qmi.h"
 #include "debug.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,
 static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 						 void *data)
 						 void *data)
 {
 {
@@ -865,17 +903,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 
 
 	set_bit(ICNSS_WLFW_CONNECTED, &priv->state);
 	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);
 	ret = wlfw_ind_register_send_sync_msg(priv);
 	if (ret < 0) {
 	if (ret < 0) {
@@ -1194,10 +1223,8 @@ static int icnss_driver_event_fw_ready_ind(struct icnss_priv *priv, void *data)
 		goto out;
 		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)) {
 	if (test_bit(ICNSS_PD_RESTART, &priv->state)) {
 		ret = icnss_pd_restart_complete(priv);
 		ret = icnss_pd_restart_complete(priv);
@@ -2319,6 +2346,57 @@ static int icnss_wpss_ssr_register_notifier(struct icnss_priv *priv)
 	return ret;
 	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,
 static int icnss_slate_notifier_nb(struct notifier_block *nb,
 				   unsigned long code,
 				   unsigned long code,
 				   void *data)
 				   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);
 	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);
 		set_bit(ICNSS_SLATE_UP, &priv->state);
 		complete(&priv->slate_boot_complete);
 		complete(&priv->slate_boot_complete);
 		icnss_pr_dbg("Slate boot complete, state: 0x%lx\n",
 		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;
 	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)
 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);
 	icnss_modem_ssr_register_notifier(priv);
 
 
-	if (priv->is_slate_rfa)
+	if (priv->is_slate_rfa) {
 		icnss_slate_ssr_register_notifier(priv);
 		icnss_slate_ssr_register_notifier(priv);
+		icnss_register_slate_event_notifier(priv);
+	}
 
 
 	if (test_bit(SSR_ONLY, &priv->ctrl_params.quirks)) {
 	if (test_bit(SSR_ONLY, &priv->ctrl_params.quirks)) {
 		icnss_pr_dbg("PDR disabled through module parameter\n");
 		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_WORK(&priv->event_work, icnss_driver_event_work);
 	INIT_LIST_HEAD(&priv->event_list);
 	INIT_LIST_HEAD(&priv->event_list);
 
 
+	if (priv->is_slate_rfa)
+		init_completion(&priv->slate_boot_complete);
+
 	ret = icnss_register_fw_service(priv);
 	ret = icnss_register_fw_service(priv);
 	if (ret < 0) {
 	if (ret < 0) {
 		icnss_pr_err("fw service registration failed: %d\n", ret);
 		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);
 	init_completion(&priv->unblock_shutdown);
 
 
-	if (priv->is_slate_rfa)
-		init_completion(&priv->slate_boot_complete);
-
 	if (priv->device_id == WCN6750_DEVICE_ID ||
 	if (priv->device_id == WCN6750_DEVICE_ID ||
 	    priv->device_id == WCN6450_DEVICE_ID) {
 	    priv->device_id == WCN6450_DEVICE_ID) {
 		priv->soc_wake_wq = alloc_workqueue("icnss_soc_wake_event",
 		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);
 	complete_all(&priv->unblock_shutdown);
 
 
-	if (priv->is_slate_rfa)
+	if (priv->is_slate_rfa) {
 		icnss_slate_ssr_unregister_notifier(priv);
 		icnss_slate_ssr_unregister_notifier(priv);
+		icnss_unregister_slate_event_notifier(priv);
+	}
 
 
 	icnss_destroy_ramdump_device(priv->msa0_dump_dev);
 	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_QMI_DMS_CONNECTED,
 	ICNSS_SLATE_SSR_REGISTERED,
 	ICNSS_SLATE_SSR_REGISTERED,
 	ICNSS_SLATE_UP,
 	ICNSS_SLATE_UP,
+	ICNSS_SLATE_READY,
 	ICNSS_LOW_POWER,
 	ICNSS_LOW_POWER,
 };
 };
 
 
@@ -505,6 +506,10 @@ struct icnss_priv {
 	u32 rf_subtype;
 	u32 rf_subtype;
 	u8 is_slate_rfa;
 	u8 is_slate_rfa;
 	struct completion slate_boot_complete;
 	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 recovery_timer;
 	struct timer_list wpss_ssr_timer;
 	struct timer_list wpss_ssr_timer;
 	bool wpss_self_recovery_enabled;
 	bool wpss_self_recovery_enabled;

+ 4 - 0
inc/cnss2.h

@@ -248,6 +248,7 @@ enum cnss_recovery_reason {
 
 
 enum cnss_fw_caps {
 enum cnss_fw_caps {
 	CNSS_FW_CAP_DIRECT_LINK_SUPPORT,
 	CNSS_FW_CAP_DIRECT_LINK_SUPPORT,
+	CNSS_FW_CAP_AUX_UC_SUPPORT,
 };
 };
 
 
 enum cnss_remote_mem_type {
 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,
 extern int cnss_get_curr_therm_cdev_state(struct device *dev,
 					  unsigned long *thermal_state,
 					  unsigned long *thermal_state,
 					  int tcdev_id);
 					  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 */
 #endif /* _NET_CNSS2_H */

+ 8 - 2
wlan_platform_modules.bzl

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