Skip to content

Commit de82f60

Browse files
Michael BottiniLorenzo Pieralisi
authored andcommitted
PCI/ASPM: Add pci_enable_link_state()
Add pci_enable_link_state() to allow devices to change the default BIOS configured states. Clears the BIOS default settings then sets the new states and reconfigures the link under the semaphore. Also add PCIE_LINK_STATE_ALL macro for convenience for callers that want to enable all link states. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael Bottini <[email protected]> Signed-off-by: David E. Box <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Reviewed-by: Kuppuswamy Sathyanarayanan <[email protected]> Acked-by: Bjorn Helgaas <[email protected]>
1 parent 1b929c0 commit de82f60

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

drivers/pci/pcie/aspm.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,60 @@ int pci_disable_link_state(struct pci_dev *pdev, int state)
11811181
}
11821182
EXPORT_SYMBOL(pci_disable_link_state);
11831183

1184+
/**
1185+
* pci_enable_link_state - Clear and set the default device link state so that
1186+
* the link may be allowed to enter the specified states. Note that if the
1187+
* BIOS didn't grant ASPM control to the OS, this does nothing because we can't
1188+
* touch the LNKCTL register. Also note that this does not enable states
1189+
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
1190+
*
1191+
* @pdev: PCI device
1192+
* @state: Mask of ASPM link states to enable
1193+
*/
1194+
int pci_enable_link_state(struct pci_dev *pdev, int state)
1195+
{
1196+
struct pcie_link_state *link = pcie_aspm_get_link(pdev);
1197+
1198+
if (!link)
1199+
return -EINVAL;
1200+
/*
1201+
* A driver requested that ASPM be enabled on this device, but
1202+
* if we don't have permission to manage ASPM (e.g., on ACPI
1203+
* systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and
1204+
* the _OSC method), we can't honor that request.
1205+
*/
1206+
if (aspm_disabled) {
1207+
pci_warn(pdev, "can't override BIOS ASPM; OS doesn't have ASPM control\n");
1208+
return -EPERM;
1209+
}
1210+
1211+
down_read(&pci_bus_sem);
1212+
mutex_lock(&aspm_lock);
1213+
link->aspm_default = 0;
1214+
if (state & PCIE_LINK_STATE_L0S)
1215+
link->aspm_default |= ASPM_STATE_L0S;
1216+
if (state & PCIE_LINK_STATE_L1)
1217+
/* L1 PM substates require L1 */
1218+
link->aspm_default |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
1219+
if (state & PCIE_LINK_STATE_L1_1)
1220+
link->aspm_default |= ASPM_STATE_L1_1;
1221+
if (state & PCIE_LINK_STATE_L1_2)
1222+
link->aspm_default |= ASPM_STATE_L1_2;
1223+
if (state & PCIE_LINK_STATE_L1_1_PCIPM)
1224+
link->aspm_default |= ASPM_STATE_L1_1_PCIPM;
1225+
if (state & PCIE_LINK_STATE_L1_2_PCIPM)
1226+
link->aspm_default |= ASPM_STATE_L1_2_PCIPM;
1227+
pcie_config_aspm_link(link, policy_to_aspm_state(link));
1228+
1229+
link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
1230+
pcie_set_clkpm(link, policy_to_clkpm_state(link));
1231+
mutex_unlock(&aspm_lock);
1232+
up_read(&pci_bus_sem);
1233+
1234+
return 0;
1235+
}
1236+
EXPORT_SYMBOL(pci_enable_link_state);
1237+
11841238
static int pcie_aspm_set_policy(const char *val,
11851239
const struct kernel_param *kp)
11861240
{

include/linux/pci.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,10 +1685,15 @@ extern bool pcie_ports_native;
16851685
#define PCIE_LINK_STATE_L1_2 BIT(4)
16861686
#define PCIE_LINK_STATE_L1_1_PCIPM BIT(5)
16871687
#define PCIE_LINK_STATE_L1_2_PCIPM BIT(6)
1688+
#define PCIE_LINK_STATE_ALL (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |\
1689+
PCIE_LINK_STATE_CLKPM | PCIE_LINK_STATE_L1_1 |\
1690+
PCIE_LINK_STATE_L1_2 | PCIE_LINK_STATE_L1_1_PCIPM |\
1691+
PCIE_LINK_STATE_L1_2_PCIPM)
16881692

16891693
#ifdef CONFIG_PCIEASPM
16901694
int pci_disable_link_state(struct pci_dev *pdev, int state);
16911695
int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
1696+
int pci_enable_link_state(struct pci_dev *pdev, int state);
16921697
void pcie_no_aspm(void);
16931698
bool pcie_aspm_support_enabled(void);
16941699
bool pcie_aspm_enabled(struct pci_dev *pdev);
@@ -1697,6 +1702,8 @@ static inline int pci_disable_link_state(struct pci_dev *pdev, int state)
16971702
{ return 0; }
16981703
static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
16991704
{ return 0; }
1705+
static inline int pci_enable_link_state(struct pci_dev *pdev, int state)
1706+
{ return 0; }
17001707
static inline void pcie_no_aspm(void) { }
17011708
static inline bool pcie_aspm_support_enabled(void) { return false; }
17021709
static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }

0 commit comments

Comments
 (0)