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