New upstream version 18.08
[deb_dpdk.git] / drivers / raw / ifpga_rawdev / base / ifpga_fme_dperf.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4
5 #include "ifpga_feature_dev.h"
6
7 #define PERF_OBJ_ROOT_ID        0xff
8
9 static int fme_dperf_get_clock(struct ifpga_fme_hw *fme, u64 *clock)
10 {
11         struct feature_fme_dperf *dperf;
12         struct feature_fme_dfpmon_clk_ctr clk;
13
14         dperf = get_fme_feature_ioaddr_by_index(fme,
15                                                 FME_FEATURE_ID_GLOBAL_DPERF);
16         clk.afu_interf_clock = readq(&dperf->clk);
17
18         *clock = clk.afu_interf_clock;
19         return 0;
20 }
21
22 static int fme_dperf_get_revision(struct ifpga_fme_hw *fme, u64 *revision)
23 {
24         struct feature_fme_dperf *dperf;
25         struct feature_header header;
26
27         dperf = get_fme_feature_ioaddr_by_index(fme,
28                                                 FME_FEATURE_ID_GLOBAL_DPERF);
29         header.csr = readq(&dperf->header);
30         *revision = header.revision;
31
32         return 0;
33 }
34
35 #define DPERF_TIMEOUT   30
36
37 static bool fabric_pobj_is_enabled(int port_id,
38                                    struct feature_fme_dperf *dperf)
39 {
40         struct feature_fme_dfpmon_fab_ctl ctl;
41
42         ctl.csr = readq(&dperf->fab_ctl);
43
44         if (ctl.port_filter == FAB_DISABLE_FILTER)
45                 return port_id == PERF_OBJ_ROOT_ID;
46
47         return port_id == ctl.port_id;
48 }
49
50 static u64 read_fabric_counter(struct ifpga_fme_hw *fme, u8 port_id,
51                                enum dperf_fab_events fab_event)
52 {
53         struct feature_fme_dfpmon_fab_ctl ctl;
54         struct feature_fme_dfpmon_fab_ctr ctr;
55         struct feature_fme_dperf *dperf;
56         u64 counter = 0;
57
58         spinlock_lock(&fme->lock);
59         dperf = get_fme_feature_ioaddr_by_index(fme,
60                                                 FME_FEATURE_ID_GLOBAL_DPERF);
61
62         /* if it is disabled, force the counter to return zero. */
63         if (!fabric_pobj_is_enabled(port_id, dperf))
64                 goto exit;
65
66         ctl.csr = readq(&dperf->fab_ctl);
67         ctl.fab_evtcode = fab_event;
68         writeq(ctl.csr, &dperf->fab_ctl);
69
70         ctr.event_code = fab_event;
71
72         if (fpga_wait_register_field(event_code, ctr,
73                                      &dperf->fab_ctr, DPERF_TIMEOUT, 1)) {
74                 dev_err(fme, "timeout, unmatched VTd event type in counter registers.\n");
75                 spinlock_unlock(&fme->lock);
76                 return -ETIMEDOUT;
77         }
78
79         ctr.csr = readq(&dperf->fab_ctr);
80         counter = ctr.fab_cnt;
81 exit:
82         spinlock_unlock(&fme->lock);
83         return counter;
84 }
85
86 #define FAB_PORT_SHOW(name, event)                                      \
87 static int fme_dperf_get_fab_port_##name(struct ifpga_fme_hw *fme,      \
88                                          u8 port_id, u64 *counter)      \
89 {                                                                       \
90         *counter = read_fabric_counter(fme, port_id, event);            \
91         return 0;                                                       \
92 }
93
94 FAB_PORT_SHOW(pcie0_read, DPERF_FAB_PCIE0_RD);
95 FAB_PORT_SHOW(pcie0_write, DPERF_FAB_PCIE0_WR);
96 FAB_PORT_SHOW(mmio_read, DPERF_FAB_MMIO_RD);
97 FAB_PORT_SHOW(mmio_write, DPERF_FAB_MMIO_WR);
98
99 static int fme_dperf_get_fab_port_enable(struct ifpga_fme_hw *fme,
100                                          u8 port_id, u64 *enable)
101 {
102         struct feature_fme_dperf *dperf;
103         int status;
104
105         dperf = get_fme_feature_ioaddr_by_index(fme,
106                                                 FME_FEATURE_ID_GLOBAL_DPERF);
107
108         status = fabric_pobj_is_enabled(port_id, dperf);
109         *enable = (u64)status;
110
111         return 0;
112 }
113
114 /*
115  * If enable one port or all port event counter in fabric, other
116  * fabric event counter originally enabled will be disable automatically.
117  */
118 static int fme_dperf_set_fab_port_enable(struct ifpga_fme_hw *fme,
119                                          u8 port_id, u64 enable)
120 {
121         struct feature_fme_dfpmon_fab_ctl ctl;
122         struct feature_fme_dperf *dperf;
123         bool state;
124
125         state = !!enable;
126
127         if (!state)
128                 return -EINVAL;
129
130         dperf = get_fme_feature_ioaddr_by_index(fme,
131                                                 FME_FEATURE_ID_GLOBAL_DPERF);
132
133         /* if it is already enabled. */
134         if (fabric_pobj_is_enabled(port_id, dperf))
135                 return 0;
136
137         spinlock_lock(&fme->lock);
138         ctl.csr = readq(&dperf->fab_ctl);
139         if (port_id == PERF_OBJ_ROOT_ID) {
140                 ctl.port_filter = FAB_DISABLE_FILTER;
141         } else {
142                 ctl.port_filter = FAB_ENABLE_FILTER;
143                 ctl.port_id = port_id;
144         }
145
146         writeq(ctl.csr, &dperf->fab_ctl);
147         spinlock_unlock(&fme->lock);
148
149         return 0;
150 }
151
152 static int fme_dperf_get_fab_freeze(struct ifpga_fme_hw *fme, u64 *freeze)
153 {
154         struct feature_fme_dperf *dperf;
155         struct feature_fme_dfpmon_fab_ctl ctl;
156
157         dperf = get_fme_feature_ioaddr_by_index(fme,
158                                                 FME_FEATURE_ID_GLOBAL_DPERF);
159         ctl.csr = readq(&dperf->fab_ctl);
160         *freeze = (u64)ctl.freeze;
161
162         return 0;
163 }
164
165 static int fme_dperf_set_fab_freeze(struct ifpga_fme_hw *fme, u64 freeze)
166 {
167         struct feature_fme_dperf *dperf;
168         struct feature_fme_dfpmon_fab_ctl ctl;
169         bool state;
170
171         state = !!freeze;
172
173         spinlock_lock(&fme->lock);
174         dperf = get_fme_feature_ioaddr_by_index(fme,
175                                                 FME_FEATURE_ID_GLOBAL_DPERF);
176         ctl.csr = readq(&dperf->fab_ctl);
177         ctl.freeze = state;
178         writeq(ctl.csr, &dperf->fab_ctl);
179         spinlock_unlock(&fme->lock);
180
181         return 0;
182 }
183
184 #define PERF_MAX_PORT_NUM       1
185
186 static int fme_global_dperf_init(struct feature *feature)
187 {
188         UNUSED(feature);
189
190         dev_info(NULL, "FME global_dperf Init.\n");
191
192         return 0;
193 }
194
195 static void fme_global_dperf_uinit(struct feature *feature)
196 {
197         UNUSED(feature);
198
199         dev_info(NULL, "FME global_dperf UInit.\n");
200 }
201
202 static int fme_dperf_fab_get_prop(struct feature *feature,
203                                   struct feature_prop *prop)
204 {
205         struct ifpga_fme_hw *fme = feature->parent;
206         u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
207         u16 id = GET_FIELD(PROP_ID, prop->prop_id);
208
209         switch (id) {
210         case 0x1: /* FREEZE */
211                 return fme_dperf_get_fab_freeze(fme, &prop->data);
212         case 0x2: /* PCIE0_READ */
213                 return fme_dperf_get_fab_port_pcie0_read(fme, sub, &prop->data);
214         case 0x3: /* PCIE0_WRITE */
215                 return fme_dperf_get_fab_port_pcie0_write(fme, sub,
216                                                           &prop->data);
217         case 0x4: /* MMIO_READ */
218                 return fme_dperf_get_fab_port_mmio_read(fme, sub, &prop->data);
219         case 0x5: /* MMIO_WRITE */
220                 return fme_dperf_get_fab_port_mmio_write(fme, sub, &prop->data);
221         case 0x6: /* ENABLE */
222                 return fme_dperf_get_fab_port_enable(fme, sub, &prop->data);
223         }
224
225         return -ENOENT;
226 }
227
228 static int fme_dperf_root_get_prop(struct feature *feature,
229                                    struct feature_prop *prop)
230 {
231         struct ifpga_fme_hw *fme = feature->parent;
232         u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
233         u16 id = GET_FIELD(PROP_ID, prop->prop_id);
234
235         if (sub != PERF_PROP_SUB_UNUSED)
236                 return -ENOENT;
237
238         switch (id) {
239         case 0x1: /* CLOCK */
240                 return fme_dperf_get_clock(fme, &prop->data);
241         case 0x2: /* REVISION */
242                 return fme_dperf_get_revision(fme, &prop->data);
243         }
244
245         return -ENOENT;
246 }
247
248 static int fme_global_dperf_get_prop(struct feature *feature,
249                                      struct feature_prop *prop)
250 {
251         u8 top = GET_FIELD(PROP_TOP, prop->prop_id);
252
253         switch (top) {
254         case PERF_PROP_TOP_FAB:
255                 return fme_dperf_fab_get_prop(feature, prop);
256         case PERF_PROP_TOP_UNUSED:
257                 return fme_dperf_root_get_prop(feature, prop);
258         }
259
260         return -ENOENT;
261 }
262
263 static int fme_dperf_fab_set_prop(struct feature *feature,
264                                   struct feature_prop *prop)
265 {
266         struct ifpga_fme_hw *fme = feature->parent;
267         u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
268         u16 id = GET_FIELD(PROP_ID, prop->prop_id);
269
270         switch (id) {
271         case 0x1: /* FREEZE - fab root only prop */
272                 if (sub != PERF_PROP_SUB_UNUSED)
273                         return -ENOENT;
274                 return fme_dperf_set_fab_freeze(fme, prop->data);
275         case 0x6: /* ENABLE - fab both root and sub */
276                 return fme_dperf_set_fab_port_enable(fme, sub, prop->data);
277         }
278
279         return -ENOENT;
280 }
281
282 static int fme_global_dperf_set_prop(struct feature *feature,
283                                      struct feature_prop *prop)
284 {
285         u8 top = GET_FIELD(PROP_TOP, prop->prop_id);
286
287         switch (top) {
288         case PERF_PROP_TOP_FAB:
289                 return fme_dperf_fab_set_prop(feature, prop);
290         }
291
292         return -ENOENT;
293 }
294
295 struct feature_ops fme_global_dperf_ops = {
296         .init = fme_global_dperf_init,
297         .uinit = fme_global_dperf_uinit,
298         .get_prop = fme_global_dperf_get_prop,
299         .set_prop = fme_global_dperf_set_prop,
300
301 };