aspm.c 25.6 KB
Newer Older
S
Shaohua Li 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * File:	drivers/pci/pcie/aspm.c
 * Enabling PCIE link L0s/L1 state and Clock Power Management
 *
 * 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
struct aspm_latency {
	u32 l0s;			/* L0s latency (nsec) */
	u32 l1;				/* L1 latency (nsec) */
S
Shaohua Li 已提交
32 33 34
};

struct pcie_link_state {
35 36 37 38 39
	struct pci_dev *pdev;		/* Upstream component of the Link */
	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 已提交
40 41

	/* ASPM state */
42 43 44 45
	u32 aspm_support:2;		/* Supported ASPM state */
	u32 aspm_enabled:2;		/* Enabled ASPM state */
	u32 aspm_default:2;		/* Default ASPM state by BIOS */

46 47 48 49 50
	/* 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 */

51 52
	u32 has_switch:1;		/* Downstream has switches? */

53 54
	/* Latencies */
	struct aspm_latency latency;	/* Exit latency */
S
Shaohua Li 已提交
55
	/*
56 57
	 * Endpoint acceptable latencies. A pcie downstream port only
	 * has one slot under it, so at most there are 8 functions.
S
Shaohua Li 已提交
58
	 */
59
	struct aspm_latency acceptable[8];
S
Shaohua Li 已提交
60 61
};

62
static int aspm_disabled, aspm_force;
S
Shaohua Li 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75
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"
};

76 77
#define LINK_RETRAIN_TIMEOUT HZ

78
static int policy_to_aspm_state(struct pcie_link_state *link)
S
Shaohua Li 已提交
79 80 81 82 83 84 85
{
	switch (aspm_policy) {
	case POLICY_PERFORMANCE:
		/* Disable ASPM and Clock PM */
		return 0;
	case POLICY_POWERSAVE:
		/* Enable ASPM L0s/L1 */
86
		return PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1;
S
Shaohua Li 已提交
87
	case POLICY_DEFAULT:
88
		return link->aspm_default;
S
Shaohua Li 已提交
89 90 91 92
	}
	return 0;
}

93
static int policy_to_clkpm_state(struct pcie_link_state *link)
S
Shaohua Li 已提交
94 95 96 97 98 99 100 101 102
{
	switch (aspm_policy) {
	case POLICY_PERFORMANCE:
		/* Disable ASPM and Clock PM */
		return 0;
	case POLICY_POWERSAVE:
		/* Disable Clock PM */
		return 1;
	case POLICY_DEFAULT:
103
		return link->clkpm_default;
S
Shaohua Li 已提交
104 105 106 107
	}
	return 0;
}

108
static void pcie_set_clock_pm(struct pcie_link_state *link, int enable)
S
Shaohua Li 已提交
109 110 111
{
	int pos;
	u16 reg16;
112 113
	struct pci_dev *child;
	struct pci_bus *linkbus = link->pdev->subordinate;
S
Shaohua Li 已提交
114

115 116
	list_for_each_entry(child, &linkbus->devices, bus_list) {
		pos = pci_find_capability(child, PCI_CAP_ID_EXP);
S
Shaohua Li 已提交
117 118
		if (!pos)
			return;
119
		pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
S
Shaohua Li 已提交
120 121 122 123
		if (enable)
			reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
		else
			reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
124
		pci_write_config_word(child, pos + PCI_EXP_LNKCTL, reg16);
S
Shaohua Li 已提交
125
	}
126
	link->clkpm_enabled = !!enable;
S
Shaohua Li 已提交
127 128
}

129
static void pcie_check_clock_pm(struct pcie_link_state *link, int blacklist)
S
Shaohua Li 已提交
130
{
131
	int pos, capable = 1, enabled = 1;
S
Shaohua Li 已提交
132 133
	u32 reg32;
	u16 reg16;
134 135
	struct pci_dev *child;
	struct pci_bus *linkbus = link->pdev->subordinate;
S
Shaohua Li 已提交
136 137

	/* All functions should have the same cap and state, take the worst */
138 139
	list_for_each_entry(child, &linkbus->devices, bus_list) {
		pos = pci_find_capability(child, PCI_CAP_ID_EXP);
S
Shaohua Li 已提交
140 141
		if (!pos)
			return;
142
		pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32);
S
Shaohua Li 已提交
143 144 145 146 147
		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
			capable = 0;
			enabled = 0;
			break;
		}
148
		pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
S
Shaohua Li 已提交
149 150 151
		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
			enabled = 0;
	}
152 153
	link->clkpm_enabled = enabled;
	link->clkpm_default = enabled;
154
	if (!blacklist) {
155 156
		link->clkpm_capable = capable;
		pcie_set_clock_pm(link, policy_to_clkpm_state(link));
157
	} else {
158 159
		link->clkpm_capable = 0;
		pcie_set_clock_pm(link, 0);
160 161 162
	}
}

163
static bool pcie_aspm_downstream_has_switch(struct pcie_link_state *link)
164
{
165 166
	struct pci_dev *child;
	struct pci_bus *linkbus = link->pdev->subordinate;
167

168 169
	list_for_each_entry(child, &linkbus->devices, bus_list) {
		if (child->pcie_type == PCI_EXP_TYPE_UPSTREAM)
170 171 172
			return true;
	}
	return false;
S
Shaohua Li 已提交
173 174 175 176 177 178 179
}

/*
 * 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.
 */
180
static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
S
Shaohua Li 已提交
181
{
182 183
	int ppos, cpos, same_clock = 1;
	u16 reg16, parent_reg, child_reg[8];
184
	unsigned long start_jiffies;
185 186
	struct pci_dev *child, *parent = link->pdev;
	struct pci_bus *linkbus = parent->subordinate;
S
Shaohua Li 已提交
187
	/*
188
	 * All functions of a slot should have the same Slot Clock
S
Shaohua Li 已提交
189
	 * Configuration, so just check one function
190 191 192
	 */
	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
	BUG_ON(!child->is_pcie);
S
Shaohua Li 已提交
193 194

	/* Check downstream component if bit Slot Clock Configuration is 1 */
195 196
	cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
	pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16);
S
Shaohua Li 已提交
197 198 199 200
	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
		same_clock = 0;

	/* Check upstream component if bit Slot Clock Configuration is 1 */
201 202
	ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
	pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
S
Shaohua Li 已提交
203 204 205 206
	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
		same_clock = 0;

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

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

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

231
	/* Wait for link training end. Break out after waiting for timeout */
232
	start_jiffies = jiffies;
233
	for (;;) {
234
		pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
S
Shaohua Li 已提交
235 236
		if (!(reg16 & PCI_EXP_LNKSTA_LT))
			break;
237 238 239
		if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
			break;
		msleep(1);
S
Shaohua Li 已提交
240
	}
241 242 243 244 245 246 247 248 249 250
	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) {
		cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
		pci_write_config_word(child, cpos + PCI_EXP_LNKCTL,
				      child_reg[PCI_FUNC(child->devfn)]);
251
	}
252
	pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, parent_reg);
S
Shaohua Li 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
}

/*
 * calc_L0S_latency: Convert L0s latency encoding to ns
 */
static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
{
	unsigned int ns = 64;

	if (latency_encoding == 0x7) {
		if (ac)
			ns = -1U;
		else
			ns = 5*1000; /* > 4us */
	} else
		ns *= (1 << latency_encoding);
	return ns;
}

/*
 * calc_L1_latency: Convert L1 latency encoding to ns
 */
static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
{
	unsigned int ns = 1000;

	if (latency_encoding == 0x7) {
		if (ac)
			ns = -1U;
		else
			ns = 65*1000; /* > 64us */
	} else
		ns *= (1 << latency_encoding);
	return ns;
}

static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
	unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
{
	int pos;
	u16 reg16;
	u32 reg32;
	unsigned int latency;

297
	*l0s = *l1 = *enabled = 0;
S
Shaohua Li 已提交
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
	pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
	*state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
	if (*state != PCIE_LINK_STATE_L0S &&
		*state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
		*state = 0;
	if (*state == 0)
		return;

	latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
	*l0s = calc_L0S_latency(latency, 0);
	if (*state & PCIE_LINK_STATE_L1) {
		latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
		*l1 = calc_L1_latency(latency, 0);
	}
	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
	*enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
}

317
static void pcie_aspm_cap_init(struct pcie_link_state *link)
S
Shaohua Li 已提交
318
{
319
	u32 support, l0s, l1, enabled;
320 321
	struct pci_dev *child, *parent = link->pdev;
	struct pci_bus *linkbus = parent->subordinate;
S
Shaohua Li 已提交
322 323

	/* upstream component states */
324 325 326 327 328
	pcie_aspm_get_cap_device(parent, &support, &l0s, &l1, &enabled);
	link->aspm_support = support;
	link->latency.l0s = l0s;
	link->latency.l1 = l1;
	link->aspm_enabled = enabled;
329

S
Shaohua Li 已提交
330
	/* downstream component states, all functions have the same setting */
331 332 333 334 335 336 337
	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
	pcie_aspm_get_cap_device(child, &support, &l0s, &l1, &enabled);
	link->aspm_support &= support;
	link->latency.l0s = max_t(u32, link->latency.l0s, l0s);
	link->latency.l1 = max_t(u32, link->latency.l1, l1);

	if (!link->aspm_support)
S
Shaohua Li 已提交
338
		return;
339

340 341
	link->aspm_enabled &= link->aspm_support;
	link->aspm_default = link->aspm_enabled;
S
Shaohua Li 已提交
342 343

	/* ENDPOINT states*/
344
	list_for_each_entry(child, &linkbus->devices, bus_list) {
S
Shaohua Li 已提交
345 346 347
		int pos;
		u32 reg32;
		unsigned int latency;
348
		struct aspm_latency *acceptable =
349
			&link->acceptable[PCI_FUNC(child->devfn)];
S
Shaohua Li 已提交
350

351 352
		if (child->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
		    child->pcie_type != PCI_EXP_TYPE_LEG_END)
S
Shaohua Li 已提交
353 354
			continue;

355 356
		pos = pci_find_capability(child, PCI_CAP_ID_EXP);
		pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
S
Shaohua Li 已提交
357 358
		latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
		latency = calc_L0S_latency(latency, 1);
359
		acceptable->l0s = latency;
360
		if (link->aspm_support & PCIE_LINK_STATE_L1) {
S
Shaohua Li 已提交
361 362
			latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
			latency = calc_L1_latency(latency, 1);
363
			acceptable->l1 = latency;
S
Shaohua Li 已提交
364 365 366 367 368 369 370 371
		}
	}
}

static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
	unsigned int state)
{
	struct pci_dev *parent_dev, *tmp_dev;
372
	unsigned int l1_latency = 0;
S
Shaohua Li 已提交
373
	struct pcie_link_state *link_state;
374
	struct aspm_latency *acceptable;
S
Shaohua Li 已提交
375 376 377

	parent_dev = pdev->bus->self;
	link_state = parent_dev->link_state;
378
	state &= link_state->aspm_support;
S
Shaohua Li 已提交
379 380
	if (state == 0)
		return 0;
381
	acceptable = &link_state->acceptable[PCI_FUNC(pdev->devfn)];
S
Shaohua Li 已提交
382 383 384 385 386 387 388 389 390 391 392 393 394

	/*
	 * Check latency for endpoint device.
	 * TBD: The latency from the endpoint to root complex vary per
	 * switch's upstream link state above the device. Here we just do a
	 * simple check which assumes all links above the device can be in L1
	 * state, that is we just consider the worst case. If switch's upstream
	 * link can't be put into L0S/L1, then our check is too strictly.
	 */
	tmp_dev = pdev;
	while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
		parent_dev = tmp_dev->bus->self;
		link_state = parent_dev->link_state;
395 396 397 398 399 400 401 402
		if ((state & PCIE_LINK_STATE_L0S) &&
		    (link_state->latency.l0s > acceptable->l0s))
			state &= ~PCIE_LINK_STATE_L0S;

		if ((state & PCIE_LINK_STATE_L1) &&
		    (link_state->latency.l1 + l1_latency > acceptable->l1))
			state &= ~PCIE_LINK_STATE_L1;

S
Shaohua Li 已提交
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
		if (!parent_dev->bus->self) /* parent_dev is a root port */
			break;
		else {
			/*
			 * parent_dev is the downstream port of a switch, make
			 * tmp_dev the upstream port of the switch
			 */
			tmp_dev = parent_dev->bus->self;
			/*
			 * every switch on the path to root complex need 1 more
			 * microsecond for L1. Spec doesn't mention L0S.
			 */
			if (state & PCIE_LINK_STATE_L1)
				l1_latency += 1000;
		}
	}
	return state;
}

422
static u32 pcie_aspm_check_state(struct pcie_link_state *link, u32 state)
S
Shaohua Li 已提交
423
{
424 425 426
	pci_power_t power_state;
	struct pci_dev *child;
	struct pci_bus *linkbus = link->pdev->subordinate;
S
Shaohua Li 已提交
427

428
	/* If no child, ignore the link */
429
	if (list_empty(&linkbus->devices))
430
		return state;
431 432 433 434 435 436 437 438 439 440 441

	list_for_each_entry(child, &linkbus->devices, bus_list) {
		/*
		 * If downstream component of a link is pci bridge, we
		 * disable ASPM for now for the link
		 */
		if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
			return 0;

		if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
		     child->pcie_type != PCI_EXP_TYPE_LEG_END))
S
Shaohua Li 已提交
442 443
			continue;
		/* Device not in D0 doesn't need check latency */
444 445 446
		power_state = child->current_state;
		if (power_state == PCI_D1 || power_state == PCI_D2 ||
		    power_state == PCI_D3hot || power_state == PCI_D3cold)
S
Shaohua Li 已提交
447
			continue;
448
		state = __pcie_aspm_check_state_one(child, state);
S
Shaohua Li 已提交
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
	}
	return state;
}

static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
{
	u16 reg16;
	int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);

	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
	reg16 &= ~0x3;
	reg16 |= state;
	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
}

464
static void __pcie_aspm_config_link(struct pcie_link_state *link, u32 state)
S
Shaohua Li 已提交
465
{
466 467
	struct pci_dev *child, *parent = link->pdev;
	struct pci_bus *linkbus = parent->subordinate;
S
Shaohua Li 已提交
468

469
	/* If no child, disable the link */
470
	if (list_empty(&linkbus->devices))
471
		state = 0;
S
Shaohua Li 已提交
472
	/*
473 474
	 * If the downstream component has pci bridge function, don't
	 * do ASPM now.
S
Shaohua Li 已提交
475
	 */
476 477 478
	list_for_each_entry(child, &linkbus->devices, bus_list) {
		if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
			return;
S
Shaohua Li 已提交
479 480
	}
	/*
481 482 483 484
	 * 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 已提交
485 486
	 */
	if (state & PCIE_LINK_STATE_L1)
487
		__pcie_aspm_config_one_dev(parent, state);
S
Shaohua Li 已提交
488

489 490
	list_for_each_entry(child, &linkbus->devices, bus_list)
		__pcie_aspm_config_one_dev(child, state);
S
Shaohua Li 已提交
491 492

	if (!(state & PCIE_LINK_STATE_L1))
493
		__pcie_aspm_config_one_dev(parent, state);
S
Shaohua Li 已提交
494

495
	link->aspm_enabled = state;
S
Shaohua Li 已提交
496 497
}

498 499 500 501 502 503 504 505
static struct pcie_link_state *get_root_port_link(struct pcie_link_state *link)
{
	struct pcie_link_state *root_port_link = link;
	while (root_port_link->parent)
		root_port_link = root_port_link->parent;
	return root_port_link;
}

506 507 508
/* Check the whole hierarchy, and configure each link in the hierarchy */
static void __pcie_aspm_configure_link_state(struct pcie_link_state *link,
					     u32 state)
S
Shaohua Li 已提交
509
{
510
	struct pcie_link_state *leaf, *root = get_root_port_link(link);
S
Shaohua Li 已提交
511

512
	state &= (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
S
Shaohua Li 已提交
513

514
	/* Check all links who have specific root port link */
515
	list_for_each_entry(leaf, &link_list, sibling) {
516
		if (!list_empty(&leaf->children) ||
517
		    get_root_port_link(leaf) != root)
518
			continue;
519
		state = pcie_aspm_check_state(leaf, state);
520
	}
521 522 523
	/* Check root port link too in case it hasn't children */
	state = pcie_aspm_check_state(root, state);
	if (link->aspm_enabled == state)
S
Shaohua Li 已提交
524
		return;
525
	/*
526
	 * We must change the hierarchy. See comments in
527 528 529
	 * __pcie_aspm_config_link for the order
	 **/
	if (state & PCIE_LINK_STATE_L1) {
530
		list_for_each_entry(leaf, &link_list, sibling) {
531 532
			if (get_root_port_link(leaf) == root)
				__pcie_aspm_config_link(leaf, state);
533 534
		}
	} else {
535
		list_for_each_entry_reverse(leaf, &link_list, sibling) {
536 537
			if (get_root_port_link(leaf) == root)
				__pcie_aspm_config_link(leaf, state);
538 539
		}
	}
S
Shaohua Li 已提交
540 541 542 543 544 545
}

/*
 * pcie_aspm_configure_link_state: enable/disable PCI express link state
 * @pdev: the root port or switch downstream port
 */
546 547
static void pcie_aspm_configure_link_state(struct pcie_link_state *link,
					   u32 state)
S
Shaohua Li 已提交
548 549 550
{
	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
551
	__pcie_aspm_configure_link_state(link, state);
S
Shaohua Li 已提交
552 553 554 555
	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);
}

556
static void free_link_state(struct pcie_link_state *link)
S
Shaohua Li 已提交
557
{
558 559
	link->pdev->link_state = NULL;
	kfree(link);
S
Shaohua Li 已提交
560 561
}

562 563 564 565
static int pcie_aspm_sanity_check(struct pci_dev *pdev)
{
	struct pci_dev *child_dev;
	int child_pos;
566
	u32 reg32;
567 568 569 570 571 572 573 574 575

	/*
	 * Some functions in a slot might not all be PCIE functions, very
	 * strange. Disable ASPM for the whole slot
	 */
	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
		child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
		if (!child_pos)
			return -EINVAL;
576 577 578 579 580 581 582

		/*
		 * 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
		 */
		pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP,
			&reg32);
S
Sitsofe Wheeler 已提交
583
		if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
584 585 586
			dev_printk(KERN_INFO, &child_dev->dev, "disabling ASPM"
				" on pre-1.1 PCIe device.  You can enable it"
				" with 'pcie_aspm=force'\n");
587 588
			return -EINVAL;
		}
589 590 591 592
	}
	return 0;
}

S
Shaohua Li 已提交
593 594 595 596 597 598 599 600 601 602
/*
 * 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)
{
	unsigned int state;
	struct pcie_link_state *link_state;
	int error = 0;
603
	int blacklist;
S
Shaohua Li 已提交
604 605 606 607 608 609

	if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
		return;
	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
		return;
610 611 612 613
	/* VIA has a strange chipset, root port is under a bridge */
	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
		pdev->bus->self)
		return;
S
Shaohua Li 已提交
614 615 616 617
	down_read(&pci_bus_sem);
	if (list_empty(&pdev->subordinate->devices))
		goto out;

618
	blacklist = !!pcie_aspm_sanity_check(pdev);
619

S
Shaohua Li 已提交
620 621 622 623 624 625
	mutex_lock(&aspm_lock);

	link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
	if (!link_state)
		goto unlock_out;

626 627 628 629
	INIT_LIST_HEAD(&link_state->children);
	INIT_LIST_HEAD(&link_state->link);
	if (pdev->bus->self) {/* this is a switch */
		struct pcie_link_state *parent_link_state;
S
Shaohua Li 已提交
630

631 632 633 634 635 636 637 638
		parent_link_state = pdev->bus->parent->self->link_state;
		if (!parent_link_state) {
			kfree(link_state);
			goto unlock_out;
		}
		list_add(&link_state->link, &parent_link_state->children);
		link_state->parent = parent_link_state;
	}
639 640
	link_state->pdev = pdev;
	link_state->has_switch = pcie_aspm_downstream_has_switch(link_state);
641
	pdev->link_state = link_state;
S
Shaohua Li 已提交
642

643
	if (!blacklist) {
644 645
		pcie_aspm_configure_common_clock(link_state);
		pcie_aspm_cap_init(link_state);
646
	} else {
647 648 649
		link_state->aspm_enabled =
			(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
		link_state->aspm_default = 0;
650
		/* Set support state to 0, so we will disable ASPM later */
651
		link_state->aspm_support = 0;
652
	}
S
Shaohua Li 已提交
653

654
	list_add(&link_state->sibling, &link_list);
S
Shaohua Li 已提交
655

656
	if (link_state->has_switch) {
657 658 659 660 661
		/*
		 * If link has switch, delay the link config. The leaf link
		 * initialization will config the whole hierarchy. but we must
		 * make sure BIOS doesn't set unsupported link state
		 **/
662 663 664
		state = pcie_aspm_check_state(link_state,
					      link_state->aspm_default);
		__pcie_aspm_config_link(link_state, state);
665
	} else
666 667
		__pcie_aspm_configure_link_state(link_state,
			policy_to_aspm_state(link_state));
668

669
	pcie_check_clock_pm(link_state, blacklist);
670

S
Shaohua Li 已提交
671 672
unlock_out:
	if (error)
673
		free_link_state(link_state);
S
Shaohua Li 已提交
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
	mutex_unlock(&aspm_lock);
out:
	up_read(&pci_bus_sem);
}

/* @pdev: the endpoint device */
void pcie_aspm_exit_link_state(struct pci_dev *pdev)
{
	struct pci_dev *parent = pdev->bus->self;
	struct pcie_link_state *link_state = parent->link_state;

	if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
		return;
	if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
		parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
		return;
	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);

	/*
	 * All PCIe functions are in one slot, remove one function will remove
695
	 * the whole slot, so just wait until we are the last function left.
S
Shaohua Li 已提交
696
	 */
697
	if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices))
S
Shaohua Li 已提交
698 699 700 701
		goto out;

	/* All functions are removed, so just disable ASPM for the link */
	__pcie_aspm_config_one_dev(parent, 0);
702
	list_del(&link_state->sibling);
703
	list_del(&link_state->link);
S
Shaohua Li 已提交
704 705
	/* Clock PM is for endpoint device */

706
	free_link_state(link_state);
S
Shaohua Li 已提交
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
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)
{
	struct pcie_link_state *link_state = pdev->link_state;

	if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
		return;
	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
		return;
	/*
	 * devices changed PM state, we should recheck if latency meets all
	 * functions' requirement
	 */
726
	pcie_aspm_configure_link_state(link_state, link_state->aspm_enabled);
S
Shaohua Li 已提交
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
}

/*
 * 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;
	struct pcie_link_state *link_state;

	if (aspm_disabled || !pdev->is_pcie)
		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);
	link_state = parent->link_state;
749
	link_state->aspm_support &= ~state;
S
Shaohua Li 已提交
750
	if (state & PCIE_LINK_STATE_CLKPM)
751
		link_state->clkpm_capable = 0;
S
Shaohua Li 已提交
752

753
	__pcie_aspm_configure_link_state(link_state, link_state->aspm_enabled);
754
	if (!link_state->clkpm_capable && link_state->clkpm_enabled)
755
		pcie_set_clock_pm(link_state, 0);
S
Shaohua Li 已提交
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
	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;
	struct pcie_link_state *link_state;

	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;
777
	list_for_each_entry(link_state, &link_list, sibling) {
778 779
		__pcie_aspm_configure_link_state(link_state,
			policy_to_aspm_state(link_state));
780
		if (link_state->clkpm_capable &&
781 782 783
		    link_state->clkpm_enabled != policy_to_clkpm_state(link_state))
			pcie_set_clock_pm(link_state,
					  policy_to_clkpm_state(link_state));
S
Shaohua Li 已提交
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812

	}
	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;

813
	return sprintf(buf, "%d\n", link_state->aspm_enabled);
S
Shaohua Li 已提交
814 815 816 817 818 819 820
}

static ssize_t link_state_store(struct device *dev,
		struct device_attribute *attr,
		const char *buf,
		size_t n)
{
821
	struct pci_dev *pdev = to_pci_dev(dev);
S
Shaohua Li 已提交
822 823 824 825 826 827 828
	int state;

	if (n < 1)
		return -EINVAL;
	state = buf[0]-'0';
	if (state >= 0 && state <= 3) {
		/* setup link aspm state */
829
		pcie_aspm_configure_link_state(pdev->link_state, state);
S
Shaohua Li 已提交
830 831 832 833 834 835 836 837 838 839 840 841 842
		return n;
	}

	return -EINVAL;
}

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;

843
	return sprintf(buf, "%d\n", link_state->clkpm_enabled);
S
Shaohua Li 已提交
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
}

static ssize_t clk_ctl_store(struct device *dev,
		struct device_attribute *attr,
		const char *buf,
		size_t n)
{
	struct pci_dev *pci_device = to_pci_dev(dev);
	int state;

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

	down_read(&pci_bus_sem);
	mutex_lock(&aspm_lock);
860
	pcie_set_clock_pm(pci_device->link_state, !!state);
S
Shaohua Li 已提交
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
	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;

	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
		return;

879
	if (link_state->aspm_support)
S
Shaohua Li 已提交
880 881
		sysfs_add_file_to_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 890 891 892 893 894
		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;

	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
		return;

895
	if (link_state->aspm_support)
S
Shaohua Li 已提交
896 897
		sysfs_remove_file_from_group(&pdev->dev.kobj,
			&dev_attr_link_state.attr, power_group);
898
	if (link_state->clkpm_capable)
S
Shaohua Li 已提交
899 900 901 902 903 904 905
		sysfs_remove_file_from_group(&pdev->dev.kobj,
			&dev_attr_clk_ctl.attr, power_group);
}
#endif

static int __init pcie_aspm_disable(char *str)
{
906 907 908 909 910 911 912
	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 已提交
913 914 915
	return 1;
}

916
__setup("pcie_aspm=", pcie_aspm_disable);
S
Shaohua Li 已提交
917

918 919
void pcie_no_aspm(void)
{
920 921
	if (!aspm_force)
		aspm_disabled = 1;
922 923
}

924 925 926 927 928 929 930
/**
 * 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 已提交
931
{
932
       return !aspm_disabled;
S
Shaohua Li 已提交
933
}
934
EXPORT_SYMBOL(pcie_aspm_enabled);
S
Shaohua Li 已提交
935