diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2023-04-17 00:40:31 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2023-04-17 00:40:31 -0700 |
commit | 58e28d767d9b33016dec92b998e53caec74ffebf (patch) | |
tree | 6dcd40c65025fdf4bc2022ff25e54a9bbc87bebd | |
parent | 1c7d481a2491b2b724848f98fb8fc71498b77a14 (diff) | |
parent | ddbe3d0e4eb2bf564a0a00ad577bca3d18dda28b (diff) | |
download | wlan-platform-58e28d767d9b33016dec92b998e53caec74ffebf.tar.gz |
Merge ddbe3d0e4eb2bf564a0a00ad577bca3d18dda28b on remote branch
Change-Id: Iad5d2e142adb48ed5086ba8c0c66284296eb6fb5
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | Kbuild | 4 | ||||
-rw-r--r-- | cnss2/bus.c | 23 | ||||
-rw-r--r-- | cnss2/bus.h | 6 | ||||
-rw-r--r-- | cnss2/genl.c | 9 | ||||
-rw-r--r-- | cnss2/main.c | 65 | ||||
-rw-r--r-- | cnss2/pci.c | 170 | ||||
-rw-r--r-- | cnss2/pci.h | 5 | ||||
-rw-r--r-- | cnss2/pci_platform.h | 15 | ||||
-rw-r--r-- | cnss2/pci_qcom.c | 13 | ||||
-rw-r--r-- | cnss2/qmi.c | 68 | ||||
-rw-r--r-- | cnss2/reg.h | 2 | ||||
-rw-r--r-- | icnss2/main.c | 22 | ||||
-rw-r--r-- | inc/cnss2.h | 1 |
14 files changed, 348 insertions, 57 deletions
@@ -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 @@ -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 { |