File Index
Files and directories
Sign in
FILE

tlp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pci/pcie/tlp.c C
  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/bitfield.h>
 11#include <linux/pci.h>
 12#include <linux/string.h>
 13
 14#include "../pci.h"
 15
 16/**
 17 * aer_tlp_log_len - Calculate AER Capability TLP Header/Prefix Log length
 18 * @dev: PCIe device
 19 * @aercc: AER Capabilities and Control register value
 20 *
 21 * Return: TLP Header/Prefix Log length
 22 */
 23unsigned int aer_tlp_log_len(struct pci_dev *dev, u32 aercc)
 24{
 25	if (aercc & PCI_ERR_CAP_TLP_LOG_FLIT)
 26		return FIELD_GET(PCI_ERR_CAP_TLP_LOG_SIZE, aercc);
 27
 28	return PCIE_STD_NUM_TLP_HEADERLOG +
 29	       ((aercc & PCI_ERR_CAP_PREFIX_LOG_PRESENT) ?
 30		dev->eetlp_prefix_max : 0);
 31}
 32
 33#ifdef CONFIG_PCIE_DPC
 34/**
 35 * dpc_tlp_log_len - Calculate DPC RP PIO TLP Header/Prefix Log length
 36 * @dev: PCIe device
 37 *
 38 * Return: TLP Header/Prefix Log length
 39 */
 40unsigned int dpc_tlp_log_len(struct pci_dev *dev)
 41{
 42	/* Remove ImpSpec Log register from the count */
 43	if (dev->dpc_rp_log_size >= PCIE_STD_NUM_TLP_HEADERLOG + 1)
 44		return dev->dpc_rp_log_size - 1;
 45
 46	return dev->dpc_rp_log_size;
 47}
 48#endif
 49
 50/**
 51 * pcie_read_tlp_log - read TLP Header Log
 52 * @dev: PCIe device
 53 * @where: PCI Config offset of TLP Header Log
 54 * @where2: PCI Config offset of TLP Prefix Log
 55 * @tlp_len: TLP Log length (Header Log + TLP Prefix Log in DWORDs)
 56 * @flit: TLP Logged in Flit mode
 57 * @log: TLP Log structure to fill
 58 *
 59 * Fill @log from TLP Header Log registers, e.g., AER or DPC.
 60 *
 61 * Return: 0 on success and filled TLP Log structure, <0 on error.
 62 */
 63int pcie_read_tlp_log(struct pci_dev *dev, int where, int where2,
 64		      unsigned int tlp_len, bool flit, struct pcie_tlp_log *log)
 65{
 66	unsigned int i;
 67	int off, ret;
 68
 69	if (tlp_len > ARRAY_SIZE(log->dw))
 70		tlp_len = ARRAY_SIZE(log->dw);
 71
 72	memset(log, 0, sizeof(*log));
 73
 74	for (i = 0; i < tlp_len; i++) {
 75		if (i < PCIE_STD_NUM_TLP_HEADERLOG)
 76			off = where + i * 4;
 77		else
 78			off = where2 + (i - PCIE_STD_NUM_TLP_HEADERLOG) * 4;
 79
 80		ret = pci_read_config_dword(dev, off, &log->dw[i]);
 81		if (ret)
 82			return pcibios_err_to_errno(ret);
 83	}
 84
 85	/*
 86	 * Hard-code non-Flit mode to 4 DWORDs, for now. The exact length
 87	 * can only be known if the TLP is parsed.
 88	 */
 89	log->header_len = flit ? tlp_len : 4;
 90	log->flit = flit;
 91
 92	return 0;
 93}
 94
 95#define EE_PREFIX_STR " E-E Prefixes:"
 96
 97/**
 98 * pcie_print_tlp_log - Print TLP Header / Prefix Log contents
 99 * @dev: PCIe device
100 * @log: TLP Log structure
101 * @level: Printk log level
102 * @pfx: String prefix
103 *
104 * Prints TLP Header and Prefix Log information held by @log.
105 */
106void pcie_print_tlp_log(const struct pci_dev *dev,
107			const struct pcie_tlp_log *log, const char *level,
108			const char *pfx)
109{
110	/* EE_PREFIX_STR fits the extended DW space needed for the Flit mode */
111	char buf[11 * PCIE_STD_MAX_TLP_HEADERLOG + 1];
112	unsigned int i;
113	int len;
114
115	len = scnprintf(buf, sizeof(buf), "%#010x %#010x %#010x %#010x",
116			log->dw[0], log->dw[1], log->dw[2], log->dw[3]);
117
118	if (log->flit) {
119		for (i = PCIE_STD_NUM_TLP_HEADERLOG; i < log->header_len; i++) {
120			len += scnprintf(buf + len, sizeof(buf) - len,
121					 " %#010x", log->dw[i]);
122		}
123	} else {
124		if (log->prefix[0])
125			len += scnprintf(buf + len, sizeof(buf) - len,
126					 EE_PREFIX_STR);
127		for (i = 0; i < ARRAY_SIZE(log->prefix); i++) {
128			if (!log->prefix[i])
129				break;
130			len += scnprintf(buf + len, sizeof(buf) - len,
131					 " %#010x", log->prefix[i]);
132		}
133	}
134
135	dev_printk(level, &dev->dev, "%sTLP Header%s: %s\n", pfx,
136		log->flit ? " (Flit)" : "", buf);
137}
~/ Read-only file preview.