Merge tag 'wireless-drivers-2020-12-22' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / drivers / net / wireless / ath / ath11k / pci.c
index 857647aa57c8a7a66c41eaafa430667d062bc88e..20b415cd96c4aadaa233aed4cbabbae6996c4201 100644 (file)
@@ -274,7 +274,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
                                      PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG,
                                      PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,
                                      PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
-       if (!ret) {
+       if (ret) {
                ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
                return ret;
        }
@@ -283,7 +283,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_REG,
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_VAL,
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
-       if (!ret) {
+       if (ret) {
                ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
                return ret;
        }
@@ -292,7 +292,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_REG,
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_VAL,
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
-       if (!ret) {
+       if (ret) {
                ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
                return ret;
        }
@@ -301,7 +301,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_REG,
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_VAL,
                                      PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
-       if (!ret) {
+       if (ret) {
                ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
                return ret;
        }
@@ -886,6 +886,32 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
                pci_disable_device(pci_dev);
 }
 
+static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
+{
+       struct ath11k_base *ab = ab_pci->ab;
+
+       pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+                                 &ab_pci->link_ctl);
+
+       ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n",
+                  ab_pci->link_ctl,
+                  u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
+                  u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
+
+       /* disable L0s and L1 */
+       pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+                                  ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
+
+       set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);
+}
+
+static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)
+{
+       if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))
+               pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+                                          ab_pci->link_ctl);
+}
+
 static int ath11k_pci_power_up(struct ath11k_base *ab)
 {
        struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
@@ -895,6 +921,11 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
        clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
        ath11k_pci_sw_reset(ab_pci->ab, true);
 
+       /* Disable ASPM during firmware download due to problems switching
+        * to AMSS state.
+        */
+       ath11k_pci_aspm_disable(ab_pci);
+
        ret = ath11k_mhi_start(ab_pci);
        if (ret) {
                ath11k_err(ab, "failed to start mhi: %d\n", ret);
@@ -908,6 +939,9 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
 {
        struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
 
+       /* restore aspm in case firmware bootup fails */
+       ath11k_pci_aspm_restore(ab_pci);
+
        ath11k_pci_force_wake(ab_pci->ab);
        ath11k_mhi_stop(ab_pci);
        clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
@@ -965,6 +999,8 @@ static int ath11k_pci_start(struct ath11k_base *ab)
 
        set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
 
+       ath11k_pci_aspm_restore(ab_pci);
+
        ath11k_pci_ce_irqs_enable(ab);
        ath11k_ce_rx_post_buf(ab);