summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2023-04-17 00:40:31 -0700
committerLinux Build Service Account <lnxbuild@localhost>2023-04-17 00:40:31 -0700
commit58e28d767d9b33016dec92b998e53caec74ffebf (patch)
tree6dcd40c65025fdf4bc2022ff25e54a9bbc87bebd
parent1c7d481a2491b2b724848f98fb8fc71498b77a14 (diff)
parentddbe3d0e4eb2bf564a0a00ad577bca3d18dda28b (diff)
downloadwlan-platform-58e28d767d9b33016dec92b998e53caec74ffebf.tar.gz
Merge ddbe3d0e4eb2bf564a0a00ad577bca3d18dda28b on remote branch
Change-Id: Iad5d2e142adb48ed5086ba8c0c66284296eb6fb5
-rw-r--r--Android.mk2
-rw-r--r--Kbuild4
-rw-r--r--cnss2/bus.c23
-rw-r--r--cnss2/bus.h6
-rw-r--r--cnss2/genl.c9
-rw-r--r--cnss2/main.c65
-rw-r--r--cnss2/pci.c170
-rw-r--r--cnss2/pci.h5
-rw-r--r--cnss2/pci_platform.h15
-rw-r--r--cnss2/pci_qcom.c13
-rw-r--r--cnss2/qmi.c68
-rw-r--r--cnss2/reg.h2
-rw-r--r--icnss2/main.c22
-rw-r--r--inc/cnss2.h1
14 files changed, 348 insertions, 57 deletions
diff --git a/Android.mk b/Android.mk
index 32a56b2..5c724c3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -31,7 +31,9 @@ CNSS_SRC_FILES := \
$(wildcard $(LOCAL_PATH)/*) \
$(wildcard $(LOCAL_PATH)/*/*) \
+ifeq ($(TARGET_KERNEL_DLKM_SECURE_MSM_OVERRIDE), true)
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(PWD)/$(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers
+endif
# Module.symvers needs to be generated as a intermediate module so that
# other modules which depend on WLAN platform modules can set local
diff --git a/Kbuild b/Kbuild
index 051f85f..b6b2292 100644
--- a/Kbuild
+++ b/Kbuild
@@ -52,6 +52,10 @@ ifeq ($(CONFIG_CNSS2_SSR_DRIVER_DUMP),y)
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SSR_DRIVER_DUMP
endif
+ifeq ($(CONFIG_FREE_M3_BLOB_MEM),y)
+KBUILD_CPPFLAGS += -DCONFIG_FREE_M3_BLOB_MEM
+endif
+
obj-$(CONFIG_CNSS2) += cnss2/
obj-$(CONFIG_ICNSS2) += icnss2/
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
diff --git a/cnss2/bus.c b/cnss2/bus.c
index a3084b1..e755818 100644
--- a/cnss2/bus.c
+++ b/cnss2/bus.c
@@ -48,6 +48,7 @@ enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv)
case QCA6174_DEVICE_ID:
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -653,6 +654,28 @@ int cnss_bus_set_therm_cdev_state(struct cnss_plat_data *plat_priv,
}
}
+int cnss_bus_get_msi_assignment(struct cnss_plat_data *plat_priv,
+ char *msi_name,
+ int *num_vectors,
+ u32 *user_base_data,
+ u32 *base_vector)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_get_user_msi_assignment(plat_priv->bus_priv,
+ msi_name,
+ num_vectors,
+ user_base_data,
+ base_vector);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n", plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
#if IS_ENABLED(CONFIG_MHI_BUS_MISC)
void cnss_bus_disable_mhi_satellite_cfg(struct cnss_plat_data *plat_priv)
{
diff --git a/cnss2/bus.h b/cnss2/bus.h
index ae4c6e1..57d1154 100644
--- a/cnss2/bus.h
+++ b/cnss2/bus.h
@@ -20,6 +20,7 @@
#define QCA6390_DEVICE_ID 0x1101
#define QCA6490_VENDOR_ID 0x17CB
#define QCA6490_DEVICE_ID 0x1103
+#define QCN7605_VENDOR_ID 0x17CB
#define QCN7605_DEVICE_ID 0x1102
#define KIWI_VENDOR_ID 0x17CB
#define KIWI_DEVICE_ID 0x1107
@@ -80,4 +81,9 @@ void cnss_bus_disable_mhi_satellite_cfg(struct cnss_plat_data *plat_priv);
int cnss_bus_set_therm_cdev_state(struct cnss_plat_data *plat_priv,
unsigned long thermal_state,
int tcdev_id);
+int cnss_bus_get_msi_assignment(struct cnss_plat_data *plat_priv,
+ char *msi_name,
+ int *num_vectors,
+ u32 *user_base_data,
+ u32 *base_vector);
#endif /* _CNSS_BUS_H */
diff --git a/cnss2/genl.c b/cnss2/genl.c
index 2819a1b..761a469 100644
--- a/cnss2/genl.c
+++ b/cnss2/genl.c
@@ -1,5 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
#define pr_fmt(fmt) "cnss_genl: " fmt
@@ -92,7 +95,7 @@ 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_dbg("type: %u, file_name %s, total_size: %x, seg_id %u, end %u, data_len %u\n",
+ 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);
if (!file_name)
@@ -164,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_dbg("type: %u, total_size: %x\n", type, total_size);
+ cnss_pr_vdbg("type: %u, total_size: %x\n", type, total_size);
while (remaining) {
if (remaining > CNSS_GENL_DATA_LEN_MAX) {
diff --git a/cnss2/main.c b/cnss2/main.c
index 8fa4b18..8e4959f 100644
--- a/cnss2/main.c
+++ b/cnss2/main.c
@@ -595,6 +595,9 @@ int cnss_wlan_enable(struct device *dev,
if (mode == CNSS_WALTEST || mode == CNSS_CCPM)
goto skip_cfg;
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ config->send_msi_ce = true;
+
ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, config, host_version);
if (ret)
goto out;
@@ -798,6 +801,9 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
cnss_wlfw_bdf_dnld_send_sync(plat_priv, CNSS_BDF_REGDB);
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ plat_priv->ctrl_params.bdf_type = CNSS_BDF_BIN;
+
cnss_wlfw_ini_file_send_sync(plat_priv, WLFW_CONN_ROAM_INI_V01);
ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv,
@@ -805,6 +811,9 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
if (ret)
goto out;
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ return 0;
+
ret = cnss_bus_load_m3(plat_priv);
if (ret)
goto out;
@@ -1371,8 +1380,6 @@ EXPORT_SYMBOL(cnss_idle_restart);
int cnss_idle_shutdown(struct device *dev)
{
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
- unsigned int timeout;
- int ret;
if (!plat_priv) {
cnss_pr_err("plat_priv is NULL\n");
@@ -1386,21 +1393,12 @@ int cnss_idle_shutdown(struct device *dev)
cnss_pr_dbg("Doing idle shutdown\n");
- if (!test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
- !test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
- goto skip_wait;
-
- reinit_completion(&plat_priv->recovery_complete);
- timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_RECOVERY);
- ret = wait_for_completion_timeout(&plat_priv->recovery_complete,
- msecs_to_jiffies(timeout));
- if (!ret) {
- cnss_pr_err("Timeout (%ums) waiting for recovery to complete\n",
- timeout);
- CNSS_ASSERT(0);
+ if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) ||
+ test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) {
+ cnss_pr_dbg("Recovery in progress. Ignore IDLE Shutdown\n");
+ return -EBUSY;
}
-skip_wait:
return cnss_driver_event_post(plat_priv,
CNSS_DRIVER_EVENT_IDLE_SHUTDOWN,
CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
@@ -2346,8 +2344,14 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
cnss_bus_free_qdss_mem(plat_priv);
cnss_release_antenna_sharing(plat_priv);
+
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ goto skip_shutdown;
+
cnss_bus_dev_shutdown(plat_priv);
msleep(POWER_RESET_MIN_DELAY_MS);
+
+skip_shutdown:
complete(&plat_priv->cal_complete);
clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);
@@ -3045,8 +3049,11 @@ int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
}
seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
- if (!seg)
+ if (!seg) {
+ cnss_pr_err("%s: Failed to allocate mem for seg %d\n",
+ __func__, i);
continue;
+ }
if (meta_info.entry[dump_seg->type].entry_start == 0) {
meta_info.entry[dump_seg->type].type = dump_seg->type;
@@ -3061,8 +3068,11 @@ int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
}
seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
- if (!seg)
- goto do_elf_dump;
+ if (!seg) {
+ cnss_pr_err("%s: Failed to allocate mem for elf ramdump seg\n",
+ __func__);
+ goto skip_elf_dump;
+ }
meta_info.magic = CNSS_RAMDUMP_MAGIC;
meta_info.version = CNSS_RAMDUMP_VERSION;
@@ -3072,9 +3082,9 @@ int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
seg->size = sizeof(meta_info);
list_add(&seg->node, &head);
-do_elf_dump:
ret = qcom_elf_dump(&head, info_v2->ramdump_dev, ELF_CLASS);
+skip_elf_dump:
while (!list_empty(&head)) {
seg = list_first_entry(&head, struct qcom_dump_segment, node);
list_del(&seg->node);
@@ -3115,8 +3125,9 @@ int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
[CNSS_HOST_WMI_EVENT_LOG_IDX] = "wmi_event_log_idx",
[CNSS_HOST_WMI_RX_EVENT_IDX] = "wmi_rx_event_idx"
};
- int i, j;
+ int i;
int ret = 0;
+ enum cnss_host_dump_type j;
if (!dump_enabled()) {
cnss_pr_info("Dump collection is not enabled\n");
@@ -3149,7 +3160,7 @@ int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
seg->da = (dma_addr_t)ssr_entry[i].buffer_pointer;
seg->size = ssr_entry[i].buffer_size;
- for (j = 0; j < ARRAY_SIZE(wlan_str); j++) {
+ for (j = 0; j < CNSS_HOST_DUMP_TYPE_MAX; j++) {
if (strncmp(ssr_entry[i].region_name, wlan_str[j],
strlen(wlan_str[j])) == 0) {
meta_info.entry[i].type = j;
@@ -3162,6 +3173,13 @@ int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
}
seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
+
+ if (!seg) {
+ cnss_pr_err("%s: Failed to allocate mem for host dump seg\n",
+ __func__);
+ goto skip_host_dump;
+ }
+
meta_info.magic = CNSS_RAMDUMP_MAGIC;
meta_info.version = CNSS_RAMDUMP_VERSION;
meta_info.chipset = plat_priv->device_id;
@@ -3170,7 +3188,10 @@ int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
seg->da = (dma_addr_t)&meta_info;
seg->size = sizeof(meta_info);
list_add(&seg->node, &head);
+
ret = qcom_elf_dump(&head, new_device, ELF_CLASS);
+
+skip_host_dump:
while (!list_empty(&head)) {
seg = list_first_entry(&head, struct qcom_dump_segment, node);
list_del(&seg->node);
@@ -3384,6 +3405,7 @@ int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -3406,6 +3428,7 @@ void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
diff --git a/cnss2/pci.c b/cnss2/pci.c
index f7ef9ce..fe98d72 100644
--- a/cnss2/pci.c
+++ b/cnss2/pci.c
@@ -42,6 +42,7 @@
#define QCA6390_PATH_PREFIX "qca6390/"
#define QCA6490_PATH_PREFIX "qca6490/"
+#define QCN7605_PATH_PREFIX "qcn7605/"
#define KIWI_PATH_PREFIX "kiwi/"
#define MANGO_PATH_PREFIX "mango/"
#define PEACH_PATH_PREFIX "peach/"
@@ -248,6 +249,93 @@ static const struct mhi_channel_config cnss_mhi_channels[] = {
#endif
};
+static const struct mhi_channel_config cnss_mhi_channels_genoa[] = {
+ {
+ .num = 0,
+ .name = "LOOPBACK",
+ .num_elements = 32,
+ .event_ring = 1,
+ .dir = DMA_TO_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = false,
+ },
+ {
+ .num = 1,
+ .name = "LOOPBACK",
+ .num_elements = 32,
+ .event_ring = 1,
+ .dir = DMA_FROM_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = false,
+ },
+ {
+ .num = 4,
+ .name = "DIAG",
+ .num_elements = 64,
+ .event_ring = 1,
+ .dir = DMA_TO_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = false,
+ },
+ {
+ .num = 5,
+ .name = "DIAG",
+ .num_elements = 64,
+ .event_ring = 1,
+ .dir = DMA_FROM_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = false,
+ },
+ {
+ .num = 16,
+ .name = "IPCR",
+ .num_elements = 64,
+ .event_ring = 1,
+ .dir = DMA_TO_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = false,
+ },
+ {
+ .num = 17,
+ .name = "IPCR",
+ .num_elements = 64,
+ .event_ring = 1,
+ .dir = DMA_FROM_DEVICE,
+ .ee_mask = 0x4,
+ .pollcfg = 0,
+ .doorbell = MHI_DB_BRST_DISABLE,
+ .lpm_notify = false,
+ .offload_channel = false,
+ .doorbell_mode_switch = false,
+ .auto_queue = true,
+ },
+};
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
static struct mhi_event_config cnss_mhi_events[] = {
#else
@@ -326,6 +414,20 @@ static const struct mhi_controller_config cnss_mhi_config_default = {
.m2_no_db = true,
};
+static const struct mhi_controller_config cnss_mhi_config_genoa = {
+ .max_channels = 32,
+ .timeout_ms = 10000,
+ .use_bounce_buf = false,
+ .buf_len = 0x8000,
+ .num_channels = ARRAY_SIZE(cnss_mhi_channels_genoa),
+ .ch_cfg = cnss_mhi_channels_genoa,
+ .num_events = ARRAY_SIZE(cnss_mhi_events) -
+ CNSS_MHI_SATELLITE_EVT_COUNT,
+ .event_cfg = cnss_mhi_events,
+ .m2_no_db = true,
+ .bhie_offset = 0x0324,
+};
+
static const struct mhi_controller_config cnss_mhi_config_no_satellite = {
.max_channels = 32,
.timeout_ms = 10000,
@@ -833,6 +935,9 @@ static void cnss_pci_select_window(struct cnss_pci_data *pci_priv, u32 offset)
QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET);
}
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ window_enable = QCN7605_WINDOW_ENABLE_BIT | window;
+
if (window != pci_priv->remap_window) {
pci_priv->remap_window = window;
cnss_pr_dbg("Config PCIe remap window register to 0x%x\n",
@@ -3136,6 +3241,7 @@ int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -3166,6 +3272,7 @@ int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -3196,6 +3303,7 @@ int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -3226,6 +3334,7 @@ int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -3511,10 +3620,12 @@ static int cnss_pci_suspend_driver(struct cnss_pci_data *pci_priv)
struct pci_dev *pci_dev = pci_priv->pci_dev;
struct cnss_wlan_driver *driver_ops = pci_priv->driver_ops;
int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
pm_message_t state = { .event = PM_EVENT_SUSPEND };
- if (driver_ops && driver_ops->suspend) {
+ if (test_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state) &&
+ driver_ops && driver_ops->suspend) {
ret = driver_ops->suspend(pci_dev, state);
if (ret) {
cnss_pr_err("Failed to suspend host driver, err = %d\n",
@@ -3531,8 +3642,10 @@ static int cnss_pci_resume_driver(struct cnss_pci_data *pci_priv)
struct pci_dev *pci_dev = pci_priv->pci_dev;
struct cnss_wlan_driver *driver_ops = pci_priv->driver_ops;
int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
- if (driver_ops && driver_ops->resume) {
+ if (test_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state) &&
+ driver_ops && driver_ops->resume) {
ret = driver_ops->resume(pci_dev);
if (ret)
cnss_pr_err("Failed to resume host driver, err = %d\n",
@@ -3740,6 +3853,7 @@ static int cnss_pci_suspend_noirq(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
struct cnss_wlan_driver *driver_ops;
+ struct cnss_plat_data *plat_priv;
if (!pci_priv)
goto out;
@@ -3748,7 +3862,9 @@ static int cnss_pci_suspend_noirq(struct device *dev)
goto out;
driver_ops = pci_priv->driver_ops;
- if (driver_ops && driver_ops->suspend_noirq)
+ plat_priv = pci_priv->plat_priv;
+ if (test_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state) &&
+ driver_ops && driver_ops->suspend_noirq)
ret = driver_ops->suspend_noirq(pci_dev);
if (pci_priv->disable_pc && !pci_dev->state_saved &&
@@ -3765,6 +3881,7 @@ static int cnss_pci_resume_noirq(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
struct cnss_wlan_driver *driver_ops;
+ struct cnss_plat_data *plat_priv;
if (!pci_priv)
goto out;
@@ -3772,8 +3889,10 @@ static int cnss_pci_resume_noirq(struct device *dev)
if (!cnss_is_device_powered_on(pci_priv->plat_priv))
goto out;
+ plat_priv = pci_priv->plat_priv;
driver_ops = pci_priv->driver_ops;
- if (driver_ops && driver_ops->resume_noirq &&
+ if (test_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state) &&
+ driver_ops && driver_ops->resume_noirq &&
!pci_priv->pci_link_down_ind)
ret = driver_ops->resume_noirq(pci_dev);
@@ -4836,6 +4955,19 @@ int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info)
}
EXPORT_SYMBOL(cnss_get_soc_info);
+int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
+ char *user_name,
+ int *num_vectors,
+ u32 *user_base_data,
+ u32 *base_vector)
+{
+ return cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
+ user_name,
+ num_vectors,
+ user_base_data,
+ base_vector);
+}
+
static int cnss_pci_enable_msi(struct cnss_pci_data *pci_priv)
{
int ret = 0;
@@ -5065,6 +5197,7 @@ static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv)
switch (device_id) {
case QCA6174_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
pci_priv->dma_bit_mask = PCI_DMA_MASK_32_BIT;
break;
case QCA6390_DEVICE_ID:
@@ -5705,6 +5838,10 @@ void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
}
switch (pci_priv->device_id) {
+ case QCN7605_DEVICE_ID:
+ scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
+ QCN7605_PATH_PREFIX "%s", name);
+ break;
case QCA6390_DEVICE_ID:
scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
QCA6390_PATH_PREFIX "%s", name);
@@ -6198,7 +6335,12 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
mhi_ctrl->rddm_size = pci_priv->plat_priv->ramdump_info_v2.ramdump_size;
if (!mhi_ctrl->rddm_size)
mhi_ctrl->rddm_size = RAMDUMP_SIZE_DEFAULT;
- mhi_ctrl->sbl_size = SZ_512K;
+
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ mhi_ctrl->sbl_size = SZ_256K;
+ else
+ mhi_ctrl->sbl_size = SZ_512K;
+
mhi_ctrl->seg_len = SZ_512K;
mhi_ctrl->fbc_download = true;
@@ -6208,9 +6350,13 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
/* Satellite config only supported on KIWI V2 and later chipset */
if (plat_priv->device_id <= QCA6490_DEVICE_ID ||
- (plat_priv->device_id == KIWI_DEVICE_ID &&
- plat_priv->device_version.major_version == 1))
- cnss_mhi_config = &cnss_mhi_config_no_satellite;
+ (plat_priv->device_id == KIWI_DEVICE_ID &&
+ plat_priv->device_version.major_version == 1)) {
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ cnss_mhi_config = &cnss_mhi_config_genoa;
+ else
+ cnss_mhi_config = &cnss_mhi_config_no_satellite;
+ }
mhi_ctrl->tme_supported_image = cnss_is_tme_supported(pci_priv);
@@ -6221,7 +6367,7 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
}
/* MHI satellite driver only needs to connect when DRV is supported */
- if (cnss_pci_is_drv_supported(pci_priv))
+ if (cnss_pci_get_drv_supported(pci_priv))
cnss_mhi_controller_set_base(pci_priv, bar_start);
/* BW scale CB needs to be set after registering MHI per requirement */
@@ -6610,6 +6756,9 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
if (ret)
goto unregister_ramdump;
+ /* update drv support flag */
+ cnss_pci_update_drv_supported(pci_priv);
+
ret = cnss_reg_pci_event(pci_priv);
if (ret) {
cnss_pr_err("Failed to register PCI event, err = %d\n", ret);
@@ -6635,6 +6784,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -6708,6 +6858,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
switch (pci_dev->device) {
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case KIWI_DEVICE_ID:
case MANGO_DEVICE_ID:
@@ -6738,6 +6889,7 @@ static const struct pci_device_id cnss_pci_id_table[] = {
{ QCA6174_VENDOR_ID, QCA6174_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ QCA6290_VENDOR_ID, QCA6290_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ QCA6390_VENDOR_ID, QCA6390_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
+ { QCN7605_VENDOR_ID, QCN7605_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ QCA6490_VENDOR_ID, QCA6490_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ KIWI_VENDOR_ID, KIWI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ MANGO_VENDOR_ID, MANGO_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
diff --git a/cnss2/pci.h b/cnss2/pci.h
index 036b380..73136f2 100644
--- a/cnss2/pci.h
+++ b/cnss2/pci.h
@@ -304,4 +304,9 @@ int cnss_pci_update_time_sync_period(struct cnss_pci_data *pci_priv,
int cnss_pci_set_therm_cdev_state(struct cnss_pci_data *pci_priv,
unsigned long thermal_state,
int tcdev_id);
+int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
+ char *user_name,
+ int *num_vectors,
+ u32 *user_base_data,
+ u32 *base_vector);
#endif /* _CNSS_PCI_H */
diff --git a/cnss2/pci_platform.h b/cnss2/pci_platform.h
index e76b2c8..eaa50ea 100644
--- a/cnss2/pci_platform.h
+++ b/cnss2/pci_platform.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */
+/* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */
#ifndef _CNSS_PCI_PLATFORM_H
#define _CNSS_PCI_PLATFORM_H
@@ -112,7 +112,8 @@ bool cnss_pci_is_one_msi(struct cnss_pci_data *pci_priv);
int cnss_pci_get_one_msi_mhi_irq_array_size(struct cnss_pci_data *pci_priv);
bool cnss_pci_is_force_one_msi(struct cnss_pci_data *pci_priv);
int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv);
-bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv);
+void cnss_pci_update_drv_supported(struct cnss_pci_data *pci_priv);
+
/**
* _cnss_pci_get_reg_dump() - Dump PCIe RC registers for debug
* @pci_priv: driver PCI bus context pointer
@@ -198,12 +199,18 @@ int _cnss_pci_get_reg_dump(struct cnss_pci_data *pci_priv,
return 0;
}
-bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
+void cnss_pci_update_drv_supported(struct cnss_pci_data *pci_priv)
{
- return false;
+ pci_priv->drv_supported = false;
}
+
#endif /* CONFIG_PCI_MSM */
+static inline bool cnss_pci_get_drv_supported(struct cnss_pci_data *pci_priv)
+{
+ return pci_priv->drv_supported;
+}
+
#if IS_ENABLED(CONFIG_ARCH_QCOM)
int cnss_pci_of_reserved_mem_device_init(struct cnss_pci_data *pci_priv);
int cnss_pci_wake_gpio_init(struct cnss_pci_data *pci_priv);
diff --git a/cnss2/pci_qcom.c b/cnss2/pci_qcom.c
index f0517db..70106dc 100644
--- a/cnss2/pci_qcom.c
+++ b/cnss2/pci_qcom.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */
+/* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */
#include "pci_platform.h"
#include "debug.h"
@@ -159,7 +159,7 @@ static int cnss_pci_set_link_down(struct cnss_pci_data *pci_priv)
return ret;
}
-bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
+void cnss_pci_update_drv_supported(struct cnss_pci_data *pci_priv)
{
struct pci_dev *root_port = pcie_find_root_port(pci_priv->pci_dev);
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -169,7 +169,7 @@ bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
if (!root_port) {
cnss_pr_err("PCIe DRV is not supported as root port is null\n");
pci_priv->drv_supported = false;
- return drv_supported;
+ return;
}
root_of_node = root_port->dev.of_node;
@@ -189,8 +189,6 @@ bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
plat_priv->cap.cap_flag |= CNSS_HAS_DRV_SUPPORT;
cnss_set_feature_list(plat_priv, CNSS_DRV_SUPPORT_V01);
}
-
- return drv_supported;
}
static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
@@ -268,7 +266,7 @@ int cnss_reg_pci_event(struct cnss_pci_data *pci_priv)
MSM_PCIE_EVENT_LINKDOWN |
MSM_PCIE_EVENT_WAKEUP;
- if (cnss_pci_is_drv_supported(pci_priv))
+ if (cnss_pci_get_drv_supported(pci_priv))
pci_event->events = pci_event->events |
MSM_PCIE_EVENT_DRV_CONNECT |
MSM_PCIE_EVENT_DRV_DISCONNECT;
@@ -299,6 +297,9 @@ int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
u32 pm_options = PM_OPTIONS_DEFAULT;
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+ if (!cnss_pci_get_drv_supported(pci_priv))
+ return 0;
+
if (plat_priv->adsp_pc_enabled == control) {
cnss_pr_dbg("ADSP power collapse already %s\n",
control ? "Enabled" : "Disabled");
diff --git a/cnss2/qmi.c b/cnss2/qmi.c
index 3219ace..c889e2f 100644
--- a/cnss2/qmi.c
+++ b/cnss2/qmi.c
@@ -40,6 +40,7 @@
#endif
#define HW_V1_NUMBER "v1"
#define HW_V2_NUMBER "v2"
+#define CE_MSI_NAME "CE"
#define QMI_WLFW_TIMEOUT_MS (plat_priv->ctrl_params.qmi_timeout)
#define QMI_WLFW_TIMEOUT_JF msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS)
@@ -1567,7 +1568,7 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
struct wlfw_wlan_cfg_req_msg_v01 *req;
struct wlfw_wlan_cfg_resp_msg_v01 *resp;
struct qmi_txn txn;
- u32 i;
+ u32 i, ce_id, num_vectors, user_base_data, base_vector;
int ret = 0;
if (!plat_priv)
@@ -1617,16 +1618,34 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
if (plat_priv->device_id != KIWI_DEVICE_ID &&
plat_priv->device_id != MANGO_DEVICE_ID &&
plat_priv->device_id != PEACH_DEVICE_ID) {
- req->shadow_reg_v2_valid = 1;
- if (config->num_shadow_reg_v2_cfg >
- QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
- req->shadow_reg_v2_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
- else
- req->shadow_reg_v2_len = config->num_shadow_reg_v2_cfg;
+ if (plat_priv->device_id == QCN7605_DEVICE_ID &&
+ config->num_shadow_reg_cfg) {
+ req->shadow_reg_valid = 1;
+ if (config->num_shadow_reg_cfg >
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
+ req->shadow_reg_len =
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
+ else
+ req->shadow_reg_len =
+ config->num_shadow_reg_cfg;
+ memcpy(req->shadow_reg, config->shadow_reg_cfg,
+ sizeof(struct wlfw_shadow_reg_cfg_s_v01) *
+ req->shadow_reg_len);
+ } else {
+ req->shadow_reg_v2_valid = 1;
+
+ if (config->num_shadow_reg_v2_cfg >
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
+ req->shadow_reg_v2_len =
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
+ else
+ req->shadow_reg_v2_len =
+ config->num_shadow_reg_v2_cfg;
- memcpy(req->shadow_reg_v2, config->shadow_reg_v2_cfg,
- sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
- * req->shadow_reg_v2_len);
+ memcpy(req->shadow_reg_v2, config->shadow_reg_v2_cfg,
+ sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01) *
+ req->shadow_reg_v2_len);
+ }
} else {
req->shadow_reg_v3_valid = 1;
if (config->num_shadow_reg_v3_cfg >
@@ -1641,8 +1660,33 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
plat_priv->num_shadow_regs_v3);
memcpy(req->shadow_reg_v3, config->shadow_reg_v3_cfg,
- sizeof(struct wlfw_shadow_reg_v3_cfg_s_v01)
- * req->shadow_reg_v3_len);
+ sizeof(struct wlfw_shadow_reg_v3_cfg_s_v01) *
+ req->shadow_reg_v3_len);
+ }
+
+ if (config->rri_over_ddr_cfg_valid) {
+ req->rri_over_ddr_cfg_valid = 1;
+ req->rri_over_ddr_cfg.base_addr_low =
+ config->rri_over_ddr_cfg.base_addr_low;
+ req->rri_over_ddr_cfg.base_addr_high =
+ config->rri_over_ddr_cfg.base_addr_high;
+ }
+ if (config->send_msi_ce) {
+ ret = cnss_bus_get_msi_assignment(plat_priv,
+ CE_MSI_NAME,
+ &num_vectors,
+ &user_base_data,
+ &base_vector);
+ if (!ret) {
+ req->msi_cfg_valid = 1;
+ req->msi_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
+ for (ce_id = 0; ce_id < QMI_WLFW_MAX_NUM_CE_V01;
+ ce_id++) {
+ req->msi_cfg[ce_id].ce_id = ce_id;
+ req->msi_cfg[ce_id].msi_vector =
+ (ce_id % num_vectors) + base_vector;
+ }
+ }
}
ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
diff --git a/cnss2/reg.h b/cnss2/reg.h
index e670979..64cd779 100644
--- a/cnss2/reg.h
+++ b/cnss2/reg.h
@@ -361,4 +361,6 @@
#define GCC_GCC_SPARE_REG_1 0x1E40310
#define GCC_PRE_ARES_DEBUG_TIMER_VAL 0x1E40270
+
+#define QCN7605_WINDOW_ENABLE_BIT 0x80000000
#endif
diff --git a/icnss2/main.c b/icnss2/main.c
index 9c07d1e..ed5f843 100644
--- a/icnss2/main.c
+++ b/icnss2/main.c
@@ -486,8 +486,12 @@ static int icnss_send_smp2p(struct icnss_priv *priv,
return ret;
}
- if (test_bit(ICNSS_FW_DOWN, &priv->state))
- return -ENODEV;
+ if (test_bit(ICNSS_FW_DOWN, &priv->state) ||
+ !test_bit(ICNSS_FW_READY, &priv->state)) {
+ icnss_pr_smp2p("FW down, ignoring sending SMP2P state: 0x%lx\n",
+ priv->state);
+ return -EINVAL;
+ }
value |= priv->smp2p_info[smp2p_entry].seq++;
value <<= ICNSS_SMEM_SEQ_NO_POS;
@@ -3303,6 +3307,13 @@ int icnss_force_wake_request(struct device *dev)
return -EINVAL;
}
+ if (test_bit(ICNSS_FW_DOWN, &priv->state) ||
+ !test_bit(ICNSS_FW_READY, &priv->state)) {
+ icnss_pr_soc_wake("FW down, ignoring SOC Wake request state: 0x%lx\n",
+ priv->state);
+ return -EINVAL;
+ }
+
if (atomic_inc_not_zero(&priv->soc_wake_ref_count)) {
icnss_pr_soc_wake("SOC already awake, Ref count: %d",
atomic_read(&priv->soc_wake_ref_count));
@@ -3332,6 +3343,13 @@ int icnss_force_wake_release(struct device *dev)
return -EINVAL;
}
+ if (test_bit(ICNSS_FW_DOWN, &priv->state) ||
+ !test_bit(ICNSS_FW_READY, &priv->state)) {
+ icnss_pr_soc_wake("FW down, ignoring SOC Wake release state: 0x%lx\n",
+ priv->state);
+ return -EINVAL;
+ }
+
icnss_pr_soc_wake("Calling SOC Wake response");
if (atomic_read(&priv->soc_wake_ref_count) &&
diff --git a/inc/cnss2.h b/inc/cnss2.h
index ec32ef7..53f4d9c 100644
--- a/inc/cnss2.h
+++ b/inc/cnss2.h
@@ -224,6 +224,7 @@ struct cnss_wlan_enable_cfg {
struct cnss_rri_over_ddr_cfg rri_over_ddr_cfg;
u32 num_shadow_reg_v3_cfg;
struct cnss_shadow_reg_v3_cfg *shadow_reg_v3_cfg;
+ bool send_msi_ce;
};
enum cnss_driver_mode {