0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/slab.h>
0010 #include <linux/debugfs.h>
0011
0012 #include "mvpp2.h"
0013 #include "mvpp2_prs.h"
0014 #include "mvpp2_cls.h"
0015
0016 struct mvpp2_dbgfs_prs_entry {
0017 int tid;
0018 struct mvpp2 *priv;
0019 };
0020
0021 struct mvpp2_dbgfs_c2_entry {
0022 int id;
0023 struct mvpp2 *priv;
0024 };
0025
0026 struct mvpp2_dbgfs_flow_entry {
0027 int flow;
0028 struct mvpp2 *priv;
0029 };
0030
0031 struct mvpp2_dbgfs_flow_tbl_entry {
0032 int id;
0033 struct mvpp2 *priv;
0034 };
0035
0036 struct mvpp2_dbgfs_port_flow_entry {
0037 struct mvpp2_port *port;
0038 struct mvpp2_dbgfs_flow_entry *dbg_fe;
0039 };
0040
0041 struct mvpp2_dbgfs_entries {
0042
0043 struct mvpp2_dbgfs_prs_entry prs_entries[MVPP2_PRS_TCAM_SRAM_SIZE];
0044
0045
0046 struct mvpp2_dbgfs_c2_entry c2_entries[MVPP22_CLS_C2_N_ENTRIES];
0047
0048
0049 struct mvpp2_dbgfs_flow_tbl_entry flt_entries[MVPP2_CLS_FLOWS_TBL_SIZE];
0050
0051
0052 struct mvpp2_dbgfs_flow_entry flow_entries[MVPP2_N_PRS_FLOWS];
0053
0054
0055 struct mvpp2_dbgfs_port_flow_entry port_flow_entries[MVPP2_MAX_PORTS];
0056 };
0057
0058 static int mvpp2_dbgfs_flow_flt_hits_show(struct seq_file *s, void *unused)
0059 {
0060 struct mvpp2_dbgfs_flow_tbl_entry *entry = s->private;
0061
0062 u32 hits = mvpp2_cls_flow_hits(entry->priv, entry->id);
0063
0064 seq_printf(s, "%u\n", hits);
0065
0066 return 0;
0067 }
0068
0069 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_flt_hits);
0070
0071 static int mvpp2_dbgfs_flow_dec_hits_show(struct seq_file *s, void *unused)
0072 {
0073 struct mvpp2_dbgfs_flow_entry *entry = s->private;
0074
0075 u32 hits = mvpp2_cls_lookup_hits(entry->priv, entry->flow);
0076
0077 seq_printf(s, "%u\n", hits);
0078
0079 return 0;
0080 }
0081
0082 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_dec_hits);
0083
0084 static int mvpp2_dbgfs_flow_type_show(struct seq_file *s, void *unused)
0085 {
0086 struct mvpp2_dbgfs_flow_entry *entry = s->private;
0087 const struct mvpp2_cls_flow *f;
0088 const char *flow_name;
0089
0090 f = mvpp2_cls_flow_get(entry->flow);
0091 if (!f)
0092 return -EINVAL;
0093
0094 switch (f->flow_type) {
0095 case IPV4_FLOW:
0096 flow_name = "ipv4";
0097 break;
0098 case IPV6_FLOW:
0099 flow_name = "ipv6";
0100 break;
0101 case TCP_V4_FLOW:
0102 flow_name = "tcp4";
0103 break;
0104 case TCP_V6_FLOW:
0105 flow_name = "tcp6";
0106 break;
0107 case UDP_V4_FLOW:
0108 flow_name = "udp4";
0109 break;
0110 case UDP_V6_FLOW:
0111 flow_name = "udp6";
0112 break;
0113 default:
0114 flow_name = "other";
0115 }
0116
0117 seq_printf(s, "%s\n", flow_name);
0118
0119 return 0;
0120 }
0121
0122 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_type);
0123
0124 static int mvpp2_dbgfs_flow_id_show(struct seq_file *s, void *unused)
0125 {
0126 const struct mvpp2_dbgfs_flow_entry *entry = s->private;
0127 const struct mvpp2_cls_flow *f;
0128
0129 f = mvpp2_cls_flow_get(entry->flow);
0130 if (!f)
0131 return -EINVAL;
0132
0133 seq_printf(s, "%d\n", f->flow_id);
0134
0135 return 0;
0136 }
0137
0138 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_id);
0139
0140 static int mvpp2_dbgfs_port_flow_hash_opt_show(struct seq_file *s, void *unused)
0141 {
0142 struct mvpp2_dbgfs_port_flow_entry *entry = s->private;
0143 struct mvpp2_port *port = entry->port;
0144 struct mvpp2_cls_flow_entry fe;
0145 const struct mvpp2_cls_flow *f;
0146 int flow_index;
0147 u16 hash_opts;
0148
0149 f = mvpp2_cls_flow_get(entry->dbg_fe->flow);
0150 if (!f)
0151 return -EINVAL;
0152
0153 flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);
0154
0155 mvpp2_cls_flow_read(port->priv, flow_index, &fe);
0156
0157 hash_opts = mvpp2_flow_get_hek_fields(&fe);
0158
0159 seq_printf(s, "0x%04x\n", hash_opts);
0160
0161 return 0;
0162 }
0163
0164 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_hash_opt);
0165
0166 static int mvpp2_dbgfs_port_flow_engine_show(struct seq_file *s, void *unused)
0167 {
0168 struct mvpp2_dbgfs_port_flow_entry *entry = s->private;
0169 struct mvpp2_port *port = entry->port;
0170 struct mvpp2_cls_flow_entry fe;
0171 const struct mvpp2_cls_flow *f;
0172 int flow_index, engine;
0173
0174 f = mvpp2_cls_flow_get(entry->dbg_fe->flow);
0175 if (!f)
0176 return -EINVAL;
0177
0178 flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);
0179
0180 mvpp2_cls_flow_read(port->priv, flow_index, &fe);
0181
0182 engine = mvpp2_cls_flow_eng_get(&fe);
0183
0184 seq_printf(s, "%d\n", engine);
0185
0186 return 0;
0187 }
0188
0189 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_engine);
0190
0191 static int mvpp2_dbgfs_flow_c2_hits_show(struct seq_file *s, void *unused)
0192 {
0193 struct mvpp2_dbgfs_c2_entry *entry = s->private;
0194 u32 hits;
0195
0196 hits = mvpp2_cls_c2_hit_count(entry->priv, entry->id);
0197
0198 seq_printf(s, "%u\n", hits);
0199
0200 return 0;
0201 }
0202
0203 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_hits);
0204
0205 static int mvpp2_dbgfs_flow_c2_rxq_show(struct seq_file *s, void *unused)
0206 {
0207 struct mvpp2_dbgfs_c2_entry *entry = s->private;
0208 struct mvpp2_cls_c2_entry c2;
0209 u8 qh, ql;
0210
0211 mvpp2_cls_c2_read(entry->priv, entry->id, &c2);
0212
0213 qh = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QHIGH_OFFS) &
0214 MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
0215
0216 ql = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QLOW_OFFS) &
0217 MVPP22_CLS_C2_ATTR0_QLOW_MASK;
0218
0219 seq_printf(s, "%d\n", (qh << 3 | ql));
0220
0221 return 0;
0222 }
0223
0224 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_rxq);
0225
0226 static int mvpp2_dbgfs_flow_c2_enable_show(struct seq_file *s, void *unused)
0227 {
0228 struct mvpp2_dbgfs_c2_entry *entry = s->private;
0229 struct mvpp2_cls_c2_entry c2;
0230 int enabled;
0231
0232 mvpp2_cls_c2_read(entry->priv, entry->id, &c2);
0233
0234 enabled = !!(c2.attr[2] & MVPP22_CLS_C2_ATTR2_RSS_EN);
0235
0236 seq_printf(s, "%d\n", enabled);
0237
0238 return 0;
0239 }
0240
0241 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_enable);
0242
0243 static int mvpp2_dbgfs_port_vid_show(struct seq_file *s, void *unused)
0244 {
0245 struct mvpp2_port *port = s->private;
0246 unsigned char byte[2], enable[2];
0247 struct mvpp2 *priv = port->priv;
0248 struct mvpp2_prs_entry pe;
0249 unsigned long pmap;
0250 u16 rvid;
0251 int tid;
0252
0253 for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
0254 tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
0255 mvpp2_prs_init_from_hw(priv, &pe, tid);
0256
0257 pmap = mvpp2_prs_tcam_port_map_get(&pe);
0258
0259 if (!priv->prs_shadow[tid].valid)
0260 continue;
0261
0262 if (!test_bit(port->id, &pmap))
0263 continue;
0264
0265 mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
0266 mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
0267
0268 rvid = ((byte[0] & 0xf) << 8) + byte[1];
0269
0270 seq_printf(s, "%u\n", rvid);
0271 }
0272
0273 return 0;
0274 }
0275
0276 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_vid);
0277
0278 static int mvpp2_dbgfs_port_parser_show(struct seq_file *s, void *unused)
0279 {
0280 struct mvpp2_port *port = s->private;
0281 struct mvpp2 *priv = port->priv;
0282 struct mvpp2_prs_entry pe;
0283 unsigned long pmap;
0284 int i;
0285
0286 for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {
0287 mvpp2_prs_init_from_hw(port->priv, &pe, i);
0288
0289 pmap = mvpp2_prs_tcam_port_map_get(&pe);
0290 if (priv->prs_shadow[i].valid && test_bit(port->id, &pmap))
0291 seq_printf(s, "%03d\n", i);
0292 }
0293
0294 return 0;
0295 }
0296
0297 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_parser);
0298
0299 static int mvpp2_dbgfs_filter_show(struct seq_file *s, void *unused)
0300 {
0301 struct mvpp2_port *port = s->private;
0302 struct mvpp2 *priv = port->priv;
0303 struct mvpp2_prs_entry pe;
0304 unsigned long pmap;
0305 int index, tid;
0306
0307 for (tid = MVPP2_PE_MAC_RANGE_START;
0308 tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
0309 unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
0310
0311 if (!priv->prs_shadow[tid].valid ||
0312 priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC ||
0313 priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF)
0314 continue;
0315
0316 mvpp2_prs_init_from_hw(priv, &pe, tid);
0317
0318 pmap = mvpp2_prs_tcam_port_map_get(&pe);
0319
0320
0321 if (!test_bit(port->id, &pmap))
0322 continue;
0323
0324
0325 for (index = 0; index < ETH_ALEN; index++)
0326 mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],
0327 &da_mask[index]);
0328
0329 seq_printf(s, "%pM\n", da);
0330 }
0331
0332 return 0;
0333 }
0334
0335 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_filter);
0336
0337 static int mvpp2_dbgfs_prs_lu_show(struct seq_file *s, void *unused)
0338 {
0339 struct mvpp2_dbgfs_prs_entry *entry = s->private;
0340 struct mvpp2 *priv = entry->priv;
0341
0342 seq_printf(s, "%x\n", priv->prs_shadow[entry->tid].lu);
0343
0344 return 0;
0345 }
0346
0347 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_lu);
0348
0349 static int mvpp2_dbgfs_prs_pmap_show(struct seq_file *s, void *unused)
0350 {
0351 struct mvpp2_dbgfs_prs_entry *entry = s->private;
0352 struct mvpp2_prs_entry pe;
0353 unsigned int pmap;
0354
0355 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
0356
0357 pmap = mvpp2_prs_tcam_port_map_get(&pe);
0358 pmap &= MVPP2_PRS_PORT_MASK;
0359
0360 seq_printf(s, "%02x\n", pmap);
0361
0362 return 0;
0363 }
0364
0365 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_pmap);
0366
0367 static int mvpp2_dbgfs_prs_ai_show(struct seq_file *s, void *unused)
0368 {
0369 struct mvpp2_dbgfs_prs_entry *entry = s->private;
0370 struct mvpp2_prs_entry pe;
0371 unsigned char ai, ai_mask;
0372
0373 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
0374
0375 ai = pe.tcam[MVPP2_PRS_TCAM_AI_WORD] & MVPP2_PRS_AI_MASK;
0376 ai_mask = (pe.tcam[MVPP2_PRS_TCAM_AI_WORD] >> 16) & MVPP2_PRS_AI_MASK;
0377
0378 seq_printf(s, "%02x %02x\n", ai, ai_mask);
0379
0380 return 0;
0381 }
0382
0383 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_ai);
0384
0385 static int mvpp2_dbgfs_prs_hdata_show(struct seq_file *s, void *unused)
0386 {
0387 struct mvpp2_dbgfs_prs_entry *entry = s->private;
0388 struct mvpp2_prs_entry pe;
0389 unsigned char data[8], mask[8];
0390 int i;
0391
0392 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
0393
0394 for (i = 0; i < 8; i++)
0395 mvpp2_prs_tcam_data_byte_get(&pe, i, &data[i], &mask[i]);
0396
0397 seq_printf(s, "%*phN %*phN\n", 8, data, 8, mask);
0398
0399 return 0;
0400 }
0401
0402 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hdata);
0403
0404 static int mvpp2_dbgfs_prs_sram_show(struct seq_file *s, void *unused)
0405 {
0406 struct mvpp2_dbgfs_prs_entry *entry = s->private;
0407 struct mvpp2_prs_entry pe;
0408
0409 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);
0410
0411 seq_printf(s, "%*phN\n", 14, pe.sram);
0412
0413 return 0;
0414 }
0415
0416 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_sram);
0417
0418 static int mvpp2_dbgfs_prs_hits_show(struct seq_file *s, void *unused)
0419 {
0420 struct mvpp2_dbgfs_prs_entry *entry = s->private;
0421 int val;
0422
0423 val = mvpp2_prs_hits(entry->priv, entry->tid);
0424 if (val < 0)
0425 return val;
0426
0427 seq_printf(s, "%d\n", val);
0428
0429 return 0;
0430 }
0431
0432 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hits);
0433
0434 static int mvpp2_dbgfs_prs_valid_show(struct seq_file *s, void *unused)
0435 {
0436 struct mvpp2_dbgfs_prs_entry *entry = s->private;
0437 struct mvpp2 *priv = entry->priv;
0438 int tid = entry->tid;
0439
0440 seq_printf(s, "%d\n", priv->prs_shadow[tid].valid ? 1 : 0);
0441
0442 return 0;
0443 }
0444
0445 DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_valid);
0446
0447 static int mvpp2_dbgfs_flow_port_init(struct dentry *parent,
0448 struct mvpp2_port *port,
0449 struct mvpp2_dbgfs_flow_entry *entry)
0450 {
0451 struct mvpp2_dbgfs_port_flow_entry *port_entry;
0452 struct dentry *port_dir;
0453
0454 port_dir = debugfs_create_dir(port->dev->name, parent);
0455
0456 port_entry = &port->priv->dbgfs_entries->port_flow_entries[port->id];
0457
0458 port_entry->port = port;
0459 port_entry->dbg_fe = entry;
0460
0461 debugfs_create_file("hash_opts", 0444, port_dir, port_entry,
0462 &mvpp2_dbgfs_port_flow_hash_opt_fops);
0463
0464 debugfs_create_file("engine", 0444, port_dir, port_entry,
0465 &mvpp2_dbgfs_port_flow_engine_fops);
0466
0467 return 0;
0468 }
0469
0470 static int mvpp2_dbgfs_flow_entry_init(struct dentry *parent,
0471 struct mvpp2 *priv, int flow)
0472 {
0473 struct mvpp2_dbgfs_flow_entry *entry;
0474 struct dentry *flow_entry_dir;
0475 char flow_entry_name[10];
0476 int i, ret;
0477
0478 sprintf(flow_entry_name, "%02d", flow);
0479
0480 flow_entry_dir = debugfs_create_dir(flow_entry_name, parent);
0481
0482 entry = &priv->dbgfs_entries->flow_entries[flow];
0483
0484 entry->flow = flow;
0485 entry->priv = priv;
0486
0487 debugfs_create_file("dec_hits", 0444, flow_entry_dir, entry,
0488 &mvpp2_dbgfs_flow_dec_hits_fops);
0489
0490 debugfs_create_file("type", 0444, flow_entry_dir, entry,
0491 &mvpp2_dbgfs_flow_type_fops);
0492
0493 debugfs_create_file("id", 0444, flow_entry_dir, entry,
0494 &mvpp2_dbgfs_flow_id_fops);
0495
0496
0497 for (i = 0; i < priv->port_count; i++) {
0498 ret = mvpp2_dbgfs_flow_port_init(flow_entry_dir,
0499 priv->port_list[i], entry);
0500 if (ret)
0501 return ret;
0502 }
0503
0504 return 0;
0505 }
0506
0507 static int mvpp2_dbgfs_flow_init(struct dentry *parent, struct mvpp2 *priv)
0508 {
0509 struct dentry *flow_dir;
0510 int i, ret;
0511
0512 flow_dir = debugfs_create_dir("flows", parent);
0513
0514 for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) {
0515 ret = mvpp2_dbgfs_flow_entry_init(flow_dir, priv, i);
0516 if (ret)
0517 return ret;
0518 }
0519
0520 return 0;
0521 }
0522
0523 static int mvpp2_dbgfs_prs_entry_init(struct dentry *parent,
0524 struct mvpp2 *priv, int tid)
0525 {
0526 struct mvpp2_dbgfs_prs_entry *entry;
0527 struct dentry *prs_entry_dir;
0528 char prs_entry_name[10];
0529
0530 if (tid >= MVPP2_PRS_TCAM_SRAM_SIZE)
0531 return -EINVAL;
0532
0533 sprintf(prs_entry_name, "%03d", tid);
0534
0535 prs_entry_dir = debugfs_create_dir(prs_entry_name, parent);
0536
0537 entry = &priv->dbgfs_entries->prs_entries[tid];
0538
0539 entry->tid = tid;
0540 entry->priv = priv;
0541
0542
0543 debugfs_create_file("sram", 0444, prs_entry_dir, entry,
0544 &mvpp2_dbgfs_prs_sram_fops);
0545
0546 debugfs_create_file("valid", 0644, prs_entry_dir, entry,
0547 &mvpp2_dbgfs_prs_valid_fops);
0548
0549 debugfs_create_file("lookup_id", 0644, prs_entry_dir, entry,
0550 &mvpp2_dbgfs_prs_lu_fops);
0551
0552 debugfs_create_file("ai", 0644, prs_entry_dir, entry,
0553 &mvpp2_dbgfs_prs_ai_fops);
0554
0555 debugfs_create_file("header_data", 0644, prs_entry_dir, entry,
0556 &mvpp2_dbgfs_prs_hdata_fops);
0557
0558 debugfs_create_file("hits", 0444, prs_entry_dir, entry,
0559 &mvpp2_dbgfs_prs_hits_fops);
0560
0561 debugfs_create_file("pmap", 0444, prs_entry_dir, entry,
0562 &mvpp2_dbgfs_prs_pmap_fops);
0563
0564 return 0;
0565 }
0566
0567 static int mvpp2_dbgfs_prs_init(struct dentry *parent, struct mvpp2 *priv)
0568 {
0569 struct dentry *prs_dir;
0570 int i, ret;
0571
0572 prs_dir = debugfs_create_dir("parser", parent);
0573
0574 for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {
0575 ret = mvpp2_dbgfs_prs_entry_init(prs_dir, priv, i);
0576 if (ret)
0577 return ret;
0578 }
0579
0580 return 0;
0581 }
0582
0583 static int mvpp2_dbgfs_c2_entry_init(struct dentry *parent,
0584 struct mvpp2 *priv, int id)
0585 {
0586 struct mvpp2_dbgfs_c2_entry *entry;
0587 struct dentry *c2_entry_dir;
0588 char c2_entry_name[10];
0589
0590 if (id >= MVPP22_CLS_C2_N_ENTRIES)
0591 return -EINVAL;
0592
0593 sprintf(c2_entry_name, "%03d", id);
0594
0595 c2_entry_dir = debugfs_create_dir(c2_entry_name, parent);
0596 if (!c2_entry_dir)
0597 return -ENOMEM;
0598
0599 entry = &priv->dbgfs_entries->c2_entries[id];
0600
0601 entry->id = id;
0602 entry->priv = priv;
0603
0604 debugfs_create_file("hits", 0444, c2_entry_dir, entry,
0605 &mvpp2_dbgfs_flow_c2_hits_fops);
0606
0607 debugfs_create_file("default_rxq", 0444, c2_entry_dir, entry,
0608 &mvpp2_dbgfs_flow_c2_rxq_fops);
0609
0610 debugfs_create_file("rss_enable", 0444, c2_entry_dir, entry,
0611 &mvpp2_dbgfs_flow_c2_enable_fops);
0612
0613 return 0;
0614 }
0615
0616 static int mvpp2_dbgfs_flow_tbl_entry_init(struct dentry *parent,
0617 struct mvpp2 *priv, int id)
0618 {
0619 struct mvpp2_dbgfs_flow_tbl_entry *entry;
0620 struct dentry *flow_tbl_entry_dir;
0621 char flow_tbl_entry_name[10];
0622
0623 if (id >= MVPP2_CLS_FLOWS_TBL_SIZE)
0624 return -EINVAL;
0625
0626 sprintf(flow_tbl_entry_name, "%03d", id);
0627
0628 flow_tbl_entry_dir = debugfs_create_dir(flow_tbl_entry_name, parent);
0629 if (!flow_tbl_entry_dir)
0630 return -ENOMEM;
0631
0632 entry = &priv->dbgfs_entries->flt_entries[id];
0633
0634 entry->id = id;
0635 entry->priv = priv;
0636
0637 debugfs_create_file("hits", 0444, flow_tbl_entry_dir, entry,
0638 &mvpp2_dbgfs_flow_flt_hits_fops);
0639
0640 return 0;
0641 }
0642
0643 static int mvpp2_dbgfs_cls_init(struct dentry *parent, struct mvpp2 *priv)
0644 {
0645 struct dentry *cls_dir, *c2_dir, *flow_tbl_dir;
0646 int i, ret;
0647
0648 cls_dir = debugfs_create_dir("classifier", parent);
0649 if (!cls_dir)
0650 return -ENOMEM;
0651
0652 c2_dir = debugfs_create_dir("c2", cls_dir);
0653 if (!c2_dir)
0654 return -ENOMEM;
0655
0656 for (i = 0; i < MVPP22_CLS_C2_N_ENTRIES; i++) {
0657 ret = mvpp2_dbgfs_c2_entry_init(c2_dir, priv, i);
0658 if (ret)
0659 return ret;
0660 }
0661
0662 flow_tbl_dir = debugfs_create_dir("flow_table", cls_dir);
0663 if (!flow_tbl_dir)
0664 return -ENOMEM;
0665
0666 for (i = 0; i < MVPP2_CLS_FLOWS_TBL_SIZE; i++) {
0667 ret = mvpp2_dbgfs_flow_tbl_entry_init(flow_tbl_dir, priv, i);
0668 if (ret)
0669 return ret;
0670 }
0671
0672 return 0;
0673 }
0674
0675 static int mvpp2_dbgfs_port_init(struct dentry *parent,
0676 struct mvpp2_port *port)
0677 {
0678 struct dentry *port_dir;
0679
0680 port_dir = debugfs_create_dir(port->dev->name, parent);
0681
0682 debugfs_create_file("parser_entries", 0444, port_dir, port,
0683 &mvpp2_dbgfs_port_parser_fops);
0684
0685 debugfs_create_file("mac_filter", 0444, port_dir, port,
0686 &mvpp2_dbgfs_filter_fops);
0687
0688 debugfs_create_file("vid_filter", 0444, port_dir, port,
0689 &mvpp2_dbgfs_port_vid_fops);
0690
0691 return 0;
0692 }
0693
0694 void mvpp2_dbgfs_cleanup(struct mvpp2 *priv)
0695 {
0696 debugfs_remove_recursive(priv->dbgfs_dir);
0697
0698 kfree(priv->dbgfs_entries);
0699 }
0700
0701 void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name)
0702 {
0703 struct dentry *mvpp2_dir, *mvpp2_root;
0704 int ret, i;
0705
0706 mvpp2_root = debugfs_lookup(MVPP2_DRIVER_NAME, NULL);
0707 if (!mvpp2_root)
0708 mvpp2_root = debugfs_create_dir(MVPP2_DRIVER_NAME, NULL);
0709
0710 mvpp2_dir = debugfs_create_dir(name, mvpp2_root);
0711
0712 priv->dbgfs_dir = mvpp2_dir;
0713 priv->dbgfs_entries = kzalloc(sizeof(*priv->dbgfs_entries), GFP_KERNEL);
0714 if (!priv->dbgfs_entries)
0715 goto err;
0716
0717 ret = mvpp2_dbgfs_prs_init(mvpp2_dir, priv);
0718 if (ret)
0719 goto err;
0720
0721 ret = mvpp2_dbgfs_cls_init(mvpp2_dir, priv);
0722 if (ret)
0723 goto err;
0724
0725 for (i = 0; i < priv->port_count; i++) {
0726 ret = mvpp2_dbgfs_port_init(mvpp2_dir, priv->port_list[i]);
0727 if (ret)
0728 goto err;
0729 }
0730
0731 ret = mvpp2_dbgfs_flow_init(mvpp2_dir, priv);
0732 if (ret)
0733 goto err;
0734
0735 return;
0736 err:
0737 mvpp2_dbgfs_cleanup(priv);
0738 }