aspm.c 25.4 KB
Newer Older
S
Shaohua Li 已提交
1 2
/*
 * File:	drivers/pci/pcie/aspm.c
3
 * Enabling PCIe link L0s/L1 state and Clock Power Management
S
Shaohua Li 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * Copyright (C) 2007 Intel
 * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
 * Copyright (C) Shaohua Li (shaohua.li@intel.com)
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/init.h>
#include <linux/slab.h>
19
#include <linux/jiffies.h>
20
#include <linux/delay.h>
S
Shaohua Li 已提交
21 22 23 24 25 26 27 28
#include <linux/pci-aspm.h>
#include "../pci.h"

#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
#define MODULE_PARAM_PREFIX "pcie_aspm."

29 30 31 32 33 34 35
/* Note: those are not register definitions */
#define ASPM_STATE_L0S_UP	(1)	/* Upstream direction L0s state */
#define ASPM_STATE_L0S_DW	(2)	/* Downstream direction L0s state */
#define ASPM_STATE_L1		(4)	/* L1 state */
#define ASPM_STATE_L0S		(ASPM_STATE_L0S_UP | ASPM_STATE_L0S_DW)
#define ASPM_STATE_ALL		(ASPM_STATE_L0S | ASPM_STATE_L1)

36 37 38
struct aspm_latency {
	u32 l0s;			/* L0s latency (nsec) */
	u32 l1;				/* L1 latency (nsec) */
S
Shaohua Li 已提交
39 40 41
};

struct pcie_link_state {
42
	struct pci_dev *pdev;		/* Upstream component of the Link */
43
	struct pcie_link_state *root;	/* pointer to the root port link */
44 45 46 47
	struct pcie_link_state *parent;	/* pointer to the parent Link state */
	struct list_head sibling;	/* node in link_list */
	struct list_head children;	/* list of child link states */
	struct list_head link;		/* node in parent's children list */
S
Shaohua Li 已提交
48 49

	/* ASPM state */
50 51 52 53 54
	u32 aspm_support:3;		/* Supported ASPM state */
	u32 aspm_enabled:3;		/* Enabled ASPM state */
	u32 aspm_capable:3;		/* Capable ASPM state with latency */
	u32 aspm_default:3;		/* Default ASPM state by BIOS */
	u32 aspm_disable:3;		/* Disabled ASPM state */
55

56 57 58 59 60
	/* Clock PM state */
	u32 clkpm_capable:1;		/* Clock PM capable? */
	u32 clkpm_enabled:1;		/* Current Clock PM state */
	u32 clkpm_default:1;		/* Default Clock PM state by BIOS */

61 62 63
	/* Exit latencies */
	struct aspm_latency latency_up;	/* Upstream direction exit latency */
	struct aspm_latency latency_dw;	/* Downstream direction exit latency */
S
Shaohua Li 已提交
64
	/*
65 66
	 * Endpoint acceptable latencies. A pcie downstream port only
	 * has one slot under it, so at most there are 8 functions.
S
Shaohua Li 已提交
67
	 */
68
	struct aspm_latency acceptable[8];
S
Shaohua Li 已提交
69 70
};

71
static int aspm_disabled, aspm_force;
S
Shaohua Li 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84
static DEFINE_MUTEX(aspm_lock);
static LIST_HEAD(link_list);

#define POLICY_DEFAULT 0	/* BIOS default setting */
#define POLICY_PERFORMANCE 1	/* high performance */
#define POLICY_POWERSAVE 2	/* high power saving */
static int aspm_policy;
static const char *policy_str[] = {
	[POLICY_DEFAULT] = "default",
	[POLICY_PERFORMANCE] = "performance",
	[POLICY_POWERSAVE] = "powersave"
};

85 86
#define LINK_RETRAIN_TIMEOUT HZ

87
static int policy_to_aspm_state(struct pcie_link_state *link)
S
Shaohua Li 已提交
88 89 90 91 92 93 94
{
	switch (aspm_policy) {
	case POLICY_PERFORMANCE:
		/* Disable ASPM and Clock PM */
		return 0;
	case POLICY_POWERSAVE:
		/* Enable ASPM L0s/L1 */
95
		return ASPM_STATE_ALL;
S
Shaohua Li 已提交
96
	case POLICY_DEFAULT:
97
		return link->aspm_default;
S
Shaohua Li 已提交
98 99 100 101
	}
	return 0;
}

102
static int policy_to_clkpm_state(struct pcie_link_state *link)
S
Shaohua Li 已提交
103 104 105 106 107 108 109 110 111
{
	switch (aspm_policy) {
	case POLICY_PERFORMANCE:
		/* Disable ASPM and Clock PM */
		return 0;
	case POLICY_POWERSAVE:
		/* Disable Clock PM */
		return 1;
	case POLICY_DEFAULT:
112
		return link->clkpm_default;
S
Shaohua Li 已提交
113 114 115 116
	}
	return 0;
}

K
Kenji Kaneshige 已提交
117
static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
S
Shaohua Li 已提交
118 119 120
{
	int pos;
	u16 reg16;
121 122
	struct pci_dev *child;
	struct pci_bus *linkbus = link->pdev->subordinate;
S
Shaohua Li 已提交
123

124
	list_for_each_entry(child, &linkbus->devices, bus_list) {
K
Kenji Kaneshige 已提交
125
		pos = pci_pcie_cap(child);
S
Shaohua Li 已提交
126 127
		if (!pos)
			return;
128
		pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
S
Shaohua Li 已提交
129 130 131 132
		if (enable)
			reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
		else
			reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
133
		pci_write_config_word(child, pos + PCI_EXP_LNKCTL, reg16);
S
Shaohua Li 已提交
134
	}
135
	link->clkpm_enabled = !!enable;
S
Shaohua Li 已提交
136 137
}

K
Kenji Kaneshige 已提交
138 139 140 141 142 143 144 145 146 147 148
static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
{
	/* Don't enable Clock PM if the link is not Clock PM capable */
	if (!link->clkpm_capable && enable)
		return;
	/* Need nothing if the specified equals to current state */
	if (link->clkpm_enabled == enable)
		return;
	pcie_set_clkpm_nocheck(link, enable);
}

149
static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
S
Shaohua Li 已提交
150
{
151
	int pos, capable = 1, enabled = 1;
S
Shaohua Li 已提交
152 153
	u32 reg32;
	u16 reg16;
154 155
	struct pci_dev *child;
	struct pci_bus *linkbus = link->pdev->subordinate;
S
Shaohua Li 已提交
156 157

	/* All functions should have the same cap and state, take the worst */
158
	list_for_each_entry(child, &linkbus->devices, bus_list) {
K
Kenji Kaneshige 已提交
159
		pos = pci_pcie_cap(child);
S
Shaohua Li 已提交
160 161
		if (!pos)
			return;
162
		pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32);
S
Shaohua Li 已提交
163 164 165 166 167
		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
			capable = 0;
			enabled = 0;
			break;
		}
168
		pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
S
Shaohua Li 已提交
169 170 171
		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
			enabled = 0;
	}
172 173
	link->clkpm_enabled = enabled;
	link->clkpm_default = enabled;
174
	link->clkpm_capable = (blacklist) ? 0 : capable;
175 176
}

S
Shaohua Li 已提交
177 178 179 180 181
/*
 * pcie_aspm_configure_common_clock: check if the 2 ends of a link
 *   could use common clock. If they are, configure them to use the
 *   common clock. That will reduce the ASPM state exit latency.
 */
182
static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
S
Shaohua Li 已提交
183
{
184 185
	int ppos, cpos, same_clock = 1;
	u16 reg16, parent_reg, child_reg[8];
186
	unsigned long start_jiffies;
187 188
	struct pci_dev *child, *parent = link->pdev;
	struct pci_bus *linkbus = parent->subordinate;
S
Shaohua Li 已提交
189
	/*
190
	 * All functions of a slot should have the same Slot Clock
S
Shaohua Li 已提交
191
	 * Configuration, so just check one function
192 193
	 */
	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
K
Kenji Kaneshige 已提交
194
	BUG_ON(!pci_is_pcie(child));
S
Shaohua Li 已提交
195 196

	/* Check downstream component if bit Slot Clock Configuration is 1 */
K
Kenji Kaneshige 已提交
197
	cpos = pci_pcie_cap(child);
198
	pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16);
S
Shaohua Li 已提交
199 200 201 202
	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
		same_clock = 0;

	/* Check upstream component if bit Slot Clock Configuration is 1 */
K
Kenji Kaneshige 已提交
203
	ppos = pci_pcie_cap(parent);
204
	pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
S
Shaohua Li 已提交
205 206 207 208
	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
		same_clock = 0;

	/* Configure downstream component, all functions */
209
	list_for_each_entry(child, &linkbus->devices, bus_list) {
K
Kenji Kaneshige 已提交
210
		cpos = pci_pcie_cap(child);
211 212
		pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, &reg16);
		child_reg[PCI_FUNC(child->devfn)] = reg16;
S
Shaohua Li 已提交
213 214 215 216
		if (same_clock)
			reg16 |= PCI_EXP_LNKCTL_CCC;
		else
			reg16 &= ~PCI_EXP_LNKCTL_CCC;
217
		pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, reg16);
S
Shaohua Li 已提交
218 219 220
	}

	/* Configure upstream component */
221
	pci_read_config_word(parent, ppos + PCI_EXP_LNKCTL, &reg16);
222
	parent_reg = reg16;
S
Shaohua Li 已提交
223 224 225 226
	if (same_clock)
		reg16 |= PCI_EXP_LNKCTL_CCC;
	else
		reg16 &= ~PCI_EXP_LNKCTL_CCC;
227
	pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16);
S
Shaohua Li 已提交
228

229
	/* Retrain link */
S
Shaohua Li 已提交
230
	reg16 |= PCI_EXP_LNKCTL_RL;
231
	pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16);
S
Shaohua Li 已提交
232

233
	/* Wait for link training end. Break out after waiting for timeout */
234
	start_jiffies = jiffies;
235
	for (;;) {
236
		pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
S
Shaohua Li 已提交
237 238
		if (!(reg16 & PCI_EXP_LNKSTA_LT))
			break;
239 240 241
		if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
			break;
		msleep(1);
S
Shaohua Li 已提交
242
	}
243 244 245 246 247 248 249
	if (!(reg16 & PCI_EXP_LNKSTA_LT))
		return;

	/* Training failed. Restore common clock configurations */
	dev_printk(KERN_ERR, &parent->dev,
		   "ASPM: Could not configure common clock\n");
	list_for_each_entry(child, &linkbus->devices, bus_list) {
K
Kenji Kaneshige 已提交
250
		cpos = pci_pcie_cap(child);
251 252
		pci_write_config_word(child, cpos + PCI_EXP_LNKCTL,
				      child_reg[PCI_FUNC(child->devfn)]);
253
	}
254
	pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, parent_reg);
S
Shaohua Li 已提交
255 256
}

257 258
/* Convert L0s latency encoding to ns */
static u32 calc_l0s_latency(u32 encoding)
S
Shaohua Li 已提交
259
{
260 261 262 263
	if (encoding == 0x7)
		return (5 * 1000);	/* > 4us */
	return (64 << encoding);
}
S
Shaohua Li 已提交
264

265 266 267 268 269 270
/* Convert L0s acceptable latency encoding to ns */
static u32 calc_l0s_acceptable(u32 encoding)
{
	if (encoding == 0x7)
		return -1U;
	return (64 << encoding);
S
Shaohua Li 已提交
271 272
}

273 274
/* Convert L1 latency encoding to ns */
static u32 calc_l1_latency(u32 encoding)
S
Shaohua Li 已提交
275
{
276 277 278 279
	if (encoding == 0x7)
		return (65 * 1000);	/* > 64us */
	return (1000 << encoding);
}
S
Shaohua Li 已提交
280

281 282 283 284 285 286
/* Convert L1 acceptable latency encoding to ns */
static u32 calc_l1_acceptable(u32 encoding)
{
	if (encoding == 0x7)
		return -1U;
	return (1000 << encoding);
S
Shaohua Li 已提交
287 288
}

289 290 291 292 293 294 295 296 297
struct aspm_register_info {
	u32 support:2;
	u32 enabled:2;
	u32 latency_encoding_l0s;
	u32 latency_encoding_l1;
};

static void pcie_get_aspm_reg(struct pci_dev *pdev,
			      struct aspm_register_info *info)
S
Shaohua Li 已提交
298 299 300
{
	int pos;
	u16 reg16;
301
	u32 reg32;
S
Shaohua Li 已提交
302

K
Kenji Kaneshige 已提交
303
	pos = pci_pcie_cap(pdev);
S
Shaohua Li 已提交
304
	pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
305 306 307
	info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
	info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
	info->latency_encoding_l1  = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
S
Shaohua Li 已提交
308
	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
309
	info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC;
S
Shaohua Li 已提交
310 311
}

312 313
static void pcie_aspm_check_latency(struct pci_dev *endpoint)
{
314
	u32 latency, l1_switch_latency = 0;
315 316 317 318 319 320 321 322 323 324 325 326
	struct aspm_latency *acceptable;
	struct pcie_link_state *link;

	/* Device not in D0 doesn't need latency check */
	if ((endpoint->current_state != PCI_D0) &&
	    (endpoint->current_state != PCI_UNKNOWN))
		return;

	link = endpoint->bus->self->link_state;
	acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)];

	while (link) {
327 328 329 330 331 332 333 334 335
		/* Check upstream direction L0s latency */
		if ((link->aspm_capable & ASPM_STATE_L0S_UP) &&
		    (link->latency_up.l0s > acceptable->l0s))
			link->aspm_capable &= ~ASPM_STATE_L0S_UP;

		/* Check downstream direction L0s latency */
		if ((link->aspm_capable & ASPM_STATE_L0S_DW) &&
		    (link->latency_dw.l0s > acceptable->l0s))
			link->aspm_capable &= ~ASPM_STATE_L0S_DW;
336 337 338 339 340
		/*
		 * Check L1 latency.
		 * Every switch on the path to root complex need 1
		 * more microsecond for L1. Spec doesn't mention L0s.
		 */
341 342 343 344
		latency = max_t(u32, link->latency_up.l1, link->latency_dw.l1);
		if ((link->aspm_capable & ASPM_STATE_L1) &&
		    (latency + l1_switch_latency > acceptable->l1))
			link->aspm_capable &= ~ASPM_STATE_L1;
345 346 347 348 349 350
		l1_switch_latency += 1000;

		link = link->parent;
	}
}

351
static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
S
Shaohua Li 已提交
352
{
353 354
	struct pci_dev *child, *parent = link->pdev;
	struct pci_bus *linkbus = parent->subordinate;
355
	struct aspm_register_info upreg, dwreg;
S
Shaohua Li 已提交
356

357
	if (blacklist) {
358
		/* Set enabled/disable so that we will disable ASPM later */
359 360
		link->aspm_enabled = ASPM_STATE_ALL;
		link->aspm_disable = ASPM_STATE_ALL;
361 362 363 364 365 366
		return;
	}

	/* Configure common clock before checking latencies */
	pcie_aspm_configure_common_clock(link);

367 368
	/* Get upstream/downstream components' register state */
	pcie_get_aspm_reg(parent, &upreg);
369
	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
	pcie_get_aspm_reg(child, &dwreg);

	/*
	 * Setup L0s state
	 *
	 * Note that we must not enable L0s in either direction on a
	 * given link unless components on both sides of the link each
	 * support L0s.
	 */
	if (dwreg.support & upreg.support & PCIE_LINK_STATE_L0S)
		link->aspm_support |= ASPM_STATE_L0S;
	if (dwreg.enabled & PCIE_LINK_STATE_L0S)
		link->aspm_enabled |= ASPM_STATE_L0S_UP;
	if (upreg.enabled & PCIE_LINK_STATE_L0S)
		link->aspm_enabled |= ASPM_STATE_L0S_DW;
	link->latency_up.l0s = calc_l0s_latency(upreg.latency_encoding_l0s);
	link->latency_dw.l0s = calc_l0s_latency(dwreg.latency_encoding_l0s);

	/* Setup L1 state */
	if (upreg.support & dwreg.support & PCIE_LINK_STATE_L1)
		link->aspm_support |= ASPM_STATE_L1;
	if (upreg.enabled & dwreg.enabled & PCIE_LINK_STATE_L1)
		link->aspm_enabled |= ASPM_STATE_L1;
	link->latency_up.l1 = calc_l1_latency(upreg.latency_encoding_l1);
	link->latency_dw.l1 = calc_l1_latency(dwreg.latency_encoding_l1);
395

396 397
	/* Save default state */
	link->aspm_default = link->aspm_enabled;
398 399 400

	/* Setup initial capable state. Will be updated later */
	link->aspm_capable = link->aspm_support;
401 402 403 404 405 406
	/*
	 * If the downstream component has pci bridge function, don't
	 * do ASPM for now.
	 */
	list_for_each_entry(child, &linkbus->devices, bus_list) {
		if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
407
			link->aspm_disable = ASPM_STATE_ALL;
408 409 410
			break;
		}
	}
411

412
	/* Get and check endpoint acceptable latencies */
413
	list_for_each_entry(child, &linkbus->devices, bus_list) {
S
Shaohua Li 已提交
414
		int pos;
415
		u32 reg32, encoding;
416
		struct aspm_latency *acceptable =
417
			&link->acceptable[PCI_FUNC(child->devfn)];
S
Shaohua Li 已提交
418

419 420
		if (child->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
		    child->pcie_type != PCI_EXP_TYPE_LEG_END)
S
Shaohua Li 已提交
421 422
			continue;

K
Kenji Kaneshige 已提交
423
		pos = pci_pcie_cap(child);
424
		pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
425
		/* Calculate endpoint L0s acceptable latency */
426 427
		encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
		acceptable->l0s = calc_l0s_acceptable(encoding);
428 429 430 431 432
		/* Calculate endpoint L1 acceptable latency */
		encoding = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
		acceptable->l1 = calc_l1_acceptable(encoding);

		pcie_aspm_check_latency(child);
S
Shaohua Li 已提交
433 434 435
	}
}

436
static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
S
Shaohua Li 已提交
437 438
{
	u16 reg16;
K
Kenji Kaneshige 已提交
439
	int pos = pci_pcie_cap(pdev);
S
Shaohua Li 已提交
440 441 442

	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
	reg16 &= ~0x3;
443
	reg16 |= val;
S
Shaohua Li 已提交
444 445 446
	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
}

447
static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
S
Shaohua Li 已提交
448
{
449
	u32 upstream = 0, dwstream = 0;
450 451
	struct pci_dev *child, *parent = link->pdev;
	struct pci_bus *linkbus = parent->subordinate;
S
Shaohua Li 已提交
452

453
	/* Nothing to do if the link is already in the requested state */
454
	state &= (link->aspm_capable & ~link->aspm_disable);
455 456
	if (link->aspm_enabled == state)
		return;
457 458 459 460 461 462 463 464 465
	/* Convert ASPM state to upstream/downstream ASPM register state */
	if (state & ASPM_STATE_L0S_UP)
		dwstream |= PCIE_LINK_STATE_L0S;
	if (state & ASPM_STATE_L0S_DW)
		upstream |= PCIE_LINK_STATE_L0S;
	if (state & ASPM_STATE_L1) {
		upstream |= PCIE_LINK_STATE_L1;
		dwstream |= PCIE_LINK_STATE_L1;
	}
S
Shaohua Li 已提交
466
	/*
467 468 469 470
	 * Spec 2.0 suggests all functions should be configured the
	 * same setting for ASPM. Enabling ASPM L1 should be done in
	 * upstream component first and then downstream, and vice
	 * versa for disabling ASPM L1. Spec doesn't mention L0S.
S
Shaohua Li 已提交
471
	 */
472 473
	if (state & ASPM_STATE_L1)
		pcie_config_aspm_dev(parent, upstream);
474
	list_for_each_entry(child, &linkbus->devices, bus_list)
475 476 477
		pcie_config_aspm_dev(child, dwstream);
	if (!(state & ASPM_STATE_L1))
		pcie_config_aspm_dev(parent, upstream);
S
Shaohua Li 已提交
478

479
	link->aspm_enabled = state;
S
Shaohua Li 已提交
480 481
}

482
static void pcie_config_aspm_path(struct pcie_link_state *link)
S
Shaohua Li 已提交
483
{
484 485 486
	while (link) {
		pcie_config_aspm_link(link, policy_to_aspm_state(link));
		link = link->parent;
487
	}
S
Shaohua Li 已提交
488 489
}

490
static void free_link_state(struct pcie_link_state *link)
S
Shaohua Li 已提交
491
{
492 493
	link->pdev->link_state = NULL;
	kfree(link);
S
Shaohua Li 已提交
494 495
}

496 497
static int pcie_aspm_sanity_check(struct pci_dev *pdev)
{
498 499
	struct pci_dev *child;
	int pos;
500
	u32 reg32;
501
	/*
502
	 * Some functions in a slot might not all be PCIe functions,
503
	 * very strange. Disable ASPM for the whole slot
504
	 */
505
	list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
K
Kenji Kaneshige 已提交
506
		pos = pci_pcie_cap(child);
507
		if (!pos)
508
			return -EINVAL;
509 510 511 512
		/*
		 * Disable ASPM for pre-1.1 PCIe device, we follow MS to use
		 * RBER bit to determine if a function is 1.1 version device
		 */
513
		pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
S
Sitsofe Wheeler 已提交
514
		if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
515
			dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
516 517
				" on pre-1.1 PCIe device.  You can enable it"
				" with 'pcie_aspm=force'\n");
518 519
			return -EINVAL;
		}
520 521 522 523
	}
	return 0;
}

524
static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
{
	struct pcie_link_state *link;

	link = kzalloc(sizeof(*link), GFP_KERNEL);
	if (!link)
		return NULL;
	INIT_LIST_HEAD(&link->sibling);
	INIT_LIST_HEAD(&link->children);
	INIT_LIST_HEAD(&link->link);
	link->pdev = pdev;
	if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) {
		struct pcie_link_state *parent;
		parent = pdev->bus->parent->self->link_state;
		if (!parent) {
			kfree(link);
			return NULL;
		}
		link->parent = parent;
		list_add(&link->link, &parent->children);
	}
545 546 547 548 549 550
	/* Setup a pointer to the root port link */
	if (!link->parent)
		link->root = link;
	else
		link->root = link->parent->root;

551 552 553 554 555
	list_add(&link->sibling, &link_list);
	pdev->link_state = link;
	return link;
}

S
Shaohua Li 已提交
556 557 558 559 560 561 562
/*
 * pcie_aspm_init_link_state: Initiate PCI express link state.
 * It is called after the pcie and its children devices are scaned.
 * @pdev: the root port or switch downstream port
 */
void pcie_aspm_init_link_state(struct pci_dev *pdev)
{
563
	struct pcie_link_state *link;
564
	int blacklist = !!pcie_aspm_sanity_check(pdev);
S
Shaohua Li 已提交
565

K
Kenji Kaneshige 已提交
566
	if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state)
S
Shaohua Li 已提交
567 568
		return;
	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
569
	    pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
S
Shaohua Li 已提交
570
		return;
571

572 573
	/* VIA has a strange chipset, root port is under a bridge */
	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
574
	    pdev->bus->self)
575
		return;
576

S
Shaohua Li 已提交
577 578 579 580 581
	down_read(&pci_bus_sem);
	if (list_empty(&pdev->subordinate->devices))
		goto out;

	mutex_lock(&aspm_lock);
582
	link = alloc_pcie_link_state(pdev);
583 584 585
	if (!link)
		goto unlock;
	/*
586 587 588
	 * Setup initial ASPM state. Note that we need to configure
	 * upstream links also because capable state of them can be
	 * update through pcie_aspm_cap_init().
589
	 */
590
	pcie_aspm_cap_init(link, blacklist);
S
Shaohua Li 已提交
591

592
	/* Setup initial Clock PM state */
593
	pcie_clkpm_cap_init(link, blacklist);
594 595 596 597 598 599 600 601 602 603 604 605 606 607

	/*
	 * At this stage drivers haven't had an opportunity to change the
	 * link policy setting. Enabling ASPM on broken hardware can cripple
	 * it even before the driver has had a chance to disable ASPM, so
	 * default to a safe level right now. If we're enabling ASPM beyond
	 * the BIOS's expectation, we'll do so once pci_enable_device() is
	 * called.
	 */
	if (aspm_policy != POLICY_POWERSAVE) {
		pcie_config_aspm_path(link);
		pcie_set_clkpm(link, policy_to_clkpm_state(link));
	}

608
unlock:
S
Shaohua Li 已提交
609 610 611 612 613
	mutex_unlock(&aspm_lock);
out:
	up_read(&pci_bus_sem);
}

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
/* Recheck latencies and update aspm_capable for links under the root */
static void pcie_update_aspm_capable(struct pcie_link_state *root)
{
	struct pcie_link_state *link;
	BUG_ON(root->parent);
	list_for_each_entry(link, &link_list, sibling) {
		if (link->root != root)
			continue;
		link->aspm_capable = link->aspm_support;
	}
	list_for_each_entry(link, &link_list, sibling) {
		struct pci_dev *child;
		struct pci_bus *linkbus = link->pdev->subordinate;
		if (link->root != root)
			continue;
		list_for_each_entry(child, &linkbus->devices, bus_list) {
			if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT) &&
			    (child->pcie_type != PCI_EXP_TYPE_LEG_END))
				continue;
			pcie_aspm_check_latency(child);
		}
	}
}

S
Shaohua Li 已提交
638 639 640 641
/* @pdev: the endpoint device */
void pcie_aspm_exit_link_state(struct pci_dev *pdev)
{
	struct pci_dev *parent = pdev->bus->self;
642
	struct pcie_link_state *link, *root, *parent_link;
S
Shaohua Li 已提交
643

K
Kenji Kaneshige 已提交
644 645
	if (aspm_disabled || !pci_is_pcie(pdev) ||
	    !parent || !parent->link_state)
S
Shaohua Li 已提交
646
		return;
647 648
	if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
	    (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
S
Shaohua Li 已提交
649
		return;
650

S
Shaohua Li 已提交
651 652 653 654
	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
	/*
	 * All PCIe functions are in one slot, remove one function will remove
655
	 * the whole slot, so just wait until we are the last function left.
S
Shaohua Li 已提交
656
	 */
657
	if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices))
S
Shaohua Li 已提交
658 659
		goto out;

660
	link = parent->link_state;
661
	root = link->root;
662
	parent_link = link->parent;
663

S
Shaohua Li 已提交
664
	/* All functions are removed, so just disable ASPM for the link */
665
	pcie_config_aspm_link(link, 0);
666 667
	list_del(&link->sibling);
	list_del(&link->link);
S
Shaohua Li 已提交
668
	/* Clock PM is for endpoint device */
669
	free_link_state(link);
670 671

	/* Recheck latencies and configure upstream links */
672 673 674 675
	if (parent_link) {
		pcie_update_aspm_capable(root);
		pcie_config_aspm_path(parent_link);
	}
S
Shaohua Li 已提交
676 677 678 679 680 681 682 683
out:
	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);
}

/* @pdev: the root port or switch downstream port */
void pcie_aspm_pm_state_change(struct pci_dev *pdev)
{
684
	struct pcie_link_state *link = pdev->link_state;
S
Shaohua Li 已提交
685

K
Kenji Kaneshige 已提交
686
	if (aspm_disabled || !pci_is_pcie(pdev) || !link)
S
Shaohua Li 已提交
687
		return;
688 689
	if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
	    (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
S
Shaohua Li 已提交
690 691
		return;
	/*
692 693
	 * Devices changed PM state, we should recheck if latency
	 * meets all functions' requirement
S
Shaohua Li 已提交
694
	 */
695 696 697
	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
	pcie_update_aspm_capable(link->root);
698
	pcie_config_aspm_path(link);
699 700
	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);
S
Shaohua Li 已提交
701 702 703 704 705 706 707 708 709
}

/*
 * pci_disable_link_state - disable pci device's link state, so the link will
 * never enter specific states
 */
void pci_disable_link_state(struct pci_dev *pdev, int state)
{
	struct pci_dev *parent = pdev->bus->self;
710
	struct pcie_link_state *link;
S
Shaohua Li 已提交
711

K
Kenji Kaneshige 已提交
712
	if (aspm_disabled || !pci_is_pcie(pdev))
S
Shaohua Li 已提交
713 714 715 716 717 718 719 720 721
		return;
	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
	    pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
		parent = pdev;
	if (!parent || !parent->link_state)
		return;

	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
722
	link = parent->link_state;
723 724 725 726
	if (state & PCIE_LINK_STATE_L0S)
		link->aspm_disable |= ASPM_STATE_L0S;
	if (state & PCIE_LINK_STATE_L1)
		link->aspm_disable |= ASPM_STATE_L1;
727 728
	pcie_config_aspm_link(link, policy_to_aspm_state(link));

K
Kenji Kaneshige 已提交
729
	if (state & PCIE_LINK_STATE_CLKPM) {
730 731
		link->clkpm_capable = 0;
		pcie_set_clkpm(link, 0);
K
Kenji Kaneshige 已提交
732
	}
S
Shaohua Li 已提交
733 734 735 736 737 738 739 740
	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);
}
EXPORT_SYMBOL(pci_disable_link_state);

static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
{
	int i;
741
	struct pcie_link_state *link;
S
Shaohua Li 已提交
742 743 744 745 746 747 748 749 750 751 752 753

	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
		if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
			break;
	if (i >= ARRAY_SIZE(policy_str))
		return -EINVAL;
	if (i == aspm_policy)
		return 0;

	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
	aspm_policy = i;
754 755 756
	list_for_each_entry(link, &link_list, sibling) {
		pcie_config_aspm_link(link, policy_to_aspm_state(link));
		pcie_set_clkpm(link, policy_to_clkpm_state(link));
S
Shaohua Li 已提交
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
	}
	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);
	return 0;
}

static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
{
	int i, cnt = 0;
	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
		if (i == aspm_policy)
			cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
		else
			cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
	return cnt;
}

module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
	NULL, 0644);

#ifdef CONFIG_PCIEASPM_DEBUG
static ssize_t link_state_show(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct pci_dev *pci_device = to_pci_dev(dev);
	struct pcie_link_state *link_state = pci_device->link_state;

785
	return sprintf(buf, "%d\n", link_state->aspm_enabled);
S
Shaohua Li 已提交
786 787 788 789 790 791 792
}

static ssize_t link_state_store(struct device *dev,
		struct device_attribute *attr,
		const char *buf,
		size_t n)
{
793
	struct pci_dev *pdev = to_pci_dev(dev);
794
	struct pcie_link_state *link, *root = pdev->link_state->root;
795
	u32 val = buf[0] - '0', state = 0;
S
Shaohua Li 已提交
796

797
	if (n < 1 || val > 3)
S
Shaohua Li 已提交
798 799
		return -EINVAL;

800 801 802 803 804 805
	/* Convert requested state to ASPM state */
	if (val & PCIE_LINK_STATE_L0S)
		state |= ASPM_STATE_L0S;
	if (val & PCIE_LINK_STATE_L1)
		state |= ASPM_STATE_L1;

806 807 808 809 810 811 812 813 814 815
	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
	list_for_each_entry(link, &link_list, sibling) {
		if (link->root != root)
			continue;
		pcie_config_aspm_link(link, state);
	}
	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);
	return n;
S
Shaohua Li 已提交
816 817 818 819 820 821 822 823 824
}

static ssize_t clk_ctl_show(struct device *dev,
		struct device_attribute *attr,
		char *buf)
{
	struct pci_dev *pci_device = to_pci_dev(dev);
	struct pcie_link_state *link_state = pci_device->link_state;

825
	return sprintf(buf, "%d\n", link_state->clkpm_enabled);
S
Shaohua Li 已提交
826 827 828 829 830 831 832
}

static ssize_t clk_ctl_store(struct device *dev,
		struct device_attribute *attr,
		const char *buf,
		size_t n)
{
K
Kenji Kaneshige 已提交
833
	struct pci_dev *pdev = to_pci_dev(dev);
S
Shaohua Li 已提交
834 835 836 837 838 839 840 841
	int state;

	if (n < 1)
		return -EINVAL;
	state = buf[0]-'0';

	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
K
Kenji Kaneshige 已提交
842
	pcie_set_clkpm_nocheck(pdev->link_state, !!state);
S
Shaohua Li 已提交
843 844 845 846 847 848 849 850 851 852 853 854 855 856
	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);

	return n;
}

static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);

static char power_group[] = "power";
void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
{
	struct pcie_link_state *link_state = pdev->link_state;

K
Kenji Kaneshige 已提交
857 858 859
	if (!pci_is_pcie(pdev) ||
	    (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
	     pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
S
Shaohua Li 已提交
860 861
		return;

862
	if (link_state->aspm_support)
S
Shaohua Li 已提交
863 864
		sysfs_add_file_to_group(&pdev->dev.kobj,
			&dev_attr_link_state.attr, power_group);
865
	if (link_state->clkpm_capable)
S
Shaohua Li 已提交
866 867 868 869 870 871 872 873
		sysfs_add_file_to_group(&pdev->dev.kobj,
			&dev_attr_clk_ctl.attr, power_group);
}

void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
{
	struct pcie_link_state *link_state = pdev->link_state;

K
Kenji Kaneshige 已提交
874 875 876
	if (!pci_is_pcie(pdev) ||
	    (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
	     pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
S
Shaohua Li 已提交
877 878
		return;

879
	if (link_state->aspm_support)
S
Shaohua Li 已提交
880 881
		sysfs_remove_file_from_group(&pdev->dev.kobj,
			&dev_attr_link_state.attr, power_group);
882
	if (link_state->clkpm_capable)
S
Shaohua Li 已提交
883 884 885 886 887 888 889
		sysfs_remove_file_from_group(&pdev->dev.kobj,
			&dev_attr_clk_ctl.attr, power_group);
}
#endif

static int __init pcie_aspm_disable(char *str)
{
890 891 892 893 894 895 896
	if (!strcmp(str, "off")) {
		aspm_disabled = 1;
		printk(KERN_INFO "PCIe ASPM is disabled\n");
	} else if (!strcmp(str, "force")) {
		aspm_force = 1;
		printk(KERN_INFO "PCIe ASPM is forcedly enabled\n");
	}
S
Shaohua Li 已提交
897 898 899
	return 1;
}

900
__setup("pcie_aspm=", pcie_aspm_disable);
S
Shaohua Li 已提交
901

902 903
void pcie_no_aspm(void)
{
904 905
	if (!aspm_force)
		aspm_disabled = 1;
906 907
}

908 909 910 911 912 913 914
/**
 * pcie_aspm_enabled - is PCIe ASPM enabled?
 *
 * Returns true if ASPM has not been disabled by the command-line option
 * pcie_aspm=off.
 **/
int pcie_aspm_enabled(void)
S
Shaohua Li 已提交
915
{
916
       return !aspm_disabled;
S
Shaohua Li 已提交
917
}
918
EXPORT_SYMBOL(pcie_aspm_enabled);
S
Shaohua Li 已提交
919