xref: /openbmc/linux/drivers/pci/pcie/aspm.c (revision c845428b7a9157523103100806bc8130d64769c8)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
27d715a6cSShaohua Li /*
3df62ab5eSBjorn Helgaas  * Enable PCIe link L0s/L1 state and Clock Power Management
47d715a6cSShaohua Li  *
57d715a6cSShaohua Li  * Copyright (C) 2007 Intel
67d715a6cSShaohua Li  * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
77d715a6cSShaohua Li  * Copyright (C) Shaohua Li (shaohua.li@intel.com)
87d715a6cSShaohua Li  */
97d715a6cSShaohua Li 
107d715a6cSShaohua Li #include <linux/kernel.h>
117afeb84dSBjorn Helgaas #include <linux/math.h>
127d715a6cSShaohua Li #include <linux/module.h>
137d715a6cSShaohua Li #include <linux/moduleparam.h>
147d715a6cSShaohua Li #include <linux/pci.h>
157d715a6cSShaohua Li #include <linux/pci_regs.h>
167d715a6cSShaohua Li #include <linux/errno.h>
177d715a6cSShaohua Li #include <linux/pm.h>
187d715a6cSShaohua Li #include <linux/init.h>
197d715a6cSShaohua Li #include <linux/slab.h>
202a42d9dbSThomas Renninger #include <linux/jiffies.h>
21987a4c78SAndrew Patterson #include <linux/delay.h>
227d715a6cSShaohua Li #include "../pci.h"
237d715a6cSShaohua Li 
247d715a6cSShaohua Li #ifdef MODULE_PARAM_PREFIX
257d715a6cSShaohua Li #undef MODULE_PARAM_PREFIX
267d715a6cSShaohua Li #endif
277d715a6cSShaohua Li #define MODULE_PARAM_PREFIX "pcie_aspm."
287d715a6cSShaohua Li 
29ac18018aSKenji Kaneshige /* Note: those are not register definitions */
30ac18018aSKenji Kaneshige #define ASPM_STATE_L0S_UP	(1)	/* Upstream direction L0s state */
31ac18018aSKenji Kaneshige #define ASPM_STATE_L0S_DW	(2)	/* Downstream direction L0s state */
32ac18018aSKenji Kaneshige #define ASPM_STATE_L1		(4)	/* L1 state */
33b2103ccbSRajat Jain #define ASPM_STATE_L1_1		(8)	/* ASPM L1.1 state */
34b2103ccbSRajat Jain #define ASPM_STATE_L1_2		(0x10)	/* ASPM L1.2 state */
35b2103ccbSRajat Jain #define ASPM_STATE_L1_1_PCIPM	(0x20)	/* PCI PM L1.1 state */
36b2103ccbSRajat Jain #define ASPM_STATE_L1_2_PCIPM	(0x40)	/* PCI PM L1.2 state */
37b2103ccbSRajat Jain #define ASPM_STATE_L1_SS_PCIPM	(ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1_2_PCIPM)
38b2103ccbSRajat Jain #define ASPM_STATE_L1_2_MASK	(ASPM_STATE_L1_2 | ASPM_STATE_L1_2_PCIPM)
39b2103ccbSRajat Jain #define ASPM_STATE_L1SS		(ASPM_STATE_L1_1 | ASPM_STATE_L1_1_PCIPM |\
40b2103ccbSRajat Jain 				 ASPM_STATE_L1_2_MASK)
41ac18018aSKenji Kaneshige #define ASPM_STATE_L0S		(ASPM_STATE_L0S_UP | ASPM_STATE_L0S_DW)
42b2103ccbSRajat Jain #define ASPM_STATE_ALL		(ASPM_STATE_L0S | ASPM_STATE_L1 |	\
43b2103ccbSRajat Jain 				 ASPM_STATE_L1SS)
44ac18018aSKenji Kaneshige 
457d715a6cSShaohua Li struct pcie_link_state {
465cde89d8SKenji Kaneshige 	struct pci_dev *pdev;		/* Upstream component of the Link */
47b5a0a9b5SRajat Jain 	struct pci_dev *downstream;	/* Downstream component, function 0 */
485c92ffb1SKenji Kaneshige 	struct pcie_link_state *root;	/* pointer to the root port link */
495cde89d8SKenji Kaneshige 	struct pcie_link_state *parent;	/* pointer to the parent Link state */
505cde89d8SKenji Kaneshige 	struct list_head sibling;	/* node in link_list */
517d715a6cSShaohua Li 
527d715a6cSShaohua Li 	/* ASPM state */
53b2103ccbSRajat Jain 	u32 aspm_support:7;		/* Supported ASPM state */
54b2103ccbSRajat Jain 	u32 aspm_enabled:7;		/* Enabled ASPM state */
55b2103ccbSRajat Jain 	u32 aspm_capable:7;		/* Capable ASPM state with latency */
56b2103ccbSRajat Jain 	u32 aspm_default:7;		/* Default ASPM state by BIOS */
57b2103ccbSRajat Jain 	u32 aspm_disable:7;		/* Disabled ASPM state */
5880bfdbe3SKenji Kaneshige 
594d246e45SKenji Kaneshige 	/* Clock PM state */
604d246e45SKenji Kaneshige 	u32 clkpm_capable:1;		/* Clock PM capable? */
614d246e45SKenji Kaneshige 	u32 clkpm_enabled:1;		/* Current Clock PM state */
624d246e45SKenji Kaneshige 	u32 clkpm_default:1;		/* Default Clock PM state by BIOS */
6335efea32SHeiner Kallweit 	u32 clkpm_disable:1;		/* Clock PM disabled */
647d715a6cSShaohua Li };
657d715a6cSShaohua Li 
663c076351SMatthew Garrett static int aspm_disabled, aspm_force;
678b8bae90SRafael J. Wysocki static bool aspm_support_enabled = true;
687d715a6cSShaohua Li static DEFINE_MUTEX(aspm_lock);
697d715a6cSShaohua Li static LIST_HEAD(link_list);
707d715a6cSShaohua Li 
717d715a6cSShaohua Li #define POLICY_DEFAULT 0	/* BIOS default setting */
727d715a6cSShaohua Li #define POLICY_PERFORMANCE 1	/* high performance */
737d715a6cSShaohua Li #define POLICY_POWERSAVE 2	/* high power saving */
74b2103ccbSRajat Jain #define POLICY_POWER_SUPERSAVE 3 /* possibly even more power saving */
75ad71c962SMatthew Garrett 
76ad71c962SMatthew Garrett #ifdef CONFIG_PCIEASPM_PERFORMANCE
77ad71c962SMatthew Garrett static int aspm_policy = POLICY_PERFORMANCE;
78ad71c962SMatthew Garrett #elif defined CONFIG_PCIEASPM_POWERSAVE
79ad71c962SMatthew Garrett static int aspm_policy = POLICY_POWERSAVE;
80b2103ccbSRajat Jain #elif defined CONFIG_PCIEASPM_POWER_SUPERSAVE
81b2103ccbSRajat Jain static int aspm_policy = POLICY_POWER_SUPERSAVE;
82ad71c962SMatthew Garrett #else
837d715a6cSShaohua Li static int aspm_policy;
84ad71c962SMatthew Garrett #endif
85ad71c962SMatthew Garrett 
867d715a6cSShaohua Li static const char *policy_str[] = {
877d715a6cSShaohua Li 	[POLICY_DEFAULT] = "default",
887d715a6cSShaohua Li 	[POLICY_PERFORMANCE] = "performance",
89b2103ccbSRajat Jain 	[POLICY_POWERSAVE] = "powersave",
90b2103ccbSRajat Jain 	[POLICY_POWER_SUPERSAVE] = "powersupersave"
917d715a6cSShaohua Li };
927d715a6cSShaohua Li 
9343262f00SBolarinwa O. Saheed /*
9443262f00SBolarinwa O. Saheed  * The L1 PM substate capability is only implemented in function 0 in a
9543262f00SBolarinwa O. Saheed  * multi function device.
9643262f00SBolarinwa O. Saheed  */
pci_function_0(struct pci_bus * linkbus)9743262f00SBolarinwa O. Saheed static struct pci_dev *pci_function_0(struct pci_bus *linkbus)
9843262f00SBolarinwa O. Saheed {
9943262f00SBolarinwa O. Saheed 	struct pci_dev *child;
10043262f00SBolarinwa O. Saheed 
10143262f00SBolarinwa O. Saheed 	list_for_each_entry(child, &linkbus->devices, bus_list)
10243262f00SBolarinwa O. Saheed 		if (PCI_FUNC(child->devfn) == 0)
10343262f00SBolarinwa O. Saheed 			return child;
10443262f00SBolarinwa O. Saheed 	return NULL;
10543262f00SBolarinwa O. Saheed }
10643262f00SBolarinwa O. Saheed 
policy_to_aspm_state(struct pcie_link_state * link)1075aa63583SKenji Kaneshige static int policy_to_aspm_state(struct pcie_link_state *link)
1087d715a6cSShaohua Li {
1097d715a6cSShaohua Li 	switch (aspm_policy) {
1107d715a6cSShaohua Li 	case POLICY_PERFORMANCE:
1117d715a6cSShaohua Li 		/* Disable ASPM and Clock PM */
1127d715a6cSShaohua Li 		return 0;
1137d715a6cSShaohua Li 	case POLICY_POWERSAVE:
1147d715a6cSShaohua Li 		/* Enable ASPM L0s/L1 */
115b2103ccbSRajat Jain 		return (ASPM_STATE_L0S | ASPM_STATE_L1);
116b2103ccbSRajat Jain 	case POLICY_POWER_SUPERSAVE:
117b2103ccbSRajat Jain 		/* Enable Everything */
118ac18018aSKenji Kaneshige 		return ASPM_STATE_ALL;
1197d715a6cSShaohua Li 	case POLICY_DEFAULT:
1205aa63583SKenji Kaneshige 		return link->aspm_default;
1217d715a6cSShaohua Li 	}
1227d715a6cSShaohua Li 	return 0;
1237d715a6cSShaohua Li }
1247d715a6cSShaohua Li 
policy_to_clkpm_state(struct pcie_link_state * link)1255aa63583SKenji Kaneshige static int policy_to_clkpm_state(struct pcie_link_state *link)
1267d715a6cSShaohua Li {
1277d715a6cSShaohua Li 	switch (aspm_policy) {
1287d715a6cSShaohua Li 	case POLICY_PERFORMANCE:
1297d715a6cSShaohua Li 		/* Disable ASPM and Clock PM */
1307d715a6cSShaohua Li 		return 0;
1317d715a6cSShaohua Li 	case POLICY_POWERSAVE:
132b2103ccbSRajat Jain 	case POLICY_POWER_SUPERSAVE:
133b2103ccbSRajat Jain 		/* Enable Clock PM */
1347d715a6cSShaohua Li 		return 1;
1357d715a6cSShaohua Li 	case POLICY_DEFAULT:
1365aa63583SKenji Kaneshige 		return link->clkpm_default;
1377d715a6cSShaohua Li 	}
1387d715a6cSShaohua Li 	return 0;
1397d715a6cSShaohua Li }
1407d715a6cSShaohua Li 
pcie_set_clkpm_nocheck(struct pcie_link_state * link,int enable)141430842e2SKenji Kaneshige static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
1427d715a6cSShaohua Li {
1435aa63583SKenji Kaneshige 	struct pci_dev *child;
1445aa63583SKenji Kaneshige 	struct pci_bus *linkbus = link->pdev->subordinate;
1450c0cbb6cSBjorn Helgaas 	u32 val = enable ? PCI_EXP_LNKCTL_CLKREQ_EN : 0;
1467d715a6cSShaohua Li 
1470c0cbb6cSBjorn Helgaas 	list_for_each_entry(child, &linkbus->devices, bus_list)
1480c0cbb6cSBjorn Helgaas 		pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
1490c0cbb6cSBjorn Helgaas 						   PCI_EXP_LNKCTL_CLKREQ_EN,
1500c0cbb6cSBjorn Helgaas 						   val);
1515aa63583SKenji Kaneshige 	link->clkpm_enabled = !!enable;
1527d715a6cSShaohua Li }
1537d715a6cSShaohua Li 
pcie_set_clkpm(struct pcie_link_state * link,int enable)154430842e2SKenji Kaneshige static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
155430842e2SKenji Kaneshige {
15635efea32SHeiner Kallweit 	/*
15735efea32SHeiner Kallweit 	 * Don't enable Clock PM if the link is not Clock PM capable
15835efea32SHeiner Kallweit 	 * or Clock PM is disabled
15935efea32SHeiner Kallweit 	 */
16035efea32SHeiner Kallweit 	if (!link->clkpm_capable || link->clkpm_disable)
1612f671e2dSMatthew Garrett 		enable = 0;
162430842e2SKenji Kaneshige 	/* Need nothing if the specified equals to current state */
163430842e2SKenji Kaneshige 	if (link->clkpm_enabled == enable)
164430842e2SKenji Kaneshige 		return;
165430842e2SKenji Kaneshige 	pcie_set_clkpm_nocheck(link, enable);
166430842e2SKenji Kaneshige }
167430842e2SKenji Kaneshige 
pcie_clkpm_cap_init(struct pcie_link_state * link,int blacklist)1688d349aceSKenji Kaneshige static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
1697d715a6cSShaohua Li {
170f12eb72aSJiang Liu 	int capable = 1, enabled = 1;
1717d715a6cSShaohua Li 	u32 reg32;
1727d715a6cSShaohua Li 	u16 reg16;
1735aa63583SKenji Kaneshige 	struct pci_dev *child;
1745aa63583SKenji Kaneshige 	struct pci_bus *linkbus = link->pdev->subordinate;
1757d715a6cSShaohua Li 
1767d715a6cSShaohua Li 	/* All functions should have the same cap and state, take the worst */
1775aa63583SKenji Kaneshige 	list_for_each_entry(child, &linkbus->devices, bus_list) {
178f12eb72aSJiang Liu 		pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &reg32);
1797d715a6cSShaohua Li 		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
1807d715a6cSShaohua Li 			capable = 0;
1817d715a6cSShaohua Li 			enabled = 0;
1827d715a6cSShaohua Li 			break;
1837d715a6cSShaohua Li 		}
184f12eb72aSJiang Liu 		pcie_capability_read_word(child, PCI_EXP_LNKCTL, &reg16);
1857d715a6cSShaohua Li 		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
1867d715a6cSShaohua Li 			enabled = 0;
1877d715a6cSShaohua Li 	}
1885aa63583SKenji Kaneshige 	link->clkpm_enabled = enabled;
1895aa63583SKenji Kaneshige 	link->clkpm_default = enabled;
19035efea32SHeiner Kallweit 	link->clkpm_capable = capable;
19135efea32SHeiner Kallweit 	link->clkpm_disable = blacklist ? 1 : 0;
19246bbdfa4SShaohua Li }
19346bbdfa4SShaohua Li 
1947d715a6cSShaohua Li /*
1957d715a6cSShaohua Li  * pcie_aspm_configure_common_clock: check if the 2 ends of a link
1967d715a6cSShaohua Li  *   could use common clock. If they are, configure them to use the
1977d715a6cSShaohua Li  *   common clock. That will reduce the ASPM state exit latency.
1987d715a6cSShaohua Li  */
pcie_aspm_configure_common_clock(struct pcie_link_state * link)1995aa63583SKenji Kaneshige static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
2007d715a6cSShaohua Li {
201f12eb72aSJiang Liu 	int same_clock = 1;
202e09060b3SIlpo Järvinen 	u16 reg16, ccc, parent_old_ccc, child_old_ccc[8];
2035aa63583SKenji Kaneshige 	struct pci_dev *child, *parent = link->pdev;
2045aa63583SKenji Kaneshige 	struct pci_bus *linkbus = parent->subordinate;
2057d715a6cSShaohua Li 	/*
2065aa63583SKenji Kaneshige 	 * All functions of a slot should have the same Slot Clock
2077d715a6cSShaohua Li 	 * Configuration, so just check one function
2085aa63583SKenji Kaneshige 	 */
2095aa63583SKenji Kaneshige 	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
2108b06477dSKenji Kaneshige 	BUG_ON(!pci_is_pcie(child));
2117d715a6cSShaohua Li 
2127d715a6cSShaohua Li 	/* Check downstream component if bit Slot Clock Configuration is 1 */
213f12eb72aSJiang Liu 	pcie_capability_read_word(child, PCI_EXP_LNKSTA, &reg16);
2147d715a6cSShaohua Li 	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
2157d715a6cSShaohua Li 		same_clock = 0;
2167d715a6cSShaohua Li 
2177d715a6cSShaohua Li 	/* Check upstream component if bit Slot Clock Configuration is 1 */
218f12eb72aSJiang Liu 	pcie_capability_read_word(parent, PCI_EXP_LNKSTA, &reg16);
2197d715a6cSShaohua Li 	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
2207d715a6cSShaohua Li 		same_clock = 0;
2217d715a6cSShaohua Li 
22204875177SSinan Kaya 	/* Port might be already in common clock mode */
22304875177SSinan Kaya 	pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
224e09060b3SIlpo Järvinen 	parent_old_ccc = reg16 & PCI_EXP_LNKCTL_CCC;
22504875177SSinan Kaya 	if (same_clock && (reg16 & PCI_EXP_LNKCTL_CCC)) {
22604875177SSinan Kaya 		bool consistent = true;
22704875177SSinan Kaya 
22804875177SSinan Kaya 		list_for_each_entry(child, &linkbus->devices, bus_list) {
22904875177SSinan Kaya 			pcie_capability_read_word(child, PCI_EXP_LNKCTL,
23004875177SSinan Kaya 						  &reg16);
23104875177SSinan Kaya 			if (!(reg16 & PCI_EXP_LNKCTL_CCC)) {
23204875177SSinan Kaya 				consistent = false;
23304875177SSinan Kaya 				break;
23404875177SSinan Kaya 			}
23504875177SSinan Kaya 		}
23604875177SSinan Kaya 		if (consistent)
23704875177SSinan Kaya 			return;
2383b364c65SChris Packham 		pci_info(parent, "ASPM: current common clock configuration is inconsistent, reconfiguring\n");
23904875177SSinan Kaya 	}
24004875177SSinan Kaya 
241e09060b3SIlpo Järvinen 	ccc = same_clock ? PCI_EXP_LNKCTL_CCC : 0;
2427d715a6cSShaohua Li 	/* Configure downstream component, all functions */
2435aa63583SKenji Kaneshige 	list_for_each_entry(child, &linkbus->devices, bus_list) {
244f12eb72aSJiang Liu 		pcie_capability_read_word(child, PCI_EXP_LNKCTL, &reg16);
245e09060b3SIlpo Järvinen 		child_old_ccc[PCI_FUNC(child->devfn)] = reg16 & PCI_EXP_LNKCTL_CCC;
246e09060b3SIlpo Järvinen 		pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
247e09060b3SIlpo Järvinen 						   PCI_EXP_LNKCTL_CCC, ccc);
2487d715a6cSShaohua Li 	}
2497d715a6cSShaohua Li 
2507d715a6cSShaohua Li 	/* Configure upstream component */
251e09060b3SIlpo Järvinen 	pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
252e09060b3SIlpo Järvinen 					   PCI_EXP_LNKCTL_CCC, ccc);
2537d715a6cSShaohua Li 
2541abb4739SBjorn Helgaas 	if (pcie_retrain_link(link->pdev, true)) {
2555aa63583SKenji Kaneshige 
2565aa63583SKenji Kaneshige 		/* Training failed. Restore common clock configurations */
2577506dc79SFrederick Lawler 		pci_err(parent, "ASPM: Could not configure common clock\n");
258f12eb72aSJiang Liu 		list_for_each_entry(child, &linkbus->devices, bus_list)
259e09060b3SIlpo Järvinen 			pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
260e09060b3SIlpo Järvinen 							   PCI_EXP_LNKCTL_CCC,
261e09060b3SIlpo Järvinen 							   child_old_ccc[PCI_FUNC(child->devfn)]);
262e09060b3SIlpo Järvinen 		pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
263e09060b3SIlpo Järvinen 						   PCI_EXP_LNKCTL_CCC, parent_old_ccc);
2647d715a6cSShaohua Li 	}
265f5297a01SBjorn Helgaas }
2667d715a6cSShaohua Li 
2675e0eaa7dSKenji Kaneshige /* Convert L0s latency encoding to ns */
calc_l0s_latency(u32 lnkcap)2685f7875d6SSaheed O. Bolarinwa static u32 calc_l0s_latency(u32 lnkcap)
2697d715a6cSShaohua Li {
2705f7875d6SSaheed O. Bolarinwa 	u32 encoding = (lnkcap & PCI_EXP_LNKCAP_L0SEL) >> 12;
2715f7875d6SSaheed O. Bolarinwa 
2725e0eaa7dSKenji Kaneshige 	if (encoding == 0x7)
2735e0eaa7dSKenji Kaneshige 		return (5 * 1000);	/* > 4us */
2745e0eaa7dSKenji Kaneshige 	return (64 << encoding);
2757d715a6cSShaohua Li }
2767d715a6cSShaohua Li 
2775e0eaa7dSKenji Kaneshige /* Convert L0s acceptable latency encoding to ns */
calc_l0s_acceptable(u32 encoding)2785e0eaa7dSKenji Kaneshige static u32 calc_l0s_acceptable(u32 encoding)
2797d715a6cSShaohua Li {
2805e0eaa7dSKenji Kaneshige 	if (encoding == 0x7)
2815e0eaa7dSKenji Kaneshige 		return -1U;
2825e0eaa7dSKenji Kaneshige 	return (64 << encoding);
2835e0eaa7dSKenji Kaneshige }
2847d715a6cSShaohua Li 
2855e0eaa7dSKenji Kaneshige /* Convert L1 latency encoding to ns */
calc_l1_latency(u32 lnkcap)2865f7875d6SSaheed O. Bolarinwa static u32 calc_l1_latency(u32 lnkcap)
2875e0eaa7dSKenji Kaneshige {
2885f7875d6SSaheed O. Bolarinwa 	u32 encoding = (lnkcap & PCI_EXP_LNKCAP_L1EL) >> 15;
2895f7875d6SSaheed O. Bolarinwa 
2905e0eaa7dSKenji Kaneshige 	if (encoding == 0x7)
2915e0eaa7dSKenji Kaneshige 		return (65 * 1000);	/* > 64us */
2925e0eaa7dSKenji Kaneshige 	return (1000 << encoding);
2935e0eaa7dSKenji Kaneshige }
2945e0eaa7dSKenji Kaneshige 
2955e0eaa7dSKenji Kaneshige /* Convert L1 acceptable latency encoding to ns */
calc_l1_acceptable(u32 encoding)2965e0eaa7dSKenji Kaneshige static u32 calc_l1_acceptable(u32 encoding)
2975e0eaa7dSKenji Kaneshige {
2985e0eaa7dSKenji Kaneshige 	if (encoding == 0x7)
2995e0eaa7dSKenji Kaneshige 		return -1U;
3005e0eaa7dSKenji Kaneshige 	return (1000 << encoding);
3017d715a6cSShaohua Li }
3027d715a6cSShaohua Li 
303f1f0366dSRajat Jain /* Convert L1SS T_pwr encoding to usec */
calc_l12_pwron(struct pci_dev * pdev,u32 scale,u32 val)30405a55d9cSAjay Agarwal static u32 calc_l12_pwron(struct pci_dev *pdev, u32 scale, u32 val)
305f1f0366dSRajat Jain {
306f1f0366dSRajat Jain 	switch (scale) {
307f1f0366dSRajat Jain 	case 0:
308f1f0366dSRajat Jain 		return val * 2;
309f1f0366dSRajat Jain 	case 1:
310f1f0366dSRajat Jain 		return val * 10;
311f1f0366dSRajat Jain 	case 2:
312f1f0366dSRajat Jain 		return val * 100;
313f1f0366dSRajat Jain 	}
3147506dc79SFrederick Lawler 	pci_err(pdev, "%s: Invalid T_PwrOn scale: %u\n", __func__, scale);
315f1f0366dSRajat Jain 	return 0;
316f1f0366dSRajat Jain }
317f1f0366dSRajat Jain 
3187afeb84dSBjorn Helgaas /*
3197afeb84dSBjorn Helgaas  * Encode an LTR_L1.2_THRESHOLD value for the L1 PM Substates Control 1
3207afeb84dSBjorn Helgaas  * register.  Ports enter L1.2 when the most recent LTR value is greater
3217afeb84dSBjorn Helgaas  * than or equal to LTR_L1.2_THRESHOLD, so we round up to make sure we
3227afeb84dSBjorn Helgaas  * don't enter L1.2 too aggressively.
3237afeb84dSBjorn Helgaas  *
3247afeb84dSBjorn Helgaas  * See PCIe r6.0, sec 5.5.1, 6.18, 7.8.3.3.
3257afeb84dSBjorn Helgaas  */
encode_l12_threshold(u32 threshold_us,u32 * scale,u32 * value)32680d7d7a9SBjorn Helgaas static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value)
32780d7d7a9SBjorn Helgaas {
3287afeb84dSBjorn Helgaas 	u64 threshold_ns = (u64) threshold_us * 1000;
32980d7d7a9SBjorn Helgaas 
3307afeb84dSBjorn Helgaas 	/*
3317afeb84dSBjorn Helgaas 	 * LTR_L1.2_THRESHOLD_Value ("value") is a 10-bit field with max
3327afeb84dSBjorn Helgaas 	 * value of 0x3ff.
3337afeb84dSBjorn Helgaas 	 */
3347afeb84dSBjorn Helgaas 	if (threshold_ns <= 0x3ff * 1) {
3357afeb84dSBjorn Helgaas 		*scale = 0;		/* Value times 1ns */
33680d7d7a9SBjorn Helgaas 		*value = threshold_ns;
3377afeb84dSBjorn Helgaas 	} else if (threshold_ns <= 0x3ff * 32) {
3387afeb84dSBjorn Helgaas 		*scale = 1;		/* Value times 32ns */
3397afeb84dSBjorn Helgaas 		*value = roundup(threshold_ns, 32) / 32;
3407afeb84dSBjorn Helgaas 	} else if (threshold_ns <= 0x3ff * 1024) {
3417afeb84dSBjorn Helgaas 		*scale = 2;		/* Value times 1024ns */
3427afeb84dSBjorn Helgaas 		*value = roundup(threshold_ns, 1024) / 1024;
3437afeb84dSBjorn Helgaas 	} else if (threshold_ns <= 0x3ff * 32768) {
3447afeb84dSBjorn Helgaas 		*scale = 3;		/* Value times 32768ns */
3457afeb84dSBjorn Helgaas 		*value = roundup(threshold_ns, 32768) / 32768;
3467afeb84dSBjorn Helgaas 	} else if (threshold_ns <= 0x3ff * 1048576) {
3477afeb84dSBjorn Helgaas 		*scale = 4;		/* Value times 1048576ns */
3487afeb84dSBjorn Helgaas 		*value = roundup(threshold_ns, 1048576) / 1048576;
3497afeb84dSBjorn Helgaas 	} else if (threshold_ns <= 0x3ff * (u64) 33554432) {
3507afeb84dSBjorn Helgaas 		*scale = 5;		/* Value times 33554432ns */
3517afeb84dSBjorn Helgaas 		*value = roundup(threshold_ns, 33554432) / 33554432;
35280d7d7a9SBjorn Helgaas 	} else {
35380d7d7a9SBjorn Helgaas 		*scale = 5;
3547afeb84dSBjorn Helgaas 		*value = 0x3ff;		/* Max representable value */
35580d7d7a9SBjorn Helgaas 	}
35680d7d7a9SBjorn Helgaas }
35780d7d7a9SBjorn Helgaas 
pcie_aspm_check_latency(struct pci_dev * endpoint)35807d92760SKenji Kaneshige static void pcie_aspm_check_latency(struct pci_dev *endpoint)
35907d92760SKenji Kaneshige {
3606e332df7SSaheed O. Bolarinwa 	u32 latency, encoding, lnkcap_up, lnkcap_dw;
361fa285bafSSaheed O. Bolarinwa 	u32 l1_switch_latency = 0, latency_up_l0s;
362fa285bafSSaheed O. Bolarinwa 	u32 latency_up_l1, latency_dw_l0s, latency_dw_l1;
363fa285bafSSaheed O. Bolarinwa 	u32 acceptable_l0s, acceptable_l1;
36407d92760SKenji Kaneshige 	struct pcie_link_state *link;
36507d92760SKenji Kaneshige 
36607d92760SKenji Kaneshige 	/* Device not in D0 doesn't need latency check */
36707d92760SKenji Kaneshige 	if ((endpoint->current_state != PCI_D0) &&
36807d92760SKenji Kaneshige 	    (endpoint->current_state != PCI_UNKNOWN))
36907d92760SKenji Kaneshige 		return;
37007d92760SKenji Kaneshige 
37107d92760SKenji Kaneshige 	link = endpoint->bus->self->link_state;
3726e332df7SSaheed O. Bolarinwa 
3736e332df7SSaheed O. Bolarinwa 	/* Calculate endpoint L0s acceptable latency */
3746e332df7SSaheed O. Bolarinwa 	encoding = (endpoint->devcap & PCI_EXP_DEVCAP_L0S) >> 6;
375fa285bafSSaheed O. Bolarinwa 	acceptable_l0s = calc_l0s_acceptable(encoding);
3766e332df7SSaheed O. Bolarinwa 
3776e332df7SSaheed O. Bolarinwa 	/* Calculate endpoint L1 acceptable latency */
3786e332df7SSaheed O. Bolarinwa 	encoding = (endpoint->devcap & PCI_EXP_DEVCAP_L1) >> 9;
379fa285bafSSaheed O. Bolarinwa 	acceptable_l1 = calc_l1_acceptable(encoding);
38007d92760SKenji Kaneshige 
38107d92760SKenji Kaneshige 	while (link) {
382222578daSSaheed O. Bolarinwa 		struct pci_dev *dev = pci_function_0(link->pdev->subordinate);
383222578daSSaheed O. Bolarinwa 
384222578daSSaheed O. Bolarinwa 		/* Read direction exit latencies */
385222578daSSaheed O. Bolarinwa 		pcie_capability_read_dword(link->pdev, PCI_EXP_LNKCAP,
386222578daSSaheed O. Bolarinwa 					   &lnkcap_up);
387222578daSSaheed O. Bolarinwa 		pcie_capability_read_dword(dev, PCI_EXP_LNKCAP,
388222578daSSaheed O. Bolarinwa 					   &lnkcap_dw);
389fa285bafSSaheed O. Bolarinwa 		latency_up_l0s = calc_l0s_latency(lnkcap_up);
390fa285bafSSaheed O. Bolarinwa 		latency_up_l1 = calc_l1_latency(lnkcap_up);
391fa285bafSSaheed O. Bolarinwa 		latency_dw_l0s = calc_l0s_latency(lnkcap_dw);
392fa285bafSSaheed O. Bolarinwa 		latency_dw_l1 = calc_l1_latency(lnkcap_dw);
393222578daSSaheed O. Bolarinwa 
394ac18018aSKenji Kaneshige 		/* Check upstream direction L0s latency */
395ac18018aSKenji Kaneshige 		if ((link->aspm_capable & ASPM_STATE_L0S_UP) &&
396fa285bafSSaheed O. Bolarinwa 		    (latency_up_l0s > acceptable_l0s))
397ac18018aSKenji Kaneshige 			link->aspm_capable &= ~ASPM_STATE_L0S_UP;
398ac18018aSKenji Kaneshige 
399ac18018aSKenji Kaneshige 		/* Check downstream direction L0s latency */
400ac18018aSKenji Kaneshige 		if ((link->aspm_capable & ASPM_STATE_L0S_DW) &&
401fa285bafSSaheed O. Bolarinwa 		    (latency_dw_l0s > acceptable_l0s))
402ac18018aSKenji Kaneshige 			link->aspm_capable &= ~ASPM_STATE_L0S_DW;
40307d92760SKenji Kaneshige 		/*
40407d92760SKenji Kaneshige 		 * Check L1 latency.
40507d92760SKenji Kaneshige 		 * Every switch on the path to root complex need 1
40607d92760SKenji Kaneshige 		 * more microsecond for L1. Spec doesn't mention L0s.
407a142f4d3SRajat Jain 		 *
408a142f4d3SRajat Jain 		 * The exit latencies for L1 substates are not advertised
409a142f4d3SRajat Jain 		 * by a device.  Since the spec also doesn't mention a way
410a142f4d3SRajat Jain 		 * to determine max latencies introduced by enabling L1
411a142f4d3SRajat Jain 		 * substates on the components, it is not clear how to do
412a142f4d3SRajat Jain 		 * a L1 substate exit latency check.  We assume that the
413a142f4d3SRajat Jain 		 * L1 exit latencies advertised by a device include L1
414a142f4d3SRajat Jain 		 * substate latencies (and hence do not do any check).
41507d92760SKenji Kaneshige 		 */
416fa285bafSSaheed O. Bolarinwa 		latency = max_t(u32, latency_up_l1, latency_dw_l1);
417ac18018aSKenji Kaneshige 		if ((link->aspm_capable & ASPM_STATE_L1) &&
418fa285bafSSaheed O. Bolarinwa 		    (latency + l1_switch_latency > acceptable_l1))
419ac18018aSKenji Kaneshige 			link->aspm_capable &= ~ASPM_STATE_L1;
42007d92760SKenji Kaneshige 		l1_switch_latency += 1000;
42107d92760SKenji Kaneshige 
42207d92760SKenji Kaneshige 		link = link->parent;
42307d92760SKenji Kaneshige 	}
42407d92760SKenji Kaneshige }
42507d92760SKenji Kaneshige 
pci_clear_and_set_dword(struct pci_dev * pdev,int pos,u32 clear,u32 set)4260f1619cfSBjorn Helgaas static void pci_clear_and_set_dword(struct pci_dev *pdev, int pos,
4270f1619cfSBjorn Helgaas 				    u32 clear, u32 set)
4280f1619cfSBjorn Helgaas {
4290f1619cfSBjorn Helgaas 	u32 val;
4300f1619cfSBjorn Helgaas 
4310f1619cfSBjorn Helgaas 	pci_read_config_dword(pdev, pos, &val);
4320f1619cfSBjorn Helgaas 	val &= ~clear;
4330f1619cfSBjorn Helgaas 	val |= set;
4340f1619cfSBjorn Helgaas 	pci_write_config_dword(pdev, pos, val);
4350f1619cfSBjorn Helgaas }
4360f1619cfSBjorn Helgaas 
437f1f0366dSRajat Jain /* Calculate L1.2 PM substate timing parameters */
aspm_calc_l12_info(struct pcie_link_state * link,u32 parent_l1ss_cap,u32 child_l1ss_cap)43805a55d9cSAjay Agarwal static void aspm_calc_l12_info(struct pcie_link_state *link,
4391e8955fdSBjorn Helgaas 				u32 parent_l1ss_cap, u32 child_l1ss_cap)
440f1f0366dSRajat Jain {
441190cd42cSBjorn Helgaas 	struct pci_dev *child = link->downstream, *parent = link->pdev;
442f1f0366dSRajat Jain 	u32 val1, val2, scale1, scale2;
44380d7d7a9SBjorn Helgaas 	u32 t_common_mode, t_power_on, l1_2_threshold, scale, value;
444df8f1058SSaheed O. Bolarinwa 	u32 ctl1 = 0, ctl2 = 0;
445df8f1058SSaheed O. Bolarinwa 	u32 pctl1, pctl2, cctl1, cctl2;
446ff209eccSBjorn Helgaas 	u32 pl1_2_enables, cl1_2_enables;
447f1f0366dSRajat Jain 
448a48f3d5bSBjorn Helgaas 	/* Choose the greater of the two Port Common_Mode_Restore_Times */
4491e8955fdSBjorn Helgaas 	val1 = (parent_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
4501e8955fdSBjorn Helgaas 	val2 = (child_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
45180d7d7a9SBjorn Helgaas 	t_common_mode = max(val1, val2);
452f1f0366dSRajat Jain 
453a48f3d5bSBjorn Helgaas 	/* Choose the greater of the two Port T_POWER_ON times */
4541e8955fdSBjorn Helgaas 	val1   = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
4551e8955fdSBjorn Helgaas 	scale1 = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
4561e8955fdSBjorn Helgaas 	val2   = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
4571e8955fdSBjorn Helgaas 	scale2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
458f1f0366dSRajat Jain 
45905a55d9cSAjay Agarwal 	if (calc_l12_pwron(parent, scale1, val1) >
46005a55d9cSAjay Agarwal 	    calc_l12_pwron(child, scale2, val2)) {
461df8f1058SSaheed O. Bolarinwa 		ctl2 |= scale1 | (val1 << 3);
46205a55d9cSAjay Agarwal 		t_power_on = calc_l12_pwron(parent, scale1, val1);
46380d7d7a9SBjorn Helgaas 	} else {
464df8f1058SSaheed O. Bolarinwa 		ctl2 |= scale2 | (val2 << 3);
46505a55d9cSAjay Agarwal 		t_power_on = calc_l12_pwron(child, scale2, val2);
46680d7d7a9SBjorn Helgaas 	}
46780d7d7a9SBjorn Helgaas 
46880d7d7a9SBjorn Helgaas 	/*
46980d7d7a9SBjorn Helgaas 	 * Set LTR_L1.2_THRESHOLD to the time required to transition the
47080d7d7a9SBjorn Helgaas 	 * Link from L0 to L1.2 and back to L0 so we enter L1.2 only if
47180d7d7a9SBjorn Helgaas 	 * downstream devices report (via LTR) that they can tolerate at
47280d7d7a9SBjorn Helgaas 	 * least that much latency.
47380d7d7a9SBjorn Helgaas 	 *
47480d7d7a9SBjorn Helgaas 	 * Based on PCIe r3.1, sec 5.5.3.3.1, Figures 5-16 and 5-17, and
47580d7d7a9SBjorn Helgaas 	 * Table 5-11.  T(POWER_OFF) is at most 2us and T(L1.2) is at
47680d7d7a9SBjorn Helgaas 	 * least 4us.
47780d7d7a9SBjorn Helgaas 	 */
47880d7d7a9SBjorn Helgaas 	l1_2_threshold = 2 + 4 + t_common_mode + t_power_on;
47980d7d7a9SBjorn Helgaas 	encode_l12_threshold(l1_2_threshold, &scale, &value);
480df8f1058SSaheed O. Bolarinwa 	ctl1 |= t_common_mode << 8 | scale << 29 | value << 16;
481df8f1058SSaheed O. Bolarinwa 
4824353594eSRajat Jain 	/* Some broken devices only support dword access to L1 SS */
483df8f1058SSaheed O. Bolarinwa 	pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1, &pctl1);
484df8f1058SSaheed O. Bolarinwa 	pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, &pctl2);
485df8f1058SSaheed O. Bolarinwa 	pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL1, &cctl1);
486df8f1058SSaheed O. Bolarinwa 	pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL2, &cctl2);
487df8f1058SSaheed O. Bolarinwa 
488df8f1058SSaheed O. Bolarinwa 	if (ctl1 == pctl1 && ctl1 == cctl1 &&
489df8f1058SSaheed O. Bolarinwa 	    ctl2 == pctl2 && ctl2 == cctl2)
490df8f1058SSaheed O. Bolarinwa 		return;
491df8f1058SSaheed O. Bolarinwa 
492ff209eccSBjorn Helgaas 	/* Disable L1.2 while updating.  See PCIe r5.0, sec 5.5.4, 7.8.3.3 */
493ff209eccSBjorn Helgaas 	pl1_2_enables = pctl1 & PCI_L1SS_CTL1_L1_2_MASK;
494ff209eccSBjorn Helgaas 	cl1_2_enables = cctl1 & PCI_L1SS_CTL1_L1_2_MASK;
495df8f1058SSaheed O. Bolarinwa 
496ff209eccSBjorn Helgaas 	if (pl1_2_enables || cl1_2_enables) {
497ff209eccSBjorn Helgaas 		pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
498ff209eccSBjorn Helgaas 					PCI_L1SS_CTL1_L1_2_MASK, 0);
499ff209eccSBjorn Helgaas 		pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
500ff209eccSBjorn Helgaas 					PCI_L1SS_CTL1_L1_2_MASK, 0);
501ff209eccSBjorn Helgaas 	}
502ff209eccSBjorn Helgaas 
503ff209eccSBjorn Helgaas 	/* Program T_POWER_ON times in both ports */
504ff209eccSBjorn Helgaas 	pci_write_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, ctl2);
505ff209eccSBjorn Helgaas 	pci_write_config_dword(child, child->l1ss + PCI_L1SS_CTL2, ctl2);
506ff209eccSBjorn Helgaas 
507ff209eccSBjorn Helgaas 	/* Program Common_Mode_Restore_Time in upstream device */
508ff209eccSBjorn Helgaas 	pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
509ff209eccSBjorn Helgaas 				PCI_L1SS_CTL1_CM_RESTORE_TIME, ctl1);
510ff209eccSBjorn Helgaas 
511ff209eccSBjorn Helgaas 	/* Program LTR_L1.2_THRESHOLD time in both ports */
512ff209eccSBjorn Helgaas 	pci_clear_and_set_dword(parent,	parent->l1ss + PCI_L1SS_CTL1,
5135e85eba6SVidya Sagar 				PCI_L1SS_CTL1_LTR_L12_TH_VALUE |
514ff209eccSBjorn Helgaas 				PCI_L1SS_CTL1_LTR_L12_TH_SCALE, ctl1);
515ff209eccSBjorn Helgaas 	pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
5165e85eba6SVidya Sagar 				PCI_L1SS_CTL1_LTR_L12_TH_VALUE |
517ff209eccSBjorn Helgaas 				PCI_L1SS_CTL1_LTR_L12_TH_SCALE, ctl1);
518ff209eccSBjorn Helgaas 
519ff209eccSBjorn Helgaas 	if (pl1_2_enables || cl1_2_enables) {
520ff209eccSBjorn Helgaas 		pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1, 0,
521ff209eccSBjorn Helgaas 					pl1_2_enables);
522ff209eccSBjorn Helgaas 		pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1, 0,
523ff209eccSBjorn Helgaas 					cl1_2_enables);
524ff209eccSBjorn Helgaas 	}
525f1f0366dSRajat Jain }
526f1f0366dSRajat Jain 
aspm_l1ss_init(struct pcie_link_state * link)5279e2a0317SBjorn Helgaas static void aspm_l1ss_init(struct pcie_link_state *link)
5289e2a0317SBjorn Helgaas {
5299e2a0317SBjorn Helgaas 	struct pci_dev *child = link->downstream, *parent = link->pdev;
5309e2a0317SBjorn Helgaas 	u32 parent_l1ss_cap, child_l1ss_cap;
5319e2a0317SBjorn Helgaas 	u32 parent_l1ss_ctl1 = 0, child_l1ss_ctl1 = 0;
5329e2a0317SBjorn Helgaas 
533cfc00286SBjorn Helgaas 	if (!parent->l1ss || !child->l1ss)
534cfc00286SBjorn Helgaas 		return;
535cfc00286SBjorn Helgaas 
5369e2a0317SBjorn Helgaas 	/* Setup L1 substate */
5379e2a0317SBjorn Helgaas 	pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CAP,
5389e2a0317SBjorn Helgaas 			      &parent_l1ss_cap);
5399e2a0317SBjorn Helgaas 	pci_read_config_dword(child, child->l1ss + PCI_L1SS_CAP,
5409e2a0317SBjorn Helgaas 			      &child_l1ss_cap);
5419e2a0317SBjorn Helgaas 
5429e2a0317SBjorn Helgaas 	if (!(parent_l1ss_cap & PCI_L1SS_CAP_L1_PM_SS))
5439e2a0317SBjorn Helgaas 		parent_l1ss_cap = 0;
5449e2a0317SBjorn Helgaas 	if (!(child_l1ss_cap & PCI_L1SS_CAP_L1_PM_SS))
5459e2a0317SBjorn Helgaas 		child_l1ss_cap = 0;
5469e2a0317SBjorn Helgaas 
5479e2a0317SBjorn Helgaas 	/*
5489e2a0317SBjorn Helgaas 	 * If we don't have LTR for the entire path from the Root Complex
5499e2a0317SBjorn Helgaas 	 * to this device, we can't use ASPM L1.2 because it relies on the
5509e2a0317SBjorn Helgaas 	 * LTR_L1.2_THRESHOLD.  See PCIe r4.0, secs 5.5.4, 6.18.
5519e2a0317SBjorn Helgaas 	 */
5529e2a0317SBjorn Helgaas 	if (!child->ltr_path)
5539e2a0317SBjorn Helgaas 		child_l1ss_cap &= ~PCI_L1SS_CAP_ASPM_L1_2;
5549e2a0317SBjorn Helgaas 
5559e2a0317SBjorn Helgaas 	if (parent_l1ss_cap & child_l1ss_cap & PCI_L1SS_CAP_ASPM_L1_1)
5569e2a0317SBjorn Helgaas 		link->aspm_support |= ASPM_STATE_L1_1;
5579e2a0317SBjorn Helgaas 	if (parent_l1ss_cap & child_l1ss_cap & PCI_L1SS_CAP_ASPM_L1_2)
5589e2a0317SBjorn Helgaas 		link->aspm_support |= ASPM_STATE_L1_2;
5599e2a0317SBjorn Helgaas 	if (parent_l1ss_cap & child_l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_1)
5609e2a0317SBjorn Helgaas 		link->aspm_support |= ASPM_STATE_L1_1_PCIPM;
5619e2a0317SBjorn Helgaas 	if (parent_l1ss_cap & child_l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_2)
5629e2a0317SBjorn Helgaas 		link->aspm_support |= ASPM_STATE_L1_2_PCIPM;
5639e2a0317SBjorn Helgaas 
5649e2a0317SBjorn Helgaas 	if (parent_l1ss_cap)
5659e2a0317SBjorn Helgaas 		pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
5669e2a0317SBjorn Helgaas 				      &parent_l1ss_ctl1);
5679e2a0317SBjorn Helgaas 	if (child_l1ss_cap)
5689e2a0317SBjorn Helgaas 		pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL1,
5699e2a0317SBjorn Helgaas 				      &child_l1ss_ctl1);
5709e2a0317SBjorn Helgaas 
5719e2a0317SBjorn Helgaas 	if (parent_l1ss_ctl1 & child_l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_1)
5729e2a0317SBjorn Helgaas 		link->aspm_enabled |= ASPM_STATE_L1_1;
5739e2a0317SBjorn Helgaas 	if (parent_l1ss_ctl1 & child_l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_2)
5749e2a0317SBjorn Helgaas 		link->aspm_enabled |= ASPM_STATE_L1_2;
5759e2a0317SBjorn Helgaas 	if (parent_l1ss_ctl1 & child_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_1)
5769e2a0317SBjorn Helgaas 		link->aspm_enabled |= ASPM_STATE_L1_1_PCIPM;
5779e2a0317SBjorn Helgaas 	if (parent_l1ss_ctl1 & child_l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2)
5789e2a0317SBjorn Helgaas 		link->aspm_enabled |= ASPM_STATE_L1_2_PCIPM;
5799e2a0317SBjorn Helgaas 
580911afb9fSAjay Agarwal 	if (link->aspm_support & ASPM_STATE_L1_2_MASK)
58105a55d9cSAjay Agarwal 		aspm_calc_l12_info(link, parent_l1ss_cap, child_l1ss_cap);
5829e2a0317SBjorn Helgaas }
5839e2a0317SBjorn Helgaas 
pcie_aspm_cap_init(struct pcie_link_state * link,int blacklist)5848d349aceSKenji Kaneshige static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
5857d715a6cSShaohua Li {
5863bd7db63SYinghai Lu 	struct pci_dev *child = link->downstream, *parent = link->pdev;
587c6e5f02bSSaheed O. Bolarinwa 	u32 parent_lnkcap, child_lnkcap;
58867bcc9adSSaheed O. Bolarinwa 	u16 parent_lnkctl, child_lnkctl;
5895aa63583SKenji Kaneshige 	struct pci_bus *linkbus = parent->subordinate;
5907d715a6cSShaohua Li 
5918d349aceSKenji Kaneshige 	if (blacklist) {
592f1c0ca29SKenji Kaneshige 		/* Set enabled/disable so that we will disable ASPM later */
593ac18018aSKenji Kaneshige 		link->aspm_enabled = ASPM_STATE_ALL;
594ac18018aSKenji Kaneshige 		link->aspm_disable = ASPM_STATE_ALL;
5958d349aceSKenji Kaneshige 		return;
5968d349aceSKenji Kaneshige 	}
5978d349aceSKenji Kaneshige 
598ac18018aSKenji Kaneshige 	/*
599e53f9a28SDavid Daney 	 * If ASPM not supported, don't mess with the clocks and link,
600e53f9a28SDavid Daney 	 * bail out now.
601e53f9a28SDavid Daney 	 */
602c6e5f02bSSaheed O. Bolarinwa 	pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap);
603c6e5f02bSSaheed O. Bolarinwa 	pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap);
604c6e5f02bSSaheed O. Bolarinwa 	if (!(parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPMS))
605e53f9a28SDavid Daney 		return;
606e53f9a28SDavid Daney 
607e53f9a28SDavid Daney 	/* Configure common clock before checking latencies */
608e53f9a28SDavid Daney 	pcie_aspm_configure_common_clock(link);
609e53f9a28SDavid Daney 
610e53f9a28SDavid Daney 	/*
611c6e5f02bSSaheed O. Bolarinwa 	 * Re-read upstream/downstream components' register state after
612c6e5f02bSSaheed O. Bolarinwa 	 * clock configuration.  L0s & L1 exit latencies in the otherwise
613c6e5f02bSSaheed O. Bolarinwa 	 * read-only Link Capabilities may change depending on common clock
614c6e5f02bSSaheed O. Bolarinwa 	 * configuration (PCIe r5.0, sec 7.5.3.6).
615e53f9a28SDavid Daney 	 */
616c6e5f02bSSaheed O. Bolarinwa 	pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &parent_lnkcap);
617c6e5f02bSSaheed O. Bolarinwa 	pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap);
61867bcc9adSSaheed O. Bolarinwa 	pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &parent_lnkctl);
61967bcc9adSSaheed O. Bolarinwa 	pcie_capability_read_word(child, PCI_EXP_LNKCTL, &child_lnkctl);
620e53f9a28SDavid Daney 
621e53f9a28SDavid Daney 	/*
622ac18018aSKenji Kaneshige 	 * Setup L0s state
623ac18018aSKenji Kaneshige 	 *
624ac18018aSKenji Kaneshige 	 * Note that we must not enable L0s in either direction on a
625ac18018aSKenji Kaneshige 	 * given link unless components on both sides of the link each
626ac18018aSKenji Kaneshige 	 * support L0s.
627ac18018aSKenji Kaneshige 	 */
628c6e5f02bSSaheed O. Bolarinwa 	if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L0S)
629ac18018aSKenji Kaneshige 		link->aspm_support |= ASPM_STATE_L0S;
630c6e5f02bSSaheed O. Bolarinwa 
63167bcc9adSSaheed O. Bolarinwa 	if (child_lnkctl & PCI_EXP_LNKCTL_ASPM_L0S)
632ac18018aSKenji Kaneshige 		link->aspm_enabled |= ASPM_STATE_L0S_UP;
63367bcc9adSSaheed O. Bolarinwa 	if (parent_lnkctl & PCI_EXP_LNKCTL_ASPM_L0S)
634ac18018aSKenji Kaneshige 		link->aspm_enabled |= ASPM_STATE_L0S_DW;
635ac18018aSKenji Kaneshige 
636ac18018aSKenji Kaneshige 	/* Setup L1 state */
637c6e5f02bSSaheed O. Bolarinwa 	if (parent_lnkcap & child_lnkcap & PCI_EXP_LNKCAP_ASPM_L1)
638ac18018aSKenji Kaneshige 		link->aspm_support |= ASPM_STATE_L1;
639c6e5f02bSSaheed O. Bolarinwa 
64067bcc9adSSaheed O. Bolarinwa 	if (parent_lnkctl & child_lnkctl & PCI_EXP_LNKCTL_ASPM_L1)
641ac18018aSKenji Kaneshige 		link->aspm_enabled |= ASPM_STATE_L1;
64280bfdbe3SKenji Kaneshige 
6439e2a0317SBjorn Helgaas 	aspm_l1ss_init(link);
644f1f0366dSRajat Jain 
645b127bd55SKenji Kaneshige 	/* Save default state */
646b127bd55SKenji Kaneshige 	link->aspm_default = link->aspm_enabled;
64707d92760SKenji Kaneshige 
64807d92760SKenji Kaneshige 	/* Setup initial capable state. Will be updated later */
64907d92760SKenji Kaneshige 	link->aspm_capable = link->aspm_support;
650b127bd55SKenji Kaneshige 
651b7206cbfSKenji Kaneshige 	/* Get and check endpoint acceptable latencies */
6525aa63583SKenji Kaneshige 	list_for_each_entry(child, &linkbus->devices, bus_list) {
65362f87c0eSYijing Wang 		if (pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT &&
65462f87c0eSYijing Wang 		    pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END)
6557d715a6cSShaohua Li 			continue;
6567d715a6cSShaohua Li 
65707d92760SKenji Kaneshige 		pcie_aspm_check_latency(child);
6587d715a6cSShaohua Li 	}
6597d715a6cSShaohua Li }
6607d715a6cSShaohua Li 
661aeda9adeSRajat Jain /* Configure the ASPM L1 substates */
pcie_config_aspm_l1ss(struct pcie_link_state * link,u32 state)662aeda9adeSRajat Jain static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state)
663aeda9adeSRajat Jain {
664aeda9adeSRajat Jain 	u32 val, enable_req;
665aeda9adeSRajat Jain 	struct pci_dev *child = link->downstream, *parent = link->pdev;
666aeda9adeSRajat Jain 
667aeda9adeSRajat Jain 	enable_req = (link->aspm_enabled ^ state) & state;
668aeda9adeSRajat Jain 
669aeda9adeSRajat Jain 	/*
670aeda9adeSRajat Jain 	 * Here are the rules specified in the PCIe spec for enabling L1SS:
671aeda9adeSRajat Jain 	 * - When enabling L1.x, enable bit at parent first, then at child
672aeda9adeSRajat Jain 	 * - When disabling L1.x, disable bit at child first, then at parent
673aeda9adeSRajat Jain 	 * - When enabling ASPM L1.x, need to disable L1
674aeda9adeSRajat Jain 	 *   (at child followed by parent).
675aeda9adeSRajat Jain 	 * - The ASPM/PCIPM L1.2 must be disabled while programming timing
676aeda9adeSRajat Jain 	 *   parameters
677aeda9adeSRajat Jain 	 *
678aeda9adeSRajat Jain 	 * To keep it simple, disable all L1SS bits first, and later enable
679aeda9adeSRajat Jain 	 * what is needed.
680aeda9adeSRajat Jain 	 */
681aeda9adeSRajat Jain 
682aeda9adeSRajat Jain 	/* Disable all L1 substates */
683ecdf57b4SSaheed O. Bolarinwa 	pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
684aeda9adeSRajat Jain 				PCI_L1SS_CTL1_L1SS_MASK, 0);
685ecdf57b4SSaheed O. Bolarinwa 	pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
686aeda9adeSRajat Jain 				PCI_L1SS_CTL1_L1SS_MASK, 0);
687aeda9adeSRajat Jain 	/*
688aeda9adeSRajat Jain 	 * If needed, disable L1, and it gets enabled later
689aeda9adeSRajat Jain 	 * in pcie_config_aspm_link().
690aeda9adeSRajat Jain 	 */
691aeda9adeSRajat Jain 	if (enable_req & (ASPM_STATE_L1_1 | ASPM_STATE_L1_2)) {
6924afc65cfSIlpo Järvinen 		pcie_capability_clear_word(child, PCI_EXP_LNKCTL,
6934afc65cfSIlpo Järvinen 					   PCI_EXP_LNKCTL_ASPM_L1);
6944afc65cfSIlpo Järvinen 		pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
6954afc65cfSIlpo Järvinen 					   PCI_EXP_LNKCTL_ASPM_L1);
696aeda9adeSRajat Jain 	}
697aeda9adeSRajat Jain 
698aeda9adeSRajat Jain 	val = 0;
699aeda9adeSRajat Jain 	if (state & ASPM_STATE_L1_1)
700aeda9adeSRajat Jain 		val |= PCI_L1SS_CTL1_ASPM_L1_1;
701aeda9adeSRajat Jain 	if (state & ASPM_STATE_L1_2)
702aeda9adeSRajat Jain 		val |= PCI_L1SS_CTL1_ASPM_L1_2;
703aeda9adeSRajat Jain 	if (state & ASPM_STATE_L1_1_PCIPM)
704aeda9adeSRajat Jain 		val |= PCI_L1SS_CTL1_PCIPM_L1_1;
705aeda9adeSRajat Jain 	if (state & ASPM_STATE_L1_2_PCIPM)
706aeda9adeSRajat Jain 		val |= PCI_L1SS_CTL1_PCIPM_L1_2;
707aeda9adeSRajat Jain 
708aeda9adeSRajat Jain 	/* Enable what we need to enable */
709ecdf57b4SSaheed O. Bolarinwa 	pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
71058a3862aSYicong Yang 				PCI_L1SS_CTL1_L1SS_MASK, val);
711ecdf57b4SSaheed O. Bolarinwa 	pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
71258a3862aSYicong Yang 				PCI_L1SS_CTL1_L1SS_MASK, val);
713aeda9adeSRajat Jain }
714aeda9adeSRajat Jain 
pcie_config_aspm_dev(struct pci_dev * pdev,u32 val)715ac18018aSKenji Kaneshige static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
7167d715a6cSShaohua Li {
71775083206SBjorn Helgaas 	pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
71875083206SBjorn Helgaas 					   PCI_EXP_LNKCTL_ASPMC, val);
7197d715a6cSShaohua Li }
7207d715a6cSShaohua Li 
pcie_config_aspm_link(struct pcie_link_state * link,u32 state)721b7206cbfSKenji Kaneshige static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
7227d715a6cSShaohua Li {
723ac18018aSKenji Kaneshige 	u32 upstream = 0, dwstream = 0;
724aeda9adeSRajat Jain 	struct pci_dev *child = link->downstream, *parent = link->pdev;
7255aa63583SKenji Kaneshige 	struct pci_bus *linkbus = parent->subordinate;
7267d715a6cSShaohua Li 
727aeda9adeSRajat Jain 	/* Enable only the states that were not explicitly disabled */
728b7206cbfSKenji Kaneshige 	state &= (link->aspm_capable & ~link->aspm_disable);
729aeda9adeSRajat Jain 
730aeda9adeSRajat Jain 	/* Can't enable any substates if L1 is not enabled */
731aeda9adeSRajat Jain 	if (!(state & ASPM_STATE_L1))
732aeda9adeSRajat Jain 		state &= ~ASPM_STATE_L1SS;
733aeda9adeSRajat Jain 
734aeda9adeSRajat Jain 	/* Spec says both ports must be in D0 before enabling PCI PM substates*/
735aeda9adeSRajat Jain 	if (parent->current_state != PCI_D0 || child->current_state != PCI_D0) {
736aeda9adeSRajat Jain 		state &= ~ASPM_STATE_L1_SS_PCIPM;
737aeda9adeSRajat Jain 		state |= (link->aspm_enabled & ASPM_STATE_L1_SS_PCIPM);
738aeda9adeSRajat Jain 	}
739aeda9adeSRajat Jain 
740aeda9adeSRajat Jain 	/* Nothing to do if the link is already in the requested state */
741f1c0ca29SKenji Kaneshige 	if (link->aspm_enabled == state)
7427d715a6cSShaohua Li 		return;
743ac18018aSKenji Kaneshige 	/* Convert ASPM state to upstream/downstream ASPM register state */
744ac18018aSKenji Kaneshige 	if (state & ASPM_STATE_L0S_UP)
74575083206SBjorn Helgaas 		dwstream |= PCI_EXP_LNKCTL_ASPM_L0S;
746ac18018aSKenji Kaneshige 	if (state & ASPM_STATE_L0S_DW)
74775083206SBjorn Helgaas 		upstream |= PCI_EXP_LNKCTL_ASPM_L0S;
748ac18018aSKenji Kaneshige 	if (state & ASPM_STATE_L1) {
74975083206SBjorn Helgaas 		upstream |= PCI_EXP_LNKCTL_ASPM_L1;
75075083206SBjorn Helgaas 		dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
751ac18018aSKenji Kaneshige 	}
752aeda9adeSRajat Jain 
753aeda9adeSRajat Jain 	if (link->aspm_capable & ASPM_STATE_L1SS)
754aeda9adeSRajat Jain 		pcie_config_aspm_l1ss(link, state);
755aeda9adeSRajat Jain 
7567d715a6cSShaohua Li 	/*
7575aa63583SKenji Kaneshige 	 * Spec 2.0 suggests all functions should be configured the
7585aa63583SKenji Kaneshige 	 * same setting for ASPM. Enabling ASPM L1 should be done in
7595aa63583SKenji Kaneshige 	 * upstream component first and then downstream, and vice
7605aa63583SKenji Kaneshige 	 * versa for disabling ASPM L1. Spec doesn't mention L0S.
7617d715a6cSShaohua Li 	 */
762ac18018aSKenji Kaneshige 	if (state & ASPM_STATE_L1)
763ac18018aSKenji Kaneshige 		pcie_config_aspm_dev(parent, upstream);
7645aa63583SKenji Kaneshige 	list_for_each_entry(child, &linkbus->devices, bus_list)
765ac18018aSKenji Kaneshige 		pcie_config_aspm_dev(child, dwstream);
766ac18018aSKenji Kaneshige 	if (!(state & ASPM_STATE_L1))
767ac18018aSKenji Kaneshige 		pcie_config_aspm_dev(parent, upstream);
7687d715a6cSShaohua Li 
7695aa63583SKenji Kaneshige 	link->aspm_enabled = state;
7707d715a6cSShaohua Li }
7717d715a6cSShaohua Li 
pcie_config_aspm_path(struct pcie_link_state * link)772b7206cbfSKenji Kaneshige static void pcie_config_aspm_path(struct pcie_link_state *link)
7737d715a6cSShaohua Li {
774b7206cbfSKenji Kaneshige 	while (link) {
775b7206cbfSKenji Kaneshige 		pcie_config_aspm_link(link, policy_to_aspm_state(link));
776b7206cbfSKenji Kaneshige 		link = link->parent;
77746bbdfa4SShaohua Li 	}
7787d715a6cSShaohua Li }
7797d715a6cSShaohua Li 
free_link_state(struct pcie_link_state * link)7805aa63583SKenji Kaneshige static void free_link_state(struct pcie_link_state *link)
7817d715a6cSShaohua Li {
7825aa63583SKenji Kaneshige 	link->pdev->link_state = NULL;
7835aa63583SKenji Kaneshige 	kfree(link);
7847d715a6cSShaohua Li }
7857d715a6cSShaohua Li 
pcie_aspm_sanity_check(struct pci_dev * pdev)786ddc9753fSShaohua Li static int pcie_aspm_sanity_check(struct pci_dev *pdev)
787ddc9753fSShaohua Li {
7883647584dSKenji Kaneshige 	struct pci_dev *child;
789149e1637SShaohua Li 	u32 reg32;
7902f671e2dSMatthew Garrett 
791ddc9753fSShaohua Li 	/*
79245e829eaSStefan Assmann 	 * Some functions in a slot might not all be PCIe functions,
7933647584dSKenji Kaneshige 	 * very strange. Disable ASPM for the whole slot
794ddc9753fSShaohua Li 	 */
7953647584dSKenji Kaneshige 	list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
796f12eb72aSJiang Liu 		if (!pci_is_pcie(child))
797ddc9753fSShaohua Li 			return -EINVAL;
798c9651e70SMatthew Garrett 
799c9651e70SMatthew Garrett 		/*
800c9651e70SMatthew Garrett 		 * If ASPM is disabled then we're not going to change
801c9651e70SMatthew Garrett 		 * the BIOS state. It's safe to continue even if it's a
802c9651e70SMatthew Garrett 		 * pre-1.1 device
803c9651e70SMatthew Garrett 		 */
804c9651e70SMatthew Garrett 
805c9651e70SMatthew Garrett 		if (aspm_disabled)
806c9651e70SMatthew Garrett 			continue;
807c9651e70SMatthew Garrett 
808149e1637SShaohua Li 		/*
809149e1637SShaohua Li 		 * Disable ASPM for pre-1.1 PCIe device, we follow MS to use
810149e1637SShaohua Li 		 * RBER bit to determine if a function is 1.1 version device
811149e1637SShaohua Li 		 */
812f12eb72aSJiang Liu 		pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
813e1f4f59dSSitsofe Wheeler 		if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
8147506dc79SFrederick Lawler 			pci_info(child, "disabling ASPM on pre-1.1 PCIe device.  You can enable it with 'pcie_aspm=force'\n");
815149e1637SShaohua Li 			return -EINVAL;
816149e1637SShaohua Li 		}
817ddc9753fSShaohua Li 	}
818ddc9753fSShaohua Li 	return 0;
819ddc9753fSShaohua Li }
820ddc9753fSShaohua Li 
alloc_pcie_link_state(struct pci_dev * pdev)821b7206cbfSKenji Kaneshige static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
8228d349aceSKenji Kaneshige {
8238d349aceSKenji Kaneshige 	struct pcie_link_state *link;
8248d349aceSKenji Kaneshige 
8258d349aceSKenji Kaneshige 	link = kzalloc(sizeof(*link), GFP_KERNEL);
8268d349aceSKenji Kaneshige 	if (!link)
8278d349aceSKenji Kaneshige 		return NULL;
828030305d6SBjorn Helgaas 
8298d349aceSKenji Kaneshige 	INIT_LIST_HEAD(&link->sibling);
8308d349aceSKenji Kaneshige 	link->pdev = pdev;
8313bd7db63SYinghai Lu 	link->downstream = pci_function_0(pdev->subordinate);
832030305d6SBjorn Helgaas 
833030305d6SBjorn Helgaas 	/*
834030305d6SBjorn Helgaas 	 * Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe
835ee8bdfb6SArd Biesheuvel 	 * hierarchies.  Note that some PCIe host implementations omit
836ee8bdfb6SArd Biesheuvel 	 * the root ports entirely, in which case a downstream port on
837ee8bdfb6SArd Biesheuvel 	 * a switch may become the root of the link state chain for all
838ee8bdfb6SArd Biesheuvel 	 * its subordinate endpoints.
839030305d6SBjorn Helgaas 	 */
840030305d6SBjorn Helgaas 	if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
841ee8bdfb6SArd Biesheuvel 	    pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE ||
842ee8bdfb6SArd Biesheuvel 	    !pdev->bus->parent->self) {
843030305d6SBjorn Helgaas 		link->root = link;
844030305d6SBjorn Helgaas 	} else {
8458d349aceSKenji Kaneshige 		struct pcie_link_state *parent;
846030305d6SBjorn Helgaas 
8478d349aceSKenji Kaneshige 		parent = pdev->bus->parent->self->link_state;
8488d349aceSKenji Kaneshige 		if (!parent) {
8498d349aceSKenji Kaneshige 			kfree(link);
8508d349aceSKenji Kaneshige 			return NULL;
8518d349aceSKenji Kaneshige 		}
852030305d6SBjorn Helgaas 
8538d349aceSKenji Kaneshige 		link->parent = parent;
854030305d6SBjorn Helgaas 		link->root = link->parent->root;
8558d349aceSKenji Kaneshige 	}
8565c92ffb1SKenji Kaneshige 
8578d349aceSKenji Kaneshige 	list_add(&link->sibling, &link_list);
8588d349aceSKenji Kaneshige 	pdev->link_state = link;
8598d349aceSKenji Kaneshige 	return link;
8608d349aceSKenji Kaneshige }
8618d349aceSKenji Kaneshige 
pcie_aspm_update_sysfs_visibility(struct pci_dev * pdev)86272ea91afSHeiner Kallweit static void pcie_aspm_update_sysfs_visibility(struct pci_dev *pdev)
86372ea91afSHeiner Kallweit {
86472ea91afSHeiner Kallweit 	struct pci_dev *child;
86572ea91afSHeiner Kallweit 
86672ea91afSHeiner Kallweit 	list_for_each_entry(child, &pdev->subordinate->devices, bus_list)
86772ea91afSHeiner Kallweit 		sysfs_update_group(&child->dev.kobj, &aspm_ctrl_attr_group);
86872ea91afSHeiner Kallweit }
86972ea91afSHeiner Kallweit 
8707d715a6cSShaohua Li /*
8717d715a6cSShaohua Li  * pcie_aspm_init_link_state: Initiate PCI express link state.
872f7625980SBjorn Helgaas  * It is called after the pcie and its children devices are scanned.
8737d715a6cSShaohua Li  * @pdev: the root port or switch downstream port
8747d715a6cSShaohua Li  */
pcie_aspm_init_link_state(struct pci_dev * pdev)8757d715a6cSShaohua Li void pcie_aspm_init_link_state(struct pci_dev *pdev)
8767d715a6cSShaohua Li {
8778d349aceSKenji Kaneshige 	struct pcie_link_state *link;
878b7206cbfSKenji Kaneshige 	int blacklist = !!pcie_aspm_sanity_check(pdev);
8797d715a6cSShaohua Li 
880b07b864eSBjorn Helgaas 	if (!aspm_support_enabled)
881a26d5ecbSJoe Lawrence 		return;
882a26d5ecbSJoe Lawrence 
883c8fc9339SYijing Wang 	if (pdev->link_state)
8847d715a6cSShaohua Li 		return;
885c8fc9339SYijing Wang 
886c8fc9339SYijing Wang 	/*
887c8fc9339SYijing Wang 	 * We allocate pcie_link_state for the component on the upstream
888ca784104SMika Westerberg 	 * end of a Link, so there's nothing to do unless this device is
889ca784104SMika Westerberg 	 * downstream port.
890c8fc9339SYijing Wang 	 */
891ca784104SMika Westerberg 	if (!pcie_downstream_port(pdev))
8927d715a6cSShaohua Li 		return;
8938d349aceSKenji Kaneshige 
8948e822df7SShaohua Li 	/* VIA has a strange chipset, root port is under a bridge */
89562f87c0eSYijing Wang 	if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT &&
8968e822df7SShaohua Li 	    pdev->bus->self)
8978e822df7SShaohua Li 		return;
8988d349aceSKenji Kaneshige 
8997d715a6cSShaohua Li 	down_read(&pci_bus_sem);
9007d715a6cSShaohua Li 	if (list_empty(&pdev->subordinate->devices))
9017d715a6cSShaohua Li 		goto out;
9027d715a6cSShaohua Li 
9037d715a6cSShaohua Li 	mutex_lock(&aspm_lock);
904b7206cbfSKenji Kaneshige 	link = alloc_pcie_link_state(pdev);
9058d349aceSKenji Kaneshige 	if (!link)
9068d349aceSKenji Kaneshige 		goto unlock;
90746bbdfa4SShaohua Li 	/*
908b7206cbfSKenji Kaneshige 	 * Setup initial ASPM state. Note that we need to configure
909b7206cbfSKenji Kaneshige 	 * upstream links also because capable state of them can be
910b7206cbfSKenji Kaneshige 	 * update through pcie_aspm_cap_init().
9118d349aceSKenji Kaneshige 	 */
912b7206cbfSKenji Kaneshige 	pcie_aspm_cap_init(link, blacklist);
91346bbdfa4SShaohua Li 
9148d349aceSKenji Kaneshige 	/* Setup initial Clock PM state */
915b7206cbfSKenji Kaneshige 	pcie_clkpm_cap_init(link, blacklist);
91641cd766bSMatthew Garrett 
91741cd766bSMatthew Garrett 	/*
91841cd766bSMatthew Garrett 	 * At this stage drivers haven't had an opportunity to change the
91941cd766bSMatthew Garrett 	 * link policy setting. Enabling ASPM on broken hardware can cripple
92041cd766bSMatthew Garrett 	 * it even before the driver has had a chance to disable ASPM, so
92141cd766bSMatthew Garrett 	 * default to a safe level right now. If we're enabling ASPM beyond
92241cd766bSMatthew Garrett 	 * the BIOS's expectation, we'll do so once pci_enable_device() is
92341cd766bSMatthew Garrett 	 * called.
92441cd766bSMatthew Garrett 	 */
925b2103ccbSRajat Jain 	if (aspm_policy != POLICY_POWERSAVE &&
926b2103ccbSRajat Jain 	    aspm_policy != POLICY_POWER_SUPERSAVE) {
92741cd766bSMatthew Garrett 		pcie_config_aspm_path(link);
928b7206cbfSKenji Kaneshige 		pcie_set_clkpm(link, policy_to_clkpm_state(link));
92941cd766bSMatthew Garrett 	}
93041cd766bSMatthew Garrett 
93172ea91afSHeiner Kallweit 	pcie_aspm_update_sysfs_visibility(pdev);
93272ea91afSHeiner Kallweit 
9338d349aceSKenji Kaneshige unlock:
9347d715a6cSShaohua Li 	mutex_unlock(&aspm_lock);
9357d715a6cSShaohua Li out:
9367d715a6cSShaohua Li 	up_read(&pci_bus_sem);
9377d715a6cSShaohua Li }
9387d715a6cSShaohua Li 
93907d92760SKenji Kaneshige /* Recheck latencies and update aspm_capable for links under the root */
pcie_update_aspm_capable(struct pcie_link_state * root)94007d92760SKenji Kaneshige static void pcie_update_aspm_capable(struct pcie_link_state *root)
94107d92760SKenji Kaneshige {
94207d92760SKenji Kaneshige 	struct pcie_link_state *link;
94307d92760SKenji Kaneshige 	BUG_ON(root->parent);
94407d92760SKenji Kaneshige 	list_for_each_entry(link, &link_list, sibling) {
94507d92760SKenji Kaneshige 		if (link->root != root)
94607d92760SKenji Kaneshige 			continue;
94707d92760SKenji Kaneshige 		link->aspm_capable = link->aspm_support;
94807d92760SKenji Kaneshige 	}
94907d92760SKenji Kaneshige 	list_for_each_entry(link, &link_list, sibling) {
95007d92760SKenji Kaneshige 		struct pci_dev *child;
95107d92760SKenji Kaneshige 		struct pci_bus *linkbus = link->pdev->subordinate;
95207d92760SKenji Kaneshige 		if (link->root != root)
95307d92760SKenji Kaneshige 			continue;
95407d92760SKenji Kaneshige 		list_for_each_entry(child, &linkbus->devices, bus_list) {
95562f87c0eSYijing Wang 			if ((pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT) &&
95662f87c0eSYijing Wang 			    (pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END))
95707d92760SKenji Kaneshige 				continue;
95807d92760SKenji Kaneshige 			pcie_aspm_check_latency(child);
95907d92760SKenji Kaneshige 		}
96007d92760SKenji Kaneshige 	}
96107d92760SKenji Kaneshige }
96207d92760SKenji Kaneshige 
9637d715a6cSShaohua Li /* @pdev: the endpoint device */
pcie_aspm_exit_link_state(struct pci_dev * pdev)9647d715a6cSShaohua Li void pcie_aspm_exit_link_state(struct pci_dev *pdev)
9657d715a6cSShaohua Li {
9667d715a6cSShaohua Li 	struct pci_dev *parent = pdev->bus->self;
967b7206cbfSKenji Kaneshige 	struct pcie_link_state *link, *root, *parent_link;
9687d715a6cSShaohua Li 
96984fb913cSMyron Stowe 	if (!parent || !parent->link_state)
9707d715a6cSShaohua Li 		return;
971fc87e919SKenji Kaneshige 
9727d715a6cSShaohua Li 	down_read(&pci_bus_sem);
9737d715a6cSShaohua Li 	mutex_lock(&aspm_lock);
9747d715a6cSShaohua Li 
975fc87e919SKenji Kaneshige 	link = parent->link_state;
97607d92760SKenji Kaneshige 	root = link->root;
977b7206cbfSKenji Kaneshige 	parent_link = link->parent;
978fc87e919SKenji Kaneshige 
979456d8aa3SDing Hui 	/*
980456d8aa3SDing Hui 	 * link->downstream is a pointer to the pci_dev of function 0.  If
981456d8aa3SDing Hui 	 * we remove that function, the pci_dev is about to be deallocated,
982456d8aa3SDing Hui 	 * so we can't use link->downstream again.  Free the link state to
983456d8aa3SDing Hui 	 * avoid this.
984456d8aa3SDing Hui 	 *
985456d8aa3SDing Hui 	 * If we're removing a non-0 function, it's possible we could
986456d8aa3SDing Hui 	 * retain the link state, but PCIe r6.0, sec 7.5.3.7, recommends
987456d8aa3SDing Hui 	 * programming the same ASPM Control value for all functions of
988456d8aa3SDing Hui 	 * multi-function devices, so disable ASPM for all of them.
989456d8aa3SDing Hui 	 */
990b7206cbfSKenji Kaneshige 	pcie_config_aspm_link(link, 0);
991fc87e919SKenji Kaneshige 	list_del(&link->sibling);
992fc87e919SKenji Kaneshige 	free_link_state(link);
99307d92760SKenji Kaneshige 
99407d92760SKenji Kaneshige 	/* Recheck latencies and configure upstream links */
995b26a34aaSKenji Kaneshige 	if (parent_link) {
99607d92760SKenji Kaneshige 		pcie_update_aspm_capable(root);
997b7206cbfSKenji Kaneshige 		pcie_config_aspm_path(parent_link);
998b26a34aaSKenji Kaneshige 	}
999456d8aa3SDing Hui 
10007d715a6cSShaohua Li 	mutex_unlock(&aspm_lock);
10017d715a6cSShaohua Li 	up_read(&pci_bus_sem);
10027d715a6cSShaohua Li }
10037d715a6cSShaohua Li 
1004*b0f44788SJohan Hovold /*
1005*b0f44788SJohan Hovold  * @pdev: the root port or switch downstream port
1006*b0f44788SJohan Hovold  * @locked: whether pci_bus_sem is held
1007*b0f44788SJohan Hovold  */
pcie_aspm_pm_state_change(struct pci_dev * pdev,bool locked)1008*b0f44788SJohan Hovold void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked)
10098cc22ba3SBjorn Helgaas {
10108cc22ba3SBjorn Helgaas 	struct pcie_link_state *link = pdev->link_state;
10118cc22ba3SBjorn Helgaas 
10128cc22ba3SBjorn Helgaas 	if (aspm_disabled || !link)
10138cc22ba3SBjorn Helgaas 		return;
10148cc22ba3SBjorn Helgaas 	/*
10158cc22ba3SBjorn Helgaas 	 * Devices changed PM state, we should recheck if latency
10168cc22ba3SBjorn Helgaas 	 * meets all functions' requirement
10178cc22ba3SBjorn Helgaas 	 */
1018*b0f44788SJohan Hovold 	if (!locked)
10198cc22ba3SBjorn Helgaas 		down_read(&pci_bus_sem);
10208cc22ba3SBjorn Helgaas 	mutex_lock(&aspm_lock);
10218cc22ba3SBjorn Helgaas 	pcie_update_aspm_capable(link->root);
10228cc22ba3SBjorn Helgaas 	pcie_config_aspm_path(link);
10238cc22ba3SBjorn Helgaas 	mutex_unlock(&aspm_lock);
1024*b0f44788SJohan Hovold 	if (!locked)
10258cc22ba3SBjorn Helgaas 		up_read(&pci_bus_sem);
10268cc22ba3SBjorn Helgaas }
10278cc22ba3SBjorn Helgaas 
pcie_aspm_powersave_config_link(struct pci_dev * pdev)10281a680b7cSNaga Chumbalkar void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
10291a680b7cSNaga Chumbalkar {
10301a680b7cSNaga Chumbalkar 	struct pcie_link_state *link = pdev->link_state;
10311a680b7cSNaga Chumbalkar 
1032f9b8cd7cSYijing Wang 	if (aspm_disabled || !link)
10331a680b7cSNaga Chumbalkar 		return;
10341a680b7cSNaga Chumbalkar 
1035b2103ccbSRajat Jain 	if (aspm_policy != POLICY_POWERSAVE &&
1036b2103ccbSRajat Jain 	    aspm_policy != POLICY_POWER_SUPERSAVE)
10371a680b7cSNaga Chumbalkar 		return;
10381a680b7cSNaga Chumbalkar 
10391a680b7cSNaga Chumbalkar 	down_read(&pci_bus_sem);
10401a680b7cSNaga Chumbalkar 	mutex_lock(&aspm_lock);
10411a680b7cSNaga Chumbalkar 	pcie_config_aspm_path(link);
10421a680b7cSNaga Chumbalkar 	pcie_set_clkpm(link, policy_to_clkpm_state(link));
10431a680b7cSNaga Chumbalkar 	mutex_unlock(&aspm_lock);
10441a680b7cSNaga Chumbalkar 	up_read(&pci_bus_sem);
10451a680b7cSNaga Chumbalkar }
10461a680b7cSNaga Chumbalkar 
pcie_aspm_get_link(struct pci_dev * pdev)1047687aaf38SHeiner Kallweit static struct pcie_link_state *pcie_aspm_get_link(struct pci_dev *pdev)
10487d715a6cSShaohua Li {
1049687aaf38SHeiner Kallweit 	struct pci_dev *bridge;
10507d715a6cSShaohua Li 
10513c076351SMatthew Garrett 	if (!pci_is_pcie(pdev))
1052687aaf38SHeiner Kallweit 		return NULL;
10533c076351SMatthew Garrett 
1054687aaf38SHeiner Kallweit 	bridge = pci_upstream_bridge(pdev);
1055687aaf38SHeiner Kallweit 	if (!bridge || !pci_is_pcie(bridge))
1056687aaf38SHeiner Kallweit 		return NULL;
1057687aaf38SHeiner Kallweit 
1058687aaf38SHeiner Kallweit 	return bridge->link_state;
1059687aaf38SHeiner Kallweit }
1060687aaf38SHeiner Kallweit 
__pci_disable_link_state(struct pci_dev * pdev,int state,bool sem)1061687aaf38SHeiner Kallweit static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
1062687aaf38SHeiner Kallweit {
1063687aaf38SHeiner Kallweit 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
1064687aaf38SHeiner Kallweit 
1065687aaf38SHeiner Kallweit 	if (!link)
10664cfd2188SHeiner Kallweit 		return -EINVAL;
10672add0ec1SBjorn Helgaas 	/*
10682add0ec1SBjorn Helgaas 	 * A driver requested that ASPM be disabled on this device, but
10692add0ec1SBjorn Helgaas 	 * if we don't have permission to manage ASPM (e.g., on ACPI
10702add0ec1SBjorn Helgaas 	 * systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and
10712add0ec1SBjorn Helgaas 	 * the _OSC method), we can't honor that request.  Windows has
10722add0ec1SBjorn Helgaas 	 * a similar mechanism using "PciASPMOptOut", which is also
10732add0ec1SBjorn Helgaas 	 * ignored in this situation.
10742add0ec1SBjorn Helgaas 	 */
1075e127a04fSBjorn Helgaas 	if (aspm_disabled) {
10767506dc79SFrederick Lawler 		pci_warn(pdev, "can't disable ASPM; OS doesn't have ASPM control\n");
10774cfd2188SHeiner Kallweit 		return -EPERM;
10782add0ec1SBjorn Helgaas 	}
10792add0ec1SBjorn Helgaas 
10809f728f53SYinghai Lu 	if (sem)
10817d715a6cSShaohua Li 		down_read(&pci_bus_sem);
10827d715a6cSShaohua Li 	mutex_lock(&aspm_lock);
1083ac18018aSKenji Kaneshige 	if (state & PCIE_LINK_STATE_L0S)
1084ac18018aSKenji Kaneshige 		link->aspm_disable |= ASPM_STATE_L0S;
1085ac18018aSKenji Kaneshige 	if (state & PCIE_LINK_STATE_L1)
108684d24fe4SHeiner Kallweit 		/* L1 PM substates require L1 */
108784d24fe4SHeiner Kallweit 		link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
1088aff5d055SHeiner Kallweit 	if (state & PCIE_LINK_STATE_L1_1)
1089aff5d055SHeiner Kallweit 		link->aspm_disable |= ASPM_STATE_L1_1;
1090aff5d055SHeiner Kallweit 	if (state & PCIE_LINK_STATE_L1_2)
1091aff5d055SHeiner Kallweit 		link->aspm_disable |= ASPM_STATE_L1_2;
1092aff5d055SHeiner Kallweit 	if (state & PCIE_LINK_STATE_L1_1_PCIPM)
1093aff5d055SHeiner Kallweit 		link->aspm_disable |= ASPM_STATE_L1_1_PCIPM;
1094aff5d055SHeiner Kallweit 	if (state & PCIE_LINK_STATE_L1_2_PCIPM)
1095aff5d055SHeiner Kallweit 		link->aspm_disable |= ASPM_STATE_L1_2_PCIPM;
1096b7206cbfSKenji Kaneshige 	pcie_config_aspm_link(link, policy_to_aspm_state(link));
1097b7206cbfSKenji Kaneshige 
109835efea32SHeiner Kallweit 	if (state & PCIE_LINK_STATE_CLKPM)
109935efea32SHeiner Kallweit 		link->clkpm_disable = 1;
110035efea32SHeiner Kallweit 	pcie_set_clkpm(link, policy_to_clkpm_state(link));
11017d715a6cSShaohua Li 	mutex_unlock(&aspm_lock);
11029f728f53SYinghai Lu 	if (sem)
11037d715a6cSShaohua Li 		up_read(&pci_bus_sem);
11044cfd2188SHeiner Kallweit 
11054cfd2188SHeiner Kallweit 	return 0;
11067d715a6cSShaohua Li }
11079f728f53SYinghai Lu 
pci_disable_link_state_locked(struct pci_dev * pdev,int state)11084cfd2188SHeiner Kallweit int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
11099f728f53SYinghai Lu {
11104cfd2188SHeiner Kallweit 	return __pci_disable_link_state(pdev, state, false);
11119f728f53SYinghai Lu }
11129f728f53SYinghai Lu EXPORT_SYMBOL(pci_disable_link_state_locked);
11139f728f53SYinghai Lu 
11142dfca877SYijing Wang /**
11152dfca877SYijing Wang  * pci_disable_link_state - Disable device's link state, so the link will
11162dfca877SYijing Wang  * never enter specific states.  Note that if the BIOS didn't grant ASPM
11172dfca877SYijing Wang  * control to the OS, this does nothing because we can't touch the LNKCTL
11184cfd2188SHeiner Kallweit  * register. Returns 0 or a negative errno.
11192dfca877SYijing Wang  *
11202dfca877SYijing Wang  * @pdev: PCI device
11212dfca877SYijing Wang  * @state: ASPM link state to disable
11222dfca877SYijing Wang  */
pci_disable_link_state(struct pci_dev * pdev,int state)11234cfd2188SHeiner Kallweit int pci_disable_link_state(struct pci_dev *pdev, int state)
11249f728f53SYinghai Lu {
11254cfd2188SHeiner Kallweit 	return __pci_disable_link_state(pdev, state, true);
11269f728f53SYinghai Lu }
11277d715a6cSShaohua Li EXPORT_SYMBOL(pci_disable_link_state);
11287d715a6cSShaohua Li 
__pci_enable_link_state(struct pci_dev * pdev,int state,bool locked)11291e1f461eSJohan Hovold static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
1130de82f60fSMichael Bottini {
1131de82f60fSMichael Bottini 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
1132de82f60fSMichael Bottini 
1133de82f60fSMichael Bottini 	if (!link)
1134de82f60fSMichael Bottini 		return -EINVAL;
1135de82f60fSMichael Bottini 	/*
1136de82f60fSMichael Bottini 	 * A driver requested that ASPM be enabled on this device, but
1137de82f60fSMichael Bottini 	 * if we don't have permission to manage ASPM (e.g., on ACPI
1138de82f60fSMichael Bottini 	 * systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and
1139de82f60fSMichael Bottini 	 * the _OSC method), we can't honor that request.
1140de82f60fSMichael Bottini 	 */
1141de82f60fSMichael Bottini 	if (aspm_disabled) {
1142de82f60fSMichael Bottini 		pci_warn(pdev, "can't override BIOS ASPM; OS doesn't have ASPM control\n");
1143de82f60fSMichael Bottini 		return -EPERM;
1144de82f60fSMichael Bottini 	}
1145de82f60fSMichael Bottini 
11461e1f461eSJohan Hovold 	if (!locked)
1147de82f60fSMichael Bottini 		down_read(&pci_bus_sem);
1148de82f60fSMichael Bottini 	mutex_lock(&aspm_lock);
1149de82f60fSMichael Bottini 	link->aspm_default = 0;
1150de82f60fSMichael Bottini 	if (state & PCIE_LINK_STATE_L0S)
1151de82f60fSMichael Bottini 		link->aspm_default |= ASPM_STATE_L0S;
1152de82f60fSMichael Bottini 	if (state & PCIE_LINK_STATE_L1)
115325edb25dSAjay Agarwal 		link->aspm_default |= ASPM_STATE_L1;
115480950a54SAjay Agarwal 	/* L1 PM substates require L1 */
1155de82f60fSMichael Bottini 	if (state & PCIE_LINK_STATE_L1_1)
115680950a54SAjay Agarwal 		link->aspm_default |= ASPM_STATE_L1_1 | ASPM_STATE_L1;
1157de82f60fSMichael Bottini 	if (state & PCIE_LINK_STATE_L1_2)
115880950a54SAjay Agarwal 		link->aspm_default |= ASPM_STATE_L1_2 | ASPM_STATE_L1;
1159de82f60fSMichael Bottini 	if (state & PCIE_LINK_STATE_L1_1_PCIPM)
116080950a54SAjay Agarwal 		link->aspm_default |= ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1;
1161de82f60fSMichael Bottini 	if (state & PCIE_LINK_STATE_L1_2_PCIPM)
116280950a54SAjay Agarwal 		link->aspm_default |= ASPM_STATE_L1_2_PCIPM | ASPM_STATE_L1;
1163de82f60fSMichael Bottini 	pcie_config_aspm_link(link, policy_to_aspm_state(link));
1164de82f60fSMichael Bottini 
1165de82f60fSMichael Bottini 	link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
1166de82f60fSMichael Bottini 	pcie_set_clkpm(link, policy_to_clkpm_state(link));
1167de82f60fSMichael Bottini 	mutex_unlock(&aspm_lock);
11681e1f461eSJohan Hovold 	if (!locked)
1169de82f60fSMichael Bottini 		up_read(&pci_bus_sem);
1170de82f60fSMichael Bottini 
1171de82f60fSMichael Bottini 	return 0;
1172de82f60fSMichael Bottini }
11731e1f461eSJohan Hovold 
11741e1f461eSJohan Hovold /**
11751e1f461eSJohan Hovold  * pci_enable_link_state - Clear and set the default device link state so that
11761e1f461eSJohan Hovold  * the link may be allowed to enter the specified states. Note that if the
11771e1f461eSJohan Hovold  * BIOS didn't grant ASPM control to the OS, this does nothing because we can't
11781e1f461eSJohan Hovold  * touch the LNKCTL register. Also note that this does not enable states
11791e1f461eSJohan Hovold  * disabled by pci_disable_link_state(). Return 0 or a negative errno.
11801e1f461eSJohan Hovold  *
11811e1f461eSJohan Hovold  * @pdev: PCI device
11821e1f461eSJohan Hovold  * @state: Mask of ASPM link states to enable
11831e1f461eSJohan Hovold  */
pci_enable_link_state(struct pci_dev * pdev,int state)11841e1f461eSJohan Hovold int pci_enable_link_state(struct pci_dev *pdev, int state)
11851e1f461eSJohan Hovold {
11861e1f461eSJohan Hovold 	return __pci_enable_link_state(pdev, state, false);
11871e1f461eSJohan Hovold }
1188de82f60fSMichael Bottini EXPORT_SYMBOL(pci_enable_link_state);
1189de82f60fSMichael Bottini 
11901e1f461eSJohan Hovold /**
11911e1f461eSJohan Hovold  * pci_enable_link_state_locked - Clear and set the default device link state
11921e1f461eSJohan Hovold  * so that the link may be allowed to enter the specified states. Note that if
11931e1f461eSJohan Hovold  * the BIOS didn't grant ASPM control to the OS, this does nothing because we
11941e1f461eSJohan Hovold  * can't touch the LNKCTL register. Also note that this does not enable states
11951e1f461eSJohan Hovold  * disabled by pci_disable_link_state(). Return 0 or a negative errno.
11961e1f461eSJohan Hovold  *
11971e1f461eSJohan Hovold  * @pdev: PCI device
11981e1f461eSJohan Hovold  * @state: Mask of ASPM link states to enable
11991e1f461eSJohan Hovold  *
12001e1f461eSJohan Hovold  * Context: Caller holds pci_bus_sem read lock.
12011e1f461eSJohan Hovold  */
pci_enable_link_state_locked(struct pci_dev * pdev,int state)12021e1f461eSJohan Hovold int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
12031e1f461eSJohan Hovold {
12041e1f461eSJohan Hovold 	lockdep_assert_held_read(&pci_bus_sem);
12051e1f461eSJohan Hovold 
12061e1f461eSJohan Hovold 	return __pci_enable_link_state(pdev, state, true);
12071e1f461eSJohan Hovold }
12081e1f461eSJohan Hovold EXPORT_SYMBOL(pci_enable_link_state_locked);
12091e1f461eSJohan Hovold 
pcie_aspm_set_policy(const char * val,const struct kernel_param * kp)1210e4dca7b7SKees Cook static int pcie_aspm_set_policy(const char *val,
1211e4dca7b7SKees Cook 				const struct kernel_param *kp)
12127d715a6cSShaohua Li {
12137d715a6cSShaohua Li 	int i;
1214b7206cbfSKenji Kaneshige 	struct pcie_link_state *link;
12157d715a6cSShaohua Li 
1216bbfa306aSNaga Chumbalkar 	if (aspm_disabled)
1217bbfa306aSNaga Chumbalkar 		return -EPERM;
121836131ce9SAndy Shevchenko 	i = sysfs_match_string(policy_str, val);
121936131ce9SAndy Shevchenko 	if (i < 0)
122036131ce9SAndy Shevchenko 		return i;
12217d715a6cSShaohua Li 	if (i == aspm_policy)
12227d715a6cSShaohua Li 		return 0;
12237d715a6cSShaohua Li 
12247d715a6cSShaohua Li 	down_read(&pci_bus_sem);
12257d715a6cSShaohua Li 	mutex_lock(&aspm_lock);
12267d715a6cSShaohua Li 	aspm_policy = i;
1227b7206cbfSKenji Kaneshige 	list_for_each_entry(link, &link_list, sibling) {
1228b7206cbfSKenji Kaneshige 		pcie_config_aspm_link(link, policy_to_aspm_state(link));
1229b7206cbfSKenji Kaneshige 		pcie_set_clkpm(link, policy_to_clkpm_state(link));
12307d715a6cSShaohua Li 	}
12317d715a6cSShaohua Li 	mutex_unlock(&aspm_lock);
12327d715a6cSShaohua Li 	up_read(&pci_bus_sem);
12337d715a6cSShaohua Li 	return 0;
12347d715a6cSShaohua Li }
12357d715a6cSShaohua Li 
pcie_aspm_get_policy(char * buffer,const struct kernel_param * kp)1236e4dca7b7SKees Cook static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp)
12377d715a6cSShaohua Li {
12387d715a6cSShaohua Li 	int i, cnt = 0;
12397d715a6cSShaohua Li 	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
12407d715a6cSShaohua Li 		if (i == aspm_policy)
12417d715a6cSShaohua Li 			cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
12427d715a6cSShaohua Li 		else
12437d715a6cSShaohua Li 			cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
12443167e3d3SXiongfeng Wang 	cnt += sprintf(buffer + cnt, "\n");
12457d715a6cSShaohua Li 	return cnt;
12467d715a6cSShaohua Li }
12477d715a6cSShaohua Li 
12487d715a6cSShaohua Li module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
12497d715a6cSShaohua Li 	NULL, 0644);
12507d715a6cSShaohua Li 
1251accd2dd7SRafael J. Wysocki /**
1252accd2dd7SRafael J. Wysocki  * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
1253accd2dd7SRafael J. Wysocki  * @pdev: Target device.
12545e0c21c7SBjorn Helgaas  *
12555e0c21c7SBjorn Helgaas  * Relies on the upstream bridge's link_state being valid.  The link_state
12565e0c21c7SBjorn Helgaas  * is deallocated only when the last child of the bridge (i.e., @pdev or a
12575e0c21c7SBjorn Helgaas  * sibling) is removed, and the caller should be holding a reference to
12585e0c21c7SBjorn Helgaas  * @pdev, so this should be safe.
1259accd2dd7SRafael J. Wysocki  */
pcie_aspm_enabled(struct pci_dev * pdev)1260accd2dd7SRafael J. Wysocki bool pcie_aspm_enabled(struct pci_dev *pdev)
1261accd2dd7SRafael J. Wysocki {
1262687aaf38SHeiner Kallweit 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
1263accd2dd7SRafael J. Wysocki 
1264687aaf38SHeiner Kallweit 	if (!link)
1265accd2dd7SRafael J. Wysocki 		return false;
1266accd2dd7SRafael J. Wysocki 
1267687aaf38SHeiner Kallweit 	return link->aspm_enabled;
1268accd2dd7SRafael J. Wysocki }
1269accd2dd7SRafael J. Wysocki EXPORT_SYMBOL_GPL(pcie_aspm_enabled);
1270accd2dd7SRafael J. Wysocki 
aspm_attr_show_common(struct device * dev,struct device_attribute * attr,char * buf,u8 state)127172ea91afSHeiner Kallweit static ssize_t aspm_attr_show_common(struct device *dev,
127272ea91afSHeiner Kallweit 				     struct device_attribute *attr,
127372ea91afSHeiner Kallweit 				     char *buf, u8 state)
127472ea91afSHeiner Kallweit {
127572ea91afSHeiner Kallweit 	struct pci_dev *pdev = to_pci_dev(dev);
127672ea91afSHeiner Kallweit 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
127772ea91afSHeiner Kallweit 
1278f8cf6e51SKrzysztof Wilczyński 	return sysfs_emit(buf, "%d\n", (link->aspm_enabled & state) ? 1 : 0);
127972ea91afSHeiner Kallweit }
128072ea91afSHeiner Kallweit 
aspm_attr_store_common(struct device * dev,struct device_attribute * attr,const char * buf,size_t len,u8 state)128172ea91afSHeiner Kallweit static ssize_t aspm_attr_store_common(struct device *dev,
128272ea91afSHeiner Kallweit 				      struct device_attribute *attr,
128372ea91afSHeiner Kallweit 				      const char *buf, size_t len, u8 state)
128472ea91afSHeiner Kallweit {
128572ea91afSHeiner Kallweit 	struct pci_dev *pdev = to_pci_dev(dev);
128672ea91afSHeiner Kallweit 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
128772ea91afSHeiner Kallweit 	bool state_enable;
128872ea91afSHeiner Kallweit 
1289e0f7b192SKrzysztof Wilczyński 	if (kstrtobool(buf, &state_enable) < 0)
129072ea91afSHeiner Kallweit 		return -EINVAL;
129172ea91afSHeiner Kallweit 
129272ea91afSHeiner Kallweit 	down_read(&pci_bus_sem);
129372ea91afSHeiner Kallweit 	mutex_lock(&aspm_lock);
129472ea91afSHeiner Kallweit 
129572ea91afSHeiner Kallweit 	if (state_enable) {
129672ea91afSHeiner Kallweit 		link->aspm_disable &= ~state;
129772ea91afSHeiner Kallweit 		/* need to enable L1 for substates */
129872ea91afSHeiner Kallweit 		if (state & ASPM_STATE_L1SS)
129972ea91afSHeiner Kallweit 			link->aspm_disable &= ~ASPM_STATE_L1;
130072ea91afSHeiner Kallweit 	} else {
130172ea91afSHeiner Kallweit 		link->aspm_disable |= state;
13027fce228cSHeiner Kallweit 		if (state & ASPM_STATE_L1)
13037fce228cSHeiner Kallweit 			link->aspm_disable |= ASPM_STATE_L1SS;
130472ea91afSHeiner Kallweit 	}
130572ea91afSHeiner Kallweit 
130672ea91afSHeiner Kallweit 	pcie_config_aspm_link(link, policy_to_aspm_state(link));
130772ea91afSHeiner Kallweit 
130872ea91afSHeiner Kallweit 	mutex_unlock(&aspm_lock);
130972ea91afSHeiner Kallweit 	up_read(&pci_bus_sem);
131072ea91afSHeiner Kallweit 
131172ea91afSHeiner Kallweit 	return len;
131272ea91afSHeiner Kallweit }
131372ea91afSHeiner Kallweit 
131472ea91afSHeiner Kallweit #define ASPM_ATTR(_f, _s)						\
131572ea91afSHeiner Kallweit static ssize_t _f##_show(struct device *dev,				\
131672ea91afSHeiner Kallweit 			 struct device_attribute *attr, char *buf)	\
131772ea91afSHeiner Kallweit { return aspm_attr_show_common(dev, attr, buf, ASPM_STATE_##_s); }	\
131872ea91afSHeiner Kallweit 									\
131972ea91afSHeiner Kallweit static ssize_t _f##_store(struct device *dev,				\
132072ea91afSHeiner Kallweit 			  struct device_attribute *attr,		\
132172ea91afSHeiner Kallweit 			  const char *buf, size_t len)			\
132272ea91afSHeiner Kallweit { return aspm_attr_store_common(dev, attr, buf, len, ASPM_STATE_##_s); }
132372ea91afSHeiner Kallweit 
ASPM_ATTR(l0s_aspm,L0S)132472ea91afSHeiner Kallweit ASPM_ATTR(l0s_aspm, L0S)
132572ea91afSHeiner Kallweit ASPM_ATTR(l1_aspm, L1)
132672ea91afSHeiner Kallweit ASPM_ATTR(l1_1_aspm, L1_1)
132772ea91afSHeiner Kallweit ASPM_ATTR(l1_2_aspm, L1_2)
132872ea91afSHeiner Kallweit ASPM_ATTR(l1_1_pcipm, L1_1_PCIPM)
132972ea91afSHeiner Kallweit ASPM_ATTR(l1_2_pcipm, L1_2_PCIPM)
133072ea91afSHeiner Kallweit 
133172ea91afSHeiner Kallweit static ssize_t clkpm_show(struct device *dev,
133272ea91afSHeiner Kallweit 			  struct device_attribute *attr, char *buf)
133372ea91afSHeiner Kallweit {
133472ea91afSHeiner Kallweit 	struct pci_dev *pdev = to_pci_dev(dev);
133572ea91afSHeiner Kallweit 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
133672ea91afSHeiner Kallweit 
1337f8cf6e51SKrzysztof Wilczyński 	return sysfs_emit(buf, "%d\n", link->clkpm_enabled);
133872ea91afSHeiner Kallweit }
133972ea91afSHeiner Kallweit 
clkpm_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)134072ea91afSHeiner Kallweit static ssize_t clkpm_store(struct device *dev,
134172ea91afSHeiner Kallweit 			   struct device_attribute *attr,
134272ea91afSHeiner Kallweit 			   const char *buf, size_t len)
134372ea91afSHeiner Kallweit {
134472ea91afSHeiner Kallweit 	struct pci_dev *pdev = to_pci_dev(dev);
134572ea91afSHeiner Kallweit 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
134672ea91afSHeiner Kallweit 	bool state_enable;
134772ea91afSHeiner Kallweit 
1348e0f7b192SKrzysztof Wilczyński 	if (kstrtobool(buf, &state_enable) < 0)
134972ea91afSHeiner Kallweit 		return -EINVAL;
135072ea91afSHeiner Kallweit 
135172ea91afSHeiner Kallweit 	down_read(&pci_bus_sem);
135272ea91afSHeiner Kallweit 	mutex_lock(&aspm_lock);
135372ea91afSHeiner Kallweit 
135472ea91afSHeiner Kallweit 	link->clkpm_disable = !state_enable;
135572ea91afSHeiner Kallweit 	pcie_set_clkpm(link, policy_to_clkpm_state(link));
135672ea91afSHeiner Kallweit 
135772ea91afSHeiner Kallweit 	mutex_unlock(&aspm_lock);
135872ea91afSHeiner Kallweit 	up_read(&pci_bus_sem);
135972ea91afSHeiner Kallweit 
136072ea91afSHeiner Kallweit 	return len;
136172ea91afSHeiner Kallweit }
136272ea91afSHeiner Kallweit 
136372ea91afSHeiner Kallweit static DEVICE_ATTR_RW(clkpm);
136472ea91afSHeiner Kallweit static DEVICE_ATTR_RW(l0s_aspm);
136572ea91afSHeiner Kallweit static DEVICE_ATTR_RW(l1_aspm);
136672ea91afSHeiner Kallweit static DEVICE_ATTR_RW(l1_1_aspm);
136772ea91afSHeiner Kallweit static DEVICE_ATTR_RW(l1_2_aspm);
136872ea91afSHeiner Kallweit static DEVICE_ATTR_RW(l1_1_pcipm);
136972ea91afSHeiner Kallweit static DEVICE_ATTR_RW(l1_2_pcipm);
137072ea91afSHeiner Kallweit 
137172ea91afSHeiner Kallweit static struct attribute *aspm_ctrl_attrs[] = {
137272ea91afSHeiner Kallweit 	&dev_attr_clkpm.attr,
137372ea91afSHeiner Kallweit 	&dev_attr_l0s_aspm.attr,
137472ea91afSHeiner Kallweit 	&dev_attr_l1_aspm.attr,
137572ea91afSHeiner Kallweit 	&dev_attr_l1_1_aspm.attr,
137672ea91afSHeiner Kallweit 	&dev_attr_l1_2_aspm.attr,
137772ea91afSHeiner Kallweit 	&dev_attr_l1_1_pcipm.attr,
137872ea91afSHeiner Kallweit 	&dev_attr_l1_2_pcipm.attr,
137972ea91afSHeiner Kallweit 	NULL
138072ea91afSHeiner Kallweit };
138172ea91afSHeiner Kallweit 
aspm_ctrl_attrs_are_visible(struct kobject * kobj,struct attribute * a,int n)138272ea91afSHeiner Kallweit static umode_t aspm_ctrl_attrs_are_visible(struct kobject *kobj,
138372ea91afSHeiner Kallweit 					   struct attribute *a, int n)
138472ea91afSHeiner Kallweit {
138572ea91afSHeiner Kallweit 	struct device *dev = kobj_to_dev(kobj);
138672ea91afSHeiner Kallweit 	struct pci_dev *pdev = to_pci_dev(dev);
138772ea91afSHeiner Kallweit 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
138872ea91afSHeiner Kallweit 	static const u8 aspm_state_map[] = {
138972ea91afSHeiner Kallweit 		ASPM_STATE_L0S,
139072ea91afSHeiner Kallweit 		ASPM_STATE_L1,
139172ea91afSHeiner Kallweit 		ASPM_STATE_L1_1,
139272ea91afSHeiner Kallweit 		ASPM_STATE_L1_2,
139372ea91afSHeiner Kallweit 		ASPM_STATE_L1_1_PCIPM,
139472ea91afSHeiner Kallweit 		ASPM_STATE_L1_2_PCIPM,
139572ea91afSHeiner Kallweit 	};
139672ea91afSHeiner Kallweit 
139772ea91afSHeiner Kallweit 	if (aspm_disabled || !link)
139872ea91afSHeiner Kallweit 		return 0;
139972ea91afSHeiner Kallweit 
140072ea91afSHeiner Kallweit 	if (n == 0)
140172ea91afSHeiner Kallweit 		return link->clkpm_capable ? a->mode : 0;
140272ea91afSHeiner Kallweit 
140372ea91afSHeiner Kallweit 	return link->aspm_capable & aspm_state_map[n - 1] ? a->mode : 0;
140472ea91afSHeiner Kallweit }
140572ea91afSHeiner Kallweit 
140672ea91afSHeiner Kallweit const struct attribute_group aspm_ctrl_attr_group = {
140772ea91afSHeiner Kallweit 	.name = "link",
140872ea91afSHeiner Kallweit 	.attrs = aspm_ctrl_attrs,
140972ea91afSHeiner Kallweit 	.is_visible = aspm_ctrl_attrs_are_visible,
141072ea91afSHeiner Kallweit };
141172ea91afSHeiner Kallweit 
pcie_aspm_disable(char * str)14127d715a6cSShaohua Li static int __init pcie_aspm_disable(char *str)
14137d715a6cSShaohua Li {
1414d6d38574SShaohua Li 	if (!strcmp(str, "off")) {
14153c076351SMatthew Garrett 		aspm_policy = POLICY_DEFAULT;
14167d715a6cSShaohua Li 		aspm_disabled = 1;
14178b8bae90SRafael J. Wysocki 		aspm_support_enabled = false;
1418d6d38574SShaohua Li 		printk(KERN_INFO "PCIe ASPM is disabled\n");
1419d6d38574SShaohua Li 	} else if (!strcmp(str, "force")) {
1420d6d38574SShaohua Li 		aspm_force = 1;
14218072ba1bSMichael Witten 		printk(KERN_INFO "PCIe ASPM is forcibly enabled\n");
1422d6d38574SShaohua Li 	}
14237d715a6cSShaohua Li 	return 1;
14247d715a6cSShaohua Li }
14257d715a6cSShaohua Li 
1426d6d38574SShaohua Li __setup("pcie_aspm=", pcie_aspm_disable);
14277d715a6cSShaohua Li 
pcie_no_aspm(void)14285fde244dSShaohua Li void pcie_no_aspm(void)
14295fde244dSShaohua Li {
14303c076351SMatthew Garrett 	/*
14313c076351SMatthew Garrett 	 * Disabling ASPM is intended to prevent the kernel from modifying
14323c076351SMatthew Garrett 	 * existing hardware state, not to clear existing state. To that end:
14333c076351SMatthew Garrett 	 * (a) set policy to POLICY_DEFAULT in order to avoid changing state
14343c076351SMatthew Garrett 	 * (b) prevent userspace from changing policy
14353c076351SMatthew Garrett 	 */
14363c076351SMatthew Garrett 	if (!aspm_force) {
14373c076351SMatthew Garrett 		aspm_policy = POLICY_DEFAULT;
14385fde244dSShaohua Li 		aspm_disabled = 1;
14395fde244dSShaohua Li 	}
14403c076351SMatthew Garrett }
14415fde244dSShaohua Li 
pcie_aspm_support_enabled(void)14428b8bae90SRafael J. Wysocki bool pcie_aspm_support_enabled(void)
14438b8bae90SRafael J. Wysocki {
14448b8bae90SRafael J. Wysocki 	return aspm_support_enabled;
14458b8bae90SRafael J. Wysocki }
1446