History

PCI: let pci_disable_link_state propagate errors

Drivers may rely on pci_disable_link_state() having disabled certain ASPM link states. If OS can't control ASPM then pci_disable_link_state() turns into a no-op w/o informing the caller. The driver therefore may falsely assume the respective ASPM link states are disabled. Let pci_disable_link_state() propagate errors to the caller, enabling the caller to react accordingly.

Heiner Kallweit committed 7 years ago

Commit 4cfd2181 parent dca73a62 files · +15 −12Browse files

Unified · Split

2 files
  1. drivers/pci/pcie/aspm.c +11 −9
  2. include/linux/pci-aspm.h +4 −3
drivers/pci/pcie/aspm.c+11−9
@@ -1062,18 +1062,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) · 1061 unmodified lines
1062 up_read(&pci_bus_sem);1062 up_read(&pci_bus_sem);
1063}1063}
1064 1064
1065static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)1065static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
1066{1066{
1067 struct pci_dev *parent = pdev->bus->self;1067 struct pci_dev *parent = pdev->bus->self;
1068 struct pcie_link_state *link;1068 struct pcie_link_state *link;
1069 1069
1070 if (!pci_is_pcie(pdev))1070 if (!pci_is_pcie(pdev))
1071 return;1071 return 0;
1072 1072
1073 if (pdev->has_secondary_link)1073 if (pdev->has_secondary_link)
1074 parent = pdev;1074 parent = pdev;
1075 if (!parent || !parent->link_state)1075 if (!parent || !parent->link_state)
1076 return;1076 return -EINVAL;
1077 1077
1078 /*1078 /*
1079 * A driver requested that ASPM be disabled on this device, but1079 * A driver requested that ASPM be disabled on this device, but
@@ -1085,7 +1085,7 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) · 5 unmodified lines
1085 */1085 */
1086 if (aspm_disabled) {1086 if (aspm_disabled) {
1087 pci_warn(pdev, "can't disable ASPM; OS doesn't have ASPM control\n");1087 pci_warn(pdev, "can't disable ASPM; OS doesn't have ASPM control\n");
1088 return;1088 return -EPERM;
1089 }1089 }
1090 1090
1091 if (sem)1091 if (sem)
@@ -1105,11 +1105,13 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) · 13 unmodified lines
1105 mutex_unlock(&aspm_lock);1105 mutex_unlock(&aspm_lock);
1106 if (sem)1106 if (sem)
1107 up_read(&pci_bus_sem);1107 up_read(&pci_bus_sem);
1108
1109 return 0;
1108}1110}
1109 1111
1110void pci_disable_link_state_locked(struct pci_dev *pdev, int state)1112int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
1111{1113{
1112 __pci_disable_link_state(pdev, state, false);1114 return __pci_disable_link_state(pdev, state, false);
1113}1115}
1114EXPORT_SYMBOL(pci_disable_link_state_locked);1116EXPORT_SYMBOL(pci_disable_link_state_locked);
1115 1117
@@ -1117,14 +1119,14 @@ EXPORT_SYMBOL(pci_disable_link_state_locked); · 1 unmodified line
1117 * pci_disable_link_state - Disable device's link state, so the link will1119 * pci_disable_link_state - Disable device's link state, so the link will
1118 * never enter specific states. Note that if the BIOS didn't grant ASPM1120 * never enter specific states. Note that if the BIOS didn't grant ASPM
1119 * control to the OS, this does nothing because we can't touch the LNKCTL1121 * control to the OS, this does nothing because we can't touch the LNKCTL
1120 * register.1122 * register. Returns 0 or a negative errno.
1121 *1123 *
1122 * @pdev: PCI device1124 * @pdev: PCI device
1123 * @state: ASPM link state to disable1125 * @state: ASPM link state to disable
1124 */1126 */
1125void pci_disable_link_state(struct pci_dev *pdev, int state)1127int pci_disable_link_state(struct pci_dev *pdev, int state)
1126{1128{
1127 __pci_disable_link_state(pdev, state, true);1129 return __pci_disable_link_state(pdev, state, true);
1128}1130}
1129EXPORT_SYMBOL(pci_disable_link_state);1131EXPORT_SYMBOL(pci_disable_link_state);
1130 1132
include/linux/pci-aspm.h+4−3
@@ -24,11 +24,12 @@ · 23 unmodified lines
24#define PCIE_LINK_STATE_CLKPM 424#define PCIE_LINK_STATE_CLKPM 4
25 25
26#ifdef CONFIG_PCIEASPM26#ifdef CONFIG_PCIEASPM
27void pci_disable_link_state(struct pci_dev *pdev, int state);27int pci_disable_link_state(struct pci_dev *pdev, int state);
28void pci_disable_link_state_locked(struct pci_dev *pdev, int state);28int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
29void pcie_no_aspm(void);29void pcie_no_aspm(void);
30#else30#else
31static inline void pci_disable_link_state(struct pci_dev *pdev, int state) { }31static inline int pci_disable_link_state(struct pci_dev *pdev, int state)
32{ return 0; }
32static inline void pcie_no_aspm(void) { }33static inline void pcie_no_aspm(void) { }
33#endif34#endif
34 35

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t