Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[sfrench/cifs-2.6.git] / drivers / hwtracing / ptt / hisi_ptt.h
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 */