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