xref: /openbmc/linux/drivers/infiniband/hw/hfi1/aspm.c (revision 0898782247ae533d1f4e47a06bc5d4870931b284)
1*bf3b1e0cSMichael J. Ruhl // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2*bf3b1e0cSMichael J. Ruhl /*
3*bf3b1e0cSMichael J. Ruhl  * Copyright(c) 2019 Intel Corporation.
4*bf3b1e0cSMichael J. Ruhl  *
5*bf3b1e0cSMichael J. Ruhl  */
6*bf3b1e0cSMichael J. Ruhl 
7*bf3b1e0cSMichael J. Ruhl #include "aspm.h"
8*bf3b1e0cSMichael J. Ruhl 
9*bf3b1e0cSMichael J. Ruhl /* Time after which the timer interrupt will re-enable ASPM */
10*bf3b1e0cSMichael J. Ruhl #define ASPM_TIMER_MS 1000
11*bf3b1e0cSMichael J. Ruhl /* Time for which interrupts are ignored after a timer has been scheduled */
12*bf3b1e0cSMichael J. Ruhl #define ASPM_RESCHED_TIMER_MS (ASPM_TIMER_MS / 2)
13*bf3b1e0cSMichael J. Ruhl /* Two interrupts within this time trigger ASPM disable */
14*bf3b1e0cSMichael J. Ruhl #define ASPM_TRIGGER_MS 1
15*bf3b1e0cSMichael J. Ruhl #define ASPM_TRIGGER_NS (ASPM_TRIGGER_MS * 1000 * 1000ull)
16*bf3b1e0cSMichael J. Ruhl #define ASPM_L1_SUPPORTED(reg) \
17*bf3b1e0cSMichael J. Ruhl 	((((reg) & PCI_EXP_LNKCAP_ASPMS) >> 10) & 0x2)
18*bf3b1e0cSMichael J. Ruhl 
19*bf3b1e0cSMichael J. Ruhl uint aspm_mode = ASPM_MODE_DISABLED;
20*bf3b1e0cSMichael J. Ruhl module_param_named(aspm, aspm_mode, uint, 0444);
21*bf3b1e0cSMichael J. Ruhl MODULE_PARM_DESC(aspm, "PCIe ASPM: 0: disable, 1: enable, 2: dynamic");
22*bf3b1e0cSMichael J. Ruhl 
aspm_hw_l1_supported(struct hfi1_devdata * dd)23*bf3b1e0cSMichael J. Ruhl static bool aspm_hw_l1_supported(struct hfi1_devdata *dd)
24*bf3b1e0cSMichael J. Ruhl {
25*bf3b1e0cSMichael J. Ruhl 	struct pci_dev *parent = dd->pcidev->bus->self;
26*bf3b1e0cSMichael J. Ruhl 	u32 up, dn;
27*bf3b1e0cSMichael J. Ruhl 
28*bf3b1e0cSMichael J. Ruhl 	/*
29*bf3b1e0cSMichael J. Ruhl 	 * If the driver does not have access to the upstream component,
30*bf3b1e0cSMichael J. Ruhl 	 * it cannot support ASPM L1 at all.
31*bf3b1e0cSMichael J. Ruhl 	 */
32*bf3b1e0cSMichael J. Ruhl 	if (!parent)
33*bf3b1e0cSMichael J. Ruhl 		return false;
34*bf3b1e0cSMichael J. Ruhl 
35*bf3b1e0cSMichael J. Ruhl 	pcie_capability_read_dword(dd->pcidev, PCI_EXP_LNKCAP, &dn);
36*bf3b1e0cSMichael J. Ruhl 	dn = ASPM_L1_SUPPORTED(dn);
37*bf3b1e0cSMichael J. Ruhl 
38*bf3b1e0cSMichael J. Ruhl 	pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, &up);
39*bf3b1e0cSMichael J. Ruhl 	up = ASPM_L1_SUPPORTED(up);
40*bf3b1e0cSMichael J. Ruhl 
41*bf3b1e0cSMichael J. Ruhl 	/* ASPM works on A-step but is reported as not supported */
42*bf3b1e0cSMichael J. Ruhl 	return (!!dn || is_ax(dd)) && !!up;
43*bf3b1e0cSMichael J. Ruhl }
44*bf3b1e0cSMichael J. Ruhl 
45*bf3b1e0cSMichael J. Ruhl /* Set L1 entrance latency for slower entry to L1 */
aspm_hw_set_l1_ent_latency(struct hfi1_devdata * dd)46*bf3b1e0cSMichael J. Ruhl static void aspm_hw_set_l1_ent_latency(struct hfi1_devdata *dd)
47*bf3b1e0cSMichael J. Ruhl {
48*bf3b1e0cSMichael J. Ruhl 	u32 l1_ent_lat = 0x4u;
49*bf3b1e0cSMichael J. Ruhl 	u32 reg32;
50*bf3b1e0cSMichael J. Ruhl 
51*bf3b1e0cSMichael J. Ruhl 	pci_read_config_dword(dd->pcidev, PCIE_CFG_REG_PL3, &reg32);
52*bf3b1e0cSMichael J. Ruhl 	reg32 &= ~PCIE_CFG_REG_PL3_L1_ENT_LATENCY_SMASK;
53*bf3b1e0cSMichael J. Ruhl 	reg32 |= l1_ent_lat << PCIE_CFG_REG_PL3_L1_ENT_LATENCY_SHIFT;
54*bf3b1e0cSMichael J. Ruhl 	pci_write_config_dword(dd->pcidev, PCIE_CFG_REG_PL3, reg32);
55*bf3b1e0cSMichael J. Ruhl }
56*bf3b1e0cSMichael J. Ruhl 
aspm_hw_enable_l1(struct hfi1_devdata * dd)57*bf3b1e0cSMichael J. Ruhl static void aspm_hw_enable_l1(struct hfi1_devdata *dd)
58*bf3b1e0cSMichael J. Ruhl {
59*bf3b1e0cSMichael J. Ruhl 	struct pci_dev *parent = dd->pcidev->bus->self;
60*bf3b1e0cSMichael J. Ruhl 
61*bf3b1e0cSMichael J. Ruhl 	/*
62*bf3b1e0cSMichael J. Ruhl 	 * If the driver does not have access to the upstream component,
63*bf3b1e0cSMichael J. Ruhl 	 * it cannot support ASPM L1 at all.
64*bf3b1e0cSMichael J. Ruhl 	 */
65*bf3b1e0cSMichael J. Ruhl 	if (!parent)
66*bf3b1e0cSMichael J. Ruhl 		return;
67*bf3b1e0cSMichael J. Ruhl 
68*bf3b1e0cSMichael J. Ruhl 	/* Enable ASPM L1 first in upstream component and then downstream */
69*bf3b1e0cSMichael J. Ruhl 	pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
70*bf3b1e0cSMichael J. Ruhl 					   PCI_EXP_LNKCTL_ASPMC,
71*bf3b1e0cSMichael J. Ruhl 					   PCI_EXP_LNKCTL_ASPM_L1);
72*bf3b1e0cSMichael J. Ruhl 	pcie_capability_clear_and_set_word(dd->pcidev, PCI_EXP_LNKCTL,
73*bf3b1e0cSMichael J. Ruhl 					   PCI_EXP_LNKCTL_ASPMC,
74*bf3b1e0cSMichael J. Ruhl 					   PCI_EXP_LNKCTL_ASPM_L1);
75*bf3b1e0cSMichael J. Ruhl }
76*bf3b1e0cSMichael J. Ruhl 
aspm_hw_disable_l1(struct hfi1_devdata * dd)77*bf3b1e0cSMichael J. Ruhl void aspm_hw_disable_l1(struct hfi1_devdata *dd)
78*bf3b1e0cSMichael J. Ruhl {
79*bf3b1e0cSMichael J. Ruhl 	struct pci_dev *parent = dd->pcidev->bus->self;
80*bf3b1e0cSMichael J. Ruhl 
81*bf3b1e0cSMichael J. Ruhl 	/* Disable ASPM L1 first in downstream component and then upstream */
82*bf3b1e0cSMichael J. Ruhl 	pcie_capability_clear_and_set_word(dd->pcidev, PCI_EXP_LNKCTL,
83*bf3b1e0cSMichael J. Ruhl 					   PCI_EXP_LNKCTL_ASPMC, 0x0);
84*bf3b1e0cSMichael J. Ruhl 	if (parent)
85*bf3b1e0cSMichael J. Ruhl 		pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
86*bf3b1e0cSMichael J. Ruhl 						   PCI_EXP_LNKCTL_ASPMC, 0x0);
87*bf3b1e0cSMichael J. Ruhl }
88*bf3b1e0cSMichael J. Ruhl 
aspm_enable(struct hfi1_devdata * dd)89*bf3b1e0cSMichael J. Ruhl static  void aspm_enable(struct hfi1_devdata *dd)
90*bf3b1e0cSMichael J. Ruhl {
91*bf3b1e0cSMichael J. Ruhl 	if (dd->aspm_enabled || aspm_mode == ASPM_MODE_DISABLED ||
92*bf3b1e0cSMichael J. Ruhl 	    !dd->aspm_supported)
93*bf3b1e0cSMichael J. Ruhl 		return;
94*bf3b1e0cSMichael J. Ruhl 
95*bf3b1e0cSMichael J. Ruhl 	aspm_hw_enable_l1(dd);
96*bf3b1e0cSMichael J. Ruhl 	dd->aspm_enabled = true;
97*bf3b1e0cSMichael J. Ruhl }
98*bf3b1e0cSMichael J. Ruhl 
aspm_disable(struct hfi1_devdata * dd)99*bf3b1e0cSMichael J. Ruhl static  void aspm_disable(struct hfi1_devdata *dd)
100*bf3b1e0cSMichael J. Ruhl {
101*bf3b1e0cSMichael J. Ruhl 	if (!dd->aspm_enabled || aspm_mode == ASPM_MODE_ENABLED)
102*bf3b1e0cSMichael J. Ruhl 		return;
103*bf3b1e0cSMichael J. Ruhl 
104*bf3b1e0cSMichael J. Ruhl 	aspm_hw_disable_l1(dd);
105*bf3b1e0cSMichael J. Ruhl 	dd->aspm_enabled = false;
106*bf3b1e0cSMichael J. Ruhl }
107*bf3b1e0cSMichael J. Ruhl 
aspm_disable_inc(struct hfi1_devdata * dd)108*bf3b1e0cSMichael J. Ruhl static  void aspm_disable_inc(struct hfi1_devdata *dd)
109*bf3b1e0cSMichael J. Ruhl {
110*bf3b1e0cSMichael J. Ruhl 	unsigned long flags;
111*bf3b1e0cSMichael J. Ruhl 
112*bf3b1e0cSMichael J. Ruhl 	spin_lock_irqsave(&dd->aspm_lock, flags);
113*bf3b1e0cSMichael J. Ruhl 	aspm_disable(dd);
114*bf3b1e0cSMichael J. Ruhl 	atomic_inc(&dd->aspm_disabled_cnt);
115*bf3b1e0cSMichael J. Ruhl 	spin_unlock_irqrestore(&dd->aspm_lock, flags);
116*bf3b1e0cSMichael J. Ruhl }
117*bf3b1e0cSMichael J. Ruhl 
aspm_enable_dec(struct hfi1_devdata * dd)118*bf3b1e0cSMichael J. Ruhl static  void aspm_enable_dec(struct hfi1_devdata *dd)
119*bf3b1e0cSMichael J. Ruhl {
120*bf3b1e0cSMichael J. Ruhl 	unsigned long flags;
121*bf3b1e0cSMichael J. Ruhl 
122*bf3b1e0cSMichael J. Ruhl 	spin_lock_irqsave(&dd->aspm_lock, flags);
123*bf3b1e0cSMichael J. Ruhl 	if (atomic_dec_and_test(&dd->aspm_disabled_cnt))
124*bf3b1e0cSMichael J. Ruhl 		aspm_enable(dd);
125*bf3b1e0cSMichael J. Ruhl 	spin_unlock_irqrestore(&dd->aspm_lock, flags);
126*bf3b1e0cSMichael J. Ruhl }
127*bf3b1e0cSMichael J. Ruhl 
128*bf3b1e0cSMichael J. Ruhl /* ASPM processing for each receive context interrupt */
__aspm_ctx_disable(struct hfi1_ctxtdata * rcd)129*bf3b1e0cSMichael J. Ruhl void __aspm_ctx_disable(struct hfi1_ctxtdata *rcd)
130*bf3b1e0cSMichael J. Ruhl {
131*bf3b1e0cSMichael J. Ruhl 	bool restart_timer;
132*bf3b1e0cSMichael J. Ruhl 	bool close_interrupts;
133*bf3b1e0cSMichael J. Ruhl 	unsigned long flags;
134*bf3b1e0cSMichael J. Ruhl 	ktime_t now, prev;
135*bf3b1e0cSMichael J. Ruhl 
136*bf3b1e0cSMichael J. Ruhl 	spin_lock_irqsave(&rcd->aspm_lock, flags);
137*bf3b1e0cSMichael J. Ruhl 	/* PSM contexts are open */
138*bf3b1e0cSMichael J. Ruhl 	if (!rcd->aspm_intr_enable)
139*bf3b1e0cSMichael J. Ruhl 		goto unlock;
140*bf3b1e0cSMichael J. Ruhl 
141*bf3b1e0cSMichael J. Ruhl 	prev = rcd->aspm_ts_last_intr;
142*bf3b1e0cSMichael J. Ruhl 	now = ktime_get();
143*bf3b1e0cSMichael J. Ruhl 	rcd->aspm_ts_last_intr = now;
144*bf3b1e0cSMichael J. Ruhl 
145*bf3b1e0cSMichael J. Ruhl 	/* An interrupt pair close together in time */
146*bf3b1e0cSMichael J. Ruhl 	close_interrupts = ktime_to_ns(ktime_sub(now, prev)) < ASPM_TRIGGER_NS;
147*bf3b1e0cSMichael J. Ruhl 
148*bf3b1e0cSMichael J. Ruhl 	/* Don't push out our timer till this much time has elapsed */
149*bf3b1e0cSMichael J. Ruhl 	restart_timer = ktime_to_ns(ktime_sub(now, rcd->aspm_ts_timer_sched)) >
150*bf3b1e0cSMichael J. Ruhl 				    ASPM_RESCHED_TIMER_MS * NSEC_PER_MSEC;
151*bf3b1e0cSMichael J. Ruhl 	restart_timer = restart_timer && close_interrupts;
152*bf3b1e0cSMichael J. Ruhl 
153*bf3b1e0cSMichael J. Ruhl 	/* Disable ASPM and schedule timer */
154*bf3b1e0cSMichael J. Ruhl 	if (rcd->aspm_enabled && close_interrupts) {
155*bf3b1e0cSMichael J. Ruhl 		aspm_disable_inc(rcd->dd);
156*bf3b1e0cSMichael J. Ruhl 		rcd->aspm_enabled = false;
157*bf3b1e0cSMichael J. Ruhl 		restart_timer = true;
158*bf3b1e0cSMichael J. Ruhl 	}
159*bf3b1e0cSMichael J. Ruhl 
160*bf3b1e0cSMichael J. Ruhl 	if (restart_timer) {
161*bf3b1e0cSMichael J. Ruhl 		mod_timer(&rcd->aspm_timer,
162*bf3b1e0cSMichael J. Ruhl 			  jiffies + msecs_to_jiffies(ASPM_TIMER_MS));
163*bf3b1e0cSMichael J. Ruhl 		rcd->aspm_ts_timer_sched = now;
164*bf3b1e0cSMichael J. Ruhl 	}
165*bf3b1e0cSMichael J. Ruhl unlock:
166*bf3b1e0cSMichael J. Ruhl 	spin_unlock_irqrestore(&rcd->aspm_lock, flags);
167*bf3b1e0cSMichael J. Ruhl }
168*bf3b1e0cSMichael J. Ruhl 
169*bf3b1e0cSMichael J. Ruhl /* Timer function for re-enabling ASPM in the absence of interrupt activity */
aspm_ctx_timer_function(struct timer_list * t)170*bf3b1e0cSMichael J. Ruhl static  void aspm_ctx_timer_function(struct timer_list *t)
171*bf3b1e0cSMichael J. Ruhl {
172*bf3b1e0cSMichael J. Ruhl 	struct hfi1_ctxtdata *rcd = from_timer(rcd, t, aspm_timer);
173*bf3b1e0cSMichael J. Ruhl 	unsigned long flags;
174*bf3b1e0cSMichael J. Ruhl 
175*bf3b1e0cSMichael J. Ruhl 	spin_lock_irqsave(&rcd->aspm_lock, flags);
176*bf3b1e0cSMichael J. Ruhl 	aspm_enable_dec(rcd->dd);
177*bf3b1e0cSMichael J. Ruhl 	rcd->aspm_enabled = true;
178*bf3b1e0cSMichael J. Ruhl 	spin_unlock_irqrestore(&rcd->aspm_lock, flags);
179*bf3b1e0cSMichael J. Ruhl }
180*bf3b1e0cSMichael J. Ruhl 
181*bf3b1e0cSMichael J. Ruhl /*
182*bf3b1e0cSMichael J. Ruhl  * Disable interrupt processing for verbs contexts when PSM or VNIC contexts
183*bf3b1e0cSMichael J. Ruhl  * are open.
184*bf3b1e0cSMichael J. Ruhl  */
aspm_disable_all(struct hfi1_devdata * dd)185*bf3b1e0cSMichael J. Ruhl void aspm_disable_all(struct hfi1_devdata *dd)
186*bf3b1e0cSMichael J. Ruhl {
187*bf3b1e0cSMichael J. Ruhl 	struct hfi1_ctxtdata *rcd;
188*bf3b1e0cSMichael J. Ruhl 	unsigned long flags;
189*bf3b1e0cSMichael J. Ruhl 	u16 i;
190*bf3b1e0cSMichael J. Ruhl 
191*bf3b1e0cSMichael J. Ruhl 	for (i = 0; i < dd->first_dyn_alloc_ctxt; i++) {
192*bf3b1e0cSMichael J. Ruhl 		rcd = hfi1_rcd_get_by_index(dd, i);
193*bf3b1e0cSMichael J. Ruhl 		if (rcd) {
194*bf3b1e0cSMichael J. Ruhl 			del_timer_sync(&rcd->aspm_timer);
195*bf3b1e0cSMichael J. Ruhl 			spin_lock_irqsave(&rcd->aspm_lock, flags);
196*bf3b1e0cSMichael J. Ruhl 			rcd->aspm_intr_enable = false;
197*bf3b1e0cSMichael J. Ruhl 			spin_unlock_irqrestore(&rcd->aspm_lock, flags);
198*bf3b1e0cSMichael J. Ruhl 			hfi1_rcd_put(rcd);
199*bf3b1e0cSMichael J. Ruhl 		}
200*bf3b1e0cSMichael J. Ruhl 	}
201*bf3b1e0cSMichael J. Ruhl 
202*bf3b1e0cSMichael J. Ruhl 	aspm_disable(dd);
203*bf3b1e0cSMichael J. Ruhl 	atomic_set(&dd->aspm_disabled_cnt, 0);
204*bf3b1e0cSMichael J. Ruhl }
205*bf3b1e0cSMichael J. Ruhl 
206*bf3b1e0cSMichael J. Ruhl /* Re-enable interrupt processing for verbs contexts */
aspm_enable_all(struct hfi1_devdata * dd)207*bf3b1e0cSMichael J. Ruhl void aspm_enable_all(struct hfi1_devdata *dd)
208*bf3b1e0cSMichael J. Ruhl {
209*bf3b1e0cSMichael J. Ruhl 	struct hfi1_ctxtdata *rcd;
210*bf3b1e0cSMichael J. Ruhl 	unsigned long flags;
211*bf3b1e0cSMichael J. Ruhl 	u16 i;
212*bf3b1e0cSMichael J. Ruhl 
213*bf3b1e0cSMichael J. Ruhl 	aspm_enable(dd);
214*bf3b1e0cSMichael J. Ruhl 
215*bf3b1e0cSMichael J. Ruhl 	if (aspm_mode != ASPM_MODE_DYNAMIC)
216*bf3b1e0cSMichael J. Ruhl 		return;
217*bf3b1e0cSMichael J. Ruhl 
218*bf3b1e0cSMichael J. Ruhl 	for (i = 0; i < dd->first_dyn_alloc_ctxt; i++) {
219*bf3b1e0cSMichael J. Ruhl 		rcd = hfi1_rcd_get_by_index(dd, i);
220*bf3b1e0cSMichael J. Ruhl 		if (rcd) {
221*bf3b1e0cSMichael J. Ruhl 			spin_lock_irqsave(&rcd->aspm_lock, flags);
222*bf3b1e0cSMichael J. Ruhl 			rcd->aspm_intr_enable = true;
223*bf3b1e0cSMichael J. Ruhl 			rcd->aspm_enabled = true;
224*bf3b1e0cSMichael J. Ruhl 			spin_unlock_irqrestore(&rcd->aspm_lock, flags);
225*bf3b1e0cSMichael J. Ruhl 			hfi1_rcd_put(rcd);
226*bf3b1e0cSMichael J. Ruhl 		}
227*bf3b1e0cSMichael J. Ruhl 	}
228*bf3b1e0cSMichael J. Ruhl }
229*bf3b1e0cSMichael J. Ruhl 
aspm_ctx_init(struct hfi1_ctxtdata * rcd)230*bf3b1e0cSMichael J. Ruhl static  void aspm_ctx_init(struct hfi1_ctxtdata *rcd)
231*bf3b1e0cSMichael J. Ruhl {
232*bf3b1e0cSMichael J. Ruhl 	spin_lock_init(&rcd->aspm_lock);
233*bf3b1e0cSMichael J. Ruhl 	timer_setup(&rcd->aspm_timer, aspm_ctx_timer_function, 0);
234*bf3b1e0cSMichael J. Ruhl 	rcd->aspm_intr_supported = rcd->dd->aspm_supported &&
235*bf3b1e0cSMichael J. Ruhl 		aspm_mode == ASPM_MODE_DYNAMIC &&
236*bf3b1e0cSMichael J. Ruhl 		rcd->ctxt < rcd->dd->first_dyn_alloc_ctxt;
237*bf3b1e0cSMichael J. Ruhl }
238*bf3b1e0cSMichael J. Ruhl 
aspm_init(struct hfi1_devdata * dd)239*bf3b1e0cSMichael J. Ruhl void aspm_init(struct hfi1_devdata *dd)
240*bf3b1e0cSMichael J. Ruhl {
241*bf3b1e0cSMichael J. Ruhl 	struct hfi1_ctxtdata *rcd;
242*bf3b1e0cSMichael J. Ruhl 	u16 i;
243*bf3b1e0cSMichael J. Ruhl 
244*bf3b1e0cSMichael J. Ruhl 	spin_lock_init(&dd->aspm_lock);
245*bf3b1e0cSMichael J. Ruhl 	dd->aspm_supported = aspm_hw_l1_supported(dd);
246*bf3b1e0cSMichael J. Ruhl 
247*bf3b1e0cSMichael J. Ruhl 	for (i = 0; i < dd->first_dyn_alloc_ctxt; i++) {
248*bf3b1e0cSMichael J. Ruhl 		rcd = hfi1_rcd_get_by_index(dd, i);
249*bf3b1e0cSMichael J. Ruhl 		if (rcd)
250*bf3b1e0cSMichael J. Ruhl 			aspm_ctx_init(rcd);
251*bf3b1e0cSMichael J. Ruhl 		hfi1_rcd_put(rcd);
252*bf3b1e0cSMichael J. Ruhl 	}
253*bf3b1e0cSMichael J. Ruhl 
254*bf3b1e0cSMichael J. Ruhl 	/* Start with ASPM disabled */
255*bf3b1e0cSMichael J. Ruhl 	aspm_hw_set_l1_ent_latency(dd);
256*bf3b1e0cSMichael J. Ruhl 	dd->aspm_enabled = false;
257*bf3b1e0cSMichael J. Ruhl 	aspm_hw_disable_l1(dd);
258*bf3b1e0cSMichael J. Ruhl 
259*bf3b1e0cSMichael J. Ruhl 	/* Now turn on ASPM if configured */
260*bf3b1e0cSMichael J. Ruhl 	aspm_enable_all(dd);
261*bf3b1e0cSMichael J. Ruhl }
262*bf3b1e0cSMichael J. Ruhl 
aspm_exit(struct hfi1_devdata * dd)263*bf3b1e0cSMichael J. Ruhl void aspm_exit(struct hfi1_devdata *dd)
264*bf3b1e0cSMichael J. Ruhl {
265*bf3b1e0cSMichael J. Ruhl 	aspm_disable_all(dd);
266*bf3b1e0cSMichael J. Ruhl 
267*bf3b1e0cSMichael J. Ruhl 	/* Turn on ASPM on exit to conserve power */
268*bf3b1e0cSMichael J. Ruhl 	aspm_enable(dd);
269*bf3b1e0cSMichael J. Ruhl }
270*bf3b1e0cSMichael J. Ruhl 
271