Skip to content

Commit b63c6df

Browse files
committed
Merge branch 'pci/aspm'
* pci/aspm: PCI/ASPM: Fix L1 substate handling in aspm_attr_store_common() Revert "PCI/ASPM: Disable only ASPM_STATE_L1 when driver, disables L1" PCI/ASPM: Convert printk() to pr_*() and add include PCI/ASPM: Remove unnecessary includes PCI/ASPM: Use FIELD_MAX() instead of literals PCI/ASPM: Use time constants PCI/ASPM: Return U32_MAX instead of bit magic construct PCI/ASPM: Use FIELD_GET/PREP() to access PCIe capability fields PCI: Add PCI_L1SS_CTL2 fields
2 parents b3fabba + 8e37372 commit b63c6df

File tree

2 files changed

+45
-33
lines changed

2 files changed

+45
-33
lines changed

drivers/pci/pcie/aspm.c

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
* Copyright (C) Shaohua Li ([email protected])
88
*/
99

10+
#include <linux/bitfield.h>
1011
#include <linux/kernel.h>
12+
#include <linux/limits.h>
1113
#include <linux/math.h>
1214
#include <linux/module.h>
1315
#include <linux/moduleparam.h>
@@ -16,9 +18,10 @@
1618
#include <linux/errno.h>
1719
#include <linux/pm.h>
1820
#include <linux/init.h>
21+
#include <linux/printk.h>
1922
#include <linux/slab.h>
20-
#include <linux/jiffies.h>
21-
#include <linux/delay.h>
23+
#include <linux/time.h>
24+
2225
#include "../pci.h"
2326

2427
#ifdef MODULE_PARAM_PREFIX
@@ -267,37 +270,37 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
267270
/* Convert L0s latency encoding to ns */
268271
static u32 calc_l0s_latency(u32 lnkcap)
269272
{
270-
u32 encoding = (lnkcap & PCI_EXP_LNKCAP_L0SEL) >> 12;
273+
u32 encoding = FIELD_GET(PCI_EXP_LNKCAP_L0SEL, lnkcap);
271274

272275
if (encoding == 0x7)
273-
return (5 * 1000); /* > 4us */
276+
return 5 * NSEC_PER_USEC; /* > 4us */
274277
return (64 << encoding);
275278
}
276279

277280
/* Convert L0s acceptable latency encoding to ns */
278281
static u32 calc_l0s_acceptable(u32 encoding)
279282
{
280283
if (encoding == 0x7)
281-
return -1U;
284+
return U32_MAX;
282285
return (64 << encoding);
283286
}
284287

285288
/* Convert L1 latency encoding to ns */
286289
static u32 calc_l1_latency(u32 lnkcap)
287290
{
288-
u32 encoding = (lnkcap & PCI_EXP_LNKCAP_L1EL) >> 15;
291+
u32 encoding = FIELD_GET(PCI_EXP_LNKCAP_L1EL, lnkcap);
289292

290293
if (encoding == 0x7)
291-
return (65 * 1000); /* > 64us */
292-
return (1000 << encoding);
294+
return 65 * NSEC_PER_USEC; /* > 64us */
295+
return NSEC_PER_USEC << encoding;
293296
}
294297

295298
/* Convert L1 acceptable latency encoding to ns */
296299
static u32 calc_l1_acceptable(u32 encoding)
297300
{
298301
if (encoding == 0x7)
299-
return -1U;
300-
return (1000 << encoding);
302+
return U32_MAX;
303+
return NSEC_PER_USEC << encoding;
301304
}
302305

303306
/* Convert L1SS T_pwr encoding to usec */
@@ -325,33 +328,33 @@ static u32 calc_l12_pwron(struct pci_dev *pdev, u32 scale, u32 val)
325328
*/
326329
static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value)
327330
{
328-
u64 threshold_ns = (u64) threshold_us * 1000;
331+
u64 threshold_ns = (u64)threshold_us * NSEC_PER_USEC;
329332

330333
/*
331334
* LTR_L1.2_THRESHOLD_Value ("value") is a 10-bit field with max
332335
* value of 0x3ff.
333336
*/
334-
if (threshold_ns <= 0x3ff * 1) {
337+
if (threshold_ns <= 1 * FIELD_MAX(PCI_L1SS_CTL1_LTR_L12_TH_VALUE)) {
335338
*scale = 0; /* Value times 1ns */
336339
*value = threshold_ns;
337-
} else if (threshold_ns <= 0x3ff * 32) {
340+
} else if (threshold_ns <= 32 * FIELD_MAX(PCI_L1SS_CTL1_LTR_L12_TH_VALUE)) {
338341
*scale = 1; /* Value times 32ns */
339342
*value = roundup(threshold_ns, 32) / 32;
340-
} else if (threshold_ns <= 0x3ff * 1024) {
343+
} else if (threshold_ns <= 1024 * FIELD_MAX(PCI_L1SS_CTL1_LTR_L12_TH_VALUE)) {
341344
*scale = 2; /* Value times 1024ns */
342345
*value = roundup(threshold_ns, 1024) / 1024;
343-
} else if (threshold_ns <= 0x3ff * 32768) {
346+
} else if (threshold_ns <= 32768 * FIELD_MAX(PCI_L1SS_CTL1_LTR_L12_TH_VALUE)) {
344347
*scale = 3; /* Value times 32768ns */
345348
*value = roundup(threshold_ns, 32768) / 32768;
346-
} else if (threshold_ns <= 0x3ff * 1048576) {
349+
} else if (threshold_ns <= 1048576 * FIELD_MAX(PCI_L1SS_CTL1_LTR_L12_TH_VALUE)) {
347350
*scale = 4; /* Value times 1048576ns */
348351
*value = roundup(threshold_ns, 1048576) / 1048576;
349-
} else if (threshold_ns <= 0x3ff * (u64) 33554432) {
352+
} else if (threshold_ns <= (u64)33554432 * FIELD_MAX(PCI_L1SS_CTL1_LTR_L12_TH_VALUE)) {
350353
*scale = 5; /* Value times 33554432ns */
351354
*value = roundup(threshold_ns, 33554432) / 33554432;
352355
} else {
353356
*scale = 5;
354-
*value = 0x3ff; /* Max representable value */
357+
*value = FIELD_MAX(PCI_L1SS_CTL1_LTR_L12_TH_VALUE);
355358
}
356359
}
357360

@@ -371,11 +374,11 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint)
371374
link = endpoint->bus->self->link_state;
372375

373376
/* Calculate endpoint L0s acceptable latency */
374-
encoding = (endpoint->devcap & PCI_EXP_DEVCAP_L0S) >> 6;
377+
encoding = FIELD_GET(PCI_EXP_DEVCAP_L0S, endpoint->devcap);
375378
acceptable_l0s = calc_l0s_acceptable(encoding);
376379

377380
/* Calculate endpoint L1 acceptable latency */
378-
encoding = (endpoint->devcap & PCI_EXP_DEVCAP_L1) >> 9;
381+
encoding = FIELD_GET(PCI_EXP_DEVCAP_L1, endpoint->devcap);
379382
acceptable_l1 = calc_l1_acceptable(encoding);
380383

381384
while (link) {
@@ -417,7 +420,7 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint)
417420
if ((link->aspm_capable & ASPM_STATE_L1) &&
418421
(latency + l1_switch_latency > acceptable_l1))
419422
link->aspm_capable &= ~ASPM_STATE_L1;
420-
l1_switch_latency += 1000;
423+
l1_switch_latency += NSEC_PER_USEC;
421424

422425
link = link->parent;
423426
}
@@ -446,22 +449,24 @@ static void aspm_calc_l12_info(struct pcie_link_state *link,
446449
u32 pl1_2_enables, cl1_2_enables;
447450

448451
/* Choose the greater of the two Port Common_Mode_Restore_Times */
449-
val1 = (parent_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
450-
val2 = (child_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
452+
val1 = FIELD_GET(PCI_L1SS_CAP_CM_RESTORE_TIME, parent_l1ss_cap);
453+
val2 = FIELD_GET(PCI_L1SS_CAP_CM_RESTORE_TIME, child_l1ss_cap);
451454
t_common_mode = max(val1, val2);
452455

453456
/* Choose the greater of the two Port T_POWER_ON times */
454-
val1 = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
455-
scale1 = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
456-
val2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
457-
scale2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
457+
val1 = FIELD_GET(PCI_L1SS_CAP_P_PWR_ON_VALUE, parent_l1ss_cap);
458+
scale1 = FIELD_GET(PCI_L1SS_CAP_P_PWR_ON_SCALE, parent_l1ss_cap);
459+
val2 = FIELD_GET(PCI_L1SS_CAP_P_PWR_ON_VALUE, child_l1ss_cap);
460+
scale2 = FIELD_GET(PCI_L1SS_CAP_P_PWR_ON_SCALE, child_l1ss_cap);
458461

459462
if (calc_l12_pwron(parent, scale1, val1) >
460463
calc_l12_pwron(child, scale2, val2)) {
461-
ctl2 |= scale1 | (val1 << 3);
464+
ctl2 |= FIELD_PREP(PCI_L1SS_CTL2_T_PWR_ON_SCALE, scale1) |
465+
FIELD_PREP(PCI_L1SS_CTL2_T_PWR_ON_VALUE, val1);
462466
t_power_on = calc_l12_pwron(parent, scale1, val1);
463467
} else {
464-
ctl2 |= scale2 | (val2 << 3);
468+
ctl2 |= FIELD_PREP(PCI_L1SS_CTL2_T_PWR_ON_SCALE, scale2) |
469+
FIELD_PREP(PCI_L1SS_CTL2_T_PWR_ON_VALUE, val2);
465470
t_power_on = calc_l12_pwron(child, scale2, val2);
466471
}
467472

@@ -477,7 +482,9 @@ static void aspm_calc_l12_info(struct pcie_link_state *link,
477482
*/
478483
l1_2_threshold = 2 + 4 + t_common_mode + t_power_on;
479484
encode_l12_threshold(l1_2_threshold, &scale, &value);
480-
ctl1 |= t_common_mode << 8 | scale << 29 | value << 16;
485+
ctl1 |= FIELD_PREP(PCI_L1SS_CTL1_CM_RESTORE_TIME, t_common_mode) |
486+
FIELD_PREP(PCI_L1SS_CTL1_LTR_L12_TH_VALUE, value) |
487+
FIELD_PREP(PCI_L1SS_CTL1_LTR_L12_TH_SCALE, scale);
481488

482489
/* Some broken devices only support dword access to L1 SS */
483490
pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1, &pctl1);
@@ -1059,7 +1066,8 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
10591066
if (state & PCIE_LINK_STATE_L0S)
10601067
link->aspm_disable |= ASPM_STATE_L0S;
10611068
if (state & PCIE_LINK_STATE_L1)
1062-
link->aspm_disable |= ASPM_STATE_L1;
1069+
/* L1 PM substates require L1 */
1070+
link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
10631071
if (state & PCIE_LINK_STATE_L1_1)
10641072
link->aspm_disable |= ASPM_STATE_L1_1;
10651073
if (state & PCIE_LINK_STATE_L1_2)
@@ -1247,6 +1255,8 @@ static ssize_t aspm_attr_store_common(struct device *dev,
12471255
link->aspm_disable &= ~ASPM_STATE_L1;
12481256
} else {
12491257
link->aspm_disable |= state;
1258+
if (state & ASPM_STATE_L1)
1259+
link->aspm_disable |= ASPM_STATE_L1SS;
12501260
}
12511261

12521262
pcie_config_aspm_link(link, policy_to_aspm_state(link));
@@ -1361,10 +1371,10 @@ static int __init pcie_aspm_disable(char *str)
13611371
aspm_policy = POLICY_DEFAULT;
13621372
aspm_disabled = 1;
13631373
aspm_support_enabled = false;
1364-
printk(KERN_INFO "PCIe ASPM is disabled\n");
1374+
pr_info("PCIe ASPM is disabled\n");
13651375
} else if (!strcmp(str, "force")) {
13661376
aspm_force = 1;
1367-
printk(KERN_INFO "PCIe ASPM is forcibly enabled\n");
1377+
pr_info("PCIe ASPM is forcibly enabled\n");
13681378
}
13691379
return 1;
13701380
}

include/uapi/linux/pci_regs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,8 @@
10881088
#define PCI_L1SS_CTL1_LTR_L12_TH_VALUE 0x03ff0000 /* LTR_L1.2_THRESHOLD_Value */
10891089
#define PCI_L1SS_CTL1_LTR_L12_TH_SCALE 0xe0000000 /* LTR_L1.2_THRESHOLD_Scale */
10901090
#define PCI_L1SS_CTL2 0x0c /* Control 2 Register */
1091+
#define PCI_L1SS_CTL2_T_PWR_ON_SCALE 0x00000003 /* T_POWER_ON Scale */
1092+
#define PCI_L1SS_CTL2_T_PWR_ON_VALUE 0x000000f8 /* T_POWER_ON Value */
10911093

10921094
/* Designated Vendor-Specific (DVSEC, PCI_EXT_CAP_ID_DVSEC) */
10931095
#define PCI_DVSEC_HEADER1 0x4 /* Designated Vendor-Specific Header1 */

0 commit comments

Comments
 (0)