// SPDX-License-Identifier: GPL-2.0 /* * HiSilicon PCIe Trace and Tuning (PTT) support * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. */ #include #include #include #include #include #include #include #include #include #include "../color.h" #include "hisi-ptt-pkt-decoder.h" /* * For 8DW format, the bit[31:11] of DW0 is always 0x1fffff, which can be * used to distinguish the data format. * 8DW format is like: * bits [ 31:11 ][ 10:0 ] * |---------------------------------------|-------------------| * DW0 [ 0x1fffff ][ Reserved (0x7ff) ] * DW1 [ Prefix ] * DW2 [ Header DW0 ] * DW3 [ Header DW1 ] * DW4 [ Header DW2 ] * DW5 [ Header DW3 ] * DW6 [ Reserved (0x0) ] * DW7 [ Time ] * * 4DW format is like: * bits [31:30] [ 29:25 ][24][23][22][21][ 20:11 ][ 10:0 ] * |-----|---------|---|---|---|---|-------------|-------------| * DW0 [ Fmt ][ Type ][T9][T8][TH][SO][ Length ][ Time ] * DW1 [ Header DW1 ] * DW2 [ Header DW2 ] * DW3 [ Header DW3 ] */ enum hisi_ptt_8dw_pkt_field_type { HISI_PTT_8DW_CHK_AND_RSV0, HISI_PTT_8DW_PREFIX, HISI_PTT_8DW_HEAD0, HISI_PTT_8DW_HEAD1, HISI_PTT_8DW_HEAD2, HISI_PTT_8DW_HEAD3, HISI_PTT_8DW_RSV1, HISI_PTT_8DW_TIME, HISI_PTT_8DW_TYPE_MAX }; enum hisi_ptt_4dw_pkt_field_type { HISI_PTT_4DW_HEAD1, HISI_PTT_4DW_HEAD2, HISI_PTT_4DW_HEAD3, HISI_PTT_4DW_TYPE_MAX }; static const char * const hisi_ptt_8dw_pkt_field_name[] = { [HISI_PTT_8DW_PREFIX] = "Prefix", [HISI_PTT_8DW_HEAD0] = "Header DW0", [HISI_PTT_8DW_HEAD1] = "Header DW1", [HISI_PTT_8DW_HEAD2] = "Header DW2", [HISI_PTT_8DW_HEAD3] = "Header DW3", [HISI_PTT_8DW_TIME] = "Time" }; static const char * const hisi_ptt_4dw_pkt_field_name[] = { [HISI_PTT_4DW_HEAD1] = "Header DW1", [HISI_PTT_4DW_HEAD2] = "Header DW2", [HISI_PTT_4DW_HEAD3] = "Header DW3", }; static void hisi_ptt_print_pkt(const unsigned char *buf, int pos, const char *desc) { const char *color = PERF_COLOR_BLUE; uint8_t byte; uint32_t dw; int i; dw = get_unaligned_le32(buf + pos); printf("."); color_fprintf(stdout, color, " %08x: ", pos); for (i = 0; i < HISI_PTT_FIELD_LENGTH; i++) { byte = (dw >> (24 - i * 8)) & 0xFF; color_fprintf(stdout, color, "%02x ", byte); } for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++) color_fprintf(stdout, color, " "); color_fprintf(stdout, color, " %s\n", desc); } static int hisi_ptt_8dw_pkt_desc(const unsigned char *buf, int pos) { int i; for (i = 0; i < HISI_PTT_8DW_TYPE_MAX; i++) { /* Do not show 8DW check field and reserved fields */ if (i == HISI_PTT_8DW_CHK_AND_RSV0 || i == HISI_PTT_8DW_RSV1) { pos += HISI_PTT_FIELD_LENGTH; continue; } hisi_ptt_print_pkt(buf, pos, hisi_ptt_8dw_pkt_field_name[i]); pos += HISI_PTT_FIELD_LENGTH; } return hisi_ptt_pkt_size[HISI_PTT_8DW_PKT]; } static void hisi_ptt_4dw_print_dw0(const unsigned char *buf, int pos) { const char *color = PERF_COLOR_BLUE; uint8_t byte; uint32_t dw; int i; dw = get_unaligned_le32(buf + pos); printf("."); color_fprintf(stdout, color, " %08x: ", pos); for (i = 0; i < HISI_PTT_FIELD_LENGTH; i++) { byte = (dw >> (24 - i * 8)) & 0xFF; color_fprintf(stdout, color, "%02x ", byte); } for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++) color_fprintf(stdout, color, " "); color_fprintf(stdout, color, " %s %x %s %x %s %x %s %x %s %x %s %x %s %x %s %x\n", "Format", FIELD_GET(HISI_PTT_HEAD0_4DW_FORMAT, dw), "Type", FIELD_GET(HISI_PTT_HEAD0_4DW_TYPE, dw), "T9", FIELD_GET(HISI_PTT_HEAD0_4DW_T9, dw), "T8", FIELD_GET(HISI_PTT_HEAD0_4DW_T8, dw), "TH", FIELD_GET(HISI_PTT_HEAD0_4DW_TH, dw), "SO", FIELD_GET(HISI_PTT_HEAD0_4DW_SO, dw), "Length", FIELD_GET(HISI_PTT_HEAD0_4DW_LEN, dw), "Time", FIELD_GET(HISI_PTT_HEAD0_4DW_TIME, dw)); } static int hisi_ptt_4dw_pkt_desc(const unsigned char *buf, int pos) { int i; hisi_ptt_4dw_print_dw0(buf, pos); pos += HISI_PTT_FIELD_LENGTH; for (i = 0; i < HISI_PTT_4DW_TYPE_MAX; i++) { hisi_ptt_print_pkt(buf, pos, hisi_ptt_4dw_pkt_field_name[i]); pos += HISI_PTT_FIELD_LENGTH; } return hisi_ptt_pkt_size[HISI_PTT_4DW_PKT]; } int hisi_ptt_pkt_desc(const unsigned char *buf, int pos, enum hisi_ptt_pkt_type type) { if (type == HISI_PTT_8DW_PKT) return hisi_ptt_8dw_pkt_desc(buf, pos); return hisi_ptt_4dw_pkt_desc(buf, pos); }