diff --git a/Kbuild b/Kbuild index f666f417b2..961e7eb296 100644 --- a/Kbuild +++ b/Kbuild @@ -38,6 +38,10 @@ ifeq ($(CONFIG_CNSS_HW_SECURE_DISABLE), y) KBUILD_CPPFLAGS += -DCONFIG_CNSS_HW_SECURE_DISABLE endif +ifeq ($(CONFIG_CNSS_HW_SECURE_SMEM), y) +KBUILD_CPPFLAGS += -DCONFIG_CNSS_HW_SECURE_SMEM +endif + ifeq ($(CONFIG_CNSS2_CONDITIONAL_POWEROFF),y) KBUILD_CPPFLAGS += -DCONFIG_CNSS2_CONDITIONAL_POWEROFF endif diff --git a/Makefile b/Makefile index f49b8e35c2..b9757ab27f 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,17 @@ WLAN_PLATFORM_ROOT = $(shell pwd) # so enable all flags (including debug flag CONFIG_CNSS2_DEBUG) by # default. KBUILD_OPTIONS := WLAN_PLATFORM_ROOT=$(WLAN_PLATFORM_ROOT) -ifeq ($(USE_EXTERNAL_CONFIGS),) +ifeq ($(WLAN_BASEMACHINE),qcs40x) +KBUILD_OPTIONS += CONFIG_CNSS_OUT_OF_TREE=y +KBUILD_OPTIONS += CONFIG_ICNSS2=m +KBUILD_OPTIONS += CONFIG_ICNSS2_QMI=y +KBUILD_OPTIONS += CONFIG_ICNSS2_DEBUG=y +KBUILD_OPTIONS += CONFIG_CNSS_QMI_SVC=m +KBUILD_OPTIONS += CONFIG_WCNSS_MEM_PRE_ALLOC=m +KBUILD_OPTIONS += CONFIG_CNSS_UTILS=m +KBUILD_OPTIONS += CONFIG_CNSS_GENL=m +KBUILD_OPTIONS += CONFIG_CNSS_PLAT_IPC_QMI_SVC=m +else ifeq ($(USE_EXTERNAL_CONFIGS),) KBUILD_OPTIONS += CONFIG_CNSS_OUT_OF_TREE=y KBUILD_OPTIONS += CONFIG_CNSS2=m KBUILD_OPTIONS += CONFIG_ICNSS2=m diff --git a/cnss2/Kconfig b/cnss2/Kconfig index 3b4c5e9f35..29787fc668 100644 --- a/cnss2/Kconfig +++ b/cnss2/Kconfig @@ -144,6 +144,13 @@ config CNSS_HW_SECURE_DISABLE handle WLAN cold boot initialization sequence changes if HW is disabled at boot and WLAN resume sequence after WLAN HW is enabled. +config CNSS_HW_SECURE_SMEM + bool "Enable SMEM API based HW peripheral security" + depends on CNSS2 + help + If enabled, CNSS platform driver will use SMEM APIs intead of SCM + APIs to check peripheral secure state of HW. + config CNSS2_SSR_DRIVER_DUMP bool "Enable Host SSR DRIVER DUMP Collection" depends on CNSS2 diff --git a/cnss2/main.c b/cnss2/main.c index 6f907be92f..3de5a70133 100644 --- a/cnss2/main.c +++ b/cnss2/main.c @@ -35,16 +35,21 @@ #include "reg.h" #ifdef CONFIG_CNSS_HW_SECURE_DISABLE +#ifdef CONFIG_CNSS_HW_SECURE_SMEM +#include +#define PERISEC_SMEM_ID 651 +#define HW_WIFI_UID 0x508 +#else #include "smcinvoke.h" #include "smcinvoke_object.h" #include "IClientEnv.h" - #define HW_STATE_UID 0x108 #define HW_OP_GET_STATE 1 #define HW_WIFI_UID 0x508 #define FEATURE_NOT_SUPPORTED 12 #define PERIPHERAL_NOT_FOUND 10 #endif +#endif #define CNSS_DUMP_FORMAT_VER 0x11 #define CNSS_DUMP_FORMAT_VER_V2 0x22 @@ -4349,11 +4354,39 @@ out: return ret; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0)) +union cnss_device_group_devres { + const struct attribute_group *group; +}; + +static void devm_cnss_group_remove(struct device *dev, void *res) +{ + union cnss_device_group_devres *devres = res; + const struct attribute_group *group = devres->group; + + cnss_pr_dbg("%s: removing group %p\n", __func__, group); + sysfs_remove_group(&dev->kobj, group); +} + +static int devm_cnss_group_match(struct device *dev, void *res, void *data) +{ + return ((union cnss_device_group_devres *)res) == data; +} + +static void cnss_remove_sysfs(struct cnss_plat_data *plat_priv) +{ + cnss_remove_sysfs_link(plat_priv); + WARN_ON(devres_release(&plat_priv->plat_dev->dev, + devm_cnss_group_remove, devm_cnss_group_match, + (void *)&cnss_attr_group)); +} +#else static void cnss_remove_sysfs(struct cnss_plat_data *plat_priv) { cnss_remove_sysfs_link(plat_priv); devm_device_remove_group(&plat_priv->plat_dev->dev, &cnss_attr_group); } +#endif static int cnss_event_work_init(struct cnss_plat_data *plat_priv) { @@ -4394,6 +4427,40 @@ static int cnss_reboot_notifier(struct notifier_block *nb, } #ifdef CONFIG_CNSS_HW_SECURE_DISABLE +#ifdef CONFIG_CNSS_HW_SECURE_SMEM +int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv) +{ + uint32_t *peripheralStateInfo = NULL; + size_t size = 0; + + /* Once this flag is set, secure peripheral feature + * will not be supported till next reboot + */ + if (plat_priv->sec_peri_feature_disable) + return 0; + + peripheralStateInfo = qcom_smem_get(QCOM_SMEM_HOST_ANY, PERISEC_SMEM_ID, &size); + if (IS_ERR_OR_NULL(peripheralStateInfo)) { + if (PTR_ERR(peripheralStateInfo) != -ENOENT) + CNSS_ASSERT(0); + + cnss_pr_dbg("Secure HW feature not enabled. ret = %d\n", + PTR_ERR(peripheralStateInfo)); + plat_priv->sec_peri_feature_disable = true; + return 0; + } + + cnss_pr_dbg("Secure HW state: %d\n", *peripheralStateInfo); + if ((*peripheralStateInfo >> (HW_WIFI_UID - 0x500)) & 0x1) + set_bit(CNSS_WLAN_HW_DISABLED, + &plat_priv->driver_state); + else + clear_bit(CNSS_WLAN_HW_DISABLED, + &plat_priv->driver_state); + + return 0; +} +#else int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv) { struct Object client_env; @@ -4459,6 +4526,7 @@ end: } return ret; } +#endif #else int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv) { diff --git a/cnss2/main.h b/cnss2/main.h index bd37abb29d..d2ccc1d97d 100644 --- a/cnss2/main.h +++ b/cnss2/main.h @@ -25,7 +25,6 @@ #include #if IS_ENABLED(CONFIG_MSM_QMP) #include -#include #endif #ifdef CONFIG_CNSS_OUT_OF_TREE #include "cnss2.h" diff --git a/cnss2/pineapple_consolidate_defconfig b/cnss2/pineapple_consolidate_defconfig index f2bc390235..cf4d1ad7bf 100644 --- a/cnss2/pineapple_consolidate_defconfig +++ b/cnss2/pineapple_consolidate_defconfig @@ -5,6 +5,7 @@ CONFIG_CNSS_QMI_SVC=m CONFIG_BUS_AUTO_SUSPEND=y CONFIG_CNSS2_SSR_DRIVER_DUMP=y CONFIG_CNSS_HW_SECURE_DISABLE=y +CONFIG_CNSS_HW_SECURE_SMEM=y CONFIG_CNSS2_SMMU_DB_SUPPORT=y CONFIG_CNSS_PLAT_IPC_QMI_SVC=m CONFIG_WCNSS_MEM_PRE_ALLOC=m diff --git a/cnss2/pineapple_gki_defconfig b/cnss2/pineapple_gki_defconfig index 800b39a03c..403fac6ea7 100644 --- a/cnss2/pineapple_gki_defconfig +++ b/cnss2/pineapple_gki_defconfig @@ -5,6 +5,7 @@ CONFIG_CNSS_QMI_SVC=m CONFIG_BUS_AUTO_SUSPEND=y CONFIG_CNSS2_SSR_DRIVER_DUMP=y CONFIG_CNSS_HW_SECURE_DISABLE=y +CONFIG_CNSS_HW_SECURE_SMEM=y CONFIG_CNSS2_SMMU_DB_SUPPORT=y CONFIG_CNSS_PLAT_IPC_QMI_SVC=m CONFIG_WCNSS_MEM_PRE_ALLOC=m diff --git a/cnss2/power.c b/cnss2/power.c index 7203f34688..fbd351f5fd 100644 --- a/cnss2/power.c +++ b/cnss2/power.c @@ -18,6 +18,9 @@ #include "main.h" #include "debug.h" #include "bus.h" +#if IS_ENABLED(CONFIG_MSM_QMP) +#include +#endif #if IS_ENABLED(CONFIG_ARCH_QCOM) static struct cnss_vreg_cfg cnss_vreg_list[] = { diff --git a/icnss2/main.c b/icnss2/main.c index 856aa61141..f0898bc367 100644 --- a/icnss2/main.c +++ b/icnss2/main.c @@ -162,7 +162,8 @@ static ssize_t icnss_sysfs_store(struct kobject *kobj, icnss_pr_dbg("Received shutdown indication"); atomic_set(&priv->is_shutdown, true); - if (priv->wpss_supported && priv->device_id == ADRASTEA_DEVICE_ID) + if ((priv->wpss_supported || priv->rproc_fw_download) && + priv->device_id == ADRASTEA_DEVICE_ID) icnss_wpss_unload(priv); return count; } @@ -1589,15 +1590,22 @@ out: static int icnss_fw_crashed(struct icnss_priv *priv, struct icnss_event_pd_service_down_data *event_data) { + struct icnss_uevent_fw_down_data fw_down_data = {0}; + icnss_pr_dbg("FW crashed, state: 0x%lx\n", priv->state); set_bit(ICNSS_PD_RESTART, &priv->state); - clear_bit(ICNSS_FW_READY, &priv->state); icnss_pm_stay_awake(priv); - if (test_bit(ICNSS_DRIVER_PROBED, &priv->state)) - icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_CRASHED, NULL); + if (test_bit(ICNSS_DRIVER_PROBED, &priv->state) && + test_bit(ICNSS_FW_READY, &priv->state)) { + clear_bit(ICNSS_FW_READY, &priv->state); + fw_down_data.crashed = true; + icnss_call_driver_uevent(priv, + ICNSS_UEVENT_FW_DOWN, + &fw_down_data); + } if (event_data && event_data->fw_rejuvenate) wlfw_rejuvenate_ack_send_sync_msg(priv); @@ -2831,7 +2839,8 @@ static int icnss_enable_recovery(struct icnss_priv *priv) return 0; } - icnss_modem_ssr_register_notifier(priv); + if (!(priv->rproc_fw_download)) + icnss_modem_ssr_register_notifier(priv); if (priv->is_slate_rfa) { icnss_slate_ssr_register_notifier(priv); @@ -4069,7 +4078,7 @@ static ssize_t wpss_boot_store(struct device *dev, struct icnss_priv *priv = dev_get_drvdata(dev); int wpss_rproc = 0; - if (!priv->wpss_supported) + if (!priv->wpss_supported && !priv->rproc_fw_download) return count; if (sscanf(buf, "%du", &wpss_rproc) != 1) { @@ -4561,6 +4570,10 @@ static void icnss_init_control_params(struct icnss_priv *priv) "bdf-download-support")) priv->bdf_download_support = true; + if (of_property_read_bool(priv->pdev->dev.of_node, + "rproc-fw-download")) + priv->rproc_fw_download = true; + if (priv->bdf_download_support && priv->device_id == ADRASTEA_DEVICE_ID) priv->ctrl_params.bdf_type = ICNSS_BDF_BIN; } @@ -4766,9 +4779,11 @@ static int icnss_probe(struct platform_device *pdev) priv->use_nv_mac = icnss_use_nv_mac(priv); icnss_pr_dbg("NV MAC feature is %s\n", priv->use_nv_mac ? "Mandatory":"Not Mandatory"); - INIT_WORK(&wpss_loader, icnss_wpss_load); } + if (priv->wpss_supported || priv->rproc_fw_download) + INIT_WORK(&wpss_loader, icnss_wpss_load); + timer_setup(&priv->recovery_timer, icnss_recovery_timeout_hdlr, 0); diff --git a/icnss2/main.h b/icnss2/main.h index e6a91cbaab..a16aac0a2f 100644 --- a/icnss2/main.h +++ b/icnss2/main.h @@ -523,6 +523,7 @@ struct icnss_priv { enum icnss_rd_card_chain_cap rd_card_chain_cap; enum icnss_phy_he_channel_width_cap phy_he_channel_width_cap; enum icnss_phy_qam_cap phy_qam_cap; + bool rproc_fw_download; }; struct icnss_reg_info {