mvpp2_debugfs.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for Marvell PPv2 network controller for Armada 375 SoC.
  4. *
  5. * Copyright (C) 2018 Marvell
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/slab.h>
  9. #include <linux/debugfs.h>
  10. #include "mvpp2.h"
  11. #include "mvpp2_prs.h"
  12. #include "mvpp2_cls.h"
  13. struct mvpp2_dbgfs_prs_entry {
  14. int tid;
  15. struct mvpp2 *priv;
  16. };
  17. struct mvpp2_dbgfs_c2_entry {
  18. int id;
  19. struct mvpp2 *priv;
  20. };
  21. struct mvpp2_dbgfs_flow_entry {
  22. int flow;
  23. struct mvpp2 *priv;
  24. };
  25. struct mvpp2_dbgfs_flow_tbl_entry {
  26. int id;
  27. struct mvpp2 *priv;
  28. };
  29. struct mvpp2_dbgfs_port_flow_entry {
  30. struct mvpp2_port *port;
  31. struct mvpp2_dbgfs_flow_entry *dbg_fe;
  32. };
  33. struct mvpp2_dbgfs_entries {
  34. /* Entries for Header Parser debug info */
  35. struct mvpp2_dbgfs_prs_entry prs_entries[MVPP2_PRS_TCAM_SRAM_SIZE];
  36. /* Entries for Classifier C2 engine debug info */
  37. struct mvpp2_dbgfs_c2_entry c2_entries[MVPP22_CLS_C2_N_ENTRIES];
  38. /* Entries for Classifier Flow Table debug info */
  39. struct mvpp2_dbgfs_flow_tbl_entry flt_entries[MVPP2_CLS_FLOWS_TBL_SIZE];
  40. /* Entries for Classifier flows debug info */
  41. struct mvpp2_dbgfs_flow_entry flow_entries[MVPP2_N_PRS_FLOWS];
  42. /* Entries for per-port flows debug info */
  43. struct mvpp2_dbgfs_port_flow_entry port_flow_entries[MVPP2_MAX_PORTS];
  44. };
  45. static int mvpp2_dbgfs_flow_flt_hits_show(struct seq_file *s, void *unused)
  46. {
  47. struct mvpp2_dbgfs_flow_tbl_entry *entry = s->private;
  48. u32 hits = mvpp2_cls_flow_hits(entry->priv, entry->id);
  49. seq_printf(s, "%u\n", hits);
  50. return 0;
  51. }
  52. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_flt_hits);
  53. static int mvpp2_dbgfs_flow_dec_hits_show(struct seq_file *s, void *unused)
  54. {
  55. struct mvpp2_dbgfs_flow_entry *entry = s->private;
  56. u32 hits = mvpp2_cls_lookup_hits(entry->priv, entry->flow);
  57. seq_printf(s, "%u\n", hits);
  58. return 0;
  59. }
  60. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_dec_hits);
  61. static int mvpp2_dbgfs_flow_type_show(struct seq_file *s, void *unused)
  62. {
  63. struct mvpp2_dbgfs_flow_entry *entry = s->private;
  64. const struct mvpp2_cls_flow *f;
  65. const char *flow_name;
  66. f = mvpp2_cls_flow_get(entry->flow);
  67. if (!f)
  68. return -EINVAL;
  69. switch (f->flow_type) {
  70. case IPV4_FLOW:
  71. flow_name = "ipv4";
  72. break;
  73. case IPV6_FLOW:
  74. flow_name = "ipv6";
  75. break;
  76. case TCP_V4_FLOW:
  77. flow_name = "tcp4";
  78. break;
  79. case TCP_V6_FLOW:
  80. flow_name = "tcp6";
  81. break;
  82. case UDP_V4_FLOW:
  83. flow_name = "udp4";
  84. break;
  85. case UDP_V6_FLOW:
  86. flow_name = "udp6";
  87. break;
  88. default:
  89. flow_name = "other";
  90. }
  91. seq_printf(s, "%s\n", flow_name);
  92. return 0;
  93. }
  94. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_type);
  95. static int mvpp2_dbgfs_flow_id_show(struct seq_file *s, void *unused)
  96. {
  97. const struct mvpp2_dbgfs_flow_entry *entry = s->private;
  98. const struct mvpp2_cls_flow *f;
  99. f = mvpp2_cls_flow_get(entry->flow);
  100. if (!f)
  101. return -EINVAL;
  102. seq_printf(s, "%d\n", f->flow_id);
  103. return 0;
  104. }
  105. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_id);
  106. static int mvpp2_dbgfs_port_flow_hash_opt_show(struct seq_file *s, void *unused)
  107. {
  108. struct mvpp2_dbgfs_port_flow_entry *entry = s->private;
  109. struct mvpp2_port *port = entry->port;
  110. struct mvpp2_cls_flow_entry fe;
  111. const struct mvpp2_cls_flow *f;
  112. int flow_index;
  113. u16 hash_opts;
  114. f = mvpp2_cls_flow_get(entry->dbg_fe->flow);
  115. if (!f)
  116. return -EINVAL;
  117. flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);
  118. mvpp2_cls_flow_read(port->priv, flow_index, &fe);
  119. hash_opts = mvpp2_flow_get_hek_fields(&fe);
  120. seq_printf(s, "0x%04x\n", hash_opts);
  121. return 0;
  122. }
  123. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_hash_opt);
  124. static int mvpp2_dbgfs_port_flow_engine_show(struct seq_file *s, void *unused)
  125. {
  126. struct mvpp2_dbgfs_port_flow_entry *entry = s->private;
  127. struct mvpp2_port *port = entry->port;
  128. struct mvpp2_cls_flow_entry fe;
  129. const struct mvpp2_cls_flow *f;
  130. int flow_index, engine;
  131. f = mvpp2_cls_flow_get(entry->dbg_fe->flow);
  132. if (!f)
  133. return -EINVAL;
  134. flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);
  135. mvpp2_cls_flow_read(port->priv, flow_index, &fe);
  136. engine = mvpp2_cls_flow_eng_get(&fe);
  137. seq_printf(s, "%d\n", engine);
  138. return 0;
  139. }
  140. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_engine);
  141. static int mvpp2_dbgfs_flow_c2_hits_show(struct seq_file *s, void *unused)
  142. {
  143. struct mvpp2_dbgfs_c2_entry *entry = s->private;
  144. u32 hits;
  145. hits = mvpp2_cls_c2_hit_count(entry->priv, entry->id);
  146. seq_printf(s, "%u\n", hits);
  147. return 0;
  148. }
  149. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_hits);
  150. static int mvpp2_dbgfs_flow_c2_rxq_show(struct seq_file *s, void *unused)
  151. {
  152. struct mvpp2_dbgfs_c2_entry *entry = s->private;
  153. struct mvpp2_cls_c2_entry c2;
  154. u8 qh, ql;
  155. mvpp2_cls_c2_read(entry->priv, entry->id, &c2);
  156. qh = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QHIGH_OFFS) &
  157. MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
  158. ql = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QLOW_OFFS) &
  159. MVPP22_CLS_C2_ATTR0_QLOW_MASK;
  160. seq_printf(s, "%d\n", (qh << 3 | ql));
  161. return 0;
  162. }
  163. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_rxq);
  164. static int mvpp2_dbgfs_flow_c2_enable_show(struct seq_file *s, void *unused)
  165. {
  166. struct mvpp2_dbgfs_c2_entry *entry = s->private;
  167. struct mvpp2_cls_c2_entry c2;
  168. int enabled;
  169. mvpp2_cls_c2_read(entry->priv, entry->id, &c2);
  170. enabled = !!(c2.attr[2] & MVPP22_CLS_C2_ATTR2_RSS_EN);
  171. seq_printf(s, "%d\n", enabled);
  172. return 0;
  173. }
  174. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_enable);
  175. static int mvpp2_dbgfs_port_vid_show(struct seq_file *s, void *unused)
  176. {
  177. struct mvpp2_port *port = s->private;
  178. unsigned char byte[2], enable[2];
  179. struct mvpp2 *priv = port->priv;
  180. struct mvpp2_prs_entry pe;
  181. unsigned long pmap;
  182. u16 rvid;
  183. int tid;
  184. for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
  185. tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
  186. mvpp2_prs_init_from_hw(priv, &pe, tid);
  187. pmap = mvpp2_prs_tcam_port_map_get(&pe);
  188. if (!priv->prs_shadow[tid].valid)
  189. continue;
  190. if (!test_bit(port->id, &pmap))
  191. continue;
  192. mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
  193. mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
  194. rvid = ((byte[0] & 0xf) << 8) + byte[1];
  195. seq_printf(s, "%u\n", rvid);
  196. }
  197. return 0;
  198. }
  199. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_vid);
  200. static int mvpp2_dbgfs_port_parser_show(struct seq_file *s, void *unused)
  201. {
  202. struct mvpp2_port *port = s->private;
  203. struct mvpp2 *priv = port->priv;
  204. struct mvpp2_prs_entry pe;
  205. unsigned long pmap;
  206. int i;
  207. for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {
  208. mvpp2_prs_init_from_hw(port->priv, &pe, i);
  209. pmap = mvpp2_prs_tcam_port_map_get(&pe);
  210. if (priv->prs_shadow[i].valid && test_bit(port->id, &pmap))
  211. seq_printf(s, "%03d\n", i);
  212. }
  213. return 0;
  214. }
  215. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_parser);
  216. static int mvpp2_dbgfs_filter_show(struct seq_file *s, void *unused)
  217. {
  218. struct mvpp2_port *port = s->private;
  219. struct mvpp2 *priv = port->priv;
  220. struct mvpp2_prs_entry pe;
  221. unsigned long pmap;
  222. int index, tid;
  223. for (tid = MVPP2_PE_MAC_RANGE_START;
  224. tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
  225. unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
  226. if (!priv->prs_shadow[tid].valid ||
  227. priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC ||
  228. priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF)
  229. continue;
  230. mvpp2_prs_init_from_hw(priv, &pe, tid);
  231. pmap = mvpp2_prs_tcam_port_map_get(&pe);
  232. /* We only want entries active on this port */
  233. if (!test_bit(port->id, &pmap))
  234. continue;
  235. /* Read mac addr from entry */
  236. for (index = 0; index < ETH_ALEN; index++)
  237. mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],
  238. &da_mask[index]);
  239. seq_printf(s, "%pM\n", da);
  240. }
  241. return 0;
  242. }
  243. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_filter);
  244. static int mvpp2_dbgfs_prs_lu_show(struct seq_file *s, void *unused)
  245. {
  246. struct mvpp2_dbgfs_prs_entry *entry = s->private;
  247. struct mvpp2 *priv = entry->priv;
  248. seq_printf(s, "%x\n", priv->prs_shadow[entry->tid].lu);
  249. return 0;
  250. }
  251. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_lu);
  252. static int mvpp2_dbgfs_prs_pmap_show(struct seq_file *s, void *unused)
  253. {
  254. struct mvpp2_dbgfs_prs_entry *entry = s->private;
  255. struct mvpp2_prs_entry pe;
  256. unsigned int pmap;
  257. mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
  258. pmap = mvpp2_prs_tcam_port_map_get(&pe);
  259. pmap &= MVPP2_PRS_PORT_MASK;
  260. seq_printf(s, "%02x\n", pmap);
  261. return 0;
  262. }
  263. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_pmap);
  264. static int mvpp2_dbgfs_prs_ai_show(struct seq_file *s, void *unused)
  265. {
  266. struct mvpp2_dbgfs_prs_entry *entry = s->private;
  267. struct mvpp2_prs_entry pe;
  268. unsigned char ai, ai_mask;
  269. mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
  270. ai = pe.tcam[MVPP2_PRS_TCAM_AI_WORD] & MVPP2_PRS_AI_MASK;
  271. ai_mask = (pe.tcam[MVPP2_PRS_TCAM_AI_WORD] >> 16) & MVPP2_PRS_AI_MASK;
  272. seq_printf(s, "%02x %02x\n", ai, ai_mask);
  273. return 0;
  274. }
  275. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_ai);
  276. static int mvpp2_dbgfs_prs_hdata_show(struct seq_file *s, void *unused)
  277. {
  278. struct mvpp2_dbgfs_prs_entry *entry = s->private;
  279. struct mvpp2_prs_entry pe;
  280. unsigned char data[8], mask[8];
  281. int i;
  282. mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
  283. for (i = 0; i < 8; i++)
  284. mvpp2_prs_tcam_data_byte_get(&pe, i, &data[i], &mask[i]);
  285. seq_printf(s, "%*phN %*phN\n", 8, data, 8, mask);
  286. return 0;
  287. }
  288. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hdata);
  289. static int mvpp2_dbgfs_prs_sram_show(struct seq_file *s, void *unused)
  290. {
  291. struct mvpp2_dbgfs_prs_entry *entry = s->private;
  292. struct mvpp2_prs_entry pe;
  293. mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
  294. seq_printf(s, "%*phN\n", 14, pe.sram);
  295. return 0;
  296. }
  297. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_sram);
  298. static int mvpp2_dbgfs_prs_hits_show(struct seq_file *s, void *unused)
  299. {
  300. struct mvpp2_dbgfs_prs_entry *entry = s->private;
  301. int val;
  302. val = mvpp2_prs_hits(entry->priv, entry->tid);
  303. if (val < 0)
  304. return val;
  305. seq_printf(s, "%d\n", val);
  306. return 0;
  307. }
  308. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hits);
  309. static int mvpp2_dbgfs_prs_valid_show(struct seq_file *s, void *unused)
  310. {
  311. struct mvpp2_dbgfs_prs_entry *entry = s->private;
  312. struct mvpp2 *priv = entry->priv;
  313. int tid = entry->tid;
  314. seq_printf(s, "%d\n", priv->prs_shadow[tid].valid ? 1 : 0);
  315. return 0;
  316. }
  317. DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_valid);
  318. static int mvpp2_dbgfs_flow_port_init(struct dentry *parent,
  319. struct mvpp2_port *port,
  320. struct mvpp2_dbgfs_flow_entry *entry)
  321. {
  322. struct mvpp2_dbgfs_port_flow_entry *port_entry;
  323. struct dentry *port_dir;
  324. port_dir = debugfs_create_dir(port->dev->name, parent);
  325. port_entry = &port->priv->dbgfs_entries->port_flow_entries[port->id];
  326. port_entry->port = port;
  327. port_entry->dbg_fe = entry;
  328. debugfs_create_file("hash_opts", 0444, port_dir, port_entry,
  329. &mvpp2_dbgfs_port_flow_hash_opt_fops);
  330. debugfs_create_file("engine", 0444, port_dir, port_entry,
  331. &mvpp2_dbgfs_port_flow_engine_fops);
  332. return 0;
  333. }
  334. static int mvpp2_dbgfs_flow_entry_init(struct dentry *parent,
  335. struct mvpp2 *priv, int flow)
  336. {
  337. struct mvpp2_dbgfs_flow_entry *entry;
  338. struct dentry *flow_entry_dir;
  339. char flow_entry_name[10];
  340. int i, ret;
  341. sprintf(flow_entry_name, "%02d", flow);
  342. flow_entry_dir = debugfs_create_dir(flow_entry_name, parent);
  343. entry = &priv->dbgfs_entries->flow_entries[flow];
  344. entry->flow = flow;
  345. entry->priv = priv;
  346. debugfs_create_file("dec_hits", 0444, flow_entry_dir, entry,
  347. &mvpp2_dbgfs_flow_dec_hits_fops);
  348. debugfs_create_file("type", 0444, flow_entry_dir, entry,
  349. &mvpp2_dbgfs_flow_type_fops);
  350. debugfs_create_file("id", 0444, flow_entry_dir, entry,
  351. &mvpp2_dbgfs_flow_id_fops);
  352. /* Create entry for each port */
  353. for (i = 0; i < priv->port_count; i++) {
  354. ret = mvpp2_dbgfs_flow_port_init(flow_entry_dir,
  355. priv->port_list[i], entry);
  356. if (ret)
  357. return ret;
  358. }
  359. return 0;
  360. }
  361. static int mvpp2_dbgfs_flow_init(struct dentry *parent, struct mvpp2 *priv)
  362. {
  363. struct dentry *flow_dir;
  364. int i, ret;
  365. flow_dir = debugfs_create_dir("flows", parent);
  366. for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) {
  367. ret = mvpp2_dbgfs_flow_entry_init(flow_dir, priv, i);
  368. if (ret)
  369. return ret;
  370. }
  371. return 0;
  372. }
  373. static int mvpp2_dbgfs_prs_entry_init(struct dentry *parent,
  374. struct mvpp2 *priv, int tid)
  375. {
  376. struct mvpp2_dbgfs_prs_entry *entry;
  377. struct dentry *prs_entry_dir;
  378. char prs_entry_name[10];
  379. if (tid >= MVPP2_PRS_TCAM_SRAM_SIZE)
  380. return -EINVAL;
  381. sprintf(prs_entry_name, "%03d", tid);
  382. prs_entry_dir = debugfs_create_dir(prs_entry_name, parent);
  383. entry = &priv->dbgfs_entries->prs_entries[tid];
  384. entry->tid = tid;
  385. entry->priv = priv;
  386. /* Create each attr */
  387. debugfs_create_file("sram", 0444, prs_entry_dir, entry,
  388. &mvpp2_dbgfs_prs_sram_fops);
  389. debugfs_create_file("valid", 0644, prs_entry_dir, entry,
  390. &mvpp2_dbgfs_prs_valid_fops);
  391. debugfs_create_file("lookup_id", 0644, prs_entry_dir, entry,
  392. &mvpp2_dbgfs_prs_lu_fops);
  393. debugfs_create_file("ai", 0644, prs_entry_dir, entry,
  394. &mvpp2_dbgfs_prs_ai_fops);
  395. debugfs_create_file("header_data", 0644, prs_entry_dir, entry,
  396. &mvpp2_dbgfs_prs_hdata_fops);
  397. debugfs_create_file("hits", 0444, prs_entry_dir, entry,
  398. &mvpp2_dbgfs_prs_hits_fops);
  399. debugfs_create_file("pmap", 0444, prs_entry_dir, entry,
  400. &mvpp2_dbgfs_prs_pmap_fops);
  401. return 0;
  402. }
  403. static int mvpp2_dbgfs_prs_init(struct dentry *parent, struct mvpp2 *priv)
  404. {
  405. struct dentry *prs_dir;
  406. int i, ret;
  407. prs_dir = debugfs_create_dir("parser", parent);
  408. for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {
  409. ret = mvpp2_dbgfs_prs_entry_init(prs_dir, priv, i);
  410. if (ret)
  411. return ret;
  412. }
  413. return 0;
  414. }
  415. static int mvpp2_dbgfs_c2_entry_init(struct dentry *parent,
  416. struct mvpp2 *priv, int id)
  417. {
  418. struct mvpp2_dbgfs_c2_entry *entry;
  419. struct dentry *c2_entry_dir;
  420. char c2_entry_name[10];
  421. if (id >= MVPP22_CLS_C2_N_ENTRIES)
  422. return -EINVAL;
  423. sprintf(c2_entry_name, "%03d", id);
  424. c2_entry_dir = debugfs_create_dir(c2_entry_name, parent);
  425. entry = &priv->dbgfs_entries->c2_entries[id];
  426. entry->id = id;
  427. entry->priv = priv;
  428. debugfs_create_file("hits", 0444, c2_entry_dir, entry,
  429. &mvpp2_dbgfs_flow_c2_hits_fops);
  430. debugfs_create_file("default_rxq", 0444, c2_entry_dir, entry,
  431. &mvpp2_dbgfs_flow_c2_rxq_fops);
  432. debugfs_create_file("rss_enable", 0444, c2_entry_dir, entry,
  433. &mvpp2_dbgfs_flow_c2_enable_fops);
  434. return 0;
  435. }
  436. static int mvpp2_dbgfs_flow_tbl_entry_init(struct dentry *parent,
  437. struct mvpp2 *priv, int id)
  438. {
  439. struct mvpp2_dbgfs_flow_tbl_entry *entry;
  440. struct dentry *flow_tbl_entry_dir;
  441. char flow_tbl_entry_name[10];
  442. if (id >= MVPP2_CLS_FLOWS_TBL_SIZE)
  443. return -EINVAL;
  444. sprintf(flow_tbl_entry_name, "%03d", id);
  445. flow_tbl_entry_dir = debugfs_create_dir(flow_tbl_entry_name, parent);
  446. entry = &priv->dbgfs_entries->flt_entries[id];
  447. entry->id = id;
  448. entry->priv = priv;
  449. debugfs_create_file("hits", 0444, flow_tbl_entry_dir, entry,
  450. &mvpp2_dbgfs_flow_flt_hits_fops);
  451. return 0;
  452. }
  453. static int mvpp2_dbgfs_cls_init(struct dentry *parent, struct mvpp2 *priv)
  454. {
  455. struct dentry *cls_dir, *c2_dir, *flow_tbl_dir;
  456. int i, ret;
  457. cls_dir = debugfs_create_dir("classifier", parent);
  458. c2_dir = debugfs_create_dir("c2", cls_dir);
  459. for (i = 0; i < MVPP22_CLS_C2_N_ENTRIES; i++) {
  460. ret = mvpp2_dbgfs_c2_entry_init(c2_dir, priv, i);
  461. if (ret)
  462. return ret;
  463. }
  464. flow_tbl_dir = debugfs_create_dir("flow_table", cls_dir);
  465. for (i = 0; i < MVPP2_CLS_FLOWS_TBL_SIZE; i++) {
  466. ret = mvpp2_dbgfs_flow_tbl_entry_init(flow_tbl_dir, priv, i);
  467. if (ret)
  468. return ret;
  469. }
  470. return 0;
  471. }
  472. static int mvpp2_dbgfs_port_init(struct dentry *parent,
  473. struct mvpp2_port *port)
  474. {
  475. struct dentry *port_dir;
  476. port_dir = debugfs_create_dir(port->dev->name, parent);
  477. debugfs_create_file("parser_entries", 0444, port_dir, port,
  478. &mvpp2_dbgfs_port_parser_fops);
  479. debugfs_create_file("mac_filter", 0444, port_dir, port,
  480. &mvpp2_dbgfs_filter_fops);
  481. debugfs_create_file("vid_filter", 0444, port_dir, port,
  482. &mvpp2_dbgfs_port_vid_fops);
  483. return 0;
  484. }
  485. static struct dentry *mvpp2_root;
  486. void mvpp2_dbgfs_exit(void)
  487. {
  488. debugfs_remove(mvpp2_root);
  489. }
  490. void mvpp2_dbgfs_cleanup(struct mvpp2 *priv)
  491. {
  492. debugfs_remove_recursive(priv->dbgfs_dir);
  493. kfree(priv->dbgfs_entries);
  494. }
  495. void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name)
  496. {
  497. struct dentry *mvpp2_dir;
  498. int ret, i;
  499. if (!mvpp2_root)
  500. mvpp2_root = debugfs_create_dir(MVPP2_DRIVER_NAME, NULL);
  501. mvpp2_dir = debugfs_create_dir(name, mvpp2_root);
  502. priv->dbgfs_dir = mvpp2_dir;
  503. priv->dbgfs_entries = kzalloc(sizeof(*priv->dbgfs_entries), GFP_KERNEL);
  504. if (!priv->dbgfs_entries)
  505. goto err;
  506. ret = mvpp2_dbgfs_prs_init(mvpp2_dir, priv);
  507. if (ret)
  508. goto err;
  509. ret = mvpp2_dbgfs_cls_init(mvpp2_dir, priv);
  510. if (ret)
  511. goto err;
  512. for (i = 0; i < priv->port_count; i++) {
  513. ret = mvpp2_dbgfs_port_init(mvpp2_dir, priv->port_list[i]);
  514. if (ret)
  515. goto err;
  516. }
  517. ret = mvpp2_dbgfs_flow_init(mvpp2_dir, priv);
  518. if (ret)
  519. goto err;
  520. return;
  521. err:
  522. mvpp2_dbgfs_cleanup(priv);
  523. }