From 79edf86d87159db5a4f79ae78a4a3dc96ef2af29 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Thu, 14 Jun 2018 15:29:57 +0800 Subject: [PATCH] ASPM quirk for SM/PM/EVO 961 Signed-off-by: Kai-Heng Feng --- drivers/pci/pcie/aspm.c | 14 ++++++++++---- drivers/pci/quirks.c | 9 ++++++++- include/linux/pci-aspm.h | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 3b9b4d50cd98..9434382d26dc 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1028,7 +1028,7 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) up_read(&pci_bus_sem); } -static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) +static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, bool quirk) { struct pci_dev *parent = pdev->bus->self; struct pcie_link_state *link; @@ -1049,7 +1049,7 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) * a similar mechanism using "PciASPMOptOut", which is also * ignored in this situation. */ - if (aspm_disabled) { + if (aspm_disabled && !quirk) { dev_warn(&pdev->dev, "can't disable ASPM; OS doesn't have ASPM control\n"); return; } @@ -1075,7 +1075,7 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) void pci_disable_link_state_locked(struct pci_dev *pdev, int state) { - __pci_disable_link_state(pdev, state, false); + __pci_disable_link_state(pdev, state, false, false); } EXPORT_SYMBOL(pci_disable_link_state_locked); @@ -1090,10 +1090,16 @@ EXPORT_SYMBOL(pci_disable_link_state_locked); */ void pci_disable_link_state(struct pci_dev *pdev, int state) { - __pci_disable_link_state(pdev, state, true); + __pci_disable_link_state(pdev, state, true, false); } EXPORT_SYMBOL(pci_disable_link_state); +void pci_disable_link_state_quirk(struct pci_dev *pdev, int state) +{ + __pci_disable_link_state(pdev, state, true, true); +} +EXPORT_SYMBOL(pci_disable_link_state_quirk); + static int pcie_aspm_set_policy(const char *val, const struct kernel_param *kp) { diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 26b3ed731208..05568d14c210 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2083,7 +2083,7 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, static void quirk_disable_aspm_l0s(struct pci_dev *dev) { dev_info(&dev->dev, "Disabling L0s\n"); - pci_disable_link_state(dev, PCIE_LINK_STATE_L0S); + pci_disable_link_state_quirk(dev, PCIE_LINK_STATE_L0S); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a7, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a9, quirk_disable_aspm_l0s); @@ -2100,6 +2100,13 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s); +static void quirk_disable_aspm_l1(struct pci_dev *dev) +{ + dev_info(&dev->dev, "Disabling L1\n"); + pci_disable_link_state_quirk(dev, PCIE_LINK_STATE_L1); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SAMSUNG, 0xa804, quirk_disable_aspm_l1); + static void fixup_rev1_53c810(struct pci_dev *dev) { u32 class = dev->class; diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h index df28af5cef21..853d975c82a8 100644 --- a/include/linux/pci-aspm.h +++ b/include/linux/pci-aspm.h @@ -25,6 +25,7 @@ #ifdef CONFIG_PCIEASPM void pci_disable_link_state(struct pci_dev *pdev, int state); +void pci_disable_link_state_quirk(struct pci_dev *pdev, int state); void pci_disable_link_state_locked(struct pci_dev *pdev, int state); void pcie_no_aspm(void); #else -- 2.17.0