Merge tag 'drm-msm-fixes-2021-06-10' of https://gitlab.freedesktop.org/drm/msm into...
[linux-2.6-microblaze.git] / drivers / net / wireless / mediatek / mt76 / pci.c
1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org>
4  */
5
6 #include "mt76.h"
7 #include <linux/pci.h>
8
9 void mt76_pci_disable_aspm(struct pci_dev *pdev)
10 {
11         struct pci_dev *parent = pdev->bus->self;
12         u16 aspm_conf, parent_aspm_conf = 0;
13
14         pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf);
15         aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
16         if (parent) {
17                 pcie_capability_read_word(parent, PCI_EXP_LNKCTL,
18                                           &parent_aspm_conf);
19                 parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
20         }
21
22         if (!aspm_conf && (!parent || !parent_aspm_conf)) {
23                 /* aspm already disabled */
24                 return;
25         }
26
27         dev_info(&pdev->dev, "disabling ASPM %s %s\n",
28                  (aspm_conf & PCI_EXP_LNKCTL_ASPM_L0S) ? "L0s" : "",
29                  (aspm_conf & PCI_EXP_LNKCTL_ASPM_L1) ? "L1" : "");
30
31         if (IS_ENABLED(CONFIG_PCIEASPM)) {
32                 int err;
33
34                 err = pci_disable_link_state(pdev, aspm_conf);
35                 if (!err)
36                         return;
37         }
38
39         /* both device and parent should have the same ASPM setting.
40          * disable ASPM in downstream component first and then upstream.
41          */
42         pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_conf);
43         if (parent)
44                 pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
45                                            aspm_conf);
46 }
47 EXPORT_SYMBOL_GPL(mt76_pci_disable_aspm);