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 | */ |
99 | struct 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 | */ |
112 | struct 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 | */ |
131 | struct 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 | */ |
161 | struct 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 | */ |
175 | struct 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 | */ |
188 | struct 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 | */ |
217 | struct 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 | |