1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Driver for HiSilicon PCIe tune and trace device
4 *
5 * Copyright (c) 2022 HiSilicon Technologies Co., Ltd.
6 * Author: Yicong Yang <yangyicong@hisilicon.com>
7 */
8
9#ifndef _HISI_PTT_H
10#define _HISI_PTT_H
11
12#include <linux/bits.h>
13#include <linux/cpumask.h>
14#include <linux/device.h>
15#include <linux/kfifo.h>
16#include <linux/list.h>
17#include <linux/mutex.h>
18#include <linux/notifier.h>
19#include <linux/pci.h>
20#include <linux/perf_event.h>
21#include <linux/spinlock.h>
22#include <linux/types.h>
23#include <linux/workqueue.h>
24
25#define DRV_NAME "hisi_ptt"
26
27/*
28 * The definition of the device registers and register fields.
29 */
30#define HISI_PTT_TUNING_CTRL		0x0000
31#define   HISI_PTT_TUNING_CTRL_CODE	GENMASK(15, 0)
32#define   HISI_PTT_TUNING_CTRL_SUB	GENMASK(23, 16)
33#define HISI_PTT_TUNING_DATA		0x0004
34#define   HISI_PTT_TUNING_DATA_VAL_MASK	GENMASK(15, 0)
35#define HISI_PTT_TRACE_ADDR_SIZE	0x0800
36#define HISI_PTT_TRACE_ADDR_BASE_LO_0	0x0810
37#define HISI_PTT_TRACE_ADDR_BASE_HI_0	0x0814
38#define HISI_PTT_TRACE_ADDR_STRIDE	0x8
39#define HISI_PTT_TRACE_CTRL		0x0850
40#define   HISI_PTT_TRACE_CTRL_EN	BIT(0)
41#define   HISI_PTT_TRACE_CTRL_RST	BIT(1)
42#define   HISI_PTT_TRACE_CTRL_RXTX_SEL	GENMASK(3, 2)
43#define   HISI_PTT_TRACE_CTRL_TYPE_SEL	GENMASK(7, 4)
44#define   HISI_PTT_TRACE_CTRL_DATA_FORMAT	BIT(14)
45#define   HISI_PTT_TRACE_CTRL_FILTER_MODE	BIT(15)
46#define   HISI_PTT_TRACE_CTRL_TARGET_SEL	GENMASK(31, 16)
47#define HISI_PTT_TRACE_INT_STAT		0x0890
48#define   HISI_PTT_TRACE_INT_STAT_MASK	GENMASK(3, 0)
49#define HISI_PTT_TRACE_INT_MASK		0x0894
50#define HISI_PTT_TUNING_INT_STAT	0x0898
51#define   HISI_PTT_TUNING_INT_STAT_MASK	BIT(0)
52#define HISI_PTT_TRACE_WR_STS		0x08a0
53#define   HISI_PTT_TRACE_WR_STS_WRITE	GENMASK(27, 0)
54#define   HISI_PTT_TRACE_WR_STS_BUFFER	GENMASK(29, 28)
55#define HISI_PTT_TRACE_STS		0x08b0
56#define   HISI_PTT_TRACE_IDLE		BIT(0)
57#define HISI_PTT_DEVICE_RANGE		0x0fe0
58#define   HISI_PTT_DEVICE_RANGE_UPPER	GENMASK(31, 16)
59#define   HISI_PTT_DEVICE_RANGE_LOWER	GENMASK(15, 0)
60#define HISI_PTT_LOCATION		0x0fe8
61#define   HISI_PTT_CORE_ID		GENMASK(15, 0)
62#define   HISI_PTT_SICL_ID		GENMASK(31, 16)
63
64/* Parameters of PTT trace DMA part. */
65#define HISI_PTT_TRACE_DMA_IRQ			0
66#define HISI_PTT_TRACE_BUF_CNT			4
67#define HISI_PTT_TRACE_BUF_SIZE			SZ_4M
68#define HISI_PTT_TRACE_TOTAL_BUF_SIZE		(HISI_PTT_TRACE_BUF_SIZE * \
69						 HISI_PTT_TRACE_BUF_CNT)
70/* Wait time for hardware DMA to reset */
71#define HISI_PTT_RESET_TIMEOUT_US	10UL
72#define HISI_PTT_RESET_POLL_INTERVAL_US	1UL
73/* Poll timeout and interval for waiting hardware work to finish */
74#define HISI_PTT_WAIT_TUNE_TIMEOUT_US	1000000UL
75#define HISI_PTT_WAIT_TRACE_TIMEOUT_US	100UL
76#define HISI_PTT_WAIT_POLL_INTERVAL_US	10UL
77
78/* FIFO size for dynamically updating the PTT trace filter list. */
79#define HISI_PTT_FILTER_UPDATE_FIFO_SIZE	16
80/* Delay time for filter updating work */
81#define HISI_PTT_WORK_DELAY_MS			100UL
82
83#define HISI_PCIE_CORE_PORT_ID(devfn)	((PCI_SLOT(devfn) & 0x7) << 1)
84
85/* Definition of the PMU configs */
86#define HISI_PTT_PMU_FILTER_IS_PORT	BIT(19)
87#define HISI_PTT_PMU_FILTER_VAL_MASK	GENMASK(15, 0)
88#define HISI_PTT_PMU_DIRECTION_MASK	GENMASK(23, 20)
89#define HISI_PTT_PMU_TYPE_MASK		GENMASK(31, 24)
90#define HISI_PTT_PMU_FORMAT_MASK	GENMASK(35, 32)
91
92/**
93 * struct hisi_ptt_tune_desc - Describe tune event for PTT tune
94 * @hisi_ptt:   PTT device this tune event belongs to
95 * @name:       name of this event
96 * @event_code: code of the event
97 */
98struct hisi_ptt_tune_desc {
99	struct hisi_ptt *hisi_ptt;
100	const char *name;
101	u32 event_code;
102};
103
104/**
105 * struct hisi_ptt_dma_buffer - Describe a single trace buffer of PTT trace.
106 *                              The detail of the data format is described
107 *                              in the documentation of PTT device.
108 * @dma:   DMA address of this buffer visible to the device
109 * @addr:  virtual address of this buffer visible to the cpu
110 */
111struct hisi_ptt_dma_buffer {
112	dma_addr_t dma;
113	void *addr;
114};
115
116/**
117 * struct hisi_ptt_trace_ctrl - Control and status of PTT trace
118 * @trace_buf: array of the trace buffers for holding the trace data.
119 *             the length will be HISI_PTT_TRACE_BUF_CNT.
120 * @handle:    perf output handle of current trace session
121 * @buf_index: the index of current using trace buffer
122 * @on_cpu:    current tracing cpu
123 * @started:   current trace status, true for started
124 * @is_port:   whether we're tracing root port or not
125 * @direction: direction of the TLP headers to trace
126 * @filter:    filter value for tracing the TLP headers
127 * @format:    format of the TLP headers to trace
128 * @type:      type of the TLP headers to trace
129 */
130struct hisi_ptt_trace_ctrl {
131	struct hisi_ptt_dma_buffer *trace_buf;
132	struct perf_output_handle handle;
133	u32 buf_index;
134	int on_cpu;
135	bool started;
136	bool is_port;
137	u32 direction:2;
138	u32 filter:16;
139	u32 format:1;
140	u32 type:4;
141};
142
143/*
144 * sysfs attribute group name for root port filters and requester filters:
145 * /sys/devices/hisi_ptt<sicl_id>_<core_id>/root_port_filters
146 * and
147 * /sys/devices/hisi_ptt<sicl_id>_<core_id>/requester_filters
148 */
149#define HISI_PTT_RP_FILTERS_GRP_NAME	"root_port_filters"
150#define HISI_PTT_REQ_FILTERS_GRP_NAME	"requester_filters"
151
152/**
153 * struct hisi_ptt_filter_desc - Descriptor of the PTT trace filter
154 * @attr:    sysfs attribute of this filter
155 * @list:    entry of this descriptor in the filter list
156 * @is_port: the PCI device of the filter is a Root Port or not
157 * @name:    name of this filter, same as the name of the related PCI device
158 * @devid:   the PCI device's devid of the filter
159 */
160struct hisi_ptt_filter_desc {
161	struct device_attribute attr;
162	struct list_head list;
163	bool is_port;
164	char *name;
165	u16 devid;
166};
167
168/**
169 * struct hisi_ptt_filter_update_info - Information for PTT filter updating
170 * @is_port:    the PCI device to update is a Root Port or not
171 * @is_add:     adding to the filter or not
172 * @devid:      the PCI device's devid of the filter
173 */
174struct hisi_ptt_filter_update_info {
175	bool is_port;
176	bool is_add;
177	u16 devid;
178};
179
180/**
181 * struct hisi_ptt_pmu_buf - Descriptor of the AUX buffer of PTT trace
182 * @length:   size of the AUX buffer
183 * @nr_pages: number of pages of the AUX buffer
184 * @base:     start address of AUX buffer
185 * @pos:      position in the AUX buffer to commit traced data
186 */
187struct hisi_ptt_pmu_buf {
188	size_t length;
189	int nr_pages;
190	void *base;
191	long pos;
192};
193
194/**
195 * struct hisi_ptt - Per PTT device data
196 * @trace_ctrl:   the control information of PTT trace
197 * @hisi_ptt_nb:  dynamic filter update notifier
198 * @hotplug_node: node for register cpu hotplug event
199 * @hisi_ptt_pmu: the pum device of trace
200 * @iobase:       base IO address of the device
201 * @pdev:         pci_dev of this PTT device
202 * @tune_lock:    lock to serialize the tune process
203 * @pmu_lock:     lock to serialize the perf process
204 * @trace_irq:    interrupt number used by trace
205 * @upper_bdf:    the upper BDF range of the PCI devices managed by this PTT device
206 * @lower_bdf:    the lower BDF range of the PCI devices managed by this PTT device
207 * @port_filters: the filter list of root ports
208 * @req_filters:  the filter list of requester ID
209 * @filter_lock:  lock to protect the filters
210 * @sysfs_inited: whether the filters' sysfs entries has been initialized
211 * @port_mask:    port mask of the managed root ports
212 * @work:         delayed work for filter updating
213 * @filter_update_lock: spinlock to protect the filter update fifo
214 * @filter_update_fifo: fifo of the filters waiting to update the filter list
215 */
216struct hisi_ptt {
217	struct hisi_ptt_trace_ctrl trace_ctrl;
218	struct notifier_block hisi_ptt_nb;
219	struct hlist_node hotplug_node;
220	struct pmu hisi_ptt_pmu;
221	void __iomem *iobase;
222	struct pci_dev *pdev;
223	struct mutex tune_lock;
224	spinlock_t pmu_lock;
225	int trace_irq;
226	u32 upper_bdf;
227	u32 lower_bdf;
228
229	/*
230	 * The trace TLP headers can either be filtered by certain
231	 * root port, or by the requester ID. Organize the filters
232	 * by @port_filters and @req_filters here. The mask of all
233	 * the valid ports is also cached for doing sanity check
234	 * of user input.
235	 */
236	struct list_head port_filters;
237	struct list_head req_filters;
238	struct mutex filter_lock;
239	bool sysfs_inited;
240	u16 port_mask;
241
242	/*
243	 * We use a delayed work here to avoid indefinitely waiting for
244	 * the hisi_ptt->mutex which protecting the filter list. The
245	 * work will be delayed only if the mutex can not be held,
246	 * otherwise no delay will be applied.
247	 */
248	struct delayed_work work;
249	spinlock_t filter_update_lock;
250	DECLARE_KFIFO(filter_update_kfifo, struct hisi_ptt_filter_update_info,
251		      HISI_PTT_FILTER_UPDATE_FIFO_SIZE);
252};
253
254#define to_hisi_ptt(pmu) container_of(pmu, struct hisi_ptt, hisi_ptt_pmu)
255
256#endif /* _HISI_PTT_H */
257