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

source code of linux/drivers/hwtracing/ptt/hisi_ptt.h