History

PCI: Add TLP Prefix reading to pcie_read_tlp_log()

pcie_read_tlp_log() handles only 4 Header Log DWORDs but TLP Prefix Log (PCIe r6.1 secs 7.8.4.12 & 7.9.14.13) may also be present. Generalize pcie_read_tlp_log() and struct pcie_tlp_log to also handle TLP Prefix Log. The relevant registers are formatted identically in AER and DPC Capability, but has these variations: a) The offsets of TLP Prefix Log registers vary. b) DPC RP PIO TLP Prefix Log register can be < 4 DWORDs. c) AER TLP Prefix Log Present (PCIe r6.1 sec 7.8.4.7) can indicate Prefix Log is not present. Therefore callers must pass the offset of the TLP Prefix Log register and the entire length to pcie_read_tlp_log() to be able to read the correct number of TLP Prefix DWORDs from the correct offset.

Ilpo Järvinen committed 1 year ago

Commit ad41dde1 parent e5321ae6 files · +68 −18Browse files

Unified · Split

6 files
  1. drivers/pci/pci.h +4 −1
  2. drivers/pci/pcie/aer.c +4 −1
  3. drivers/pci/pcie/dpc.c +6 −7
  4. drivers/pci/pcie/tlp.c +47 −5
  5. include/linux/aer.h +1 −0
  6. include/uapi/linux/pci_regs.h +6 −4
drivers/pci/pci.h+4−1
@@ -550,7 +550,9 @@ struct aer_err_info { · 549 unmodified lines
550550 int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info);
551551 void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
552552
553−int pcie_read_tlp_log(struct pci_dev *dev, int where, struct pcie_tlp_log *log);
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);
554556 #endif /* CONFIG_PCIEAER */
555557
556558 #ifdef CONFIG_PCIEPORTBUS
@@ -569,6 +571,7 @@ void pci_dpc_init(struct pci_dev *pdev); · 12 unmodified lines
569571 void dpc_process_error(struct pci_dev *pdev);
570572 pci_ers_result_t dpc_reset_link(struct pci_dev *pdev);
571573 bool pci_dpc_recovered(struct pci_dev *pdev);
574+unsigned int dpc_tlp_log_len(struct pci_dev *dev);
572575 #else
573576 static inline void pci_save_dpc_state(struct pci_dev *dev) { }
574577 static inline void pci_restore_dpc_state(struct pci_dev *dev) { }
drivers/pci/pcie/aer.c+4−1
@@ -1248,7 +1248,10 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) · 1247 unmodified lines
12481248
12491249 if (info->status & AER_LOG_TLP_MASKS) {
12501250 info->tlp_header_valid = 1;
1251− pcie_read_tlp_log(dev, aer + PCI_ERR_HEADER_LOG, &info->tlp);
1251+ pcie_read_tlp_log(dev, aer + PCI_ERR_HEADER_LOG,
1252+ aer + PCI_ERR_PREFIX_LOG,
1253+ aer_tlp_log_len(dev, aercc),
1254+ &info->tlp);
12521255 }
12531256 }
12541257
drivers/pci/pcie/dpc.c+6−7
@@ -190,7 +190,7 @@ out: · 189 unmodified lines
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,19 @@ static void dpc_process_rp_pio_error(struct pci_dev *pdev) · 20 unmodified lines
217217
218218 if (pdev->dpc_rp_log_size < PCIE_STD_NUM_TLP_HEADERLOG)
219219 goto clear_status;
220− pcie_read_tlp_log(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG, &tlp_log);
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);
221223 pci_err(pdev, "TLP Header: %#010x %#010x %#010x %#010x\n",
222224 tlp_log.dw[0], tlp_log.dw[1], tlp_log.dw[2], tlp_log.dw[3]);
225+ for (i = 0; i < pdev->dpc_rp_log_size - PCIE_STD_NUM_TLP_HEADERLOG - 1; i++)
226+ pci_err(pdev, "TLP Prefix Header: dw%d, %#010x\n", i, tlp_log.prefix[i]);
223227
224228 if (pdev->dpc_rp_log_size < PCIE_STD_NUM_TLP_HEADERLOG + 1)
225229 goto clear_status;
226230 pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_IMPSPEC_LOG, &log);
227231 pci_err(pdev, "RP PIO ImpSpec Log %#010x\n", log);
228232
229− for (i = 0; i < pdev->dpc_rp_log_size - PCIE_STD_NUM_TLP_HEADERLOG - 1; 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− }
234233 clear_status:
235234 pci_write_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, status);
236235 }
drivers/pci/pcie/tlp.c+47−5
@@ -11,26 +11,68 @@ · 10 unmodified lines
1111
1212 #include "../pci.h"
1313
14+/**
15+ * aer_tlp_log_len - Calculate AER Capability TLP Header/Prefix Log length
16+ * @dev: PCIe device
17+ * @aercc: AER Capabilities and Control register value
18+ *
19+ * Return: TLP Header/Prefix Log length
20+ */
21+unsigned int aer_tlp_log_len(struct pci_dev *dev, u32 aercc)
22+{
23+ return PCIE_STD_NUM_TLP_HEADERLOG +
24+ ((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 - Calculate 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 >= PCIE_STD_NUM_TLP_HEADERLOG + 1)
39+ return dev->dpc_rp_log_size - 1;
40+
41+ return dev->dpc_rp_log_size;
42+}
43+#endif
44+
1445 /**
1546 * pcie_read_tlp_log - read TLP Header Log
1647 * @dev: PCIe device
1748 * @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)
1851 * @log: TLP Log structure to fill
1952 *
2053 * Fill @log from TLP Header Log registers, e.g., AER or DPC.
2154 *
2255 * Return: 0 on success and filled TLP Log structure, <0 on error.
2356 */
24−int pcie_read_tlp_log(struct pci_dev *dev, int where,
25− struct pcie_tlp_log *log)
57+int pcie_read_tlp_log(struct pci_dev *dev, int where, int where2,
58+ unsigned int tlp_len, struct pcie_tlp_log *log)
2659 {
2760 unsigned int i;
28− int ret;
61+ int off, ret;
62+ u32 *to;
2963
3064 memset(log, 0, sizeof(*log));
3165
32− for (i = 0; i < PCIE_STD_NUM_TLP_HEADERLOG; i++) {
33− ret = pci_read_config_dword(dev, where + i * 4, &log->dw[i]);
66+ for (i = 0; i < tlp_len; i++) {
67+ if (i < PCIE_STD_NUM_TLP_HEADERLOG) {
68+ off = where + i * 4;
69+ to = &log->dw[i];
70+ } else {
71+ off = where2 + (i - PCIE_STD_NUM_TLP_HEADERLOG) * 4;
72+ to = &log->prefix[i - PCIE_STD_NUM_TLP_HEADERLOG];
73+ }
74+
75+ ret = pci_read_config_dword(dev, off, to);
3476 if (ret)
3577 return pcibios_err_to_errno(ret);
3678 }
include/linux/aer.h+1−0
@@ -27,6 +27,7 @@ struct pci_dev; · 26 unmodified lines
2727
2828 struct pcie_tlp_log {
2929 u32 dw[PCIE_STD_NUM_TLP_HEADERLOG];
30+ u32 prefix[PCIE_STD_MAX_TLP_PREFIXLOG];
3031 };
3132
3233 struct aer_capability_regs {
include/uapi/linux/pci_regs.h+6−4
@@ -790,10 +790,11 @@ · 789 unmodified lines
790790 /* Same bits as above */
791791 #define PCI_ERR_CAP 0x18 /* Advanced Error Capabilities & Ctrl*/
792792 #define PCI_ERR_CAP_FEP(x) ((x) & 0x1f) /* First Error Pointer */
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 */
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 */
797798 #define PCI_ERR_HEADER_LOG 0x1c /* Header Log Register (16 bytes) */
798799 #define PCI_ERR_ROOT_COMMAND 0x2c /* Root Error Command */
799800 #define PCI_ERR_ROOT_CMD_COR_EN 0x00000001 /* Correctable Err Reporting Enable */
@@ -809,6 +810,7 @@ · 9 unmodified lines
809810 #define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */
810811 #define PCI_ERR_ROOT_AER_IRQ 0xf8000000 /* Advanced Error Interrupt Message Number */
811812 #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) */
812814
813815 /* Virtual Channel */
814816 #define PCI_VC_PORT_CAP1 0x04