Skip to content

Commit dbb82b6

Browse files
author
Fox Snowpatch
committed
1 parent 2dd0957 commit dbb82b6

File tree

11 files changed

+153
-60
lines changed

11 files changed

+153
-60
lines changed

drivers/pci/ats.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
410410
if (WARN_ON(pdev->pasid_enabled))
411411
return -EBUSY;
412412

413-
if (!pdev->eetlp_prefix_path && !pdev->pasid_no_tlp)
413+
if (!pdev->eetlp_prefix_max && !pdev->pasid_no_tlp)
414414
return -EINVAL;
415415

416416
if (!pasid)

drivers/pci/pci.c

-28
Original file line numberDiff line numberDiff line change
@@ -1099,34 +1099,6 @@ static void pci_enable_acs(struct pci_dev *dev)
10991099
pci_write_config_word(dev, pos + PCI_ACS_CTRL, caps.ctrl);
11001100
}
11011101

1102-
/**
1103-
* pcie_read_tlp_log - read TLP Header Log
1104-
* @dev: PCIe device
1105-
* @where: PCI Config offset of TLP Header Log
1106-
* @tlp_log: TLP Log structure to fill
1107-
*
1108-
* Fill @tlp_log from TLP Header Log registers, e.g., AER or DPC.
1109-
*
1110-
* Return: 0 on success and filled TLP Log structure, <0 on error.
1111-
*/
1112-
int pcie_read_tlp_log(struct pci_dev *dev, int where,
1113-
struct pcie_tlp_log *tlp_log)
1114-
{
1115-
int i, ret;
1116-
1117-
memset(tlp_log, 0, sizeof(*tlp_log));
1118-
1119-
for (i = 0; i < 4; i++) {
1120-
ret = pci_read_config_dword(dev, where + i * 4,
1121-
&tlp_log->dw[i]);
1122-
if (ret)
1123-
return pcibios_err_to_errno(ret);
1124-
}
1125-
1126-
return 0;
1127-
}
1128-
EXPORT_SYMBOL_GPL(pcie_read_tlp_log);
1129-
11301102
/**
11311103
* pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
11321104
* @dev: PCI device to have its BARs restored

drivers/pci/pci.h

+9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <linux/pci.h>
66

7+
struct pcie_tlp_log;
8+
79
/* Number of possible devfns: 0.0 to 1f.7 inclusive */
810
#define MAX_NR_DEVFNS 256
911

@@ -547,6 +549,12 @@ struct aer_err_info {
547549

548550
int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info);
549551
void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
552+
553+
int pcie_read_tlp_log(struct pci_dev *dev, int where, int where2,
554+
unsigned int tlp_len, struct pcie_tlp_log *log);
555+
unsigned int aer_tlp_log_len(struct pci_dev *dev, u32 aercc);
556+
void pcie_print_tlp_log(const struct pci_dev *dev,
557+
const struct pcie_tlp_log *log, const char *pfx);
550558
#endif /* CONFIG_PCIEAER */
551559

552560
#ifdef CONFIG_PCIEPORTBUS
@@ -565,6 +573,7 @@ void pci_dpc_init(struct pci_dev *pdev);
565573
void dpc_process_error(struct pci_dev *pdev);
566574
pci_ers_result_t dpc_reset_link(struct pci_dev *pdev);
567575
bool pci_dpc_recovered(struct pci_dev *pdev);
576+
unsigned int dpc_tlp_log_len(struct pci_dev *dev);
568577
#else
569578
static inline void pci_save_dpc_state(struct pci_dev *dev) { }
570579
static inline void pci_restore_dpc_state(struct pci_dev *dev) { }

drivers/pci/pcie/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pcieportdrv-y := portdrv.o rcec.o
77
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o bwctrl.o
88

99
obj-y += aspm.o
10-
obj-$(CONFIG_PCIEAER) += aer.o err.o
10+
obj-$(CONFIG_PCIEAER) += aer.o err.o tlp.o
1111
obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o
1212
obj-$(CONFIG_PCIE_PME) += pme.o
1313
obj-$(CONFIG_PCIE_DPC) += dpc.o

drivers/pci/pcie/aer.c

+6-9
Original file line numberDiff line numberDiff line change
@@ -665,12 +665,6 @@ static void pci_rootport_aer_stats_incr(struct pci_dev *pdev,
665665
}
666666
}
667667

668-
static void __print_tlp_header(struct pci_dev *dev, struct pcie_tlp_log *t)
669-
{
670-
pci_err(dev, " TLP Header: %08x %08x %08x %08x\n",
671-
t->dw[0], t->dw[1], t->dw[2], t->dw[3]);
672-
}
673-
674668
static void __aer_print_error(struct pci_dev *dev,
675669
struct aer_err_info *info)
676670
{
@@ -725,7 +719,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
725719
__aer_print_error(dev, info);
726720

727721
if (info->tlp_header_valid)
728-
__print_tlp_header(dev, &info->tlp);
722+
pcie_print_tlp_log(dev, &info->tlp, dev_fmt(" "));
729723

730724
out:
731725
if (info->id && info->error_dev_num > 1 && info->id == id)
@@ -797,7 +791,7 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
797791
aer->uncor_severity);
798792

799793
if (tlp_header_valid)
800-
__print_tlp_header(dev, &aer->header_log);
794+
pcie_print_tlp_log(dev, &aer->header_log, dev_fmt(" "));
801795

802796
trace_aer_event(dev_name(&dev->dev), (status & ~mask),
803797
aer_severity, tlp_header_valid, &aer->header_log);
@@ -1248,7 +1242,10 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
12481242

12491243
if (info->status & AER_LOG_TLP_MASKS) {
12501244
info->tlp_header_valid = 1;
1251-
pcie_read_tlp_log(dev, aer + PCI_ERR_HEADER_LOG, &info->tlp);
1245+
pcie_read_tlp_log(dev, aer + PCI_ERR_HEADER_LOG,
1246+
aer + PCI_ERR_PREFIX_LOG,
1247+
aer_tlp_log_len(dev, aercc),
1248+
&info->tlp);
12521249
}
12531250
}
12541251

drivers/pci/pcie/dpc.c

+5-9
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ pci_ers_result_t dpc_reset_link(struct pci_dev *pdev)
190190
static void dpc_process_rp_pio_error(struct pci_dev *pdev)
191191
{
192192
u16 cap = pdev->dpc_cap, dpc_status, first_error;
193-
u32 status, mask, sev, syserr, exc, log, prefix;
193+
u32 status, mask, sev, syserr, exc, log;
194194
struct pcie_tlp_log tlp_log;
195195
int i;
196196

@@ -217,20 +217,16 @@ static void dpc_process_rp_pio_error(struct pci_dev *pdev)
217217

218218
if (pdev->dpc_rp_log_size < 4)
219219
goto clear_status;
220-
pcie_read_tlp_log(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG, &tlp_log);
221-
pci_err(pdev, "TLP Header: %#010x %#010x %#010x %#010x\n",
222-
tlp_log.dw[0], tlp_log.dw[1], tlp_log.dw[2], tlp_log.dw[3]);
220+
pcie_read_tlp_log(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG,
221+
cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG,
222+
dpc_tlp_log_len(pdev), &tlp_log);
223+
pcie_print_tlp_log(pdev, &tlp_log, dev_fmt(""));
223224

224225
if (pdev->dpc_rp_log_size < 5)
225226
goto clear_status;
226227
pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_IMPSPEC_LOG, &log);
227228
pci_err(pdev, "RP PIO ImpSpec Log %#010x\n", log);
228229

229-
for (i = 0; i < pdev->dpc_rp_log_size - 5; i++) {
230-
pci_read_config_dword(pdev,
231-
cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG + i * 4, &prefix);
232-
pci_err(pdev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix);
233-
}
234230
clear_status:
235231
pci_write_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, status);
236232
}

drivers/pci/pcie/tlp.c

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* PCIe TLP Log handling
4+
*
5+
* Copyright (C) 2024 Intel Corporation
6+
*/
7+
8+
#include <linux/aer.h>
9+
#include <linux/array_size.h>
10+
#include <linux/pci.h>
11+
#include <linux/string.h>
12+
13+
#include "../pci.h"
14+
15+
/**
16+
* aer_tlp_log_len - Calculates AER Capability TLP Header/Prefix Log length
17+
* @dev: PCIe device
18+
* @aercc: AER Capabilities and Control register value
19+
*
20+
* Return: TLP Header/Prefix Log length
21+
*/
22+
unsigned int aer_tlp_log_len(struct pci_dev *dev, u32 aercc)
23+
{
24+
return 4 + (aercc & PCI_ERR_CAP_PREFIX_LOG_PRESENT) ?
25+
dev->eetlp_prefix_max : 0;
26+
}
27+
28+
#ifdef CONFIG_PCIE_DPC
29+
/**
30+
* dpc_tlp_log_len - Calculates DPC RP PIO TLP Header/Prefix Log length
31+
* @dev: PCIe device
32+
*
33+
* Return: TLP Header/Prefix Log length
34+
*/
35+
unsigned int dpc_tlp_log_len(struct pci_dev *dev)
36+
{
37+
/* Remove ImpSpec Log register from the count */
38+
if (dev->dpc_rp_log_size >= 5)
39+
return dev->dpc_rp_log_size - 1;
40+
41+
return dev->dpc_rp_log_size;
42+
}
43+
#endif
44+
45+
/**
46+
* pcie_read_tlp_log - read TLP Header Log
47+
* @dev: PCIe device
48+
* @where: PCI Config offset of TLP Header Log
49+
* @where2: PCI Config offset of TLP Prefix Log
50+
* @tlp_len: TLP Log length (Header Log + TLP Prefix Log in DWORDs)
51+
* @log: TLP Log structure to fill
52+
*
53+
* Fill @log from TLP Header Log registers, e.g., AER or DPC.
54+
*
55+
* Return: 0 on success and filled TLP Log structure, <0 on error.
56+
*/
57+
int pcie_read_tlp_log(struct pci_dev *dev, int where, int where2,
58+
unsigned int tlp_len, struct pcie_tlp_log *log)
59+
{
60+
unsigned int i;
61+
int off, ret;
62+
u32 *to;
63+
64+
memset(log, 0, sizeof(*log));
65+
66+
for (i = 0; i < tlp_len; i++) {
67+
if (i < 4) {
68+
off = where + i * 4;
69+
to = &log->dw[i];
70+
} else {
71+
off = where2 + (i - 4) * 4;
72+
to = &log->prefix[i - 4];
73+
}
74+
75+
ret = pci_read_config_dword(dev, off, to);
76+
if (ret)
77+
return pcibios_err_to_errno(ret);
78+
}
79+
80+
return 0;
81+
}
82+
83+
#define EE_PREFIX_STR " E-E Prefixes:"
84+
85+
/**
86+
* pcie_print_tlp_log - Print TLP Header / Prefix Log contents
87+
* @dev: PCIe device
88+
* @log: TLP Log structure
89+
* @pfx: String prefix
90+
*
91+
* Prints TLP Header and Prefix Log information held by @log.
92+
*/
93+
void pcie_print_tlp_log(const struct pci_dev *dev,
94+
const struct pcie_tlp_log *log, const char *pfx)
95+
{
96+
char buf[11 * (4 + ARRAY_SIZE(log->prefix)) + sizeof(EE_PREFIX_STR)];
97+
unsigned int i;
98+
int len;
99+
100+
len = scnprintf(buf, sizeof(buf), "%#010x %#010x %#010x %#010x",
101+
log->dw[0], log->dw[1], log->dw[2], log->dw[3]);
102+
103+
if (log->prefix[0])
104+
len += scnprintf(buf + len, sizeof(buf) - len, EE_PREFIX_STR);
105+
for (i = 0; i < ARRAY_SIZE(log->prefix); i++) {
106+
if (!log->prefix[i])
107+
break;
108+
len += scnprintf(buf + len, sizeof(buf) - len,
109+
" %#010x", log->prefix[i]);
110+
}
111+
112+
pci_err(dev, "%sTLP Header: %s\n", pfx, buf);
113+
}

drivers/pci/probe.c

+9-5
Original file line numberDiff line numberDiff line change
@@ -2251,8 +2251,8 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev)
22512251

22522252
static void pci_configure_eetlp_prefix(struct pci_dev *dev)
22532253
{
2254-
#ifdef CONFIG_PCI_PASID
22552254
struct pci_dev *bridge;
2255+
unsigned int eetlp_max;
22562256
int pcie_type;
22572257
u32 cap;
22582258

@@ -2264,15 +2264,19 @@ static void pci_configure_eetlp_prefix(struct pci_dev *dev)
22642264
return;
22652265

22662266
pcie_type = pci_pcie_type(dev);
2267+
2268+
eetlp_max = FIELD_GET(PCI_EXP_DEVCAP2_EE_PREFIX_MAX, cap);
2269+
/* 00b means 4 */
2270+
eetlp_max = eetlp_max ?: 4;
2271+
22672272
if (pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
22682273
pcie_type == PCI_EXP_TYPE_RC_END)
2269-
dev->eetlp_prefix_path = 1;
2274+
dev->eetlp_prefix_max = eetlp_max;
22702275
else {
22712276
bridge = pci_upstream_bridge(dev);
2272-
if (bridge && bridge->eetlp_prefix_path)
2273-
dev->eetlp_prefix_path = 1;
2277+
if (bridge && bridge->eetlp_prefix_max)
2278+
dev->eetlp_prefix_max = eetlp_max;
22742279
}
2275-
#endif
22762280
}
22772281

22782282
static void pci_configure_serr(struct pci_dev *dev)

include/linux/aer.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct pci_dev;
2020

2121
struct pcie_tlp_log {
2222
u32 dw[4];
23+
u32 prefix[4];
2324
};
2425

2526
struct aer_capability_regs {
@@ -37,8 +38,6 @@ struct aer_capability_regs {
3738
u16 uncor_err_source;
3839
};
3940

40-
int pcie_read_tlp_log(struct pci_dev *dev, int where, struct pcie_tlp_log *log);
41-
4241
#if defined(CONFIG_PCIEAER)
4342
int pci_aer_clear_nonfatal_status(struct pci_dev *dev);
4443
int pcie_aer_is_native(struct pci_dev *dev);

include/linux/pci.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ struct pci_dev {
407407
supported from root to here */
408408
#endif
409409
unsigned int pasid_no_tlp:1; /* PASID works without TLP Prefix */
410-
unsigned int eetlp_prefix_path:1; /* End-to-End TLP Prefix */
410+
unsigned int eetlp_prefix_max:3; /* Max # of End-End TLP Prefixes, 0=not supported */
411411

412412
pci_channel_state_t error_state; /* Current connectivity state */
413413
struct device dev; /* Generic device interface */

include/uapi/linux/pci_regs.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@
665665
#define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */
666666
#define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */
667667
#define PCI_EXP_DEVCAP2_EE_PREFIX 0x00200000 /* End-End TLP Prefix */
668+
#define PCI_EXP_DEVCAP2_EE_PREFIX_MAX 0x00c00000 /* Max End-End TLP Prefixes */
668669
#define PCI_EXP_DEVCTL2 0x28 /* Device Control 2 */
669670
#define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */
670671
#define PCI_EXP_DEVCTL2_COMP_TMOUT_DIS 0x0010 /* Completion Timeout Disable */
@@ -789,10 +790,11 @@
789790
/* Same bits as above */
790791
#define PCI_ERR_CAP 0x18 /* Advanced Error Capabilities & Ctrl*/
791792
#define PCI_ERR_CAP_FEP(x) ((x) & 0x1f) /* First Error Pointer */
792-
#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */
793-
#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */
794-
#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */
795-
#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */
793+
#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */
794+
#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */
795+
#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */
796+
#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */
797+
#define PCI_ERR_CAP_PREFIX_LOG_PRESENT 0x00000800 /* TLP Prefix Log Present */
796798
#define PCI_ERR_HEADER_LOG 0x1c /* Header Log Register (16 bytes) */
797799
#define PCI_ERR_ROOT_COMMAND 0x2c /* Root Error Command */
798800
#define PCI_ERR_ROOT_CMD_COR_EN 0x00000001 /* Correctable Err Reporting Enable */
@@ -808,6 +810,7 @@
808810
#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */
809811
#define PCI_ERR_ROOT_AER_IRQ 0xf8000000 /* Advanced Error Interrupt Message Number */
810812
#define PCI_ERR_ROOT_ERR_SRC 0x34 /* Error Source Identification */
813+
#define PCI_ERR_PREFIX_LOG 0x38 /* TLP Prefix LOG Register (up to 16 bytes) */
811814

812815
/* Virtual Channel */
813816
#define PCI_VC_PORT_CAP1 0x04

0 commit comments

Comments
 (0)