735 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for Marvell PPv2 network controller for Armada 375 SoC.4 *5 * Copyright (C) 2018 Marvell6 */7 8#include <linux/kernel.h>9#include <linux/slab.h>10#include <linux/debugfs.h>11 12#include "mvpp2.h"13#include "mvpp2_prs.h"14#include "mvpp2_cls.h"15 16struct mvpp2_dbgfs_prs_entry {17 int tid;18 struct mvpp2 *priv;19};20 21struct mvpp2_dbgfs_c2_entry {22 int id;23 struct mvpp2 *priv;24};25 26struct mvpp2_dbgfs_flow_entry {27 int flow;28 struct mvpp2 *priv;29};30 31struct mvpp2_dbgfs_flow_tbl_entry {32 int id;33 struct mvpp2 *priv;34};35 36struct mvpp2_dbgfs_port_flow_entry {37 struct mvpp2_port *port;38 struct mvpp2_dbgfs_flow_entry *dbg_fe;39};40 41struct mvpp2_dbgfs_entries {42 /* Entries for Header Parser debug info */43 struct mvpp2_dbgfs_prs_entry prs_entries[MVPP2_PRS_TCAM_SRAM_SIZE];44 45 /* Entries for Classifier C2 engine debug info */46 struct mvpp2_dbgfs_c2_entry c2_entries[MVPP22_CLS_C2_N_ENTRIES];47 48 /* Entries for Classifier Flow Table debug info */49 struct mvpp2_dbgfs_flow_tbl_entry flt_entries[MVPP2_CLS_FLOWS_TBL_SIZE];50 51 /* Entries for Classifier flows debug info */52 struct mvpp2_dbgfs_flow_entry flow_entries[MVPP2_N_PRS_FLOWS];53 54 /* Entries for per-port flows debug info */55 struct mvpp2_dbgfs_port_flow_entry port_flow_entries[MVPP2_MAX_PORTS];56};57 58static int mvpp2_dbgfs_flow_flt_hits_show(struct seq_file *s, void *unused)59{60 struct mvpp2_dbgfs_flow_tbl_entry *entry = s->private;61 62 u32 hits = mvpp2_cls_flow_hits(entry->priv, entry->id);63 64 seq_printf(s, "%u\n", hits);65 66 return 0;67}68 69DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_flt_hits);70 71static int mvpp2_dbgfs_flow_dec_hits_show(struct seq_file *s, void *unused)72{73 struct mvpp2_dbgfs_flow_entry *entry = s->private;74 75 u32 hits = mvpp2_cls_lookup_hits(entry->priv, entry->flow);76 77 seq_printf(s, "%u\n", hits);78 79 return 0;80}81 82DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_dec_hits);83 84static int mvpp2_dbgfs_flow_type_show(struct seq_file *s, void *unused)85{86 struct mvpp2_dbgfs_flow_entry *entry = s->private;87 const struct mvpp2_cls_flow *f;88 const char *flow_name;89 90 f = mvpp2_cls_flow_get(entry->flow);91 if (!f)92 return -EINVAL;93 94 switch (f->flow_type) {95 case IPV4_FLOW:96 flow_name = "ipv4";97 break;98 case IPV6_FLOW:99 flow_name = "ipv6";100 break;101 case TCP_V4_FLOW:102 flow_name = "tcp4";103 break;104 case TCP_V6_FLOW:105 flow_name = "tcp6";106 break;107 case UDP_V4_FLOW:108 flow_name = "udp4";109 break;110 case UDP_V6_FLOW:111 flow_name = "udp6";112 break;113 default:114 flow_name = "other";115 }116 117 seq_printf(s, "%s\n", flow_name);118 119 return 0;120}121 122DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_type);123 124static int mvpp2_dbgfs_flow_id_show(struct seq_file *s, void *unused)125{126 const struct mvpp2_dbgfs_flow_entry *entry = s->private;127 const struct mvpp2_cls_flow *f;128 129 f = mvpp2_cls_flow_get(entry->flow);130 if (!f)131 return -EINVAL;132 133 seq_printf(s, "%d\n", f->flow_id);134 135 return 0;136}137 138DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_id);139 140static int mvpp2_dbgfs_port_flow_hash_opt_show(struct seq_file *s, void *unused)141{142 struct mvpp2_dbgfs_port_flow_entry *entry = s->private;143 struct mvpp2_port *port = entry->port;144 struct mvpp2_cls_flow_entry fe;145 const struct mvpp2_cls_flow *f;146 int flow_index;147 u16 hash_opts;148 149 f = mvpp2_cls_flow_get(entry->dbg_fe->flow);150 if (!f)151 return -EINVAL;152 153 flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);154 155 mvpp2_cls_flow_read(port->priv, flow_index, &fe);156 157 hash_opts = mvpp2_flow_get_hek_fields(&fe);158 159 seq_printf(s, "0x%04x\n", hash_opts);160 161 return 0;162}163 164DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_hash_opt);165 166static int mvpp2_dbgfs_port_flow_engine_show(struct seq_file *s, void *unused)167{168 struct mvpp2_dbgfs_port_flow_entry *entry = s->private;169 struct mvpp2_port *port = entry->port;170 struct mvpp2_cls_flow_entry fe;171 const struct mvpp2_cls_flow *f;172 int flow_index, engine;173 174 f = mvpp2_cls_flow_get(entry->dbg_fe->flow);175 if (!f)176 return -EINVAL;177 178 flow_index = MVPP2_CLS_FLT_HASH_ENTRY(entry->port->id, f->flow_id);179 180 mvpp2_cls_flow_read(port->priv, flow_index, &fe);181 182 engine = mvpp2_cls_flow_eng_get(&fe);183 184 seq_printf(s, "%d\n", engine);185 186 return 0;187}188 189DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_flow_engine);190 191static int mvpp2_dbgfs_flow_c2_hits_show(struct seq_file *s, void *unused)192{193 struct mvpp2_dbgfs_c2_entry *entry = s->private;194 u32 hits;195 196 hits = mvpp2_cls_c2_hit_count(entry->priv, entry->id);197 198 seq_printf(s, "%u\n", hits);199 200 return 0;201}202 203DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_hits);204 205static int mvpp2_dbgfs_flow_c2_rxq_show(struct seq_file *s, void *unused)206{207 struct mvpp2_dbgfs_c2_entry *entry = s->private;208 struct mvpp2_cls_c2_entry c2;209 u8 qh, ql;210 211 mvpp2_cls_c2_read(entry->priv, entry->id, &c2);212 213 qh = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QHIGH_OFFS) &214 MVPP22_CLS_C2_ATTR0_QHIGH_MASK;215 216 ql = (c2.attr[0] >> MVPP22_CLS_C2_ATTR0_QLOW_OFFS) &217 MVPP22_CLS_C2_ATTR0_QLOW_MASK;218 219 seq_printf(s, "%d\n", (qh << 3 | ql));220 221 return 0;222}223 224DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_rxq);225 226static int mvpp2_dbgfs_flow_c2_enable_show(struct seq_file *s, void *unused)227{228 struct mvpp2_dbgfs_c2_entry *entry = s->private;229 struct mvpp2_cls_c2_entry c2;230 int enabled;231 232 mvpp2_cls_c2_read(entry->priv, entry->id, &c2);233 234 enabled = !!(c2.attr[2] & MVPP22_CLS_C2_ATTR2_RSS_EN);235 236 seq_printf(s, "%d\n", enabled);237 238 return 0;239}240 241DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_flow_c2_enable);242 243static int mvpp2_dbgfs_port_vid_show(struct seq_file *s, void *unused)244{245 struct mvpp2_port *port = s->private;246 unsigned char byte[2], enable[2];247 struct mvpp2 *priv = port->priv;248 struct mvpp2_prs_entry pe;249 unsigned long pmap;250 u16 rvid;251 int tid;252 253 for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);254 tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {255 mvpp2_prs_init_from_hw(priv, &pe, tid);256 257 pmap = mvpp2_prs_tcam_port_map_get(&pe);258 259 if (!priv->prs_shadow[tid].valid)260 continue;261 262 if (!test_bit(port->id, &pmap))263 continue;264 265 mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);266 mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);267 268 rvid = ((byte[0] & 0xf) << 8) + byte[1];269 270 seq_printf(s, "%u\n", rvid);271 }272 273 return 0;274}275 276DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_vid);277 278static int mvpp2_dbgfs_port_parser_show(struct seq_file *s, void *unused)279{280 struct mvpp2_port *port = s->private;281 struct mvpp2 *priv = port->priv;282 struct mvpp2_prs_entry pe;283 unsigned long pmap;284 int i;285 286 for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {287 mvpp2_prs_init_from_hw(port->priv, &pe, i);288 289 pmap = mvpp2_prs_tcam_port_map_get(&pe);290 if (priv->prs_shadow[i].valid && test_bit(port->id, &pmap))291 seq_printf(s, "%03d\n", i);292 }293 294 return 0;295}296 297DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_port_parser);298 299static int mvpp2_dbgfs_filter_show(struct seq_file *s, void *unused)300{301 struct mvpp2_port *port = s->private;302 struct mvpp2 *priv = port->priv;303 struct mvpp2_prs_entry pe;304 unsigned long pmap;305 int index, tid;306 307 for (tid = MVPP2_PE_MAC_RANGE_START;308 tid <= MVPP2_PE_MAC_RANGE_END; tid++) {309 unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];310 311 if (!priv->prs_shadow[tid].valid ||312 priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC ||313 priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF)314 continue;315 316 mvpp2_prs_init_from_hw(priv, &pe, tid);317 318 pmap = mvpp2_prs_tcam_port_map_get(&pe);319 320 /* We only want entries active on this port */321 if (!test_bit(port->id, &pmap))322 continue;323 324 /* Read mac addr from entry */325 for (index = 0; index < ETH_ALEN; index++)326 mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],327 &da_mask[index]);328 329 seq_printf(s, "%pM\n", da);330 }331 332 return 0;333}334 335DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_filter);336 337static int mvpp2_dbgfs_prs_lu_show(struct seq_file *s, void *unused)338{339 struct mvpp2_dbgfs_prs_entry *entry = s->private;340 struct mvpp2 *priv = entry->priv;341 342 seq_printf(s, "%x\n", priv->prs_shadow[entry->tid].lu);343 344 return 0;345}346 347DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_lu);348 349static int mvpp2_dbgfs_prs_pmap_show(struct seq_file *s, void *unused)350{351 struct mvpp2_dbgfs_prs_entry *entry = s->private;352 struct mvpp2_prs_entry pe;353 unsigned int pmap;354 355 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);356 357 pmap = mvpp2_prs_tcam_port_map_get(&pe);358 pmap &= MVPP2_PRS_PORT_MASK;359 360 seq_printf(s, "%02x\n", pmap);361 362 return 0;363}364 365DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_pmap);366 367static int mvpp2_dbgfs_prs_ai_show(struct seq_file *s, void *unused)368{369 struct mvpp2_dbgfs_prs_entry *entry = s->private;370 struct mvpp2_prs_entry pe;371 unsigned char ai, ai_mask;372 373 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);374 375 ai = pe.tcam[MVPP2_PRS_TCAM_AI_WORD] & MVPP2_PRS_AI_MASK;376 ai_mask = (pe.tcam[MVPP2_PRS_TCAM_AI_WORD] >> 16) & MVPP2_PRS_AI_MASK;377 378 seq_printf(s, "%02x %02x\n", ai, ai_mask);379 380 return 0;381}382 383DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_ai);384 385static int mvpp2_dbgfs_prs_hdata_show(struct seq_file *s, void *unused)386{387 struct mvpp2_dbgfs_prs_entry *entry = s->private;388 struct mvpp2_prs_entry pe;389 unsigned char data[8], mask[8];390 int i;391 392 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);393 394 for (i = 0; i < 8; i++)395 mvpp2_prs_tcam_data_byte_get(&pe, i, &data[i], &mask[i]);396 397 seq_printf(s, "%*phN %*phN\n", 8, data, 8, mask);398 399 return 0;400}401 402DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hdata);403 404static int mvpp2_dbgfs_prs_sram_show(struct seq_file *s, void *unused)405{406 struct mvpp2_dbgfs_prs_entry *entry = s->private;407 struct mvpp2_prs_entry pe;408 409 mvpp2_prs_init_from_hw(entry->priv, &pe, entry->tid);410 411 seq_printf(s, "%*phN\n", 14, pe.sram);412 413 return 0;414}415 416DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_sram);417 418static int mvpp2_dbgfs_prs_hits_show(struct seq_file *s, void *unused)419{420 struct mvpp2_dbgfs_prs_entry *entry = s->private;421 int val;422 423 val = mvpp2_prs_hits(entry->priv, entry->tid);424 if (val < 0)425 return val;426 427 seq_printf(s, "%d\n", val);428 429 return 0;430}431 432DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_hits);433 434static int mvpp2_dbgfs_prs_valid_show(struct seq_file *s, void *unused)435{436 struct mvpp2_dbgfs_prs_entry *entry = s->private;437 struct mvpp2 *priv = entry->priv;438 int tid = entry->tid;439 440 seq_printf(s, "%d\n", priv->prs_shadow[tid].valid ? 1 : 0);441 442 return 0;443}444 445DEFINE_SHOW_ATTRIBUTE(mvpp2_dbgfs_prs_valid);446 447static int mvpp2_dbgfs_flow_port_init(struct dentry *parent,448 struct mvpp2_port *port,449 struct mvpp2_dbgfs_flow_entry *entry)450{451 struct mvpp2_dbgfs_port_flow_entry *port_entry;452 struct dentry *port_dir;453 454 port_dir = debugfs_create_dir(port->dev->name, parent);455 456 port_entry = &port->priv->dbgfs_entries->port_flow_entries[port->id];457 458 port_entry->port = port;459 port_entry->dbg_fe = entry;460 461 debugfs_create_file("hash_opts", 0444, port_dir, port_entry,462 &mvpp2_dbgfs_port_flow_hash_opt_fops);463 464 debugfs_create_file("engine", 0444, port_dir, port_entry,465 &mvpp2_dbgfs_port_flow_engine_fops);466 467 return 0;468}469 470static int mvpp2_dbgfs_flow_entry_init(struct dentry *parent,471 struct mvpp2 *priv, int flow)472{473 struct mvpp2_dbgfs_flow_entry *entry;474 struct dentry *flow_entry_dir;475 char flow_entry_name[10];476 int i, ret;477 478 sprintf(flow_entry_name, "%02d", flow);479 480 flow_entry_dir = debugfs_create_dir(flow_entry_name, parent);481 482 entry = &priv->dbgfs_entries->flow_entries[flow];483 484 entry->flow = flow;485 entry->priv = priv;486 487 debugfs_create_file("dec_hits", 0444, flow_entry_dir, entry,488 &mvpp2_dbgfs_flow_dec_hits_fops);489 490 debugfs_create_file("type", 0444, flow_entry_dir, entry,491 &mvpp2_dbgfs_flow_type_fops);492 493 debugfs_create_file("id", 0444, flow_entry_dir, entry,494 &mvpp2_dbgfs_flow_id_fops);495 496 /* Create entry for each port */497 for (i = 0; i < priv->port_count; i++) {498 ret = mvpp2_dbgfs_flow_port_init(flow_entry_dir,499 priv->port_list[i], entry);500 if (ret)501 return ret;502 }503 504 return 0;505}506 507static int mvpp2_dbgfs_flow_init(struct dentry *parent, struct mvpp2 *priv)508{509 struct dentry *flow_dir;510 int i, ret;511 512 flow_dir = debugfs_create_dir("flows", parent);513 514 for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) {515 ret = mvpp2_dbgfs_flow_entry_init(flow_dir, priv, i);516 if (ret)517 return ret;518 }519 520 return 0;521}522 523static int mvpp2_dbgfs_prs_entry_init(struct dentry *parent,524 struct mvpp2 *priv, int tid)525{526 struct mvpp2_dbgfs_prs_entry *entry;527 struct dentry *prs_entry_dir;528 char prs_entry_name[10];529 530 if (tid >= MVPP2_PRS_TCAM_SRAM_SIZE)531 return -EINVAL;532 533 sprintf(prs_entry_name, "%03d", tid);534 535 prs_entry_dir = debugfs_create_dir(prs_entry_name, parent);536 537 entry = &priv->dbgfs_entries->prs_entries[tid];538 539 entry->tid = tid;540 entry->priv = priv;541 542 /* Create each attr */543 debugfs_create_file("sram", 0444, prs_entry_dir, entry,544 &mvpp2_dbgfs_prs_sram_fops);545 546 debugfs_create_file("valid", 0644, prs_entry_dir, entry,547 &mvpp2_dbgfs_prs_valid_fops);548 549 debugfs_create_file("lookup_id", 0644, prs_entry_dir, entry,550 &mvpp2_dbgfs_prs_lu_fops);551 552 debugfs_create_file("ai", 0644, prs_entry_dir, entry,553 &mvpp2_dbgfs_prs_ai_fops);554 555 debugfs_create_file("header_data", 0644, prs_entry_dir, entry,556 &mvpp2_dbgfs_prs_hdata_fops);557 558 debugfs_create_file("hits", 0444, prs_entry_dir, entry,559 &mvpp2_dbgfs_prs_hits_fops);560 561 debugfs_create_file("pmap", 0444, prs_entry_dir, entry,562 &mvpp2_dbgfs_prs_pmap_fops);563 564 return 0;565}566 567static int mvpp2_dbgfs_prs_init(struct dentry *parent, struct mvpp2 *priv)568{569 struct dentry *prs_dir;570 int i, ret;571 572 prs_dir = debugfs_create_dir("parser", parent);573 574 for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {575 ret = mvpp2_dbgfs_prs_entry_init(prs_dir, priv, i);576 if (ret)577 return ret;578 }579 580 return 0;581}582 583static int mvpp2_dbgfs_c2_entry_init(struct dentry *parent,584 struct mvpp2 *priv, int id)585{586 struct mvpp2_dbgfs_c2_entry *entry;587 struct dentry *c2_entry_dir;588 char c2_entry_name[10];589 590 if (id >= MVPP22_CLS_C2_N_ENTRIES)591 return -EINVAL;592 593 sprintf(c2_entry_name, "%03d", id);594 595 c2_entry_dir = debugfs_create_dir(c2_entry_name, parent);596 597 entry = &priv->dbgfs_entries->c2_entries[id];598 599 entry->id = id;600 entry->priv = priv;601 602 debugfs_create_file("hits", 0444, c2_entry_dir, entry,603 &mvpp2_dbgfs_flow_c2_hits_fops);604 605 debugfs_create_file("default_rxq", 0444, c2_entry_dir, entry,606 &mvpp2_dbgfs_flow_c2_rxq_fops);607 608 debugfs_create_file("rss_enable", 0444, c2_entry_dir, entry,609 &mvpp2_dbgfs_flow_c2_enable_fops);610 611 return 0;612}613 614static int mvpp2_dbgfs_flow_tbl_entry_init(struct dentry *parent,615 struct mvpp2 *priv, int id)616{617 struct mvpp2_dbgfs_flow_tbl_entry *entry;618 struct dentry *flow_tbl_entry_dir;619 char flow_tbl_entry_name[10];620 621 if (id >= MVPP2_CLS_FLOWS_TBL_SIZE)622 return -EINVAL;623 624 sprintf(flow_tbl_entry_name, "%03d", id);625 626 flow_tbl_entry_dir = debugfs_create_dir(flow_tbl_entry_name, parent);627 628 entry = &priv->dbgfs_entries->flt_entries[id];629 630 entry->id = id;631 entry->priv = priv;632 633 debugfs_create_file("hits", 0444, flow_tbl_entry_dir, entry,634 &mvpp2_dbgfs_flow_flt_hits_fops);635 636 return 0;637}638 639static int mvpp2_dbgfs_cls_init(struct dentry *parent, struct mvpp2 *priv)640{641 struct dentry *cls_dir, *c2_dir, *flow_tbl_dir;642 int i, ret;643 644 cls_dir = debugfs_create_dir("classifier", parent);645 646 c2_dir = debugfs_create_dir("c2", cls_dir);647 648 for (i = 0; i < MVPP22_CLS_C2_N_ENTRIES; i++) {649 ret = mvpp2_dbgfs_c2_entry_init(c2_dir, priv, i);650 if (ret)651 return ret;652 }653 654 flow_tbl_dir = debugfs_create_dir("flow_table", cls_dir);655 656 for (i = 0; i < MVPP2_CLS_FLOWS_TBL_SIZE; i++) {657 ret = mvpp2_dbgfs_flow_tbl_entry_init(flow_tbl_dir, priv, i);658 if (ret)659 return ret;660 }661 662 return 0;663}664 665static int mvpp2_dbgfs_port_init(struct dentry *parent,666 struct mvpp2_port *port)667{668 struct dentry *port_dir;669 670 port_dir = debugfs_create_dir(port->dev->name, parent);671 672 debugfs_create_file("parser_entries", 0444, port_dir, port,673 &mvpp2_dbgfs_port_parser_fops);674 675 debugfs_create_file("mac_filter", 0444, port_dir, port,676 &mvpp2_dbgfs_filter_fops);677 678 debugfs_create_file("vid_filter", 0444, port_dir, port,679 &mvpp2_dbgfs_port_vid_fops);680 681 return 0;682}683 684static struct dentry *mvpp2_root;685 686void mvpp2_dbgfs_exit(void)687{688 debugfs_remove(mvpp2_root);689}690 691void mvpp2_dbgfs_cleanup(struct mvpp2 *priv)692{693 debugfs_remove_recursive(priv->dbgfs_dir);694 695 kfree(priv->dbgfs_entries);696}697 698void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name)699{700 struct dentry *mvpp2_dir;701 int ret, i;702 703 if (!mvpp2_root)704 mvpp2_root = debugfs_create_dir(MVPP2_DRIVER_NAME, NULL);705 706 mvpp2_dir = debugfs_create_dir(name, mvpp2_root);707 708 priv->dbgfs_dir = mvpp2_dir;709 priv->dbgfs_entries = kzalloc(sizeof(*priv->dbgfs_entries), GFP_KERNEL);710 if (!priv->dbgfs_entries)711 goto err;712 713 ret = mvpp2_dbgfs_prs_init(mvpp2_dir, priv);714 if (ret)715 goto err;716 717 ret = mvpp2_dbgfs_cls_init(mvpp2_dir, priv);718 if (ret)719 goto err;720 721 for (i = 0; i < priv->port_count; i++) {722 ret = mvpp2_dbgfs_port_init(mvpp2_dir, priv->port_list[i]);723 if (ret)724 goto err;725 }726 727 ret = mvpp2_dbgfs_flow_init(mvpp2_dir, priv);728 if (ret)729 goto err;730 731 return;732err:733 mvpp2_dbgfs_cleanup(priv);734}735