1*a2a7221dSLuo Jie // SPDX-License-Identifier: GPL-2.0-only 2*a2a7221dSLuo Jie /* 3*a2a7221dSLuo Jie * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4*a2a7221dSLuo Jie */ 5*a2a7221dSLuo Jie 6*a2a7221dSLuo Jie /* PPE debugfs routines for display of PPE counters useful for debug. */ 7*a2a7221dSLuo Jie 8*a2a7221dSLuo Jie #include <linux/bitfield.h> 9*a2a7221dSLuo Jie #include <linux/debugfs.h> 10*a2a7221dSLuo Jie #include <linux/dev_printk.h> 11*a2a7221dSLuo Jie #include <linux/device.h> 12*a2a7221dSLuo Jie #include <linux/regmap.h> 13*a2a7221dSLuo Jie #include <linux/seq_file.h> 14*a2a7221dSLuo Jie 15*a2a7221dSLuo Jie #include "ppe.h" 16*a2a7221dSLuo Jie #include "ppe_config.h" 17*a2a7221dSLuo Jie #include "ppe_debugfs.h" 18*a2a7221dSLuo Jie #include "ppe_regs.h" 19*a2a7221dSLuo Jie 20*a2a7221dSLuo Jie #define PPE_PKT_CNT_TBL_SIZE 3 21*a2a7221dSLuo Jie #define PPE_DROP_PKT_CNT_TBL_SIZE 5 22*a2a7221dSLuo Jie 23*a2a7221dSLuo Jie #define PPE_W0_PKT_CNT GENMASK(31, 0) 24*a2a7221dSLuo Jie #define PPE_W2_DROP_PKT_CNT_LOW GENMASK(31, 8) 25*a2a7221dSLuo Jie #define PPE_W3_DROP_PKT_CNT_HIGH GENMASK(7, 0) 26*a2a7221dSLuo Jie 27*a2a7221dSLuo Jie #define PPE_GET_PKT_CNT(tbl_cnt) \ 28*a2a7221dSLuo Jie FIELD_GET(PPE_W0_PKT_CNT, *(tbl_cnt)) 29*a2a7221dSLuo Jie #define PPE_GET_DROP_PKT_CNT_LOW(tbl_cnt) \ 30*a2a7221dSLuo Jie FIELD_GET(PPE_W2_DROP_PKT_CNT_LOW, *((tbl_cnt) + 0x2)) 31*a2a7221dSLuo Jie #define PPE_GET_DROP_PKT_CNT_HIGH(tbl_cnt) \ 32*a2a7221dSLuo Jie FIELD_GET(PPE_W3_DROP_PKT_CNT_HIGH, *((tbl_cnt) + 0x3)) 33*a2a7221dSLuo Jie 34*a2a7221dSLuo Jie /** 35*a2a7221dSLuo Jie * enum ppe_cnt_size_type - PPE counter size type 36*a2a7221dSLuo Jie * @PPE_PKT_CNT_SIZE_1WORD: Counter size with single register 37*a2a7221dSLuo Jie * @PPE_PKT_CNT_SIZE_3WORD: Counter size with table of 3 words 38*a2a7221dSLuo Jie * @PPE_PKT_CNT_SIZE_5WORD: Counter size with table of 5 words 39*a2a7221dSLuo Jie * 40*a2a7221dSLuo Jie * PPE takes the different register size to record the packet counters. 41*a2a7221dSLuo Jie * It uses single register, or register table with 3 words or 5 words. 42*a2a7221dSLuo Jie * The counter with table size 5 words also records the drop counter. 43*a2a7221dSLuo Jie * There are also some other counter types occupying sizes less than 32 44*a2a7221dSLuo Jie * bits, which is not covered by this enumeration type. 45*a2a7221dSLuo Jie */ 46*a2a7221dSLuo Jie enum ppe_cnt_size_type { 47*a2a7221dSLuo Jie PPE_PKT_CNT_SIZE_1WORD, 48*a2a7221dSLuo Jie PPE_PKT_CNT_SIZE_3WORD, 49*a2a7221dSLuo Jie PPE_PKT_CNT_SIZE_5WORD, 50*a2a7221dSLuo Jie }; 51*a2a7221dSLuo Jie 52*a2a7221dSLuo Jie /** 53*a2a7221dSLuo Jie * enum ppe_cnt_type - PPE counter type. 54*a2a7221dSLuo Jie * @PPE_CNT_BM: Packet counter processed by BM. 55*a2a7221dSLuo Jie * @PPE_CNT_PARSE: Packet counter parsed on ingress. 56*a2a7221dSLuo Jie * @PPE_CNT_PORT_RX: Packet counter on the ingress port. 57*a2a7221dSLuo Jie * @PPE_CNT_VLAN_RX: VLAN packet counter received. 58*a2a7221dSLuo Jie * @PPE_CNT_L2_FWD: Packet counter processed by L2 forwarding. 59*a2a7221dSLuo Jie * @PPE_CNT_CPU_CODE: Packet counter marked with various CPU codes. 60*a2a7221dSLuo Jie * @PPE_CNT_VLAN_TX: VLAN packet counter transmitted. 61*a2a7221dSLuo Jie * @PPE_CNT_PORT_TX: Packet counter on the egress port. 62*a2a7221dSLuo Jie * @PPE_CNT_QM: Packet counter processed by QM. 63*a2a7221dSLuo Jie */ 64*a2a7221dSLuo Jie enum ppe_cnt_type { 65*a2a7221dSLuo Jie PPE_CNT_BM, 66*a2a7221dSLuo Jie PPE_CNT_PARSE, 67*a2a7221dSLuo Jie PPE_CNT_PORT_RX, 68*a2a7221dSLuo Jie PPE_CNT_VLAN_RX, 69*a2a7221dSLuo Jie PPE_CNT_L2_FWD, 70*a2a7221dSLuo Jie PPE_CNT_CPU_CODE, 71*a2a7221dSLuo Jie PPE_CNT_VLAN_TX, 72*a2a7221dSLuo Jie PPE_CNT_PORT_TX, 73*a2a7221dSLuo Jie PPE_CNT_QM, 74*a2a7221dSLuo Jie }; 75*a2a7221dSLuo Jie 76*a2a7221dSLuo Jie /** 77*a2a7221dSLuo Jie * struct ppe_debugfs_entry - PPE debugfs entry. 78*a2a7221dSLuo Jie * @name: Debugfs file name. 79*a2a7221dSLuo Jie * @counter_type: PPE packet counter type. 80*a2a7221dSLuo Jie * @ppe: PPE device. 81*a2a7221dSLuo Jie * 82*a2a7221dSLuo Jie * The PPE debugfs entry is used to create the debugfs file and passed 83*a2a7221dSLuo Jie * to debugfs_create_file() as private data. 84*a2a7221dSLuo Jie */ 85*a2a7221dSLuo Jie struct ppe_debugfs_entry { 86*a2a7221dSLuo Jie const char *name; 87*a2a7221dSLuo Jie enum ppe_cnt_type counter_type; 88*a2a7221dSLuo Jie struct ppe_device *ppe; 89*a2a7221dSLuo Jie }; 90*a2a7221dSLuo Jie 91*a2a7221dSLuo Jie static const struct ppe_debugfs_entry debugfs_files[] = { 92*a2a7221dSLuo Jie { 93*a2a7221dSLuo Jie .name = "bm", 94*a2a7221dSLuo Jie .counter_type = PPE_CNT_BM, 95*a2a7221dSLuo Jie }, 96*a2a7221dSLuo Jie { 97*a2a7221dSLuo Jie .name = "parse", 98*a2a7221dSLuo Jie .counter_type = PPE_CNT_PARSE, 99*a2a7221dSLuo Jie }, 100*a2a7221dSLuo Jie { 101*a2a7221dSLuo Jie .name = "port_rx", 102*a2a7221dSLuo Jie .counter_type = PPE_CNT_PORT_RX, 103*a2a7221dSLuo Jie }, 104*a2a7221dSLuo Jie { 105*a2a7221dSLuo Jie .name = "vlan_rx", 106*a2a7221dSLuo Jie .counter_type = PPE_CNT_VLAN_RX, 107*a2a7221dSLuo Jie }, 108*a2a7221dSLuo Jie { 109*a2a7221dSLuo Jie .name = "l2_forward", 110*a2a7221dSLuo Jie .counter_type = PPE_CNT_L2_FWD, 111*a2a7221dSLuo Jie }, 112*a2a7221dSLuo Jie { 113*a2a7221dSLuo Jie .name = "cpu_code", 114*a2a7221dSLuo Jie .counter_type = PPE_CNT_CPU_CODE, 115*a2a7221dSLuo Jie }, 116*a2a7221dSLuo Jie { 117*a2a7221dSLuo Jie .name = "vlan_tx", 118*a2a7221dSLuo Jie .counter_type = PPE_CNT_VLAN_TX, 119*a2a7221dSLuo Jie }, 120*a2a7221dSLuo Jie { 121*a2a7221dSLuo Jie .name = "port_tx", 122*a2a7221dSLuo Jie .counter_type = PPE_CNT_PORT_TX, 123*a2a7221dSLuo Jie }, 124*a2a7221dSLuo Jie { 125*a2a7221dSLuo Jie .name = "qm", 126*a2a7221dSLuo Jie .counter_type = PPE_CNT_QM, 127*a2a7221dSLuo Jie }, 128*a2a7221dSLuo Jie }; 129*a2a7221dSLuo Jie 130*a2a7221dSLuo Jie static int ppe_pkt_cnt_get(struct ppe_device *ppe_dev, u32 reg, 131*a2a7221dSLuo Jie enum ppe_cnt_size_type cnt_type, 132*a2a7221dSLuo Jie u32 *cnt, u32 *drop_cnt) 133*a2a7221dSLuo Jie { 134*a2a7221dSLuo Jie u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE]; 135*a2a7221dSLuo Jie u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE]; 136*a2a7221dSLuo Jie u32 value; 137*a2a7221dSLuo Jie int ret; 138*a2a7221dSLuo Jie 139*a2a7221dSLuo Jie switch (cnt_type) { 140*a2a7221dSLuo Jie case PPE_PKT_CNT_SIZE_1WORD: 141*a2a7221dSLuo Jie ret = regmap_read(ppe_dev->regmap, reg, &value); 142*a2a7221dSLuo Jie if (ret) 143*a2a7221dSLuo Jie return ret; 144*a2a7221dSLuo Jie 145*a2a7221dSLuo Jie *cnt = value; 146*a2a7221dSLuo Jie break; 147*a2a7221dSLuo Jie case PPE_PKT_CNT_SIZE_3WORD: 148*a2a7221dSLuo Jie ret = regmap_bulk_read(ppe_dev->regmap, reg, 149*a2a7221dSLuo Jie pkt_cnt, ARRAY_SIZE(pkt_cnt)); 150*a2a7221dSLuo Jie if (ret) 151*a2a7221dSLuo Jie return ret; 152*a2a7221dSLuo Jie 153*a2a7221dSLuo Jie *cnt = PPE_GET_PKT_CNT(pkt_cnt); 154*a2a7221dSLuo Jie break; 155*a2a7221dSLuo Jie case PPE_PKT_CNT_SIZE_5WORD: 156*a2a7221dSLuo Jie ret = regmap_bulk_read(ppe_dev->regmap, reg, 157*a2a7221dSLuo Jie drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt)); 158*a2a7221dSLuo Jie if (ret) 159*a2a7221dSLuo Jie return ret; 160*a2a7221dSLuo Jie 161*a2a7221dSLuo Jie *cnt = PPE_GET_PKT_CNT(drop_pkt_cnt); 162*a2a7221dSLuo Jie 163*a2a7221dSLuo Jie /* Drop counter with low 24 bits. */ 164*a2a7221dSLuo Jie value = PPE_GET_DROP_PKT_CNT_LOW(drop_pkt_cnt); 165*a2a7221dSLuo Jie *drop_cnt = FIELD_PREP(GENMASK(23, 0), value); 166*a2a7221dSLuo Jie 167*a2a7221dSLuo Jie /* Drop counter with high 8 bits. */ 168*a2a7221dSLuo Jie value = PPE_GET_DROP_PKT_CNT_HIGH(drop_pkt_cnt); 169*a2a7221dSLuo Jie *drop_cnt |= FIELD_PREP(GENMASK(31, 24), value); 170*a2a7221dSLuo Jie break; 171*a2a7221dSLuo Jie } 172*a2a7221dSLuo Jie 173*a2a7221dSLuo Jie return 0; 174*a2a7221dSLuo Jie } 175*a2a7221dSLuo Jie 176*a2a7221dSLuo Jie static void ppe_tbl_pkt_cnt_clear(struct ppe_device *ppe_dev, u32 reg, 177*a2a7221dSLuo Jie enum ppe_cnt_size_type cnt_type) 178*a2a7221dSLuo Jie { 179*a2a7221dSLuo Jie u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE] = {}; 180*a2a7221dSLuo Jie u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE] = {}; 181*a2a7221dSLuo Jie 182*a2a7221dSLuo Jie switch (cnt_type) { 183*a2a7221dSLuo Jie case PPE_PKT_CNT_SIZE_1WORD: 184*a2a7221dSLuo Jie regmap_write(ppe_dev->regmap, reg, 0); 185*a2a7221dSLuo Jie break; 186*a2a7221dSLuo Jie case PPE_PKT_CNT_SIZE_3WORD: 187*a2a7221dSLuo Jie regmap_bulk_write(ppe_dev->regmap, reg, 188*a2a7221dSLuo Jie pkt_cnt, ARRAY_SIZE(pkt_cnt)); 189*a2a7221dSLuo Jie break; 190*a2a7221dSLuo Jie case PPE_PKT_CNT_SIZE_5WORD: 191*a2a7221dSLuo Jie regmap_bulk_write(ppe_dev->regmap, reg, 192*a2a7221dSLuo Jie drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt)); 193*a2a7221dSLuo Jie break; 194*a2a7221dSLuo Jie } 195*a2a7221dSLuo Jie } 196*a2a7221dSLuo Jie 197*a2a7221dSLuo Jie static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq) 198*a2a7221dSLuo Jie { 199*a2a7221dSLuo Jie u32 reg, val, pkt_cnt, pkt_cnt1; 200*a2a7221dSLuo Jie int ret, i, tag; 201*a2a7221dSLuo Jie 202*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "BM SILENT_DROP:"); 203*a2a7221dSLuo Jie tag = 0; 204*a2a7221dSLuo Jie for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) { 205*a2a7221dSLuo Jie reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC; 206*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, 207*a2a7221dSLuo Jie &pkt_cnt, NULL); 208*a2a7221dSLuo Jie if (ret) { 209*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 210*a2a7221dSLuo Jie return ret; 211*a2a7221dSLuo Jie } 212*a2a7221dSLuo Jie 213*a2a7221dSLuo Jie if (pkt_cnt > 0) { 214*a2a7221dSLuo Jie if (!((++tag) % 4)) 215*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 216*a2a7221dSLuo Jie 217*a2a7221dSLuo Jie seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "port", i); 218*a2a7221dSLuo Jie } 219*a2a7221dSLuo Jie } 220*a2a7221dSLuo Jie 221*a2a7221dSLuo Jie seq_putc(seq, '\n'); 222*a2a7221dSLuo Jie 223*a2a7221dSLuo Jie /* The number of packets dropped because hardware buffers were 224*a2a7221dSLuo Jie * available only partially for the packet. 225*a2a7221dSLuo Jie */ 226*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "BM OVERFLOW_DROP:"); 227*a2a7221dSLuo Jie tag = 0; 228*a2a7221dSLuo Jie for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) { 229*a2a7221dSLuo Jie reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i; 230*a2a7221dSLuo Jie 231*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 232*a2a7221dSLuo Jie &pkt_cnt, NULL); 233*a2a7221dSLuo Jie if (ret) { 234*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 235*a2a7221dSLuo Jie return ret; 236*a2a7221dSLuo Jie } 237*a2a7221dSLuo Jie 238*a2a7221dSLuo Jie if (pkt_cnt > 0) { 239*a2a7221dSLuo Jie if (!((++tag) % 4)) 240*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 241*a2a7221dSLuo Jie 242*a2a7221dSLuo Jie seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "port", i); 243*a2a7221dSLuo Jie } 244*a2a7221dSLuo Jie } 245*a2a7221dSLuo Jie 246*a2a7221dSLuo Jie seq_putc(seq, '\n'); 247*a2a7221dSLuo Jie 248*a2a7221dSLuo Jie /* The number of currently occupied buffers, that can't be flushed. */ 249*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "BM USED/REACT:"); 250*a2a7221dSLuo Jie tag = 0; 251*a2a7221dSLuo Jie for (i = 0; i < PPE_BM_USED_CNT_TBL_ENTRIES; i++) { 252*a2a7221dSLuo Jie reg = PPE_BM_USED_CNT_TBL_ADDR + i * PPE_BM_USED_CNT_TBL_INC; 253*a2a7221dSLuo Jie ret = regmap_read(ppe_dev->regmap, reg, &val); 254*a2a7221dSLuo Jie if (ret) { 255*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 256*a2a7221dSLuo Jie return ret; 257*a2a7221dSLuo Jie } 258*a2a7221dSLuo Jie 259*a2a7221dSLuo Jie /* The number of PPE buffers used for caching the received 260*a2a7221dSLuo Jie * packets before the pause frame sent. 261*a2a7221dSLuo Jie */ 262*a2a7221dSLuo Jie pkt_cnt = FIELD_GET(PPE_BM_USED_CNT_VAL, val); 263*a2a7221dSLuo Jie 264*a2a7221dSLuo Jie reg = PPE_BM_REACT_CNT_TBL_ADDR + i * PPE_BM_REACT_CNT_TBL_INC; 265*a2a7221dSLuo Jie ret = regmap_read(ppe_dev->regmap, reg, &val); 266*a2a7221dSLuo Jie if (ret) { 267*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 268*a2a7221dSLuo Jie return ret; 269*a2a7221dSLuo Jie } 270*a2a7221dSLuo Jie 271*a2a7221dSLuo Jie /* The number of PPE buffers used for caching the received 272*a2a7221dSLuo Jie * packets after pause frame sent out. 273*a2a7221dSLuo Jie */ 274*a2a7221dSLuo Jie pkt_cnt1 = FIELD_GET(PPE_BM_REACT_CNT_VAL, val); 275*a2a7221dSLuo Jie 276*a2a7221dSLuo Jie if (pkt_cnt > 0 || pkt_cnt1 > 0) { 277*a2a7221dSLuo Jie if (!((++tag) % 4)) 278*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 279*a2a7221dSLuo Jie 280*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, pkt_cnt1, 281*a2a7221dSLuo Jie "port", i); 282*a2a7221dSLuo Jie } 283*a2a7221dSLuo Jie } 284*a2a7221dSLuo Jie 285*a2a7221dSLuo Jie seq_putc(seq, '\n'); 286*a2a7221dSLuo Jie 287*a2a7221dSLuo Jie return 0; 288*a2a7221dSLuo Jie } 289*a2a7221dSLuo Jie 290*a2a7221dSLuo Jie /* The number of packets processed by the ingress parser module of PPE. */ 291*a2a7221dSLuo Jie static int ppe_parse_pkt_counter_get(struct ppe_device *ppe_dev, 292*a2a7221dSLuo Jie struct seq_file *seq) 293*a2a7221dSLuo Jie { 294*a2a7221dSLuo Jie u32 reg, cnt = 0, tunnel_cnt = 0; 295*a2a7221dSLuo Jie int i, ret, tag = 0; 296*a2a7221dSLuo Jie 297*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "PARSE TPRX/IPRX:"); 298*a2a7221dSLuo Jie for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) { 299*a2a7221dSLuo Jie reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC; 300*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, 301*a2a7221dSLuo Jie &tunnel_cnt, NULL); 302*a2a7221dSLuo Jie if (ret) { 303*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 304*a2a7221dSLuo Jie return ret; 305*a2a7221dSLuo Jie } 306*a2a7221dSLuo Jie 307*a2a7221dSLuo Jie reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC; 308*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, 309*a2a7221dSLuo Jie &cnt, NULL); 310*a2a7221dSLuo Jie if (ret) { 311*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 312*a2a7221dSLuo Jie return ret; 313*a2a7221dSLuo Jie } 314*a2a7221dSLuo Jie 315*a2a7221dSLuo Jie if (tunnel_cnt > 0 || cnt > 0) { 316*a2a7221dSLuo Jie if (!((++tag) % 4)) 317*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 318*a2a7221dSLuo Jie 319*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u(%s=%04d)", tunnel_cnt, cnt, 320*a2a7221dSLuo Jie "port", i); 321*a2a7221dSLuo Jie } 322*a2a7221dSLuo Jie } 323*a2a7221dSLuo Jie 324*a2a7221dSLuo Jie seq_putc(seq, '\n'); 325*a2a7221dSLuo Jie 326*a2a7221dSLuo Jie return 0; 327*a2a7221dSLuo Jie } 328*a2a7221dSLuo Jie 329*a2a7221dSLuo Jie /* The number of packets received or dropped on the ingress port. */ 330*a2a7221dSLuo Jie static int ppe_port_rx_counter_get(struct ppe_device *ppe_dev, 331*a2a7221dSLuo Jie struct seq_file *seq) 332*a2a7221dSLuo Jie { 333*a2a7221dSLuo Jie u32 reg, pkt_cnt = 0, drop_cnt = 0; 334*a2a7221dSLuo Jie int ret, i, tag; 335*a2a7221dSLuo Jie 336*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "PORT RX/RX_DROP:"); 337*a2a7221dSLuo Jie tag = 0; 338*a2a7221dSLuo Jie for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) { 339*a2a7221dSLuo Jie reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i; 340*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, 341*a2a7221dSLuo Jie &pkt_cnt, &drop_cnt); 342*a2a7221dSLuo Jie if (ret) { 343*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 344*a2a7221dSLuo Jie return ret; 345*a2a7221dSLuo Jie } 346*a2a7221dSLuo Jie 347*a2a7221dSLuo Jie if (pkt_cnt > 0) { 348*a2a7221dSLuo Jie if (!((++tag) % 4)) 349*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 350*a2a7221dSLuo Jie 351*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt, 352*a2a7221dSLuo Jie "port", i); 353*a2a7221dSLuo Jie } 354*a2a7221dSLuo Jie } 355*a2a7221dSLuo Jie 356*a2a7221dSLuo Jie seq_putc(seq, '\n'); 357*a2a7221dSLuo Jie 358*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "VPORT RX/RX_DROP:"); 359*a2a7221dSLuo Jie tag = 0; 360*a2a7221dSLuo Jie for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) { 361*a2a7221dSLuo Jie reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i; 362*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, 363*a2a7221dSLuo Jie &pkt_cnt, &drop_cnt); 364*a2a7221dSLuo Jie if (ret) { 365*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 366*a2a7221dSLuo Jie return ret; 367*a2a7221dSLuo Jie } 368*a2a7221dSLuo Jie 369*a2a7221dSLuo Jie if (pkt_cnt > 0) { 370*a2a7221dSLuo Jie if (!((++tag) % 4)) 371*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 372*a2a7221dSLuo Jie 373*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt, 374*a2a7221dSLuo Jie "port", i); 375*a2a7221dSLuo Jie } 376*a2a7221dSLuo Jie } 377*a2a7221dSLuo Jie 378*a2a7221dSLuo Jie seq_putc(seq, '\n'); 379*a2a7221dSLuo Jie 380*a2a7221dSLuo Jie return 0; 381*a2a7221dSLuo Jie } 382*a2a7221dSLuo Jie 383*a2a7221dSLuo Jie /* The number of packets received or dropped by layer 2 processing. */ 384*a2a7221dSLuo Jie static int ppe_l2_counter_get(struct ppe_device *ppe_dev, 385*a2a7221dSLuo Jie struct seq_file *seq) 386*a2a7221dSLuo Jie { 387*a2a7221dSLuo Jie u32 reg, pkt_cnt = 0, drop_cnt = 0; 388*a2a7221dSLuo Jie int ret, i, tag = 0; 389*a2a7221dSLuo Jie 390*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "L2 RX/RX_DROP:"); 391*a2a7221dSLuo Jie for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) { 392*a2a7221dSLuo Jie reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i; 393*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, 394*a2a7221dSLuo Jie &pkt_cnt, &drop_cnt); 395*a2a7221dSLuo Jie if (ret) { 396*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 397*a2a7221dSLuo Jie return ret; 398*a2a7221dSLuo Jie } 399*a2a7221dSLuo Jie 400*a2a7221dSLuo Jie if (pkt_cnt > 0) { 401*a2a7221dSLuo Jie if (!((++tag) % 4)) 402*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 403*a2a7221dSLuo Jie 404*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt, 405*a2a7221dSLuo Jie "vsi", i); 406*a2a7221dSLuo Jie } 407*a2a7221dSLuo Jie } 408*a2a7221dSLuo Jie 409*a2a7221dSLuo Jie seq_putc(seq, '\n'); 410*a2a7221dSLuo Jie 411*a2a7221dSLuo Jie return 0; 412*a2a7221dSLuo Jie } 413*a2a7221dSLuo Jie 414*a2a7221dSLuo Jie /* The number of VLAN packets received by PPE. */ 415*a2a7221dSLuo Jie static int ppe_vlan_rx_counter_get(struct ppe_device *ppe_dev, 416*a2a7221dSLuo Jie struct seq_file *seq) 417*a2a7221dSLuo Jie { 418*a2a7221dSLuo Jie u32 reg, pkt_cnt = 0; 419*a2a7221dSLuo Jie int ret, i, tag = 0; 420*a2a7221dSLuo Jie 421*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "VLAN RX:"); 422*a2a7221dSLuo Jie for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) { 423*a2a7221dSLuo Jie reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i; 424*a2a7221dSLuo Jie 425*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 426*a2a7221dSLuo Jie &pkt_cnt, NULL); 427*a2a7221dSLuo Jie if (ret) { 428*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 429*a2a7221dSLuo Jie return ret; 430*a2a7221dSLuo Jie } 431*a2a7221dSLuo Jie 432*a2a7221dSLuo Jie if (pkt_cnt > 0) { 433*a2a7221dSLuo Jie if (!((++tag) % 4)) 434*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 435*a2a7221dSLuo Jie 436*a2a7221dSLuo Jie seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "vsi", i); 437*a2a7221dSLuo Jie } 438*a2a7221dSLuo Jie } 439*a2a7221dSLuo Jie 440*a2a7221dSLuo Jie seq_putc(seq, '\n'); 441*a2a7221dSLuo Jie 442*a2a7221dSLuo Jie return 0; 443*a2a7221dSLuo Jie } 444*a2a7221dSLuo Jie 445*a2a7221dSLuo Jie /* The number of packets handed to CPU by PPE. */ 446*a2a7221dSLuo Jie static int ppe_cpu_code_counter_get(struct ppe_device *ppe_dev, 447*a2a7221dSLuo Jie struct seq_file *seq) 448*a2a7221dSLuo Jie { 449*a2a7221dSLuo Jie u32 reg, pkt_cnt = 0; 450*a2a7221dSLuo Jie int ret, i; 451*a2a7221dSLuo Jie 452*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "CPU CODE:"); 453*a2a7221dSLuo Jie for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) { 454*a2a7221dSLuo Jie reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i; 455*a2a7221dSLuo Jie 456*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 457*a2a7221dSLuo Jie &pkt_cnt, NULL); 458*a2a7221dSLuo Jie if (ret) { 459*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 460*a2a7221dSLuo Jie return ret; 461*a2a7221dSLuo Jie } 462*a2a7221dSLuo Jie 463*a2a7221dSLuo Jie if (!pkt_cnt) 464*a2a7221dSLuo Jie continue; 465*a2a7221dSLuo Jie 466*a2a7221dSLuo Jie /* There are 256 CPU codes saved in the first 256 entries 467*a2a7221dSLuo Jie * of register table, and 128 drop codes for each PPE port 468*a2a7221dSLuo Jie * (0-7), the total entries is 256 + 8 * 128. 469*a2a7221dSLuo Jie */ 470*a2a7221dSLuo Jie if (i < 256) 471*a2a7221dSLuo Jie seq_printf(seq, "%10u(cpucode:%d)", pkt_cnt, i); 472*a2a7221dSLuo Jie else 473*a2a7221dSLuo Jie seq_printf(seq, "%10u(port=%04d),dropcode:%d", pkt_cnt, 474*a2a7221dSLuo Jie (i - 256) % 8, (i - 256) / 8); 475*a2a7221dSLuo Jie seq_putc(seq, '\n'); 476*a2a7221dSLuo Jie seq_printf(seq, "%-24s", ""); 477*a2a7221dSLuo Jie } 478*a2a7221dSLuo Jie 479*a2a7221dSLuo Jie seq_putc(seq, '\n'); 480*a2a7221dSLuo Jie 481*a2a7221dSLuo Jie return 0; 482*a2a7221dSLuo Jie } 483*a2a7221dSLuo Jie 484*a2a7221dSLuo Jie /* The number of packets forwarded by VLAN on the egress direction. */ 485*a2a7221dSLuo Jie static int ppe_vlan_tx_counter_get(struct ppe_device *ppe_dev, 486*a2a7221dSLuo Jie struct seq_file *seq) 487*a2a7221dSLuo Jie { 488*a2a7221dSLuo Jie u32 reg, pkt_cnt = 0; 489*a2a7221dSLuo Jie int ret, i, tag = 0; 490*a2a7221dSLuo Jie 491*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "VLAN TX:"); 492*a2a7221dSLuo Jie for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) { 493*a2a7221dSLuo Jie reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i; 494*a2a7221dSLuo Jie 495*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 496*a2a7221dSLuo Jie &pkt_cnt, NULL); 497*a2a7221dSLuo Jie if (ret) { 498*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 499*a2a7221dSLuo Jie return ret; 500*a2a7221dSLuo Jie } 501*a2a7221dSLuo Jie 502*a2a7221dSLuo Jie if (pkt_cnt > 0) { 503*a2a7221dSLuo Jie if (!((++tag) % 4)) 504*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 505*a2a7221dSLuo Jie 506*a2a7221dSLuo Jie seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "vsi", i); 507*a2a7221dSLuo Jie } 508*a2a7221dSLuo Jie } 509*a2a7221dSLuo Jie 510*a2a7221dSLuo Jie seq_putc(seq, '\n'); 511*a2a7221dSLuo Jie 512*a2a7221dSLuo Jie return 0; 513*a2a7221dSLuo Jie } 514*a2a7221dSLuo Jie 515*a2a7221dSLuo Jie /* The number of packets transmitted or dropped on the egress port. */ 516*a2a7221dSLuo Jie static int ppe_port_tx_counter_get(struct ppe_device *ppe_dev, 517*a2a7221dSLuo Jie struct seq_file *seq) 518*a2a7221dSLuo Jie { 519*a2a7221dSLuo Jie u32 reg, pkt_cnt = 0, drop_cnt = 0; 520*a2a7221dSLuo Jie int ret, i, tag; 521*a2a7221dSLuo Jie 522*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "VPORT TX/TX_DROP:"); 523*a2a7221dSLuo Jie tag = 0; 524*a2a7221dSLuo Jie for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) { 525*a2a7221dSLuo Jie reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i; 526*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 527*a2a7221dSLuo Jie &pkt_cnt, NULL); 528*a2a7221dSLuo Jie if (ret) { 529*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 530*a2a7221dSLuo Jie return ret; 531*a2a7221dSLuo Jie } 532*a2a7221dSLuo Jie 533*a2a7221dSLuo Jie reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i; 534*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 535*a2a7221dSLuo Jie &drop_cnt, NULL); 536*a2a7221dSLuo Jie if (ret) { 537*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 538*a2a7221dSLuo Jie return ret; 539*a2a7221dSLuo Jie } 540*a2a7221dSLuo Jie 541*a2a7221dSLuo Jie if (pkt_cnt > 0 || drop_cnt > 0) { 542*a2a7221dSLuo Jie if (!((++tag) % 4)) 543*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 544*a2a7221dSLuo Jie 545*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt, 546*a2a7221dSLuo Jie "port", i); 547*a2a7221dSLuo Jie } 548*a2a7221dSLuo Jie } 549*a2a7221dSLuo Jie 550*a2a7221dSLuo Jie seq_putc(seq, '\n'); 551*a2a7221dSLuo Jie 552*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "PORT TX/TX_DROP:"); 553*a2a7221dSLuo Jie tag = 0; 554*a2a7221dSLuo Jie for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) { 555*a2a7221dSLuo Jie reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i; 556*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 557*a2a7221dSLuo Jie &pkt_cnt, NULL); 558*a2a7221dSLuo Jie if (ret) { 559*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 560*a2a7221dSLuo Jie return ret; 561*a2a7221dSLuo Jie } 562*a2a7221dSLuo Jie 563*a2a7221dSLuo Jie reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i; 564*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 565*a2a7221dSLuo Jie &drop_cnt, NULL); 566*a2a7221dSLuo Jie if (ret) { 567*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 568*a2a7221dSLuo Jie return ret; 569*a2a7221dSLuo Jie } 570*a2a7221dSLuo Jie 571*a2a7221dSLuo Jie if (pkt_cnt > 0 || drop_cnt > 0) { 572*a2a7221dSLuo Jie if (!((++tag) % 4)) 573*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 574*a2a7221dSLuo Jie 575*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt, 576*a2a7221dSLuo Jie "port", i); 577*a2a7221dSLuo Jie } 578*a2a7221dSLuo Jie } 579*a2a7221dSLuo Jie 580*a2a7221dSLuo Jie seq_putc(seq, '\n'); 581*a2a7221dSLuo Jie 582*a2a7221dSLuo Jie return 0; 583*a2a7221dSLuo Jie } 584*a2a7221dSLuo Jie 585*a2a7221dSLuo Jie /* The number of packets transmitted or pending by the PPE queue. */ 586*a2a7221dSLuo Jie static int ppe_queue_counter_get(struct ppe_device *ppe_dev, 587*a2a7221dSLuo Jie struct seq_file *seq) 588*a2a7221dSLuo Jie { 589*a2a7221dSLuo Jie u32 reg, val, pkt_cnt = 0, pend_cnt = 0, drop_cnt = 0; 590*a2a7221dSLuo Jie int ret, i, tag = 0; 591*a2a7221dSLuo Jie 592*a2a7221dSLuo Jie seq_printf(seq, "%-24s", "QUEUE TX/PEND/DROP:"); 593*a2a7221dSLuo Jie for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) { 594*a2a7221dSLuo Jie reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i; 595*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 596*a2a7221dSLuo Jie &pkt_cnt, NULL); 597*a2a7221dSLuo Jie if (ret) { 598*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 599*a2a7221dSLuo Jie return ret; 600*a2a7221dSLuo Jie } 601*a2a7221dSLuo Jie 602*a2a7221dSLuo Jie if (i < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) { 603*a2a7221dSLuo Jie reg = PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR + 604*a2a7221dSLuo Jie PPE_AC_UNICAST_QUEUE_CNT_TBL_INC * i; 605*a2a7221dSLuo Jie ret = regmap_read(ppe_dev->regmap, reg, &val); 606*a2a7221dSLuo Jie if (ret) { 607*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 608*a2a7221dSLuo Jie return ret; 609*a2a7221dSLuo Jie } 610*a2a7221dSLuo Jie 611*a2a7221dSLuo Jie pend_cnt = FIELD_GET(PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT, val); 612*a2a7221dSLuo Jie 613*a2a7221dSLuo Jie reg = PPE_UNICAST_DROP_CNT_TBL_ADDR + 614*a2a7221dSLuo Jie PPE_AC_UNICAST_QUEUE_CNT_TBL_INC * 615*a2a7221dSLuo Jie (i * PPE_UNICAST_DROP_TYPES + PPE_UNICAST_DROP_FORCE_OFFSET); 616*a2a7221dSLuo Jie 617*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 618*a2a7221dSLuo Jie &drop_cnt, NULL); 619*a2a7221dSLuo Jie if (ret) { 620*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 621*a2a7221dSLuo Jie return ret; 622*a2a7221dSLuo Jie } 623*a2a7221dSLuo Jie } else { 624*a2a7221dSLuo Jie int mq_offset = i - PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES; 625*a2a7221dSLuo Jie 626*a2a7221dSLuo Jie reg = PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR + 627*a2a7221dSLuo Jie PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC * mq_offset; 628*a2a7221dSLuo Jie ret = regmap_read(ppe_dev->regmap, reg, &val); 629*a2a7221dSLuo Jie if (ret) { 630*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 631*a2a7221dSLuo Jie return ret; 632*a2a7221dSLuo Jie } 633*a2a7221dSLuo Jie 634*a2a7221dSLuo Jie pend_cnt = FIELD_GET(PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT, val); 635*a2a7221dSLuo Jie 636*a2a7221dSLuo Jie if (mq_offset < PPE_P0_MULTICAST_QUEUE_NUM) { 637*a2a7221dSLuo Jie reg = PPE_CPU_PORT_MULTICAST_FORCE_DROP_CNT_TBL_ADDR(mq_offset); 638*a2a7221dSLuo Jie } else { 639*a2a7221dSLuo Jie mq_offset -= PPE_P0_MULTICAST_QUEUE_NUM; 640*a2a7221dSLuo Jie 641*a2a7221dSLuo Jie reg = PPE_P1_MULTICAST_DROP_CNT_TBL_ADDR; 642*a2a7221dSLuo Jie reg += (mq_offset / PPE_MULTICAST_QUEUE_NUM) * 643*a2a7221dSLuo Jie PPE_MULTICAST_QUEUE_PORT_ADDR_INC; 644*a2a7221dSLuo Jie reg += (mq_offset % PPE_MULTICAST_QUEUE_NUM) * 645*a2a7221dSLuo Jie PPE_MULTICAST_DROP_CNT_TBL_INC * 646*a2a7221dSLuo Jie PPE_MULTICAST_DROP_TYPES; 647*a2a7221dSLuo Jie } 648*a2a7221dSLuo Jie 649*a2a7221dSLuo Jie ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, 650*a2a7221dSLuo Jie &drop_cnt, NULL); 651*a2a7221dSLuo Jie if (ret) { 652*a2a7221dSLuo Jie dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret); 653*a2a7221dSLuo Jie return ret; 654*a2a7221dSLuo Jie } 655*a2a7221dSLuo Jie } 656*a2a7221dSLuo Jie 657*a2a7221dSLuo Jie if (pkt_cnt > 0 || pend_cnt > 0 || drop_cnt > 0) { 658*a2a7221dSLuo Jie if (!((++tag) % 4)) 659*a2a7221dSLuo Jie seq_printf(seq, "\n%-24s", ""); 660*a2a7221dSLuo Jie 661*a2a7221dSLuo Jie seq_printf(seq, "%10u/%u/%u(%s=%04d)", 662*a2a7221dSLuo Jie pkt_cnt, pend_cnt, drop_cnt, "queue", i); 663*a2a7221dSLuo Jie } 664*a2a7221dSLuo Jie } 665*a2a7221dSLuo Jie 666*a2a7221dSLuo Jie seq_putc(seq, '\n'); 667*a2a7221dSLuo Jie 668*a2a7221dSLuo Jie return 0; 669*a2a7221dSLuo Jie } 670*a2a7221dSLuo Jie 671*a2a7221dSLuo Jie /* Display the various packet counters of PPE. */ 672*a2a7221dSLuo Jie static int ppe_packet_counter_show(struct seq_file *seq, void *v) 673*a2a7221dSLuo Jie { 674*a2a7221dSLuo Jie struct ppe_debugfs_entry *entry = seq->private; 675*a2a7221dSLuo Jie struct ppe_device *ppe_dev = entry->ppe; 676*a2a7221dSLuo Jie int ret; 677*a2a7221dSLuo Jie 678*a2a7221dSLuo Jie switch (entry->counter_type) { 679*a2a7221dSLuo Jie case PPE_CNT_BM: 680*a2a7221dSLuo Jie ret = ppe_bm_counter_get(ppe_dev, seq); 681*a2a7221dSLuo Jie break; 682*a2a7221dSLuo Jie case PPE_CNT_PARSE: 683*a2a7221dSLuo Jie ret = ppe_parse_pkt_counter_get(ppe_dev, seq); 684*a2a7221dSLuo Jie break; 685*a2a7221dSLuo Jie case PPE_CNT_PORT_RX: 686*a2a7221dSLuo Jie ret = ppe_port_rx_counter_get(ppe_dev, seq); 687*a2a7221dSLuo Jie break; 688*a2a7221dSLuo Jie case PPE_CNT_VLAN_RX: 689*a2a7221dSLuo Jie ret = ppe_vlan_rx_counter_get(ppe_dev, seq); 690*a2a7221dSLuo Jie break; 691*a2a7221dSLuo Jie case PPE_CNT_L2_FWD: 692*a2a7221dSLuo Jie ret = ppe_l2_counter_get(ppe_dev, seq); 693*a2a7221dSLuo Jie break; 694*a2a7221dSLuo Jie case PPE_CNT_CPU_CODE: 695*a2a7221dSLuo Jie ret = ppe_cpu_code_counter_get(ppe_dev, seq); 696*a2a7221dSLuo Jie break; 697*a2a7221dSLuo Jie case PPE_CNT_VLAN_TX: 698*a2a7221dSLuo Jie ret = ppe_vlan_tx_counter_get(ppe_dev, seq); 699*a2a7221dSLuo Jie break; 700*a2a7221dSLuo Jie case PPE_CNT_PORT_TX: 701*a2a7221dSLuo Jie ret = ppe_port_tx_counter_get(ppe_dev, seq); 702*a2a7221dSLuo Jie break; 703*a2a7221dSLuo Jie case PPE_CNT_QM: 704*a2a7221dSLuo Jie ret = ppe_queue_counter_get(ppe_dev, seq); 705*a2a7221dSLuo Jie break; 706*a2a7221dSLuo Jie default: 707*a2a7221dSLuo Jie ret = -EINVAL; 708*a2a7221dSLuo Jie break; 709*a2a7221dSLuo Jie } 710*a2a7221dSLuo Jie 711*a2a7221dSLuo Jie return ret; 712*a2a7221dSLuo Jie } 713*a2a7221dSLuo Jie 714*a2a7221dSLuo Jie /* Flush the various packet counters of PPE. */ 715*a2a7221dSLuo Jie static ssize_t ppe_packet_counter_write(struct file *file, 716*a2a7221dSLuo Jie const char __user *buf, 717*a2a7221dSLuo Jie size_t count, loff_t *pos) 718*a2a7221dSLuo Jie { 719*a2a7221dSLuo Jie struct ppe_debugfs_entry *entry = file_inode(file)->i_private; 720*a2a7221dSLuo Jie struct ppe_device *ppe_dev = entry->ppe; 721*a2a7221dSLuo Jie u32 reg; 722*a2a7221dSLuo Jie int i; 723*a2a7221dSLuo Jie 724*a2a7221dSLuo Jie switch (entry->counter_type) { 725*a2a7221dSLuo Jie case PPE_CNT_BM: 726*a2a7221dSLuo Jie for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) { 727*a2a7221dSLuo Jie reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC; 728*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); 729*a2a7221dSLuo Jie } 730*a2a7221dSLuo Jie 731*a2a7221dSLuo Jie for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) { 732*a2a7221dSLuo Jie reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i; 733*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 734*a2a7221dSLuo Jie } 735*a2a7221dSLuo Jie 736*a2a7221dSLuo Jie break; 737*a2a7221dSLuo Jie case PPE_CNT_PARSE: 738*a2a7221dSLuo Jie for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) { 739*a2a7221dSLuo Jie reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC; 740*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); 741*a2a7221dSLuo Jie 742*a2a7221dSLuo Jie reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC; 743*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); 744*a2a7221dSLuo Jie } 745*a2a7221dSLuo Jie 746*a2a7221dSLuo Jie break; 747*a2a7221dSLuo Jie case PPE_CNT_PORT_RX: 748*a2a7221dSLuo Jie for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) { 749*a2a7221dSLuo Jie reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i; 750*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); 751*a2a7221dSLuo Jie } 752*a2a7221dSLuo Jie 753*a2a7221dSLuo Jie for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) { 754*a2a7221dSLuo Jie reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i; 755*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); 756*a2a7221dSLuo Jie } 757*a2a7221dSLuo Jie 758*a2a7221dSLuo Jie break; 759*a2a7221dSLuo Jie case PPE_CNT_VLAN_RX: 760*a2a7221dSLuo Jie for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) { 761*a2a7221dSLuo Jie reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i; 762*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 763*a2a7221dSLuo Jie } 764*a2a7221dSLuo Jie 765*a2a7221dSLuo Jie break; 766*a2a7221dSLuo Jie case PPE_CNT_L2_FWD: 767*a2a7221dSLuo Jie for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) { 768*a2a7221dSLuo Jie reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i; 769*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); 770*a2a7221dSLuo Jie } 771*a2a7221dSLuo Jie 772*a2a7221dSLuo Jie break; 773*a2a7221dSLuo Jie case PPE_CNT_CPU_CODE: 774*a2a7221dSLuo Jie for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) { 775*a2a7221dSLuo Jie reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i; 776*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 777*a2a7221dSLuo Jie } 778*a2a7221dSLuo Jie 779*a2a7221dSLuo Jie break; 780*a2a7221dSLuo Jie case PPE_CNT_VLAN_TX: 781*a2a7221dSLuo Jie for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) { 782*a2a7221dSLuo Jie reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i; 783*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 784*a2a7221dSLuo Jie } 785*a2a7221dSLuo Jie 786*a2a7221dSLuo Jie break; 787*a2a7221dSLuo Jie case PPE_CNT_PORT_TX: 788*a2a7221dSLuo Jie for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) { 789*a2a7221dSLuo Jie reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i; 790*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 791*a2a7221dSLuo Jie 792*a2a7221dSLuo Jie reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i; 793*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 794*a2a7221dSLuo Jie } 795*a2a7221dSLuo Jie 796*a2a7221dSLuo Jie for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) { 797*a2a7221dSLuo Jie reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i; 798*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 799*a2a7221dSLuo Jie 800*a2a7221dSLuo Jie reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i; 801*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 802*a2a7221dSLuo Jie } 803*a2a7221dSLuo Jie 804*a2a7221dSLuo Jie break; 805*a2a7221dSLuo Jie case PPE_CNT_QM: 806*a2a7221dSLuo Jie for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) { 807*a2a7221dSLuo Jie reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i; 808*a2a7221dSLuo Jie ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); 809*a2a7221dSLuo Jie } 810*a2a7221dSLuo Jie 811*a2a7221dSLuo Jie break; 812*a2a7221dSLuo Jie default: 813*a2a7221dSLuo Jie break; 814*a2a7221dSLuo Jie } 815*a2a7221dSLuo Jie 816*a2a7221dSLuo Jie return count; 817*a2a7221dSLuo Jie } 818*a2a7221dSLuo Jie DEFINE_SHOW_STORE_ATTRIBUTE(ppe_packet_counter); 819*a2a7221dSLuo Jie 820*a2a7221dSLuo Jie void ppe_debugfs_setup(struct ppe_device *ppe_dev) 821*a2a7221dSLuo Jie { 822*a2a7221dSLuo Jie struct ppe_debugfs_entry *entry; 823*a2a7221dSLuo Jie int i; 824*a2a7221dSLuo Jie 825*a2a7221dSLuo Jie ppe_dev->debugfs_root = debugfs_create_dir("ppe", NULL); 826*a2a7221dSLuo Jie if (IS_ERR(ppe_dev->debugfs_root)) 827*a2a7221dSLuo Jie return; 828*a2a7221dSLuo Jie 829*a2a7221dSLuo Jie for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) { 830*a2a7221dSLuo Jie entry = devm_kzalloc(ppe_dev->dev, sizeof(*entry), GFP_KERNEL); 831*a2a7221dSLuo Jie if (!entry) 832*a2a7221dSLuo Jie return; 833*a2a7221dSLuo Jie 834*a2a7221dSLuo Jie entry->ppe = ppe_dev; 835*a2a7221dSLuo Jie entry->counter_type = debugfs_files[i].counter_type; 836*a2a7221dSLuo Jie 837*a2a7221dSLuo Jie debugfs_create_file(debugfs_files[i].name, 0444, 838*a2a7221dSLuo Jie ppe_dev->debugfs_root, entry, 839*a2a7221dSLuo Jie &ppe_packet_counter_fops); 840*a2a7221dSLuo Jie } 841*a2a7221dSLuo Jie } 842*a2a7221dSLuo Jie 843*a2a7221dSLuo Jie void ppe_debugfs_teardown(struct ppe_device *ppe_dev) 844*a2a7221dSLuo Jie { 845*a2a7221dSLuo Jie debugfs_remove_recursive(ppe_dev->debugfs_root); 846*a2a7221dSLuo Jie ppe_dev->debugfs_root = NULL; 847*a2a7221dSLuo Jie } 848