xref: /openbmc/linux/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
121da57a2SMaxime Chevallier // SPDX-License-Identifier: GPL-2.0
221da57a2SMaxime Chevallier /*
321da57a2SMaxime Chevallier  * Driver for Marvell PPv2 network controller for Armada 375 SoC.
421da57a2SMaxime Chevallier  *
521da57a2SMaxime Chevallier  * Copyright (C) 2018 Marvell
621da57a2SMaxime Chevallier  */
721da57a2SMaxime Chevallier 
821da57a2SMaxime Chevallier #include <linux/kernel.h>
921da57a2SMaxime Chevallier #include <linux/slab.h>
1021da57a2SMaxime Chevallier #include <linux/debugfs.h>
1121da57a2SMaxime Chevallier 
1221da57a2SMaxime Chevallier #include "mvpp2.h"
1321da57a2SMaxime Chevallier #include "mvpp2_prs.h"
14dba1d918SMaxime Chevallier #include "mvpp2_cls.h"
1521da57a2SMaxime Chevallier 
1621da57a2SMaxime Chevallier struct mvpp2_dbgfs_prs_entry {
1721da57a2SMaxime Chevallier 	int tid;
1821da57a2SMaxime Chevallier 	struct mvpp2 *priv;
1921da57a2SMaxime Chevallier };
2021da57a2SMaxime Chevallier 
21b607cc61SMaxime Chevallier struct mvpp2_dbgfs_c2_entry {
22b607cc61SMaxime Chevallier 	int id;
23b607cc61SMaxime Chevallier 	struct mvpp2 *priv;
24b607cc61SMaxime Chevallier };
25b607cc61SMaxime Chevallier 
26dba1d918SMaxime Chevallier struct mvpp2_dbgfs_flow_entry {
27dba1d918SMaxime Chevallier 	int flow;
28dba1d918SMaxime Chevallier 	struct mvpp2 *priv;
29dba1d918SMaxime Chevallier };
30dba1d918SMaxime Chevallier 
318aa65106SMaxime Chevallier struct mvpp2_dbgfs_flow_tbl_entry {
328aa65106SMaxime Chevallier 	int id;
338aa65106SMaxime Chevallier 	struct mvpp2 *priv;
348aa65106SMaxime Chevallier };
358aa65106SMaxime Chevallier 
36dba1d918SMaxime Chevallier struct mvpp2_dbgfs_port_flow_entry {
37dba1d918SMaxime Chevallier 	struct mvpp2_port *port;
38dba1d918SMaxime Chevallier 	struct mvpp2_dbgfs_flow_entry *dbg_fe;
39dba1d918SMaxime Chevallier };
40dba1d918SMaxime Chevallier 
417cb5e368SMaxime Chevallier struct mvpp2_dbgfs_entries {
427cb5e368SMaxime Chevallier 	/* Entries for Header Parser debug info */
437cb5e368SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry prs_entries[MVPP2_PRS_TCAM_SRAM_SIZE];
447cb5e368SMaxime Chevallier 
45b607cc61SMaxime Chevallier 	/* Entries for Classifier C2 engine debug info */
46b607cc61SMaxime Chevallier 	struct mvpp2_dbgfs_c2_entry c2_entries[MVPP22_CLS_C2_N_ENTRIES];
47b607cc61SMaxime Chevallier 
488aa65106SMaxime Chevallier 	/* Entries for Classifier Flow Table debug info */
498aa65106SMaxime Chevallier 	struct mvpp2_dbgfs_flow_tbl_entry flt_entries[MVPP2_CLS_FLOWS_TBL_SIZE];
508aa65106SMaxime Chevallier 
517cb5e368SMaxime Chevallier 	/* Entries for Classifier flows debug info */
527cb5e368SMaxime Chevallier 	struct mvpp2_dbgfs_flow_entry flow_entries[MVPP2_N_PRS_FLOWS];
537cb5e368SMaxime Chevallier 
547cb5e368SMaxime Chevallier 	/* Entries for per-port flows debug info */
557cb5e368SMaxime Chevallier 	struct mvpp2_dbgfs_port_flow_entry port_flow_entries[MVPP2_MAX_PORTS];
567cb5e368SMaxime Chevallier };
577cb5e368SMaxime Chevallier 
mvpp2_dbgfs_flow_flt_hits_show(struct seq_file * s,void * unused)58f9d30d5bSMaxime Chevallier static int mvpp2_dbgfs_flow_flt_hits_show(struct seq_file *s, void *unused)
59f9d30d5bSMaxime Chevallier {
608aa65106SMaxime Chevallier 	struct mvpp2_dbgfs_flow_tbl_entry *entry = s->private;
61f9d30d5bSMaxime Chevallier 
628aa65106SMaxime Chevallier 	u32 hits = mvpp2_cls_flow_hits(entry->priv, entry->id);
63f9d30d5bSMaxime Chevallier 
64f9d30d5bSMaxime Chevallier 	seq_printf(s, "%u\n", hits);
65f9d30d5bSMaxime Chevallier 
66f9d30d5bSMaxime Chevallier 	return 0;
67f9d30d5bSMaxime Chevallier }
68f9d30d5bSMaxime Chevallier 
69f9d30d5bSMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_flt_hits);
70f9d30d5bSMaxime Chevallier 
mvpp2_dbgfs_flow_dec_hits_show(struct seq_file * s,void * unused)71f9d30d5bSMaxime Chevallier static int mvpp2_dbgfs_flow_dec_hits_show(struct seq_file *s, void *unused)
72f9d30d5bSMaxime Chevallier {
73f9d30d5bSMaxime Chevallier 	struct mvpp2_dbgfs_flow_entry *entry = s->private;
74f9d30d5bSMaxime Chevallier 
75f9d30d5bSMaxime Chevallier 	u32 hits = mvpp2_cls_lookup_hits(entry->priv, entry->flow);
76f9d30d5bSMaxime Chevallier 
77f9d30d5bSMaxime Chevallier 	seq_printf(s, "%u\n", hits);
78f9d30d5bSMaxime Chevallier 
79f9d30d5bSMaxime Chevallier 	return 0;
80f9d30d5bSMaxime Chevallier }
81f9d30d5bSMaxime Chevallier 
82f9d30d5bSMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_dec_hits);
83f9d30d5bSMaxime Chevallier 
mvpp2_dbgfs_flow_type_show(struct seq_file * s,void * unused)84dba1d918SMaxime Chevallier static int mvpp2_dbgfs_flow_type_show(struct seq_file *s, void *unused)
85dba1d918SMaxime Chevallier {
86dba1d918SMaxime Chevallier 	struct mvpp2_dbgfs_flow_entry *entry = s->private;
870b27f865SMaxime Chevallier 	const struct mvpp2_cls_flow *f;
88dba1d918SMaxime Chevallier 	const char *flow_name;
89dba1d918SMaxime Chevallier 
90dba1d918SMaxime Chevallier 	f = mvpp2_cls_flow_get(entry->flow);
91dba1d918SMaxime Chevallier 	if (!f)
92dba1d918SMaxime Chevallier 		return -EINVAL;
93dba1d918SMaxime Chevallier 
94dba1d918SMaxime Chevallier 	switch (f->flow_type) {
95dba1d918SMaxime Chevallier 	case IPV4_FLOW:
96dba1d918SMaxime Chevallier 		flow_name = "ipv4";
97dba1d918SMaxime Chevallier 		break;
98dba1d918SMaxime Chevallier 	case IPV6_FLOW:
99dba1d918SMaxime Chevallier 		flow_name = "ipv6";
100dba1d918SMaxime Chevallier 		break;
101dba1d918SMaxime Chevallier 	case TCP_V4_FLOW:
102dba1d918SMaxime Chevallier 		flow_name = "tcp4";
103dba1d918SMaxime Chevallier 		break;
104dba1d918SMaxime Chevallier 	case TCP_V6_FLOW:
105dba1d918SMaxime Chevallier 		flow_name = "tcp6";
106dba1d918SMaxime Chevallier 		break;
107dba1d918SMaxime Chevallier 	case UDP_V4_FLOW:
108dba1d918SMaxime Chevallier 		flow_name = "udp4";
109dba1d918SMaxime Chevallier 		break;
110dba1d918SMaxime Chevallier 	case UDP_V6_FLOW:
111dba1d918SMaxime Chevallier 		flow_name = "udp6";
112dba1d918SMaxime Chevallier 		break;
113dba1d918SMaxime Chevallier 	default:
114dba1d918SMaxime Chevallier 		flow_name = "other";
115dba1d918SMaxime Chevallier 	}
116dba1d918SMaxime Chevallier 
117dba1d918SMaxime Chevallier 	seq_printf(s, "%s\n", flow_name);
118dba1d918SMaxime Chevallier 
119dba1d918SMaxime Chevallier 	return 0;
120dba1d918SMaxime Chevallier }
121dba1d918SMaxime Chevallier 
1227cb5e368SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_type);
123dba1d918SMaxime Chevallier 
mvpp2_dbgfs_flow_id_show(struct seq_file * s,void * unused)124dba1d918SMaxime Chevallier static int mvpp2_dbgfs_flow_id_show(struct seq_file *s, void *unused)
125dba1d918SMaxime Chevallier {
1260b27f865SMaxime Chevallier 	const struct mvpp2_dbgfs_flow_entry *entry = s->private;
1270b27f865SMaxime Chevallier 	const struct mvpp2_cls_flow *f;
128dba1d918SMaxime Chevallier 
129dba1d918SMaxime Chevallier 	f = mvpp2_cls_flow_get(entry->flow);
130dba1d918SMaxime Chevallier 	if (!f)
131dba1d918SMaxime Chevallier 		return -EINVAL;
132dba1d918SMaxime Chevallier 
133dba1d918SMaxime Chevallier 	seq_printf(s, "%d\n", f->flow_id);
134dba1d918SMaxime Chevallier 
135dba1d918SMaxime Chevallier 	return 0;
136dba1d918SMaxime Chevallier }
137dba1d918SMaxime Chevallier 
138dba1d918SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_id);
139dba1d918SMaxime Chevallier 
mvpp2_dbgfs_port_flow_hash_opt_show(struct seq_file * s,void * unused)140dba1d918SMaxime Chevallier static int mvpp2_dbgfs_port_flow_hash_opt_show(struct seq_file *s, void *unused)
141dba1d918SMaxime Chevallier {
142dba1d918SMaxime Chevallier 	struct mvpp2_dbgfs_port_flow_entry *entry = s->private;
143dba1d918SMaxime Chevallier 	struct mvpp2_port *port = entry->port;
144dba1d918SMaxime Chevallier 	struct mvpp2_cls_flow_entry fe;
1450b27f865SMaxime Chevallier 	const struct mvpp2_cls_flow *f;
146dba1d918SMaxime Chevallier 	int flow_index;
147dba1d918SMaxime Chevallier 	u16 hash_opts;
148dba1d918SMaxime Chevallier 
149dba1d918SMaxime Chevallier 	f = mvpp2_cls_flow_get(entry->dbg_fe->flow);
150dba1d918SMaxime Chevallier 	if (!f)
151dba1d918SMaxime Chevallier 		return -EINVAL;
152dba1d918SMaxime Chevallier 
153ff2f3cb6SMaxime Chevallier 	flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);
154dba1d918SMaxime Chevallier 
155dba1d918SMaxime Chevallier 	mvpp2_cls_flow_read(port->priv, flow_index, &fe);
156dba1d918SMaxime Chevallier 
157dba1d918SMaxime Chevallier 	hash_opts = mvpp2_flow_get_hek_fields(&fe);
158dba1d918SMaxime Chevallier 
159dba1d918SMaxime Chevallier 	seq_printf(s, "0x%04x\n", hash_opts);
160dba1d918SMaxime Chevallier 
161dba1d918SMaxime Chevallier 	return 0;
162dba1d918SMaxime Chevallier }
163dba1d918SMaxime Chevallier 
1647cb5e368SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_hash_opt);
165dba1d918SMaxime Chevallier 
mvpp2_dbgfs_port_flow_engine_show(struct seq_file * s,void * unused)166dba1d918SMaxime Chevallier static int mvpp2_dbgfs_port_flow_engine_show(struct seq_file *s, void *unused)
167dba1d918SMaxime Chevallier {
168dba1d918SMaxime Chevallier 	struct mvpp2_dbgfs_port_flow_entry *entry = s->private;
169dba1d918SMaxime Chevallier 	struct mvpp2_port *port = entry->port;
170dba1d918SMaxime Chevallier 	struct mvpp2_cls_flow_entry fe;
1710b27f865SMaxime Chevallier 	const struct mvpp2_cls_flow *f;
172dba1d918SMaxime Chevallier 	int flow_index, engine;
173dba1d918SMaxime Chevallier 
174dba1d918SMaxime Chevallier 	f = mvpp2_cls_flow_get(entry->dbg_fe->flow);
175dba1d918SMaxime Chevallier 	if (!f)
176dba1d918SMaxime Chevallier 		return -EINVAL;
177dba1d918SMaxime Chevallier 
178ff2f3cb6SMaxime Chevallier 	flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);
179dba1d918SMaxime Chevallier 
180dba1d918SMaxime Chevallier 	mvpp2_cls_flow_read(port->priv, flow_index, &fe);
181dba1d918SMaxime Chevallier 
182dba1d918SMaxime Chevallier 	engine = mvpp2_cls_flow_eng_get(&fe);
183dba1d918SMaxime Chevallier 
184dba1d918SMaxime Chevallier 	seq_printf(s, "%d\n", engine);
185dba1d918SMaxime Chevallier 
186dba1d918SMaxime Chevallier 	return 0;
187dba1d918SMaxime Chevallier }
188dba1d918SMaxime Chevallier 
189dba1d918SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_engine);
190dba1d918SMaxime Chevallier 
mvpp2_dbgfs_flow_c2_hits_show(struct seq_file * s,void * unused)191f9d30d5bSMaxime Chevallier static int mvpp2_dbgfs_flow_c2_hits_show(struct seq_file *s, void *unused)
192f9d30d5bSMaxime Chevallier {
193b607cc61SMaxime Chevallier 	struct mvpp2_dbgfs_c2_entry *entry = s->private;
194f9d30d5bSMaxime Chevallier 	u32 hits;
195f9d30d5bSMaxime Chevallier 
196b607cc61SMaxime Chevallier 	hits = mvpp2_cls_c2_hit_count(entry->priv, entry->id);
197f9d30d5bSMaxime Chevallier 
198f9d30d5bSMaxime Chevallier 	seq_printf(s, "%u\n", hits);
199f9d30d5bSMaxime Chevallier 
200f9d30d5bSMaxime Chevallier 	return 0;
201f9d30d5bSMaxime Chevallier }
202f9d30d5bSMaxime Chevallier 
203f9d30d5bSMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_hits);
204f9d30d5bSMaxime Chevallier 
mvpp2_dbgfs_flow_c2_rxq_show(struct seq_file * s,void * unused)205dba1d918SMaxime Chevallier static int mvpp2_dbgfs_flow_c2_rxq_show(struct seq_file *s, void *unused)
206dba1d918SMaxime Chevallier {
207b607cc61SMaxime Chevallier 	struct mvpp2_dbgfs_c2_entry *entry = s->private;
208dba1d918SMaxime Chevallier 	struct mvpp2_cls_c2_entry c2;
209dba1d918SMaxime Chevallier 	u8 qh, ql;
210dba1d918SMaxime Chevallier 
211b607cc61SMaxime Chevallier 	mvpp2_cls_c2_read(entry->priv, entry->id, &c2);
212dba1d918SMaxime Chevallier 
213dba1d918SMaxime Chevallier 	qh = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QHIGH_OFFS) &
214dba1d918SMaxime Chevallier 	     MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
215dba1d918SMaxime Chevallier 
216dba1d918SMaxime Chevallier 	ql = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QLOW_OFFS) &
217dba1d918SMaxime Chevallier 	     MVPP22_CLS_C2_ATTR0_QLOW_MASK;
218dba1d918SMaxime Chevallier 
219dba1d918SMaxime Chevallier 	seq_printf(s, "%d\n", (qh << 3 | ql));
220dba1d918SMaxime Chevallier 
221dba1d918SMaxime Chevallier 	return 0;
222dba1d918SMaxime Chevallier }
223dba1d918SMaxime Chevallier 
224dba1d918SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_rxq);
225dba1d918SMaxime Chevallier 
mvpp2_dbgfs_flow_c2_enable_show(struct seq_file * s,void * unused)226dba1d918SMaxime Chevallier static int mvpp2_dbgfs_flow_c2_enable_show(struct seq_file *s, void *unused)
227dba1d918SMaxime Chevallier {
228b607cc61SMaxime Chevallier 	struct mvpp2_dbgfs_c2_entry *entry = s->private;
229dba1d918SMaxime Chevallier 	struct mvpp2_cls_c2_entry c2;
230dba1d918SMaxime Chevallier 	int enabled;
231dba1d918SMaxime Chevallier 
232b607cc61SMaxime Chevallier 	mvpp2_cls_c2_read(entry->priv, entry->id, &c2);
233dba1d918SMaxime Chevallier 
234e146471fSGustavo A. R. Silva 	enabled = !!(c2.attr[2] & MVPP22_CLS_C2_ATTR2_RSS_EN);
235dba1d918SMaxime Chevallier 
236dba1d918SMaxime Chevallier 	seq_printf(s, "%d\n", enabled);
237dba1d918SMaxime Chevallier 
238dba1d918SMaxime Chevallier 	return 0;
239dba1d918SMaxime Chevallier }
240dba1d918SMaxime Chevallier 
241dba1d918SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_enable);
242dba1d918SMaxime Chevallier 
mvpp2_dbgfs_port_vid_show(struct seq_file * s,void * unused)24321da57a2SMaxime Chevallier static int mvpp2_dbgfs_port_vid_show(struct seq_file *s, void *unused)
24421da57a2SMaxime Chevallier {
24521da57a2SMaxime Chevallier 	struct mvpp2_port *port = s->private;
24621da57a2SMaxime Chevallier 	unsigned char byte[2], enable[2];
24721da57a2SMaxime Chevallier 	struct mvpp2 *priv = port->priv;
24821da57a2SMaxime Chevallier 	struct mvpp2_prs_entry pe;
24921da57a2SMaxime Chevallier 	unsigned long pmap;
25021da57a2SMaxime Chevallier 	u16 rvid;
25121da57a2SMaxime Chevallier 	int tid;
25221da57a2SMaxime Chevallier 
25321da57a2SMaxime Chevallier 	for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
25421da57a2SMaxime Chevallier 	     tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
25521da57a2SMaxime Chevallier 		mvpp2_prs_init_from_hw(priv, &pe, tid);
25621da57a2SMaxime Chevallier 
25721da57a2SMaxime Chevallier 		pmap = mvpp2_prs_tcam_port_map_get(&pe);
25821da57a2SMaxime Chevallier 
25921da57a2SMaxime Chevallier 		if (!priv->prs_shadow[tid].valid)
26021da57a2SMaxime Chevallier 			continue;
26121da57a2SMaxime Chevallier 
26221da57a2SMaxime Chevallier 		if (!test_bit(port->id, &pmap))
26321da57a2SMaxime Chevallier 			continue;
26421da57a2SMaxime Chevallier 
26521da57a2SMaxime Chevallier 		mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
26621da57a2SMaxime Chevallier 		mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
26721da57a2SMaxime Chevallier 
26821da57a2SMaxime Chevallier 		rvid = ((byte[0] & 0xf) << 8) + byte[1];
26921da57a2SMaxime Chevallier 
27021da57a2SMaxime Chevallier 		seq_printf(s, "%u\n", rvid);
27121da57a2SMaxime Chevallier 	}
27221da57a2SMaxime Chevallier 
27321da57a2SMaxime Chevallier 	return 0;
27421da57a2SMaxime Chevallier }
27521da57a2SMaxime Chevallier 
27621da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_vid);
27721da57a2SMaxime Chevallier 
mvpp2_dbgfs_port_parser_show(struct seq_file * s,void * unused)27821da57a2SMaxime Chevallier static int mvpp2_dbgfs_port_parser_show(struct seq_file *s, void *unused)
27921da57a2SMaxime Chevallier {
28021da57a2SMaxime Chevallier 	struct mvpp2_port *port = s->private;
28121da57a2SMaxime Chevallier 	struct mvpp2 *priv = port->priv;
28221da57a2SMaxime Chevallier 	struct mvpp2_prs_entry pe;
28321da57a2SMaxime Chevallier 	unsigned long pmap;
28421da57a2SMaxime Chevallier 	int i;
28521da57a2SMaxime Chevallier 
28621da57a2SMaxime Chevallier 	for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {
28721da57a2SMaxime Chevallier 		mvpp2_prs_init_from_hw(port->priv, &pe, i);
28821da57a2SMaxime Chevallier 
28921da57a2SMaxime Chevallier 		pmap = mvpp2_prs_tcam_port_map_get(&pe);
29021da57a2SMaxime Chevallier 		if (priv->prs_shadow[i].valid && test_bit(port->id, &pmap))
29121da57a2SMaxime Chevallier 			seq_printf(s, "%03d\n", i);
29221da57a2SMaxime Chevallier 	}
29321da57a2SMaxime Chevallier 
29421da57a2SMaxime Chevallier 	return 0;
29521da57a2SMaxime Chevallier }
29621da57a2SMaxime Chevallier 
29721da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_parser);
29821da57a2SMaxime Chevallier 
mvpp2_dbgfs_filter_show(struct seq_file * s,void * unused)29921da57a2SMaxime Chevallier static int mvpp2_dbgfs_filter_show(struct seq_file *s, void *unused)
30021da57a2SMaxime Chevallier {
30121da57a2SMaxime Chevallier 	struct mvpp2_port *port = s->private;
30221da57a2SMaxime Chevallier 	struct mvpp2 *priv = port->priv;
30321da57a2SMaxime Chevallier 	struct mvpp2_prs_entry pe;
30421da57a2SMaxime Chevallier 	unsigned long pmap;
30521da57a2SMaxime Chevallier 	int index, tid;
30621da57a2SMaxime Chevallier 
30721da57a2SMaxime Chevallier 	for (tid = MVPP2_PE_MAC_RANGE_START;
30821da57a2SMaxime Chevallier 	     tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
30921da57a2SMaxime Chevallier 		unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
31021da57a2SMaxime Chevallier 
31121da57a2SMaxime Chevallier 		if (!priv->prs_shadow[tid].valid ||
31221da57a2SMaxime Chevallier 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC ||
31321da57a2SMaxime Chevallier 		    priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF)
31421da57a2SMaxime Chevallier 			continue;
31521da57a2SMaxime Chevallier 
31621da57a2SMaxime Chevallier 		mvpp2_prs_init_from_hw(priv, &pe, tid);
31721da57a2SMaxime Chevallier 
31821da57a2SMaxime Chevallier 		pmap = mvpp2_prs_tcam_port_map_get(&pe);
31921da57a2SMaxime Chevallier 
32021da57a2SMaxime Chevallier 		/* We only want entries active on this port */
32121da57a2SMaxime Chevallier 		if (!test_bit(port->id, &pmap))
32221da57a2SMaxime Chevallier 			continue;
32321da57a2SMaxime Chevallier 
32421da57a2SMaxime Chevallier 		/* Read mac addr from entry */
32521da57a2SMaxime Chevallier 		for (index = 0; index < ETH_ALEN; index++)
32621da57a2SMaxime Chevallier 			mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],
32721da57a2SMaxime Chevallier 						     &da_mask[index]);
32821da57a2SMaxime Chevallier 
32921da57a2SMaxime Chevallier 		seq_printf(s, "%pM\n", da);
33021da57a2SMaxime Chevallier 	}
33121da57a2SMaxime Chevallier 
33221da57a2SMaxime Chevallier 	return 0;
33321da57a2SMaxime Chevallier }
33421da57a2SMaxime Chevallier 
33521da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_filter);
33621da57a2SMaxime Chevallier 
mvpp2_dbgfs_prs_lu_show(struct seq_file * s,void * unused)33721da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_lu_show(struct seq_file *s, void *unused)
33821da57a2SMaxime Chevallier {
33921da57a2SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry = s->private;
34021da57a2SMaxime Chevallier 	struct mvpp2 *priv = entry->priv;
34121da57a2SMaxime Chevallier 
34221da57a2SMaxime Chevallier 	seq_printf(s, "%x\n", priv->prs_shadow[entry->tid].lu);
34321da57a2SMaxime Chevallier 
34421da57a2SMaxime Chevallier 	return 0;
34521da57a2SMaxime Chevallier }
34621da57a2SMaxime Chevallier 
34721da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_lu);
34821da57a2SMaxime Chevallier 
mvpp2_dbgfs_prs_pmap_show(struct seq_file * s,void * unused)34921da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_pmap_show(struct seq_file *s, void *unused)
35021da57a2SMaxime Chevallier {
35121da57a2SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry = s->private;
35221da57a2SMaxime Chevallier 	struct mvpp2_prs_entry pe;
35321da57a2SMaxime Chevallier 	unsigned int pmap;
35421da57a2SMaxime Chevallier 
35521da57a2SMaxime Chevallier 	mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
35621da57a2SMaxime Chevallier 
35721da57a2SMaxime Chevallier 	pmap = mvpp2_prs_tcam_port_map_get(&pe);
35821da57a2SMaxime Chevallier 	pmap &= MVPP2_PRS_PORT_MASK;
35921da57a2SMaxime Chevallier 
36021da57a2SMaxime Chevallier 	seq_printf(s, "%02x\n", pmap);
36121da57a2SMaxime Chevallier 
36221da57a2SMaxime Chevallier 	return 0;
36321da57a2SMaxime Chevallier }
36421da57a2SMaxime Chevallier 
36521da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_pmap);
36621da57a2SMaxime Chevallier 
mvpp2_dbgfs_prs_ai_show(struct seq_file * s,void * unused)36721da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_ai_show(struct seq_file *s, void *unused)
36821da57a2SMaxime Chevallier {
36921da57a2SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry = s->private;
37021da57a2SMaxime Chevallier 	struct mvpp2_prs_entry pe;
37121da57a2SMaxime Chevallier 	unsigned char ai, ai_mask;
37221da57a2SMaxime Chevallier 
37321da57a2SMaxime Chevallier 	mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
37421da57a2SMaxime Chevallier 
37521da57a2SMaxime Chevallier 	ai = pe.tcam[MVPP2_PRS_TCAM_AI_WORD] & MVPP2_PRS_AI_MASK;
37621da57a2SMaxime Chevallier 	ai_mask = (pe.tcam[MVPP2_PRS_TCAM_AI_WORD] >> 16) & MVPP2_PRS_AI_MASK;
37721da57a2SMaxime Chevallier 
37821da57a2SMaxime Chevallier 	seq_printf(s, "%02x %02x\n", ai, ai_mask);
37921da57a2SMaxime Chevallier 
38021da57a2SMaxime Chevallier 	return 0;
38121da57a2SMaxime Chevallier }
38221da57a2SMaxime Chevallier 
38321da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_ai);
38421da57a2SMaxime Chevallier 
mvpp2_dbgfs_prs_hdata_show(struct seq_file * s,void * unused)38521da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_hdata_show(struct seq_file *s, void *unused)
38621da57a2SMaxime Chevallier {
38721da57a2SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry = s->private;
38821da57a2SMaxime Chevallier 	struct mvpp2_prs_entry pe;
38921da57a2SMaxime Chevallier 	unsigned char data[8], mask[8];
39021da57a2SMaxime Chevallier 	int i;
39121da57a2SMaxime Chevallier 
39221da57a2SMaxime Chevallier 	mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
39321da57a2SMaxime Chevallier 
39421da57a2SMaxime Chevallier 	for (i = 0; i < 8; i++)
39521da57a2SMaxime Chevallier 		mvpp2_prs_tcam_data_byte_get(&pe, i, &data[i], &mask[i]);
39621da57a2SMaxime Chevallier 
39721da57a2SMaxime Chevallier 	seq_printf(s, "%*phN %*phN\n", 8, data, 8, mask);
39821da57a2SMaxime Chevallier 
39921da57a2SMaxime Chevallier 	return 0;
40021da57a2SMaxime Chevallier }
40121da57a2SMaxime Chevallier 
40221da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hdata);
40321da57a2SMaxime Chevallier 
mvpp2_dbgfs_prs_sram_show(struct seq_file * s,void * unused)40421da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_sram_show(struct seq_file *s, void *unused)
40521da57a2SMaxime Chevallier {
40621da57a2SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry = s->private;
40721da57a2SMaxime Chevallier 	struct mvpp2_prs_entry pe;
40821da57a2SMaxime Chevallier 
40921da57a2SMaxime Chevallier 	mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
41021da57a2SMaxime Chevallier 
41121da57a2SMaxime Chevallier 	seq_printf(s, "%*phN\n", 14, pe.sram);
41221da57a2SMaxime Chevallier 
41321da57a2SMaxime Chevallier 	return 0;
41421da57a2SMaxime Chevallier }
41521da57a2SMaxime Chevallier 
41621da57a2SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_sram);
41721da57a2SMaxime Chevallier 
mvpp2_dbgfs_prs_hits_show(struct seq_file * s,void * unused)4181203341cSMaxime Chevallier static int mvpp2_dbgfs_prs_hits_show(struct seq_file *s, void *unused)
4191203341cSMaxime Chevallier {
4201203341cSMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry = s->private;
4211203341cSMaxime Chevallier 	int val;
4221203341cSMaxime Chevallier 
4231203341cSMaxime Chevallier 	val = mvpp2_prs_hits(entry->priv, entry->tid);
4241203341cSMaxime Chevallier 	if (val < 0)
4251203341cSMaxime Chevallier 		return val;
4261203341cSMaxime Chevallier 
4271203341cSMaxime Chevallier 	seq_printf(s, "%d\n", val);
4281203341cSMaxime Chevallier 
4291203341cSMaxime Chevallier 	return 0;
4301203341cSMaxime Chevallier }
4311203341cSMaxime Chevallier 
4321203341cSMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hits);
4331203341cSMaxime Chevallier 
mvpp2_dbgfs_prs_valid_show(struct seq_file * s,void * unused)43421da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_valid_show(struct seq_file *s, void *unused)
43521da57a2SMaxime Chevallier {
43621da57a2SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry = s->private;
43721da57a2SMaxime Chevallier 	struct mvpp2 *priv = entry->priv;
43821da57a2SMaxime Chevallier 	int tid = entry->tid;
43921da57a2SMaxime Chevallier 
44021da57a2SMaxime Chevallier 	seq_printf(s, "%d\n", priv->prs_shadow[tid].valid ? 1 : 0);
44121da57a2SMaxime Chevallier 
44221da57a2SMaxime Chevallier 	return 0;
44321da57a2SMaxime Chevallier }
44421da57a2SMaxime Chevallier 
4457cb5e368SMaxime Chevallier DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_valid);
44621da57a2SMaxime Chevallier 
mvpp2_dbgfs_flow_port_init(struct dentry * parent,struct mvpp2_port * port,struct mvpp2_dbgfs_flow_entry * entry)447dba1d918SMaxime Chevallier static int mvpp2_dbgfs_flow_port_init(struct dentry *parent,
448dba1d918SMaxime Chevallier 				      struct mvpp2_port *port,
449dba1d918SMaxime Chevallier 				      struct mvpp2_dbgfs_flow_entry *entry)
450dba1d918SMaxime Chevallier {
451dba1d918SMaxime Chevallier 	struct mvpp2_dbgfs_port_flow_entry *port_entry;
452dba1d918SMaxime Chevallier 	struct dentry *port_dir;
453dba1d918SMaxime Chevallier 
454dba1d918SMaxime Chevallier 	port_dir = debugfs_create_dir(port->dev->name, parent);
455dba1d918SMaxime Chevallier 
4567cb5e368SMaxime Chevallier 	port_entry = &port->priv->dbgfs_entries->port_flow_entries[port->id];
457dba1d918SMaxime Chevallier 
458dba1d918SMaxime Chevallier 	port_entry->port = port;
459dba1d918SMaxime Chevallier 	port_entry->dbg_fe = entry;
460dba1d918SMaxime Chevallier 
461dba1d918SMaxime Chevallier 	debugfs_create_file("hash_opts", 0444, port_dir, port_entry,
462dba1d918SMaxime Chevallier 			    &mvpp2_dbgfs_port_flow_hash_opt_fops);
463dba1d918SMaxime Chevallier 
464dba1d918SMaxime Chevallier 	debugfs_create_file("engine", 0444, port_dir, port_entry,
465dba1d918SMaxime Chevallier 			    &mvpp2_dbgfs_port_flow_engine_fops);
466dba1d918SMaxime Chevallier 
467dba1d918SMaxime Chevallier 	return 0;
468dba1d918SMaxime Chevallier }
469dba1d918SMaxime Chevallier 
mvpp2_dbgfs_flow_entry_init(struct dentry * parent,struct mvpp2 * priv,int flow)470dba1d918SMaxime Chevallier static int mvpp2_dbgfs_flow_entry_init(struct dentry *parent,
471dba1d918SMaxime Chevallier 				       struct mvpp2 *priv, int flow)
472dba1d918SMaxime Chevallier {
473dba1d918SMaxime Chevallier 	struct mvpp2_dbgfs_flow_entry *entry;
474dba1d918SMaxime Chevallier 	struct dentry *flow_entry_dir;
475dba1d918SMaxime Chevallier 	char flow_entry_name[10];
476dba1d918SMaxime Chevallier 	int i, ret;
477dba1d918SMaxime Chevallier 
478dba1d918SMaxime Chevallier 	sprintf(flow_entry_name, "%02d", flow);
479dba1d918SMaxime Chevallier 
480dba1d918SMaxime Chevallier 	flow_entry_dir = debugfs_create_dir(flow_entry_name, parent);
481dba1d918SMaxime Chevallier 
4827cb5e368SMaxime Chevallier 	entry = &priv->dbgfs_entries->flow_entries[flow];
483dba1d918SMaxime Chevallier 
484dba1d918SMaxime Chevallier 	entry->flow = flow;
485dba1d918SMaxime Chevallier 	entry->priv = priv;
486dba1d918SMaxime Chevallier 
487f9d30d5bSMaxime Chevallier 	debugfs_create_file("dec_hits", 0444, flow_entry_dir, entry,
488f9d30d5bSMaxime Chevallier 			    &mvpp2_dbgfs_flow_dec_hits_fops);
489f9d30d5bSMaxime Chevallier 
490dba1d918SMaxime Chevallier 	debugfs_create_file("type", 0444, flow_entry_dir, entry,
491dba1d918SMaxime Chevallier 			    &mvpp2_dbgfs_flow_type_fops);
492dba1d918SMaxime Chevallier 
493dba1d918SMaxime Chevallier 	debugfs_create_file("id", 0444, flow_entry_dir, entry,
494dba1d918SMaxime Chevallier 			    &mvpp2_dbgfs_flow_id_fops);
495dba1d918SMaxime Chevallier 
496dba1d918SMaxime Chevallier 	/* Create entry for each port */
497dba1d918SMaxime Chevallier 	for (i = 0; i < priv->port_count; i++) {
498dba1d918SMaxime Chevallier 		ret = mvpp2_dbgfs_flow_port_init(flow_entry_dir,
499dba1d918SMaxime Chevallier 						 priv->port_list[i], entry);
500dba1d918SMaxime Chevallier 		if (ret)
501dba1d918SMaxime Chevallier 			return ret;
502dba1d918SMaxime Chevallier 	}
503b607cc61SMaxime Chevallier 
504dba1d918SMaxime Chevallier 	return 0;
505dba1d918SMaxime Chevallier }
506dba1d918SMaxime Chevallier 
mvpp2_dbgfs_flow_init(struct dentry * parent,struct mvpp2 * priv)507dba1d918SMaxime Chevallier static int mvpp2_dbgfs_flow_init(struct dentry *parent, struct mvpp2 *priv)
508dba1d918SMaxime Chevallier {
509dba1d918SMaxime Chevallier 	struct dentry *flow_dir;
510dba1d918SMaxime Chevallier 	int i, ret;
511dba1d918SMaxime Chevallier 
512dba1d918SMaxime Chevallier 	flow_dir = debugfs_create_dir("flows", parent);
513dba1d918SMaxime Chevallier 
51493c2589cSMaxime Chevallier 	for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) {
515dba1d918SMaxime Chevallier 		ret = mvpp2_dbgfs_flow_entry_init(flow_dir, priv, i);
516dba1d918SMaxime Chevallier 		if (ret)
517dba1d918SMaxime Chevallier 			return ret;
518dba1d918SMaxime Chevallier 	}
519dba1d918SMaxime Chevallier 
520dba1d918SMaxime Chevallier 	return 0;
521dba1d918SMaxime Chevallier }
522dba1d918SMaxime Chevallier 
mvpp2_dbgfs_prs_entry_init(struct dentry * parent,struct mvpp2 * priv,int tid)52321da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_entry_init(struct dentry *parent,
52421da57a2SMaxime Chevallier 				      struct mvpp2 *priv, int tid)
52521da57a2SMaxime Chevallier {
52621da57a2SMaxime Chevallier 	struct mvpp2_dbgfs_prs_entry *entry;
52721da57a2SMaxime Chevallier 	struct dentry *prs_entry_dir;
52821da57a2SMaxime Chevallier 	char prs_entry_name[10];
52921da57a2SMaxime Chevallier 
53021da57a2SMaxime Chevallier 	if (tid >= MVPP2_PRS_TCAM_SRAM_SIZE)
53121da57a2SMaxime Chevallier 		return -EINVAL;
53221da57a2SMaxime Chevallier 
53321da57a2SMaxime Chevallier 	sprintf(prs_entry_name, "%03d", tid);
53421da57a2SMaxime Chevallier 
53521da57a2SMaxime Chevallier 	prs_entry_dir = debugfs_create_dir(prs_entry_name, parent);
53621da57a2SMaxime Chevallier 
5377cb5e368SMaxime Chevallier 	entry = &priv->dbgfs_entries->prs_entries[tid];
53821da57a2SMaxime Chevallier 
53921da57a2SMaxime Chevallier 	entry->tid = tid;
54021da57a2SMaxime Chevallier 	entry->priv = priv;
54121da57a2SMaxime Chevallier 
54221da57a2SMaxime Chevallier 	/* Create each attr */
54321da57a2SMaxime Chevallier 	debugfs_create_file("sram", 0444, prs_entry_dir, entry,
54421da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_prs_sram_fops);
54521da57a2SMaxime Chevallier 
54621da57a2SMaxime Chevallier 	debugfs_create_file("valid", 0644, prs_entry_dir, entry,
54721da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_prs_valid_fops);
54821da57a2SMaxime Chevallier 
54921da57a2SMaxime Chevallier 	debugfs_create_file("lookup_id", 0644, prs_entry_dir, entry,
55021da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_prs_lu_fops);
55121da57a2SMaxime Chevallier 
55221da57a2SMaxime Chevallier 	debugfs_create_file("ai", 0644, prs_entry_dir, entry,
55321da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_prs_ai_fops);
55421da57a2SMaxime Chevallier 
55521da57a2SMaxime Chevallier 	debugfs_create_file("header_data", 0644, prs_entry_dir, entry,
55621da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_prs_hdata_fops);
55721da57a2SMaxime Chevallier 
5581203341cSMaxime Chevallier 	debugfs_create_file("hits", 0444, prs_entry_dir, entry,
5591203341cSMaxime Chevallier 			    &mvpp2_dbgfs_prs_hits_fops);
5601203341cSMaxime Chevallier 
5618110a7a7SNathan Huckleberry 	debugfs_create_file("pmap", 0444, prs_entry_dir, entry,
5628110a7a7SNathan Huckleberry 			     &mvpp2_dbgfs_prs_pmap_fops);
5638110a7a7SNathan Huckleberry 
56421da57a2SMaxime Chevallier 	return 0;
56521da57a2SMaxime Chevallier }
56621da57a2SMaxime Chevallier 
mvpp2_dbgfs_prs_init(struct dentry * parent,struct mvpp2 * priv)56721da57a2SMaxime Chevallier static int mvpp2_dbgfs_prs_init(struct dentry *parent, struct mvpp2 *priv)
56821da57a2SMaxime Chevallier {
56921da57a2SMaxime Chevallier 	struct dentry *prs_dir;
57021da57a2SMaxime Chevallier 	int i, ret;
57121da57a2SMaxime Chevallier 
57221da57a2SMaxime Chevallier 	prs_dir = debugfs_create_dir("parser", parent);
57321da57a2SMaxime Chevallier 
57421da57a2SMaxime Chevallier 	for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {
57521da57a2SMaxime Chevallier 		ret = mvpp2_dbgfs_prs_entry_init(prs_dir, priv, i);
57621da57a2SMaxime Chevallier 		if (ret)
57721da57a2SMaxime Chevallier 			return ret;
57821da57a2SMaxime Chevallier 	}
57921da57a2SMaxime Chevallier 
58021da57a2SMaxime Chevallier 	return 0;
58121da57a2SMaxime Chevallier }
58221da57a2SMaxime Chevallier 
mvpp2_dbgfs_c2_entry_init(struct dentry * parent,struct mvpp2 * priv,int id)583b607cc61SMaxime Chevallier static int mvpp2_dbgfs_c2_entry_init(struct dentry *parent,
584b607cc61SMaxime Chevallier 				     struct mvpp2 *priv, int id)
585b607cc61SMaxime Chevallier {
586b607cc61SMaxime Chevallier 	struct mvpp2_dbgfs_c2_entry *entry;
587b607cc61SMaxime Chevallier 	struct dentry *c2_entry_dir;
588b607cc61SMaxime Chevallier 	char c2_entry_name[10];
589b607cc61SMaxime Chevallier 
590b607cc61SMaxime Chevallier 	if (id >= MVPP22_CLS_C2_N_ENTRIES)
591b607cc61SMaxime Chevallier 		return -EINVAL;
592b607cc61SMaxime Chevallier 
593b607cc61SMaxime Chevallier 	sprintf(c2_entry_name, "%03d", id);
594b607cc61SMaxime Chevallier 
595b607cc61SMaxime Chevallier 	c2_entry_dir = debugfs_create_dir(c2_entry_name, parent);
596b607cc61SMaxime Chevallier 
597b607cc61SMaxime Chevallier 	entry = &priv->dbgfs_entries->c2_entries[id];
598b607cc61SMaxime Chevallier 
599b607cc61SMaxime Chevallier 	entry->id = id;
600b607cc61SMaxime Chevallier 	entry->priv = priv;
601b607cc61SMaxime Chevallier 
602b607cc61SMaxime Chevallier 	debugfs_create_file("hits", 0444, c2_entry_dir, entry,
603b607cc61SMaxime Chevallier 			    &mvpp2_dbgfs_flow_c2_hits_fops);
604b607cc61SMaxime Chevallier 
605b607cc61SMaxime Chevallier 	debugfs_create_file("default_rxq", 0444, c2_entry_dir, entry,
606b607cc61SMaxime Chevallier 			    &mvpp2_dbgfs_flow_c2_rxq_fops);
607b607cc61SMaxime Chevallier 
608b607cc61SMaxime Chevallier 	debugfs_create_file("rss_enable", 0444, c2_entry_dir, entry,
609b607cc61SMaxime Chevallier 			    &mvpp2_dbgfs_flow_c2_enable_fops);
610b607cc61SMaxime Chevallier 
611b607cc61SMaxime Chevallier 	return 0;
612b607cc61SMaxime Chevallier }
613b607cc61SMaxime Chevallier 
mvpp2_dbgfs_flow_tbl_entry_init(struct dentry * parent,struct mvpp2 * priv,int id)6148aa65106SMaxime Chevallier static int mvpp2_dbgfs_flow_tbl_entry_init(struct dentry *parent,
6158aa65106SMaxime Chevallier 					   struct mvpp2 *priv, int id)
6168aa65106SMaxime Chevallier {
6178aa65106SMaxime Chevallier 	struct mvpp2_dbgfs_flow_tbl_entry *entry;
6188aa65106SMaxime Chevallier 	struct dentry *flow_tbl_entry_dir;
6198aa65106SMaxime Chevallier 	char flow_tbl_entry_name[10];
6208aa65106SMaxime Chevallier 
6218aa65106SMaxime Chevallier 	if (id >= MVPP2_CLS_FLOWS_TBL_SIZE)
6228aa65106SMaxime Chevallier 		return -EINVAL;
6238aa65106SMaxime Chevallier 
6248aa65106SMaxime Chevallier 	sprintf(flow_tbl_entry_name, "%03d", id);
6258aa65106SMaxime Chevallier 
6268aa65106SMaxime Chevallier 	flow_tbl_entry_dir = debugfs_create_dir(flow_tbl_entry_name, parent);
6278aa65106SMaxime Chevallier 
6288aa65106SMaxime Chevallier 	entry = &priv->dbgfs_entries->flt_entries[id];
6298aa65106SMaxime Chevallier 
6308aa65106SMaxime Chevallier 	entry->id = id;
6318aa65106SMaxime Chevallier 	entry->priv = priv;
6328aa65106SMaxime Chevallier 
6338aa65106SMaxime Chevallier 	debugfs_create_file("hits", 0444, flow_tbl_entry_dir, entry,
6348aa65106SMaxime Chevallier 			    &mvpp2_dbgfs_flow_flt_hits_fops);
6358aa65106SMaxime Chevallier 
6368aa65106SMaxime Chevallier 	return 0;
6378aa65106SMaxime Chevallier }
6388aa65106SMaxime Chevallier 
mvpp2_dbgfs_cls_init(struct dentry * parent,struct mvpp2 * priv)6398aa65106SMaxime Chevallier static int mvpp2_dbgfs_cls_init(struct dentry *parent, struct mvpp2 *priv)
6408aa65106SMaxime Chevallier {
641b607cc61SMaxime Chevallier 	struct dentry *cls_dir, *c2_dir, *flow_tbl_dir;
6428aa65106SMaxime Chevallier 	int i, ret;
6438aa65106SMaxime Chevallier 
6448aa65106SMaxime Chevallier 	cls_dir = debugfs_create_dir("classifier", parent);
6458aa65106SMaxime Chevallier 
646b607cc61SMaxime Chevallier 	c2_dir = debugfs_create_dir("c2", cls_dir);
647b607cc61SMaxime Chevallier 
648b607cc61SMaxime Chevallier 	for (i = 0; i < MVPP22_CLS_C2_N_ENTRIES; i++) {
649b607cc61SMaxime Chevallier 		ret = mvpp2_dbgfs_c2_entry_init(c2_dir, priv, i);
650b607cc61SMaxime Chevallier 		if (ret)
651b607cc61SMaxime Chevallier 			return ret;
652b607cc61SMaxime Chevallier 	}
653b607cc61SMaxime Chevallier 
6548aa65106SMaxime Chevallier 	flow_tbl_dir = debugfs_create_dir("flow_table", cls_dir);
6558aa65106SMaxime Chevallier 
6568aa65106SMaxime Chevallier 	for (i = 0; i < MVPP2_CLS_FLOWS_TBL_SIZE; i++) {
6578aa65106SMaxime Chevallier 		ret = mvpp2_dbgfs_flow_tbl_entry_init(flow_tbl_dir, priv, i);
6588aa65106SMaxime Chevallier 		if (ret)
6598aa65106SMaxime Chevallier 			return ret;
6608aa65106SMaxime Chevallier 	}
6618aa65106SMaxime Chevallier 
6628aa65106SMaxime Chevallier 	return 0;
6638aa65106SMaxime Chevallier }
6648aa65106SMaxime Chevallier 
mvpp2_dbgfs_port_init(struct dentry * parent,struct mvpp2_port * port)66521da57a2SMaxime Chevallier static int mvpp2_dbgfs_port_init(struct dentry *parent,
66621da57a2SMaxime Chevallier 				 struct mvpp2_port *port)
66721da57a2SMaxime Chevallier {
66821da57a2SMaxime Chevallier 	struct dentry *port_dir;
66921da57a2SMaxime Chevallier 
67021da57a2SMaxime Chevallier 	port_dir = debugfs_create_dir(port->dev->name, parent);
67121da57a2SMaxime Chevallier 
67221da57a2SMaxime Chevallier 	debugfs_create_file("parser_entries", 0444, port_dir, port,
67321da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_port_parser_fops);
67421da57a2SMaxime Chevallier 
67521da57a2SMaxime Chevallier 	debugfs_create_file("mac_filter", 0444, port_dir, port,
67621da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_filter_fops);
67721da57a2SMaxime Chevallier 
67821da57a2SMaxime Chevallier 	debugfs_create_file("vid_filter", 0444, port_dir, port,
67921da57a2SMaxime Chevallier 			    &mvpp2_dbgfs_port_vid_fops);
68021da57a2SMaxime Chevallier 
68121da57a2SMaxime Chevallier 	return 0;
68221da57a2SMaxime Chevallier }
68321da57a2SMaxime Chevallier 
684*0152dfeeSRussell King (Oracle) static struct dentry *mvpp2_root;
685*0152dfeeSRussell King (Oracle) 
mvpp2_dbgfs_exit(void)686*0152dfeeSRussell King (Oracle) void mvpp2_dbgfs_exit(void)
687*0152dfeeSRussell King (Oracle) {
688*0152dfeeSRussell King (Oracle) 	debugfs_remove(mvpp2_root);
689*0152dfeeSRussell King (Oracle) }
690*0152dfeeSRussell King (Oracle) 
mvpp2_dbgfs_cleanup(struct mvpp2 * priv)69121da57a2SMaxime Chevallier void mvpp2_dbgfs_cleanup(struct mvpp2 *priv)
69221da57a2SMaxime Chevallier {
69321da57a2SMaxime Chevallier 	debugfs_remove_recursive(priv->dbgfs_dir);
6947cb5e368SMaxime Chevallier 
6957cb5e368SMaxime Chevallier 	kfree(priv->dbgfs_entries);
69621da57a2SMaxime Chevallier }
69721da57a2SMaxime Chevallier 
mvpp2_dbgfs_init(struct mvpp2 * priv,const char * name)69821da57a2SMaxime Chevallier void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name)
69921da57a2SMaxime Chevallier {
700*0152dfeeSRussell King (Oracle) 	struct dentry *mvpp2_dir;
70121da57a2SMaxime Chevallier 	int ret, i;
70221da57a2SMaxime Chevallier 
703e6882aa6SGreg Kroah-Hartman 	if (!mvpp2_root)
70421da57a2SMaxime Chevallier 		mvpp2_root = debugfs_create_dir(MVPP2_DRIVER_NAME, NULL);
70521da57a2SMaxime Chevallier 
70621da57a2SMaxime Chevallier 	mvpp2_dir = debugfs_create_dir(name, mvpp2_root);
70721da57a2SMaxime Chevallier 
70821da57a2SMaxime Chevallier 	priv->dbgfs_dir = mvpp2_dir;
7097cb5e368SMaxime Chevallier 	priv->dbgfs_entries = kzalloc(sizeof(*priv->dbgfs_entries), GFP_KERNEL);
7107cb5e368SMaxime Chevallier 	if (!priv->dbgfs_entries)
7117cb5e368SMaxime Chevallier 		goto err;
71221da57a2SMaxime Chevallier 
71321da57a2SMaxime Chevallier 	ret = mvpp2_dbgfs_prs_init(mvpp2_dir, priv);
71421da57a2SMaxime Chevallier 	if (ret)
71521da57a2SMaxime Chevallier 		goto err;
71621da57a2SMaxime Chevallier 
7178aa65106SMaxime Chevallier 	ret = mvpp2_dbgfs_cls_init(mvpp2_dir, priv);
7188aa65106SMaxime Chevallier 	if (ret)
7198aa65106SMaxime Chevallier 		goto err;
7208aa65106SMaxime Chevallier 
72121da57a2SMaxime Chevallier 	for (i = 0; i < priv->port_count; i++) {
72221da57a2SMaxime Chevallier 		ret = mvpp2_dbgfs_port_init(mvpp2_dir, priv->port_list[i]);
72321da57a2SMaxime Chevallier 		if (ret)
72421da57a2SMaxime Chevallier 			goto err;
72521da57a2SMaxime Chevallier 	}
72621da57a2SMaxime Chevallier 
727dba1d918SMaxime Chevallier 	ret = mvpp2_dbgfs_flow_init(mvpp2_dir, priv);
728dba1d918SMaxime Chevallier 	if (ret)
729dba1d918SMaxime Chevallier 		goto err;
730dba1d918SMaxime Chevallier 
73121da57a2SMaxime Chevallier 	return;
73221da57a2SMaxime Chevallier err:
73321da57a2SMaxime Chevallier 	mvpp2_dbgfs_cleanup(priv);
73421da57a2SMaxime Chevallier }
735