diff --git a/Kbuild b/Kbuild index 633d1a6c0b..6d98f8164d 100644 --- a/Kbuild +++ b/Kbuild @@ -70,6 +70,10 @@ ifeq ($(CONFIG_CNSS2_SMMU_DB_SUPPORT),y) KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SMMU_DB_SUPPORT endif +ifeq ($(CONFIG_CNSS2_ENUM_WITH_LOW_SPEED),y) +KBUILD_CPPFLAGS += -DCONFIG_CNSS2_ENUM_WITH_LOW_SPEED +endif + obj-$(CONFIG_CNSS2) += cnss2/ obj-$(CONFIG_ICNSS2) += icnss2/ obj-$(CONFIG_CNSS_GENL) += cnss_genl/ diff --git a/cnss2/Kconfig b/cnss2/Kconfig index 7897ddee43..3b4c5e9f35 100644 --- a/cnss2/Kconfig +++ b/cnss2/Kconfig @@ -164,3 +164,11 @@ config WCNSS_MEM_PRE_ALLOC 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. diff --git a/cnss2/pci.c b/cnss2/pci.c index e6447a8240..a7030e9a40 100644 --- a/cnss2/pci.c +++ b/cnss2/pci.c @@ -6901,6 +6901,54 @@ static void cnss_pci_suspend_pwroff(struct pci_dev *pci_dev) } } +#ifdef CONFIG_CNSS2_ENUM_WITH_LOW_SPEED +static void +cnss_pci_downgrade_rc_speed(struct cnss_plat_data *plat_priv, u32 rc_num) +{ + int ret; + + ret = cnss_pci_set_max_link_speed(plat_priv->bus_priv, rc_num, + PCI_EXP_LNKSTA_CLS_2_5GB); + if (ret) + cnss_pr_err("Failed to set max PCIe RC%x link speed to Gen1, err = %d\n", + rc_num, ret); +} + +static void +cnss_pci_restore_rc_speed(struct cnss_pci_data *pci_priv) +{ + int ret; + struct cnss_plat_data *plat_priv = pci_priv->plat_priv; + + /* if not Genoa, do not restore rc speed */ + if (pci_priv->device_id != QCN7605_DEVICE_ID) { + /* The request 0 will reset maximum GEN speed to default */ + ret = cnss_pci_set_max_link_speed(pci_priv, plat_priv->rc_num, 0); + if (ret) + cnss_pr_err("Failed to reset max PCIe RC%x link speed to default, err = %d\n", + plat_priv->rc_num, ret); + + /* suspend/resume will trigger retain to re-establish link speed */ + ret = cnss_suspend_pci_link(pci_priv); + if (ret) + cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret); + + ret = cnss_resume_pci_link(pci_priv); + cnss_pr_err("Failed to resume PCI link, err = %d\n", ret); + } +} +#else +static void +cnss_pci_downgrade_rc_speed(struct cnss_plat_data *plat_priv, u32 rc_num) +{ +} + +static void +cnss_pci_restore_rc_speed(struct cnss_pci_data *pci_priv) +{ +} +#endif + static int cnss_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { @@ -6936,6 +6984,8 @@ static int cnss_pci_probe(struct pci_dev *pci_dev, if (plat_priv->use_pm_domain) dev->pm_domain = &cnss_pm_domain; + cnss_pci_restore_rc_speed(pci_priv); + ret = cnss_pci_get_dev_cfg_node(plat_priv); if (ret) { cnss_pr_err("Failed to get device cfg node, err = %d\n", ret); @@ -7138,6 +7188,8 @@ static int cnss_pci_enumerate(struct cnss_plat_data *plat_priv, u32 rc_num) if (ret && ret != -EPROBE_DEFER) cnss_pr_err("Failed to set max PCIe RC%x link speed to Gen2, err = %d\n", rc_num, ret); + } else { + cnss_pci_downgrade_rc_speed(plat_priv, rc_num); } cnss_pr_dbg("Trying to enumerate with PCIe RC%x\n", rc_num);