summaryrefslogtreecommitdiff
path: root/drivers/platform/mellanox/mlxbf-pmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/mellanox/mlxbf-pmc.c')
-rw-r--r--drivers/platform/mellanox/mlxbf-pmc.c1220
1 files changed, 1056 insertions, 164 deletions
diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c
index 65b4a819f1bd..16a2fd9fdd9b 100644
--- a/drivers/platform/mellanox/mlxbf-pmc.c
+++ b/drivers/platform/mellanox/mlxbf-pmc.c
@@ -15,6 +15,7 @@
#include <linux/hwmon.h>
#include <linux/platform_device.h>
#include <linux/string.h>
+#include <linux/string_helpers.h>
#include <uapi/linux/psci.h>
#define MLXBF_PMC_WRITE_REG_32 0x82000009
@@ -30,14 +31,16 @@
#define MLXBF_PMC_EVENT_SET_BF1 0
#define MLXBF_PMC_EVENT_SET_BF2 1
+#define MLXBF_PMC_EVENT_SET_BF3 2
#define MLXBF_PMC_EVENT_INFO_LEN 100
-#define MLXBF_PMC_MAX_BLOCKS 30
-#define MLXBF_PMC_MAX_ATTRS 30
+#define MLXBF_PMC_MAX_BLOCKS 40
+#define MLXBF_PMC_MAX_ATTRS 70
#define MLXBF_PMC_INFO_SZ 4
#define MLXBF_PMC_REG_SIZE 8
#define MLXBF_PMC_L3C_REG_SIZE 4
+#define MLXBF_PMC_TYPE_CRSPACE 2
#define MLXBF_PMC_TYPE_COUNTER 1
#define MLXBF_PMC_TYPE_REGISTER 0
@@ -78,6 +81,17 @@
#define MLXBF_PMC_L3C_PERF_CNT_LOW_VAL GENMASK(31, 0)
#define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0)
+#define MLXBF_PMC_CRSPACE_PERFMON_REG0 0x0
+#define MLXBF_PMC_CRSPACE_PERFSEL_SZ 4
+#define MLXBF_PMC_CRSPACE_PERFSEL0 GENMASK(23, 16)
+#define MLXBF_PMC_CRSPACE_PERFSEL1 GENMASK(7, 0)
+#define MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ 0x2
+#define MLXBF_PMC_CRSPACE_PERFMON_CTL(n) (n * MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ)
+#define MLXBF_PMC_CRSPACE_PERFMON_EN BIT(30)
+#define MLXBF_PMC_CRSPACE_PERFMON_CLR BIT(28)
+#define MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0x4)
+#define MLXBF_PMC_CRSPACE_PERFMON_VAL0(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0xc)
+
/**
* struct mlxbf_pmc_attribute - Structure to hold attribute and block info
* for each sysfs entry
@@ -87,8 +101,8 @@
*/
struct mlxbf_pmc_attribute {
struct device_attribute dev_attr;
- int index;
- int nr;
+ unsigned int index;
+ unsigned int nr;
};
/**
@@ -102,6 +116,7 @@ struct mlxbf_pmc_attribute {
* @attr_event: Attributes for "event" sysfs files
* @attr_event_list: Attributes for "event_list" sysfs files
* @attr_enable: Attributes for "enable" sysfs files
+ * @attr_count_clock: Attributes for "count_clock" sysfs files
* @block_attr: All attributes needed for the block
* @block_attr_grp: Attribute group for the block
*/
@@ -109,11 +124,12 @@ struct mlxbf_pmc_block_info {
void __iomem *mmio_base;
size_t blk_size;
size_t counters;
- int type;
+ unsigned int type;
struct mlxbf_pmc_attribute *attr_counter;
struct mlxbf_pmc_attribute *attr_event;
struct mlxbf_pmc_attribute attr_event_list;
struct mlxbf_pmc_attribute attr_enable;
+ struct mlxbf_pmc_attribute attr_count_clock;
struct attribute *block_attr[MLXBF_PMC_MAX_ATTRS];
struct attribute_group block_attr_grp;
};
@@ -124,6 +140,10 @@ struct mlxbf_pmc_block_info {
* @pdev: The kernel structure representing the device
* @total_blocks: Total number of blocks
* @tile_count: Number of tiles in the system
+ * @apt_enable: Info on enabled APTs
+ * @llt_enable: Info on enabled LLTs
+ * @mss_enable: Info on enabled MSSs
+ * @group_num: Group number assigned to each valid block
* @hwmon_dev: Hwmon device for bfperf
* @block_name: Block name
* @block: Block info
@@ -134,14 +154,18 @@ struct mlxbf_pmc_block_info {
*/
struct mlxbf_pmc_context {
struct platform_device *pdev;
- uint32_t total_blocks;
- uint32_t tile_count;
+ u32 total_blocks;
+ u32 tile_count;
+ u8 apt_enable;
+ u8 llt_enable;
+ u8 mss_enable;
+ u32 group_num;
struct device *hwmon_dev;
const char *block_name[MLXBF_PMC_MAX_BLOCKS];
struct mlxbf_pmc_block_info block[MLXBF_PMC_MAX_BLOCKS];
const struct attribute_group *groups[MLXBF_PMC_MAX_BLOCKS];
bool svc_sreg_support;
- uint32_t sreg_tbl_perf;
+ u32 sreg_tbl_perf;
unsigned int event_set;
};
@@ -151,7 +175,7 @@ struct mlxbf_pmc_context {
* @evt_name: Name of the event
*/
struct mlxbf_pmc_events {
- int evt_num;
+ u32 evt_num;
char *evt_name;
};
@@ -191,6 +215,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_smgen_events[] = {
};
static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = {
+ { 0x0, "DISABLE" },
{ 0xa0, "TPIO_DATA_BEAT" },
{ 0xa1, "TDMA_DATA_BEAT" },
{ 0xa2, "MAP_DATA_BEAT" },
@@ -214,6 +239,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = {
};
static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = {
+ { 0x0, "DISABLE" },
{ 0xa0, "TPIO_DATA_BEAT" },
{ 0xa1, "TDMA_DATA_BEAT" },
{ 0xa2, "MAP_DATA_BEAT" },
@@ -246,6 +272,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = {
};
static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = {
+ { 0x0, "DISABLE" },
{ 0x100, "ECC_SINGLE_ERROR_CNT" },
{ 0x104, "ECC_DOUBLE_ERROR_CNT" },
{ 0x114, "SERR_INJ" },
@@ -257,14 +284,174 @@ static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = {
{ 0x348, "DRAM_ECC_ERROR" },
};
-static const struct mlxbf_pmc_events mlxbf_pmc_mss_events[] = {
+static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_1[] = {
+ { 0x0, "DISABLE" },
{ 0xc0, "RXREQ_MSS" },
{ 0xc1, "RXDAT_MSS" },
{ 0xc2, "TXRSP_MSS" },
{ 0xc3, "TXDAT_MSS" },
};
+static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_3[] = {
+ {0, "SKYLIB_CDN_TX_FLITS"},
+ {1, "SKYLIB_DDN_TX_FLITS"},
+ {2, "SKYLIB_NDN_TX_FLITS"},
+ {3, "SKYLIB_SDN_TX_FLITS"},
+ {4, "SKYLIB_UDN_TX_FLITS"},
+ {5, "SKYLIB_CDN_RX_FLITS"},
+ {6, "SKYLIB_DDN_RX_FLITS"},
+ {7, "SKYLIB_NDN_RX_FLITS"},
+ {8, "SKYLIB_SDN_RX_FLITS"},
+ {9, "SKYLIB_UDN_RX_FLITS"},
+ {10, "SKYLIB_CDN_TX_STALL"},
+ {11, "SKYLIB_DDN_TX_STALL"},
+ {12, "SKYLIB_NDN_TX_STALL"},
+ {13, "SKYLIB_SDN_TX_STALL"},
+ {14, "SKYLIB_UDN_TX_STALL"},
+ {15, "SKYLIB_CDN_RX_STALL"},
+ {16, "SKYLIB_DDN_RX_STALL"},
+ {17, "SKYLIB_NDN_RX_STALL"},
+ {18, "SKYLIB_SDN_RX_STALL"},
+ {19, "SKYLIB_UDN_RX_STALL"},
+ {20, "SKYLIB_CHI_REQ0_TX_FLITS"},
+ {21, "SKYLIB_CHI_DATA0_TX_FLITS"},
+ {22, "SKYLIB_CHI_RESP0_TX_FLITS"},
+ {23, "SKYLIB_CHI_SNP0_TX_FLITS"},
+ {24, "SKYLIB_CHI_REQ1_TX_FLITS"},
+ {25, "SKYLIB_CHI_DATA1_TX_FLITS"},
+ {26, "SKYLIB_CHI_RESP1_TX_FLITS"},
+ {27, "SKYLIB_CHI_SNP1_TX_FLITS"},
+ {28, "SKYLIB_CHI_REQ2_TX_FLITS"},
+ {29, "SKYLIB_CHI_DATA2_TX_FLITS"},
+ {30, "SKYLIB_CHI_RESP2_TX_FLITS"},
+ {31, "SKYLIB_CHI_SNP2_TX_FLITS"},
+ {32, "SKYLIB_CHI_REQ3_TX_FLITS"},
+ {33, "SKYLIB_CHI_DATA3_TX_FLITS"},
+ {34, "SKYLIB_CHI_RESP3_TX_FLITS"},
+ {35, "SKYLIB_CHI_SNP3_TX_FLITS"},
+ {36, "SKYLIB_TLP_REQ_TX_FLITS"},
+ {37, "SKYLIB_TLP_RESP_TX_FLITS"},
+ {38, "SKYLIB_TLP_META_TX_FLITS"},
+ {39, "SKYLIB_AXIS_DATA_TX_FLITS"},
+ {40, "SKYLIB_AXIS_CRED_TX_FLITS"},
+ {41, "SKYLIB_APB_TX_FLITS"},
+ {42, "SKYLIB_VW_TX_FLITS"},
+ {43, "SKYLIB_GGA_MSN_W_TX_FLITS"},
+ {44, "SKYLIB_GGA_MSN_N_TX_FLITS"},
+ {45, "SKYLIB_CR_REQ_TX_FLITS"},
+ {46, "SKYLIB_CR_RESP_TX_FLITS"},
+ {47, "SKYLIB_MSN_PRNF_TX_FLITS"},
+ {48, "SKYLIB_DBG_DATA_TX_FLITS"},
+ {49, "SKYLIB_DBG_CRED_TX_FLITS"},
+ {50, "SKYLIB_CHI_REQ0_RX_FLITS"},
+ {51, "SKYLIB_CHI_DATA0_RX_FLITS"},
+ {52, "SKYLIB_CHI_RESP0_RX_FLITS"},
+ {53, "SKYLIB_CHI_SNP0_RX_FLITS"},
+ {54, "SKYLIB_CHI_REQ1_RX_FLITS"},
+ {55, "SKYLIB_CHI_DATA1_RX_FLITS"},
+ {56, "SKYLIB_CHI_RESP1_RX_FLITS"},
+ {57, "SKYLIB_CHI_SNP1_RX_FLITS"},
+ {58, "SKYLIB_CHI_REQ2_RX_FLITS"},
+ {59, "SKYLIB_CHI_DATA2_RX_FLITS"},
+ {60, "SKYLIB_CHI_RESP2_RX_FLITS"},
+ {61, "SKYLIB_CHI_SNP2_RX_FLITS"},
+ {62, "SKYLIB_CHI_REQ3_RX_FLITS"},
+ {63, "SKYLIB_CHI_DATA3_RX_FLITS"},
+ {64, "SKYLIB_CHI_RESP3_RX_FLITS"},
+ {65, "SKYLIB_CHI_SNP3_RX_FLITS"},
+ {66, "SKYLIB_TLP_REQ_RX_FLITS"},
+ {67, "SKYLIB_TLP_RESP_RX_FLITS"},
+ {68, "SKYLIB_TLP_META_RX_FLITS"},
+ {69, "SKYLIB_AXIS_DATA_RX_FLITS"},
+ {70, "SKYLIB_AXIS_CRED_RX_FLITS"},
+ {71, "SKYLIB_APB_RX_FLITS"},
+ {72, "SKYLIB_VW_RX_FLITS"},
+ {73, "SKYLIB_GGA_MSN_W_RX_FLITS"},
+ {74, "SKYLIB_GGA_MSN_N_RX_FLITS"},
+ {75, "SKYLIB_CR_REQ_RX_FLITS"},
+ {76, "SKYLIB_CR_RESP_RX_FLITS"},
+ {77, "SKYLIB_MSN_PRNF_RX_FLITS"},
+ {78, "SKYLIB_DBG_DATA_RX_FLITS"},
+ {79, "SKYLIB_DBG_CRED_RX_FLITS"},
+ {80, "SKYLIB_CHI_REQ0_TX_STALL"},
+ {81, "SKYLIB_CHI_DATA0_TX_STALL"},
+ {82, "SKYLIB_CHI_RESP0_TX_STALL"},
+ {83, "SKYLIB_CHI_SNP0_TX_STALL"},
+ {84, "SKYLIB_CHI_REQ1_TX_STALL"},
+ {85, "SKYLIB_CHI_DATA1_TX_STALL"},
+ {86, "SKYLIB_CHI_RESP1_TX_STALL"},
+ {87, "SKYLIB_CHI_SNP1_TX_STALL"},
+ {88, "SKYLIB_CHI_REQ2_TX_STALL"},
+ {89, "SKYLIB_CHI_DATA2_TX_STALL"},
+ {90, "SKYLIB_CHI_RESP2_TX_STALL"},
+ {91, "SKYLIB_CHI_SNP2_TX_STALL"},
+ {92, "SKYLIB_CHI_REQ3_TX_STALL"},
+ {93, "SKYLIB_CHI_DATA3_TX_STALL"},
+ {94, "SKYLIB_CHI_RESP3_TX_STALL"},
+ {95, "SKYLIB_CHI_SNP3_TX_STALL"},
+ {96, "SKYLIB_TLP_REQ_TX_STALL"},
+ {97, "SKYLIB_TLP_RESP_TX_STALL"},
+ {98, "SKYLIB_TLP_META_TX_STALL"},
+ {99, "SKYLIB_AXIS_DATA_TX_STALL"},
+ {100, "SKYLIB_AXIS_CRED_TX_STALL"},
+ {101, "SKYLIB_APB_TX_STALL"},
+ {102, "SKYLIB_VW_TX_STALL"},
+ {103, "SKYLIB_GGA_MSN_W_TX_STALL"},
+ {104, "SKYLIB_GGA_MSN_N_TX_STALL"},
+ {105, "SKYLIB_CR_REQ_TX_STALL"},
+ {106, "SKYLIB_CR_RESP_TX_STALL"},
+ {107, "SKYLIB_MSN_PRNF_TX_STALL"},
+ {108, "SKYLIB_DBG_DATA_TX_STALL"},
+ {109, "SKYLIB_DBG_CRED_TX_STALL"},
+ {110, "SKYLIB_CHI_REQ0_RX_STALL"},
+ {111, "SKYLIB_CHI_DATA0_RX_STALL"},
+ {112, "SKYLIB_CHI_RESP0_RX_STALL"},
+ {113, "SKYLIB_CHI_SNP0_RX_STALL"},
+ {114, "SKYLIB_CHI_REQ1_RX_STALL"},
+ {115, "SKYLIB_CHI_DATA1_RX_STALL"},
+ {116, "SKYLIB_CHI_RESP1_RX_STALL"},
+ {117, "SKYLIB_CHI_SNP1_RX_STALL"},
+ {118, "SKYLIB_CHI_REQ2_RX_STALL"},
+ {119, "SKYLIB_CHI_DATA2_RX_STALL"},
+ {120, "SKYLIB_CHI_RESP2_RX_STALL"},
+ {121, "SKYLIB_CHI_SNP2_RX_STALL"},
+ {122, "SKYLIB_CHI_REQ3_RX_STALL"},
+ {123, "SKYLIB_CHI_DATA3_RX_STALL"},
+ {124, "SKYLIB_CHI_RESP3_RX_STALL"},
+ {125, "SKYLIB_CHI_SNP3_RX_STALL"},
+ {126, "SKYLIB_TLP_REQ_RX_STALL"},
+ {127, "SKYLIB_TLP_RESP_RX_STALL"},
+ {128, "SKYLIB_TLP_META_RX_STALL"},
+ {129, "SKYLIB_AXIS_DATA_RX_STALL"},
+ {130, "SKYLIB_AXIS_CRED_RX_STALL"},
+ {131, "SKYLIB_APB_RX_STALL"},
+ {132, "SKYLIB_VW_RX_STALL"},
+ {133, "SKYLIB_GGA_MSN_W_RX_STALL"},
+ {134, "SKYLIB_GGA_MSN_N_RX_STALL"},
+ {135, "SKYLIB_CR_REQ_RX_STALL"},
+ {136, "SKYLIB_CR_RESP_RX_STALL"},
+ {137, "SKYLIB_MSN_PRNF_RX_STALL"},
+ {138, "SKYLIB_DBG_DATA_RX_STALL"},
+ {139, "SKYLIB_DBG_CRED_RX_STALL"},
+ {140, "SKYLIB_CDN_LOOPBACK_FLITS"},
+ {141, "SKYLIB_DDN_LOOPBACK_FLITS"},
+ {142, "SKYLIB_NDN_LOOPBACK_FLITS"},
+ {143, "SKYLIB_SDN_LOOPBACK_FLITS"},
+ {144, "SKYLIB_UDN_LOOPBACK_FLITS"},
+ {145, "HISTOGRAM_HISTOGRAM_BIN0"},
+ {146, "HISTOGRAM_HISTOGRAM_BIN1"},
+ {147, "HISTOGRAM_HISTOGRAM_BIN2"},
+ {148, "HISTOGRAM_HISTOGRAM_BIN3"},
+ {149, "HISTOGRAM_HISTOGRAM_BIN4"},
+ {150, "HISTOGRAM_HISTOGRAM_BIN5"},
+ {151, "HISTOGRAM_HISTOGRAM_BIN6"},
+ {152, "HISTOGRAM_HISTOGRAM_BIN7"},
+ {153, "HISTOGRAM_HISTOGRAM_BIN8"},
+ {154, "HISTOGRAM_HISTOGRAM_BIN9"},
+};
+
static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = {
+ { 0x0, "DISABLE" },
{ 0x45, "HNF_REQUESTS" },
{ 0x46, "HNF_REJECTS" },
{ 0x47, "ALL_BUSY" },
@@ -323,6 +510,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = {
};
static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = {
+ { 0x0, "DISABLE" },
{ 0x12, "CDN_REQ" },
{ 0x13, "DDN_REQ" },
{ 0x14, "NDN_REQ" },
@@ -358,7 +546,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = {
{ 0x32, "DDN_DIAG_W_INGRESS" },
{ 0x33, "DDN_DIAG_C_INGRESS" },
{ 0x34, "DDN_DIAG_CORE_SENT" },
- { 0x35, "NDN_DIAG_S_OUT_OF_CRED" },
+ { 0x35, "NDN_DIAG_N_OUT_OF_CRED" },
{ 0x36, "NDN_DIAG_S_OUT_OF_CRED" },
{ 0x37, "NDN_DIAG_E_OUT_OF_CRED" },
{ 0x38, "NDN_DIAG_W_OUT_OF_CRED" },
@@ -423,14 +611,399 @@ static const struct mlxbf_pmc_events mlxbf_pmc_l3c_events[] = {
{ 0x2b, "ANY_REJECT_BANK1" },
};
+static const struct mlxbf_pmc_events mlxbf_pmc_llt_events[] = {
+ {0, "HNF0_CYCLES"},
+ {1, "HNF0_REQS_RECEIVED"},
+ {2, "HNF0_REQS_PROCESSED"},
+ {3, "HNF0_DIR_HIT"},
+ {4, "HNF0_DIR_MISS"},
+ {5, "HNF0_DIR_RD_ALLOC"},
+ {6, "HNF0_DIR_WR_ALLOC"},
+ {7, "HNF0_DIR_VICTIM"},
+ {8, "HNF0_CL_HAZARD"},
+ {9, "HNF0_ALL_HAZARD"},
+ {10, "HNF0_PIPE_STALLS"},
+ {11, "HNF0_MEM_READS"},
+ {12, "HNF0_MEM_WRITES"},
+ {13, "HNF0_MEM_ACCESS"},
+ {14, "HNF0_DCL_READ"},
+ {15, "HNF0_DCL_INVAL"},
+ {16, "HNF0_CHI_RXDAT"},
+ {17, "HNF0_CHI_RXRSP"},
+ {18, "HNF0_CHI_TXDAT"},
+ {19, "HNF0_CHI_TXRSP"},
+ {20, "HNF0_CHI_TXSNP"},
+ {21, "HNF0_DCT_SNP"},
+ {22, "HNF0_SNP_FWD_DATA"},
+ {23, "HNF0_SNP_FWD_RSP"},
+ {24, "HNF0_SNP_RSP"},
+ {25, "HNF0_EXCL_FULL"},
+ {26, "HNF0_EXCL_WRITE_F"},
+ {27, "HNF0_EXCL_WRITE_S"},
+ {28, "HNF0_EXCL_WRITE"},
+ {29, "HNF0_EXCL_READ"},
+ {30, "HNF0_REQ_BUF_EMPTY"},
+ {31, "HNF0_ALL_MAFS_BUSY"},
+ {32, "HNF0_TXDAT_NO_LCRD"},
+ {33, "HNF0_TXSNP_NO_LCRD"},
+ {34, "HNF0_TXRSP_NO_LCRD"},
+ {35, "HNF0_TXREQ_NO_LCRD"},
+ {36, "HNF0_WRITE"},
+ {37, "HNF0_READ"},
+ {38, "HNF0_ACCESS"},
+ {39, "HNF0_MAF_N_BUSY"},
+ {40, "HNF0_MAF_N_REQS"},
+ {41, "HNF0_SEL_OPCODE"},
+ {42, "HNF1_CYCLES"},
+ {43, "HNF1_REQS_RECEIVED"},
+ {44, "HNF1_REQS_PROCESSED"},
+ {45, "HNF1_DIR_HIT"},
+ {46, "HNF1_DIR_MISS"},
+ {47, "HNF1_DIR_RD_ALLOC"},
+ {48, "HNF1_DIR_WR_ALLOC"},
+ {49, "HNF1_DIR_VICTIM"},
+ {50, "HNF1_CL_HAZARD"},
+ {51, "HNF1_ALL_HAZARD"},
+ {52, "HNF1_PIPE_STALLS"},
+ {53, "HNF1_MEM_READS"},
+ {54, "HNF1_MEM_WRITES"},
+ {55, "HNF1_MEM_ACCESS"},
+ {56, "HNF1_DCL_READ"},
+ {57, "HNF1_DCL_INVAL"},
+ {58, "HNF1_CHI_RXDAT"},
+ {59, "HNF1_CHI_RXRSP"},
+ {60, "HNF1_CHI_TXDAT"},
+ {61, "HNF1_CHI_TXRSP"},
+ {62, "HNF1_CHI_TXSNP"},
+ {63, "HNF1_DCT_SNP"},
+ {64, "HNF1_SNP_FWD_DATA"},
+ {65, "HNF1_SNP_FWD_RSP"},
+ {66, "HNF1_SNP_RSP"},
+ {67, "HNF1_EXCL_FULL"},
+ {68, "HNF1_EXCL_WRITE_F"},
+ {69, "HNF1_EXCL_WRITE_S"},
+ {70, "HNF1_EXCL_WRITE"},
+ {71, "HNF1_EXCL_READ"},
+ {72, "HNF1_REQ_BUF_EMPTY"},
+ {73, "HNF1_ALL_MAFS_BUSY"},
+ {74, "HNF1_TXDAT_NO_LCRD"},
+ {75, "HNF1_TXSNP_NO_LCRD"},
+ {76, "HNF1_TXRSP_NO_LCRD"},
+ {77, "HNF1_TXREQ_NO_LCRD"},
+ {78, "HNF1_WRITE"},
+ {79, "HNF1_READ"},
+ {80, "HNF1_ACCESS"},
+ {81, "HNF1_MAF_N_BUSY"},
+ {82, "HNF1_MAF_N_REQS"},
+ {83, "HNF1_SEL_OPCODE"},
+ {84, "GDC_BANK0_RD_REQ"},
+ {85, "GDC_BANK0_WR_REQ"},
+ {86, "GDC_BANK0_ALLOCATE"},
+ {87, "GDC_BANK0_HIT"},
+ {88, "GDC_BANK0_MISS"},
+ {89, "GDC_BANK0_INVALIDATE"},
+ {90, "GDC_BANK0_EVICT"},
+ {91, "GDC_BANK0_RD_RESP"},
+ {92, "GDC_BANK0_WR_ACK"},
+ {93, "GDC_BANK0_SNOOP"},
+ {94, "GDC_BANK0_SNOOP_NORMAL"},
+ {95, "GDC_BANK0_SNOOP_FWD"},
+ {96, "GDC_BANK0_SNOOP_STASH"},
+ {97, "GDC_BANK0_SNOOP_STASH_INDPND_RD"},
+ {98, "GDC_BANK0_FOLLOWER"},
+ {99, "GDC_BANK0_FW"},
+ {100, "GDC_BANK0_HIT_DCL_BOTH"},
+ {101, "GDC_BANK0_HIT_DCL_PARTIAL"},
+ {102, "GDC_BANK0_EVICT_DCL"},
+ {103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA0"},
+ {104, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA1"},
+ {105, "GDC_BANK0_ARB_STRB"},
+ {106, "GDC_BANK0_ARB_WAIT"},
+ {107, "GDC_BANK0_GGA_STRB"},
+ {108, "GDC_BANK0_GGA_WAIT"},
+ {109, "GDC_BANK0_FW_STRB"},
+ {110, "GDC_BANK0_FW_WAIT"},
+ {111, "GDC_BANK0_SNP_STRB"},
+ {112, "GDC_BANK0_SNP_WAIT"},
+ {113, "GDC_BANK0_MISS_INARB_STRB"},
+ {114, "GDC_BANK0_MISS_INARB_WAIT"},
+ {115, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD0"},
+ {116, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD1"},
+ {117, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD2"},
+ {118, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD3"},
+ {119, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR0"},
+ {120, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR1"},
+ {121, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR2"},
+ {122, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR3"},
+ {123, "GDC_BANK1_RD_REQ"},
+ {124, "GDC_BANK1_WR_REQ"},
+ {125, "GDC_BANK1_ALLOCATE"},
+ {126, "GDC_BANK1_HIT"},
+ {127, "GDC_BANK1_MISS"},
+ {128, "GDC_BANK1_INVALIDATE"},
+ {129, "GDC_BANK1_EVICT"},
+ {130, "GDC_BANK1_RD_RESP"},
+ {131, "GDC_BANK1_WR_ACK"},
+ {132, "GDC_BANK1_SNOOP"},
+ {133, "GDC_BANK1_SNOOP_NORMAL"},
+ {134, "GDC_BANK1_SNOOP_FWD"},
+ {135, "GDC_BANK1_SNOOP_STASH"},
+ {136, "GDC_BANK1_SNOOP_STASH_INDPND_RD"},
+ {137, "GDC_BANK1_FOLLOWER"},
+ {138, "GDC_BANK1_FW"},
+ {139, "GDC_BANK1_HIT_DCL_BOTH"},
+ {140, "GDC_BANK1_HIT_DCL_PARTIAL"},
+ {141, "GDC_BANK1_EVICT_DCL"},
+ {142, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA0"},
+ {143, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA1"},
+ {144, "GDC_BANK1_ARB_STRB"},
+ {145, "GDC_BANK1_ARB_WAIT"},
+ {146, "GDC_BANK1_GGA_STRB"},
+ {147, "GDC_BANK1_GGA_WAIT"},
+ {148, "GDC_BANK1_FW_STRB"},
+ {149, "GDC_BANK1_FW_WAIT"},
+ {150, "GDC_BANK1_SNP_STRB"},
+ {151, "GDC_BANK1_SNP_WAIT"},
+ {152, "GDC_BANK1_MISS_INARB_STRB"},
+ {153, "GDC_BANK1_MISS_INARB_WAIT"},
+ {154, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD0"},
+ {155, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD1"},
+ {156, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD2"},
+ {157, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD3"},
+ {158, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR0"},
+ {159, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR1"},
+ {160, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR2"},
+ {161, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR3"},
+ {162, "HISTOGRAM_HISTOGRAM_BIN0"},
+ {163, "HISTOGRAM_HISTOGRAM_BIN1"},
+ {164, "HISTOGRAM_HISTOGRAM_BIN2"},
+ {165, "HISTOGRAM_HISTOGRAM_BIN3"},
+ {166, "HISTOGRAM_HISTOGRAM_BIN4"},
+ {167, "HISTOGRAM_HISTOGRAM_BIN5"},
+ {168, "HISTOGRAM_HISTOGRAM_BIN6"},
+ {169, "HISTOGRAM_HISTOGRAM_BIN7"},
+ {170, "HISTOGRAM_HISTOGRAM_BIN8"},
+ {171, "HISTOGRAM_HISTOGRAM_BIN9"},
+};
+
+static const struct mlxbf_pmc_events mlxbf_pmc_llt_miss_events[] = {
+ {0, "GDC_MISS_MACHINE_RD_REQ"},
+ {1, "GDC_MISS_MACHINE_WR_REQ"},
+ {2, "GDC_MISS_MACHINE_SNP_REQ"},
+ {3, "GDC_MISS_MACHINE_EVICT_REQ"},
+ {4, "GDC_MISS_MACHINE_FW_REQ"},
+ {5, "GDC_MISS_MACHINE_RD_RESP"},
+ {6, "GDC_MISS_MACHINE_WR_RESP"},
+ {7, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP"},
+ {8, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP_TXDAT"},
+ {9, "GDC_MISS_MACHINE_CHI_TXREQ"},
+ {10, "GDC_MISS_MACHINE_CHI_RXRSP"},
+ {11, "GDC_MISS_MACHINE_CHI_TXDAT"},
+ {12, "GDC_MISS_MACHINE_CHI_RXDAT"},
+ {13, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_0"},
+ {14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1 "},
+ {15, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_2"},
+ {16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3 "},
+ {17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0 "},
+ {18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1 "},
+ {19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2 "},
+ {20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3 "},
+ {21, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_0"},
+ {22, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_1"},
+ {23, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_2"},
+ {24, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_3"},
+ {25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0 "},
+ {26, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_1"},
+ {27, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_2"},
+ {28, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_3"},
+ {29, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_0"},
+ {30, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_1"},
+ {31, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_2"},
+ {32, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_3"},
+ {33, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_4"},
+ {34, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_5"},
+ {35, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_6"},
+ {36, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_0"},
+ {37, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_1"},
+ {38, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_0"},
+ {39, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_1"},
+ {40, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_0"},
+ {41, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_1"},
+ {42, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_0"},
+ {43, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_1"},
+ {44, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_0"},
+ {45, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_1"},
+ {46, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_2"},
+ {47, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_3"},
+ {48, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_0"},
+ {49, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_1"},
+ {50, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_0"},
+ {51, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_1"},
+ {52, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_0"},
+ {53, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_1"},
+ {54, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_0"},
+ {55, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_1"},
+ {56, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_2"},
+ {57, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_3"},
+ {58, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_0"},
+ {59, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_1"},
+ {60, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_2"},
+ {61, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_3"},
+ {62, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_4"},
+ {63, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_5"},
+ {64, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_6"},
+ {65, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_7"},
+ {66, "HISTOGRAM_HISTOGRAM_BIN0"},
+ {67, "HISTOGRAM_HISTOGRAM_BIN1"},
+ {68, "HISTOGRAM_HISTOGRAM_BIN2"},
+ {69, "HISTOGRAM_HISTOGRAM_BIN3"},
+ {70, "HISTOGRAM_HISTOGRAM_BIN4"},
+ {71, "HISTOGRAM_HISTOGRAM_BIN5"},
+ {72, "HISTOGRAM_HISTOGRAM_BIN6"},
+ {73, "HISTOGRAM_HISTOGRAM_BIN7"},
+ {74, "HISTOGRAM_HISTOGRAM_BIN8"},
+ {75, "HISTOGRAM_HISTOGRAM_BIN9"},
+};
+
+static const struct mlxbf_pmc_events mlxbf_pmc_clock_events[] = {
+ { 0x0, "FMON_CLK_LAST_COUNT_PLL_D1_INST0" },
+ { 0x4, "REFERENCE_WINDOW_WIDTH_PLL_D1_INST0" },
+ { 0x8, "FMON_CLK_LAST_COUNT_PLL_D1_INST1" },
+ { 0xc, "REFERENCE_WINDOW_WIDTH_PLL_D1_INST1" },
+ { 0x10, "FMON_CLK_LAST_COUNT_PLL_G1" },
+ { 0x14, "REFERENCE_WINDOW_WIDTH_PLL_G1" },
+ { 0x18, "FMON_CLK_LAST_COUNT_PLL_W1" },
+ { 0x1c, "REFERENCE_WINDOW_WIDTH_PLL_W1" },
+ { 0x20, "FMON_CLK_LAST_COUNT_PLL_T1" },
+ { 0x24, "REFERENCE_WINDOW_WIDTH_PLL_T1" },
+ { 0x28, "FMON_CLK_LAST_COUNT_PLL_A0" },
+ { 0x2c, "REFERENCE_WINDOW_WIDTH_PLL_A0" },
+ { 0x30, "FMON_CLK_LAST_COUNT_PLL_C0" },
+ { 0x34, "REFERENCE_WINDOW_WIDTH_PLL_C0" },
+ { 0x38, "FMON_CLK_LAST_COUNT_PLL_N1" },
+ { 0x3c, "REFERENCE_WINDOW_WIDTH_PLL_N1" },
+ { 0x40, "FMON_CLK_LAST_COUNT_PLL_I1" },
+ { 0x44, "REFERENCE_WINDOW_WIDTH_PLL_I1" },
+ { 0x48, "FMON_CLK_LAST_COUNT_PLL_R1" },
+ { 0x4c, "REFERENCE_WINDOW_WIDTH_PLL_R1" },
+ { 0x50, "FMON_CLK_LAST_COUNT_PLL_P1" },
+ { 0x54, "REFERENCE_WINDOW_WIDTH_PLL_P1" },
+ { 0x58, "FMON_CLK_LAST_COUNT_REF_100_INST0" },
+ { 0x5c, "REFERENCE_WINDOW_WIDTH_REF_100_INST0" },
+ { 0x60, "FMON_CLK_LAST_COUNT_REF_100_INST1" },
+ { 0x64, "REFERENCE_WINDOW_WIDTH_REF_100_INST1" },
+ { 0x68, "FMON_CLK_LAST_COUNT_REF_156" },
+ { 0x6c, "REFERENCE_WINDOW_WIDTH_REF_156" },
+};
+
+static const struct mlxbf_pmc_events mlxbf_pmc_gga_events[] = {
+ { 0, "GGA_PERF_DESC_WQE_STRB" },
+ { 5, "GGA_PERF_DESC_CQE_STRB" },
+ { 8, "GGA_PERF_DESC_TPT_REQUEST_STRB" },
+ { 17, "GGA_PERF_DESC_TPT_RESPONSESTRB" },
+ { 120, "GGA_PERF_DESC_ENGINE0_IN_DATA_STRB" },
+ { 121, "GGA_PERF_DESC_ENGINE1_IN_DATA_STRB" },
+ { 122, "GGA_PERF_DESC_ENGINE2_IN_DATA_STRB" },
+ { 123, "GGA_PERF_DESC_ENGINE3_IN_DATA_STRB" },
+ { 124, "GGA_PERF_DESC_ENGINE4_IN_DATA_STRB" },
+ { 125, "GGA_PERF_DESC_ENGINE5_IN_DATA_STRB" },
+ { 126, "GGA_PERF_DESC_ENGINE6_IN_DATA_STRB" },
+ { 127, "GGA_PERF_DESC_ENGINE7_IN_DATA_STRB" },
+ { 128, "GGA_PERF_DESC_ENGINE8_IN_DATA_STRB" },
+ { 129, "GGA_PERF_DESC_ENGINE9_IN_DATA_STRB" },
+ { 130, "GGA_PERF_DESC_ENGINE10_IN_DATA_STRB" },
+ { 131, "GGA_PERF_DESC_ENGINE11_IN_DATA_STRB" },
+ { 132, "GGA_PERF_DESC_ENGINE12_IN_DATA_STRB" },
+ { 133, "GGA_PERF_DESC_ENGINE13_IN_DATA_STRB" },
+ { 134, "GGA_PERF_DESC_ENGINE14_IN_DATA_STRB" },
+ { 195, "GGA_PERF_DESC_ENGINE0_OUT_DATA_STRB" },
+ { 196, "GGA_PERF_DESC_ENGINE1_OUT_DATA_STRB" },
+ { 197, "GGA_PERF_DESC_ENGINE2_OUT_DATA_STRB" },
+ { 198, "GGA_PERF_DESC_ENGINE3_OUT_DATA_STRB" },
+ { 199, "GGA_PERF_DESC_ENGINE4_OUT_DATA_STRB" },
+ { 200, "GGA_PERF_DESC_ENGINE5_OUT_DATA_STRB" },
+ { 201, "GGA_PERF_DESC_ENGINE6_OUT_DATA_STRB" },
+ { 202, "GGA_PERF_DESC_ENGINE7_OUT_DATA_STRB" },
+ { 203, "GGA_PERF_DESC_ENGINE8_OUT_DATA_STRB" },
+ { 204, "GGA_PERF_DESC_ENGINE9_OUT_DATA_STRB" },
+ { 205, "GGA_PERF_DESC_ENGINE10_OUT_DATA_STRB" },
+ { 206, "GGA_PERF_DESC_ENGINE11_OUT_DATA_STRB" },
+ { 207, "GGA_PERF_DESC_ENGINE12_OUT_DATA_STRB" },
+ { 208, "GGA_PERF_DESC_ENGINE13_OUT_DATA_STRB" },
+ { 209, "GGA_PERF_DESC_ENGINE14_OUT_DATA_STRB" },
+};
+
+static const struct mlxbf_pmc_events mlxbf_pmc_apt_events[] = {
+ { 0, "APT_DATA_0" },
+ { 1, "APT_DATA_1" },
+ { 2, "APT_DATA_2" },
+ { 3, "APT_DATA_3" },
+ { 4, "APT_DATA_4" },
+ { 5, "APT_DATA_5" },
+ { 6, "APT_DATA_6" },
+ { 7, "APT_DATA_7" },
+ { 8, "APT_DATA_8" },
+ { 9, "APT_DATA_9" },
+ { 10, "APT_DATA_10" },
+ { 11, "APT_DATA_11" },
+ { 12, "APT_DATA_12" },
+ { 13, "APT_DATA_13" },
+ { 14, "APT_DATA_14" },
+ { 15, "APT_DATA_15" },
+ { 16, "APT_DATA_16" },
+ { 17, "APT_DATA_17" },
+ { 18, "APT_DATA_18" },
+ { 19, "APT_DATA_19" },
+ { 20, "APT_DATA_20" },
+ { 21, "APT_DATA_21" },
+};
+
+static const struct mlxbf_pmc_events mlxbf_pmc_emi_events[] = {
+ { 0, "MCH_WR_IN_MCH_REQ_IN_STRB" },
+ { 10, "MCH_RD_IN_MCH_REQ_IN_STRB" },
+ { 20, "MCH_RD_RESP_DATA_MCH_RESP_OUT_STRB" },
+ { 98, "EMI_ARBITER_EARB2CTRL_STRB" },
+ { 99, "EMI_ARBITER_EARB2CTRL_RAS_STRB" },
+ { 100, "EMI_ARBITER_EARB2CTRL_CAS_STRB" },
+};
+
+static const struct mlxbf_pmc_events mlxbf_pmc_prnf_events[] = {
+ { 0, "PRNF_DMA_RD_TLP_REQ" },
+ { 1, "PRNF_DMA_RD_ICMC_BYPASS_REQ" },
+ { 8, "PRNF_DMA_RD_TLP_SENT_TO_CHI" },
+ { 11, "PRNF_DMA_RD_CHI_RES" },
+ { 17, "PRNF_DMA_RD_TLP_RES_SENT" },
+ { 18, "PRNF_DMA_WR_WR0_SLICE_ALLOC_RO" },
+ { 19, "PRNF_DMA_WR_WR0_SLICE_ALLOC_NRO" },
+ { 24, "PRNF_DMA_WR_WR1_SLICE_ALLOC_RO" },
+ { 25, "PRNF_DMA_WR_WR1_SLICE_ALLOC_NRO" },
+ { 30, "PRNF_PIO_POSTED_REQ_PUSH" },
+ { 31, "PRNF_PIO_POSTED_REQ_POP" },
+ { 32, "PRNF_PIO_NP_REQ_PUSH" },
+ { 33, "PRNF_PIO_NP_REQ_POP" },
+ { 34, "PRNF_PIO_COMP_RO_PUSH" },
+ { 35, "PRNF_PIO_COMP_RO_POP" },
+ { 36, "PRNF_PIO_COMP_NRO_PUSH" },
+ { 37, "PRNF_PIO_COMP_NRO_POP" },
+};
+
+static const struct mlxbf_pmc_events mlxbf_pmc_msn_events[] = {
+ { 46, "MSN_CORE_MMA_WQE_DONE_PUSH_STRB" },
+ { 116, "MSN_CORE_MSN2MMA_WQE_STRB" },
+ { 164, "MSN_CORE_WQE_TOP_TILE_WQE_STRB" },
+ { 168, "MSN_CORE_TPT_TOP_GGA_REQ_STRB" },
+ { 171, "MSN_CORE_TPT_TOP_MMA_REQ_STRB" },
+ { 174, "MSN_CORE_TPT_TOP_GGA_RES_STRB" },
+ { 177, "MSN_CORE_TPT_TOP_MMA_RES_STRB" },
+};
+
static struct mlxbf_pmc_context *pmc;
/* UUID used to probe ATF service. */
static const char *mlxbf_pmc_svc_uuid_str = "89c036b4-e7d7-11e6-8797-001aca00bfc4";
/* Calls an SMC to access a performance register */
-static int mlxbf_pmc_secure_read(void __iomem *addr, uint32_t command,
- uint64_t *result)
+static int mlxbf_pmc_secure_read(void __iomem *addr, u32 command, u64 *result)
{
struct arm_smccc_res res;
int status, err = 0;
@@ -456,8 +1029,7 @@ static int mlxbf_pmc_secure_read(void __iomem *addr, uint32_t command,
}
/* Read from a performance counter */
-static int mlxbf_pmc_read(void __iomem *addr, uint32_t command,
- uint64_t *result)
+static int mlxbf_pmc_read(void __iomem *addr, u32 command, u64 *result)
{
if (pmc->svc_sreg_support)
return mlxbf_pmc_secure_read(addr, command, result);
@@ -471,22 +1043,21 @@ static int mlxbf_pmc_read(void __iomem *addr, uint32_t command,
}
/* Convenience function for 32-bit reads */
-static int mlxbf_pmc_readl(void __iomem *addr, uint32_t *result)
+static int mlxbf_pmc_readl(void __iomem *addr, u32 *result)
{
- uint64_t read_out;
+ u64 read_out;
int status;
status = mlxbf_pmc_read(addr, MLXBF_PMC_READ_REG_32, &read_out);
if (status)
return status;
- *result = (uint32_t)read_out;
+ *result = (u32)read_out;
return 0;
}
/* Calls an SMC to access a performance register */
-static int mlxbf_pmc_secure_write(void __iomem *addr, uint32_t command,
- uint64_t value)
+static int mlxbf_pmc_secure_write(void __iomem *addr, u32 command, u64 value)
{
struct arm_smccc_res res;
int status, err = 0;
@@ -509,7 +1080,7 @@ static int mlxbf_pmc_secure_write(void __iomem *addr, uint32_t command,
}
/* Write to a performance counter */
-static int mlxbf_pmc_write(void __iomem *addr, int command, uint64_t value)
+static int mlxbf_pmc_write(void __iomem *addr, int command, u64 value)
{
if (pmc->svc_sreg_support)
return mlxbf_pmc_secure_write(addr, command, value);
@@ -523,7 +1094,7 @@ static int mlxbf_pmc_write(void __iomem *addr, int command, uint64_t value)
}
/* Check if the register offset is within the mapped region for the block */
-static bool mlxbf_pmc_valid_range(int blk_num, uint32_t offset)
+static bool mlxbf_pmc_valid_range(unsigned int blk_num, u32 offset)
{
if ((offset >= 0) && !(offset % MLXBF_PMC_REG_SIZE) &&
(offset + MLXBF_PMC_REG_SIZE <= pmc->block[blk_num].blk_size))
@@ -533,66 +1104,112 @@ static bool mlxbf_pmc_valid_range(int blk_num, uint32_t offset)
}
/* Get the event list corresponding to a certain block */
-static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk,
- int *size)
+static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk, size_t *psize)
{
const struct mlxbf_pmc_events *events;
+ size_t size;
if (strstr(blk, "tilenet")) {
events = mlxbf_pmc_hnfnet_events;
- *size = ARRAY_SIZE(mlxbf_pmc_hnfnet_events);
+ size = ARRAY_SIZE(mlxbf_pmc_hnfnet_events);
} else if (strstr(blk, "tile")) {
events = mlxbf_pmc_hnf_events;
- *size = ARRAY_SIZE(mlxbf_pmc_hnf_events);
+ size = ARRAY_SIZE(mlxbf_pmc_hnf_events);
} else if (strstr(blk, "triogen")) {
events = mlxbf_pmc_smgen_events;
- *size = ARRAY_SIZE(mlxbf_pmc_smgen_events);
+ size = ARRAY_SIZE(mlxbf_pmc_smgen_events);
} else if (strstr(blk, "trio")) {
switch (pmc->event_set) {
case MLXBF_PMC_EVENT_SET_BF1:
events = mlxbf_pmc_trio_events_1;
- *size = ARRAY_SIZE(mlxbf_pmc_trio_events_1);
+ size = ARRAY_SIZE(mlxbf_pmc_trio_events_1);
break;
case MLXBF_PMC_EVENT_SET_BF2:
events = mlxbf_pmc_trio_events_2;
- *size = ARRAY_SIZE(mlxbf_pmc_trio_events_2);
+ size = ARRAY_SIZE(mlxbf_pmc_trio_events_2);
break;
default:
events = NULL;
- *size = 0;
+ size = 0;
break;
}
} else if (strstr(blk, "mss")) {
- events = mlxbf_pmc_mss_events;
- *size = ARRAY_SIZE(mlxbf_pmc_mss_events);
+ switch (pmc->event_set) {
+ case MLXBF_PMC_EVENT_SET_BF1:
+ case MLXBF_PMC_EVENT_SET_BF2:
+ events = mlxbf_pmc_mss_events_1;
+ size = ARRAY_SIZE(mlxbf_pmc_mss_events_1);
+ break;
+ case MLXBF_PMC_EVENT_SET_BF3:
+ events = mlxbf_pmc_mss_events_3;
+ size = ARRAY_SIZE(mlxbf_pmc_mss_events_3);
+ break;
+ default:
+ events = NULL;
+ size = 0;
+ break;
+ }
} else if (strstr(blk, "ecc")) {
events = mlxbf_pmc_ecc_events;
- *size = ARRAY_SIZE(mlxbf_pmc_ecc_events);
+ size = ARRAY_SIZE(mlxbf_pmc_ecc_events);
} else if (strstr(blk, "pcie")) {
events = mlxbf_pmc_pcie_events;
- *size = ARRAY_SIZE(mlxbf_pmc_pcie_events);
+ size = ARRAY_SIZE(mlxbf_pmc_pcie_events);
} else if (strstr(blk, "l3cache")) {
events = mlxbf_pmc_l3c_events;
- *size = ARRAY_SIZE(mlxbf_pmc_l3c_events);
+ size = ARRAY_SIZE(mlxbf_pmc_l3c_events);
} else if (strstr(blk, "gic")) {
events = mlxbf_pmc_smgen_events;
- *size = ARRAY_SIZE(mlxbf_pmc_smgen_events);
+ size = ARRAY_SIZE(mlxbf_pmc_smgen_events);
} else if (strstr(blk, "smmu")) {
events = mlxbf_pmc_smgen_events;
- *size = ARRAY_SIZE(mlxbf_pmc_smgen_events);
+ size = ARRAY_SIZE(mlxbf_pmc_smgen_events);
+ } else if (strstr(blk, "llt_miss")) {
+ events = mlxbf_pmc_llt_miss_events;
+ size = ARRAY_SIZE(mlxbf_pmc_llt_miss_events);
+ } else if (strstr(blk, "llt")) {
+ events = mlxbf_pmc_llt_events;
+ size = ARRAY_SIZE(mlxbf_pmc_llt_events);
+ } else if (strstr(blk, "clock_measure")) {
+ events = mlxbf_pmc_clock_events;
+ size = ARRAY_SIZE(mlxbf_pmc_clock_events);
+ } else if (strstr(blk, "gga")) {
+ events = mlxbf_pmc_gga_events;
+ size = ARRAY_SIZE(mlxbf_pmc_gga_events);
+ } else if (strstr(blk, "apt")) {
+ events = mlxbf_pmc_apt_events;
+ size = ARRAY_SIZE(mlxbf_pmc_apt_events);
+ } else if (strstr(blk, "emi")) {
+ events = mlxbf_pmc_emi_events;
+ size = ARRAY_SIZE(mlxbf_pmc_emi_events);
+ } else if (strstr(blk, "prnf")) {
+ events = mlxbf_pmc_prnf_events;
+ size = ARRAY_SIZE(mlxbf_pmc_prnf_events);
+ } else if (strstr(blk, "msn")) {
+ events = mlxbf_pmc_msn_events;
+ size = ARRAY_SIZE(mlxbf_pmc_msn_events);
} else {
events = NULL;
- *size = 0;
+ size = 0;
}
+ if (psize)
+ *psize = size;
+
return events;
}
+static bool mlxbf_pmc_event_supported(const char *blk)
+{
+ return !!mlxbf_pmc_event_list(blk, NULL);
+}
+
/* Get the event number given the name */
static int mlxbf_pmc_get_event_num(const char *blk, const char *evt)
{
const struct mlxbf_pmc_events *events;
- int i, size;
+ unsigned int i;
+ size_t size;
events = mlxbf_pmc_event_list(blk, &size);
if (!events)
@@ -606,11 +1223,12 @@ static int mlxbf_pmc_get_event_num(const char *blk, const char *evt)
return -ENODEV;
}
-/* Get the event number given the name */
-static char *mlxbf_pmc_get_event_name(const char *blk, int evt)
+/* Get the event name given the number */
+static char *mlxbf_pmc_get_event_name(const char *blk, u32 evt)
{
const struct mlxbf_pmc_events *events;
- int i, size;
+ unsigned int i;
+ size_t size;
events = mlxbf_pmc_event_list(blk, &size);
if (!events)
@@ -625,9 +1243,9 @@ static char *mlxbf_pmc_get_event_name(const char *blk, int evt)
}
/* Method to enable/disable/reset l3cache counters */
-static int mlxbf_pmc_config_l3_counters(int blk_num, bool enable, bool reset)
+static int mlxbf_pmc_config_l3_counters(unsigned int blk_num, bool enable, bool reset)
{
- uint32_t perfcnt_cfg = 0;
+ u32 perfcnt_cfg = 0;
if (enable)
perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_EN;
@@ -640,12 +1258,9 @@ static int mlxbf_pmc_config_l3_counters(int blk_num, bool enable, bool reset)
}
/* Method to handle l3cache counter programming */
-static int mlxbf_pmc_program_l3_counter(int blk_num, uint32_t cnt_num,
- uint32_t evt)
+static int mlxbf_pmc_program_l3_counter(unsigned int blk_num, u32 cnt_num, u32 evt)
{
- uint32_t perfcnt_sel_1 = 0;
- uint32_t perfcnt_sel = 0;
- uint32_t *wordaddr;
+ u32 perfcnt_sel_1 = 0, perfcnt_sel = 0, *wordaddr;
void __iomem *pmcaddr;
int ret;
@@ -706,11 +1321,46 @@ static int mlxbf_pmc_program_l3_counter(int blk_num, uint32_t cnt_num,
return mlxbf_pmc_write(pmcaddr, MLXBF_PMC_WRITE_REG_32, *wordaddr);
}
+/* Method to handle crspace counter programming */
+static int mlxbf_pmc_program_crspace_counter(unsigned int blk_num, u32 cnt_num, u32 evt)
+{
+ void __iomem *addr;
+ u32 word;
+ int ret;
+
+ addr = pmc->block[blk_num].mmio_base +
+ ((cnt_num / 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ);
+ ret = mlxbf_pmc_readl(addr, &word);
+ if (ret)
+ return ret;
+
+ if (cnt_num % 2) {
+ word &= ~MLXBF_PMC_CRSPACE_PERFSEL1;
+ word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL1, evt);
+ } else {
+ word &= ~MLXBF_PMC_CRSPACE_PERFSEL0;
+ word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL0, evt);
+ }
+
+ return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, word);
+}
+
+/* Method to clear crspace counter value */
+static int mlxbf_pmc_clear_crspace_counter(unsigned int blk_num, u32 cnt_num)
+{
+ void __iomem *addr;
+
+ addr = pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) +
+ (cnt_num * 4);
+
+ return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, 0x0);
+}
+
/* Method to program a counter to monitor an event */
-static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num,
- uint32_t evt, bool is_l3)
+static int mlxbf_pmc_program_counter(unsigned int blk_num, u32 cnt_num, u32 evt, bool is_l3)
{
- uint64_t perfctl, perfevt, perfmon_cfg;
+ u64 perfctl, perfevt, perfmon_cfg;
if (cnt_num >= pmc->block[blk_num].counters)
return -ENODEV;
@@ -718,6 +1368,10 @@ static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num,
if (is_l3)
return mlxbf_pmc_program_l3_counter(blk_num, cnt_num, evt);
+ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)
+ return mlxbf_pmc_program_crspace_counter(blk_num, cnt_num,
+ evt);
+
/* Configure the counter */
perfctl = FIELD_PREP(MLXBF_PMC_PERFCTL_EN0, 1);
perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_EB0, 0);
@@ -767,12 +1421,11 @@ static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num,
}
/* Method to handle l3 counter reads */
-static int mlxbf_pmc_read_l3_counter(int blk_num, uint32_t cnt_num,
- uint64_t *result)
+static int mlxbf_pmc_read_l3_counter(unsigned int blk_num, u32 cnt_num, u64 *result)
{
- uint32_t perfcnt_low = 0, perfcnt_high = 0;
- uint64_t value;
- int status = 0;
+ u32 perfcnt_low = 0, perfcnt_high = 0;
+ int status;
+ u64 value;
status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
MLXBF_PMC_L3C_PERF_CNT_LOW +
@@ -798,12 +1451,28 @@ static int mlxbf_pmc_read_l3_counter(int blk_num, uint32_t cnt_num,
return 0;
}
+/* Method to handle crspace counter reads */
+static int mlxbf_pmc_read_crspace_counter(unsigned int blk_num, u32 cnt_num, u64 *result)
+{
+ int status = 0;
+ u32 value;
+
+ status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) +
+ (cnt_num * 4), &value);
+ if (status)
+ return status;
+
+ *result = value;
+
+ return 0;
+}
+
/* Method to read the counter value */
-static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3,
- uint64_t *result)
+static int mlxbf_pmc_read_counter(unsigned int blk_num, u32 cnt_num, bool is_l3, u64 *result)
{
- uint32_t perfcfg_offset, perfval_offset;
- uint64_t perfmon_cfg;
+ u32 perfcfg_offset, perfval_offset;
+ u64 perfmon_cfg;
int status;
if (cnt_num >= pmc->block[blk_num].counters)
@@ -812,6 +1481,9 @@ static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3,
if (is_l3)
return mlxbf_pmc_read_l3_counter(blk_num, cnt_num, result);
+ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)
+ return mlxbf_pmc_read_crspace_counter(blk_num, cnt_num, result);
+
perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE;
perfval_offset = perfcfg_offset +
pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE;
@@ -834,13 +1506,11 @@ static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3,
}
/* Method to read L3 block event */
-static int mlxbf_pmc_read_l3_event(int blk_num, uint32_t cnt_num,
- uint64_t *result)
+static int mlxbf_pmc_read_l3_event(unsigned int blk_num, u32 cnt_num, u64 *result)
{
- uint32_t perfcnt_sel = 0, perfcnt_sel_1 = 0;
- uint32_t *wordaddr;
+ u32 perfcnt_sel = 0, perfcnt_sel_1 = 0, *wordaddr;
void __iomem *pmcaddr;
- uint64_t evt;
+ u64 evt;
/* Select appropriate register information */
switch (cnt_num) {
@@ -887,12 +1557,34 @@ static int mlxbf_pmc_read_l3_event(int blk_num, uint32_t cnt_num,
return 0;
}
+/* Method to read crspace block event */
+static int mlxbf_pmc_read_crspace_event(unsigned int blk_num, u32 cnt_num, u64 *result)
+{
+ u32 word, evt;
+ void __iomem *addr;
+ int ret;
+
+ addr = pmc->block[blk_num].mmio_base +
+ ((cnt_num / 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ);
+ ret = mlxbf_pmc_readl(addr, &word);
+ if (ret)
+ return ret;
+
+ if (cnt_num % 2)
+ evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL1, word);
+ else
+ evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL0, word);
+
+ *result = evt;
+
+ return 0;
+}
+
/* Method to find the event currently being monitored by a counter */
-static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3,
- uint64_t *result)
+static int mlxbf_pmc_read_event(unsigned int blk_num, u32 cnt_num, bool is_l3, u64 *result)
{
- uint32_t perfcfg_offset, perfval_offset;
- uint64_t perfmon_cfg, perfevt, perfctl;
+ u32 perfcfg_offset, perfval_offset;
+ u64 perfmon_cfg, perfevt;
if (cnt_num >= pmc->block[blk_num].counters)
return -EINVAL;
@@ -900,31 +1592,15 @@ static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3,
if (is_l3)
return mlxbf_pmc_read_l3_event(blk_num, cnt_num, result);
+ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)
+ return mlxbf_pmc_read_crspace_event(blk_num, cnt_num, result);
+
perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE;
perfval_offset = perfcfg_offset +
pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE;
/* Set counter in "read" mode */
perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,
- MLXBF_PMC_PERFCTL);
- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);
- perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0);
-
- if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset,
- MLXBF_PMC_WRITE_REG_64, perfmon_cfg))
- return -EFAULT;
-
- /* Check if the counter is enabled */
-
- if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset,
- MLXBF_PMC_READ_REG_64, &perfctl))
- return -EFAULT;
-
- if (!FIELD_GET(MLXBF_PMC_PERFCTL_EN0, perfctl))
- return -EINVAL;
-
- /* Set counter in "read" mode */
- perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,
MLXBF_PMC_PERFEVT);
perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);
perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0);
@@ -944,16 +1620,17 @@ static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3,
}
/* Method to read a register */
-static int mlxbf_pmc_read_reg(int blk_num, uint32_t offset, uint64_t *result)
+static int mlxbf_pmc_read_reg(unsigned int blk_num, u32 offset, u64 *result)
{
- uint32_t ecc_out;
+ u32 reg;
- if (strstr(pmc->block_name[blk_num], "ecc")) {
+ if ((strstr(pmc->block_name[blk_num], "ecc")) ||
+ (strstr(pmc->block_name[blk_num], "clock_measure"))) {
if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + offset,
- &ecc_out))
+ &reg))
return -EFAULT;
- *result = ecc_out;
+ *result = reg;
return 0;
}
@@ -965,8 +1642,11 @@ static int mlxbf_pmc_read_reg(int blk_num, uint32_t offset, uint64_t *result)
}
/* Method to write to a register */
-static int mlxbf_pmc_write_reg(int blk_num, uint32_t offset, uint64_t data)
+static int mlxbf_pmc_write_reg(unsigned int blk_num, u32 offset, u64 data)
{
+ if (strstr(pmc->block_name[blk_num], "clock_measure"))
+ return -EINVAL;
+
if (strstr(pmc->block_name[blk_num], "ecc")) {
return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset,
MLXBF_PMC_WRITE_REG_32, data);
@@ -985,9 +1665,10 @@ static ssize_t mlxbf_pmc_counter_show(struct device *dev,
{
struct mlxbf_pmc_attribute *attr_counter = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
- int blk_num, cnt_num, offset;
+ unsigned int blk_num, cnt_num;
bool is_l3 = false;
- uint64_t value;
+ int offset;
+ u64 value;
blk_num = attr_counter->nr;
cnt_num = attr_counter->index;
@@ -995,7 +1676,8 @@ static ssize_t mlxbf_pmc_counter_show(struct device *dev,
if (strstr(pmc->block_name[blk_num], "l3cache"))
is_l3 = true;
- if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) {
+ if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) ||
+ (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)) {
if (mlxbf_pmc_read_counter(blk_num, cnt_num, is_l3, &value))
return -EINVAL;
} else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) {
@@ -1008,7 +1690,7 @@ static ssize_t mlxbf_pmc_counter_show(struct device *dev,
} else
return -EINVAL;
- return sprintf(buf, "0x%llx\n", value);
+ return sysfs_emit(buf, "0x%llx\n", value);
}
/* Store function for "counter" sysfs files */
@@ -1018,14 +1700,16 @@ static ssize_t mlxbf_pmc_counter_store(struct device *dev,
{
struct mlxbf_pmc_attribute *attr_counter = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
- int blk_num, cnt_num, offset, err, data;
+ unsigned int blk_num, cnt_num, data;
bool is_l3 = false;
- uint64_t evt_num;
+ u64 evt_num;
+ int offset;
+ int err;
blk_num = attr_counter->nr;
cnt_num = attr_counter->index;
- err = kstrtoint(buf, 0, &data);
+ err = kstrtouint(buf, 0, &data);
if (err < 0)
return err;
@@ -1053,6 +1737,10 @@ static ssize_t mlxbf_pmc_counter_store(struct device *dev,
err = mlxbf_pmc_write_reg(blk_num, offset, data);
if (err)
return err;
+ } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {
+ if (sscanf(attr->attr.name, "counter%u", &cnt_num) != 1)
+ return -EINVAL;
+ err = mlxbf_pmc_clear_crspace_counter(blk_num, cnt_num);
} else
return -EINVAL;
@@ -1065,10 +1753,11 @@ static ssize_t mlxbf_pmc_event_show(struct device *dev,
{
struct mlxbf_pmc_attribute *attr_event = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
- int blk_num, cnt_num, err;
+ unsigned int blk_num, cnt_num;
bool is_l3 = false;
- uint64_t evt_num;
char *evt_name;
+ u64 evt_num;
+ int err;
blk_num = attr_event->nr;
cnt_num = attr_event->index;
@@ -1078,13 +1767,13 @@ static ssize_t mlxbf_pmc_event_show(struct device *dev,
err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num);
if (err)
- return sprintf(buf, "No event being monitored\n");
+ return sysfs_emit(buf, "No event being monitored\n");
evt_name = mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num);
if (!evt_name)
return -EINVAL;
- return sprintf(buf, "0x%llx: %s\n", evt_num, evt_name);
+ return sysfs_emit(buf, "0x%llx: %s\n", evt_num, evt_name);
}
/* Store function for "event" sysfs files */
@@ -1094,21 +1783,33 @@ static ssize_t mlxbf_pmc_event_store(struct device *dev,
{
struct mlxbf_pmc_attribute *attr_event = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
- int blk_num, cnt_num, evt_num, err;
+ unsigned int blk_num, cnt_num;
bool is_l3 = false;
+ char *evt_name;
+ int evt_num;
+ int err;
blk_num = attr_event->nr;
cnt_num = attr_event->index;
if (isalpha(buf[0])) {
+ /* Remove the trailing newline character if present */
+ evt_name = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
+ if (!evt_name)
+ return -ENOMEM;
+
evt_num = mlxbf_pmc_get_event_num(pmc->block_name[blk_num],
- buf);
+ evt_name);
+ kfree(evt_name);
if (evt_num < 0)
return -EINVAL;
} else {
- err = kstrtoint(buf, 0, &evt_num);
+ err = kstrtouint(buf, 0, &evt_num);
if (err < 0)
return err;
+
+ if (!mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num))
+ return -EINVAL;
}
if (strstr(pmc->block_name[blk_num], "l3cache"))
@@ -1128,9 +1829,11 @@ static ssize_t mlxbf_pmc_event_list_show(struct device *dev,
{
struct mlxbf_pmc_attribute *attr_event_list = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
- int blk_num, i, size, len = 0, ret = 0;
const struct mlxbf_pmc_events *events;
char e_info[MLXBF_PMC_EVENT_INFO_LEN];
+ unsigned int blk_num, i, len = 0;
+ size_t size;
+ int ret = 0;
blk_num = attr_event_list->nr;
@@ -1139,9 +1842,9 @@ static ssize_t mlxbf_pmc_event_list_show(struct device *dev,
return -EINVAL;
for (i = 0, buf[0] = '\0'; i < size; ++i) {
- len += sprintf(e_info, "0x%x: %s\n", events[i].evt_num,
- events[i].evt_name);
- if (len > PAGE_SIZE)
+ len += snprintf(e_info, sizeof(e_info), "0x%x: %s\n",
+ events[i].evt_num, events[i].evt_name);
+ if (len >= PAGE_SIZE)
break;
strcat(buf, e_info);
ret = len;
@@ -1150,83 +1853,177 @@ static ssize_t mlxbf_pmc_event_list_show(struct device *dev,
return ret;
}
-/* Show function for "enable" sysfs files - only for l3cache */
+/* Show function for "enable" sysfs files - only for l3cache & crspace */
static ssize_t mlxbf_pmc_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mlxbf_pmc_attribute *attr_enable = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
- uint32_t perfcnt_cfg;
- int blk_num, value;
+ unsigned int blk_num, value;
+ u32 perfcnt_cfg, word;
blk_num = attr_enable->nr;
- if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
- MLXBF_PMC_L3C_PERF_CNT_CFG,
- &perfcnt_cfg))
- return -EINVAL;
+ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {
+ if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),
+ &word))
+ return -EINVAL;
+
+ value = FIELD_GET(MLXBF_PMC_CRSPACE_PERFMON_EN, word);
+ } else {
+ if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_L3C_PERF_CNT_CFG,
+ &perfcnt_cfg))
+ return -EINVAL;
- value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg);
+ value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg);
+ }
- return sprintf(buf, "%d\n", value);
+ return sysfs_emit(buf, "%u\n", value);
}
-/* Store function for "enable" sysfs files - only for l3cache */
+/* Store function for "enable" sysfs files - only for l3cache & crspace */
static ssize_t mlxbf_pmc_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct mlxbf_pmc_attribute *attr_enable = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
- int err, en, blk_num;
+ unsigned int blk_num;
+ u32 word;
+ int err;
+ bool en;
blk_num = attr_enable->nr;
- err = kstrtoint(buf, 0, &en);
+ err = kstrtobool(buf, &en);
if (err < 0)
return err;
- if (!en) {
- err = mlxbf_pmc_config_l3_counters(blk_num, false, false);
+ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {
+ err = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),
+ &word);
if (err)
- return err;
- } else if (en == 1) {
- err = mlxbf_pmc_config_l3_counters(blk_num, false, true);
- if (err)
- return err;
- err = mlxbf_pmc_config_l3_counters(blk_num, true, false);
+ return -EINVAL;
+
+ word &= ~MLXBF_PMC_CRSPACE_PERFMON_EN;
+ word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_EN, en);
+ if (en)
+ word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_CLR, 1);
+
+ mlxbf_pmc_write(pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),
+ MLXBF_PMC_WRITE_REG_32, word);
+ } else {
+ err = mlxbf_pmc_config_l3_counters(blk_num, false, !!en);
if (err)
return err;
- } else
+
+ if (en) {
+ err = mlxbf_pmc_config_l3_counters(blk_num, true, false);
+ if (err)
+ return err;
+ }
+ }
+
+ return count;
+}
+
+/* Show function for "count_clock" sysfs files - only for crspace */
+static ssize_t mlxbf_pmc_count_clock_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mlxbf_pmc_attribute *attr_count_clock = container_of(
+ attr, struct mlxbf_pmc_attribute, dev_attr);
+ unsigned int blk_num;
+ u32 reg;
+
+ blk_num = attr_count_clock->nr;
+
+ if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters),
+ &reg))
return -EINVAL;
+ return sysfs_emit(buf, "%u\n", reg);
+}
+
+/* Store function for "count_clock" sysfs files - only for crspace */
+static ssize_t mlxbf_pmc_count_clock_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mlxbf_pmc_attribute *attr_count_clock = container_of(
+ attr, struct mlxbf_pmc_attribute, dev_attr);
+ unsigned int blk_num;
+ u32 reg;
+ int err;
+
+ blk_num = attr_count_clock->nr;
+
+ err = kstrtouint(buf, 0, &reg);
+ if (err < 0)
+ return err;
+
+ mlxbf_pmc_write(pmc->block[blk_num].mmio_base +
+ MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters),
+ MLXBF_PMC_WRITE_REG_32, reg);
+
return count;
}
/* Populate attributes for blocks with counters to monitor performance */
-static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
+static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_num)
{
struct mlxbf_pmc_attribute *attr;
- int i = 0, j = 0;
+ unsigned int i = 0, j = 0;
+
+ if (!mlxbf_pmc_event_supported(pmc->block_name[blk_num]))
+ return -ENOENT;
/* "event_list" sysfs to list events supported by the block */
attr = &pmc->block[blk_num].attr_event_list;
+ sysfs_attr_init(&attr->dev_attr.attr);
attr->dev_attr.attr.mode = 0444;
attr->dev_attr.show = mlxbf_pmc_event_list_show;
attr->nr = blk_num;
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event_list");
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;
attr = NULL;
/* "enable" sysfs to start/stop the counters. Only in L3C blocks */
- if (strstr(pmc->block_name[blk_num], "l3cache")) {
+ if (strstr(pmc->block_name[blk_num], "l3cache") ||
+ ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))) {
attr = &pmc->block[blk_num].attr_enable;
+ sysfs_attr_init(&attr->dev_attr.attr);
attr->dev_attr.attr.mode = 0644;
attr->dev_attr.show = mlxbf_pmc_enable_show;
attr->dev_attr.store = mlxbf_pmc_enable_store;
attr->nr = blk_num;
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
"enable");
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
+ pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
+ attr = NULL;
+ }
+
+ if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {
+ /* Program crspace counters to count clock cycles using "count_clock" sysfs */
+ attr = &pmc->block[blk_num].attr_count_clock;
+ sysfs_attr_init(&attr->dev_attr.attr);
+ attr->dev_attr.attr.mode = 0644;
+ attr->dev_attr.show = mlxbf_pmc_count_clock_show;
+ attr->dev_attr.store = mlxbf_pmc_count_clock_store;
+ attr->nr = blk_num;
+ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
+ "count_clock");
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
attr = NULL;
}
@@ -1246,24 +2043,28 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
/* "eventX" and "counterX" sysfs to program and read counter values */
for (j = 0; j < pmc->block[blk_num].counters; ++j) {
attr = &pmc->block[blk_num].attr_counter[j];
+ sysfs_attr_init(&attr->dev_attr.attr);
attr->dev_attr.attr.mode = 0644;
attr->dev_attr.show = mlxbf_pmc_counter_show;
attr->dev_attr.store = mlxbf_pmc_counter_store;
attr->index = j;
attr->nr = blk_num;
- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
- "counter%d", j);
+ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "counter%u", j);
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
attr = NULL;
attr = &pmc->block[blk_num].attr_event[j];
+ sysfs_attr_init(&attr->dev_attr.attr);
attr->dev_attr.attr.mode = 0644;
attr->dev_attr.show = mlxbf_pmc_event_show;
attr->dev_attr.store = mlxbf_pmc_event_store;
attr->index = j;
attr->nr = blk_num;
- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
- "event%d", j);
+ attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event%u", j);
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
attr = NULL;
}
@@ -1272,30 +2073,34 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
}
/* Populate attributes for blocks with registers to monitor performance */
-static int mlxbf_pmc_init_perftype_reg(struct device *dev, int blk_num)
+static int mlxbf_pmc_init_perftype_reg(struct device *dev, unsigned int blk_num)
{
- struct mlxbf_pmc_attribute *attr;
const struct mlxbf_pmc_events *events;
- int i = 0, j = 0;
+ struct mlxbf_pmc_attribute *attr;
+ unsigned int i = 0;
+ size_t count = 0;
- events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &j);
+ events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &count);
if (!events)
- return -EINVAL;
+ return -ENOENT;
pmc->block[blk_num].attr_event = devm_kcalloc(
- dev, j, sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL);
+ dev, count, sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL);
if (!pmc->block[blk_num].attr_event)
return -ENOMEM;
- while (j > 0) {
- --j;
- attr = &pmc->block[blk_num].attr_event[j];
+ while (count > 0) {
+ --count;
+ attr = &pmc->block[blk_num].attr_event[count];
+ sysfs_attr_init(&attr->dev_attr.attr);
attr->dev_attr.attr.mode = 0644;
attr->dev_attr.show = mlxbf_pmc_counter_show;
attr->dev_attr.store = mlxbf_pmc_counter_store;
attr->nr = blk_num;
attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
- events[j].evt_name);
+ events[count].evt_name);
+ if (!attr->dev_attr.attr.name)
+ return -ENOMEM;
pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr;
attr = NULL;
i++;
@@ -1305,17 +2110,18 @@ static int mlxbf_pmc_init_perftype_reg(struct device *dev, int blk_num)
}
/* Helper to create the bfperf sysfs sub-directories and files */
-static int mlxbf_pmc_create_groups(struct device *dev, int blk_num)
+static int mlxbf_pmc_create_groups(struct device *dev, unsigned int blk_num)
{
int err;
/* Populate attributes based on counter type */
- if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER)
+ if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) ||
+ (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))
err = mlxbf_pmc_init_perftype_counter(dev, blk_num);
else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER)
err = mlxbf_pmc_init_perftype_reg(dev, blk_num);
else
- err = -EINVAL;
+ err = -ENOENT;
if (err)
return err;
@@ -1324,7 +2130,10 @@ static int mlxbf_pmc_create_groups(struct device *dev, int blk_num)
pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr;
pmc->block[blk_num].block_attr_grp.name = devm_kasprintf(
dev, GFP_KERNEL, pmc->block_name[blk_num]);
- pmc->groups[blk_num] = &pmc->block[blk_num].block_attr_grp;
+ if (!pmc->block[blk_num].block_attr_grp.name)
+ return -ENOMEM;
+ pmc->groups[pmc->group_num] = &pmc->block[blk_num].block_attr_grp;
+ pmc->group_num++;
return 0;
}
@@ -1343,18 +2152,80 @@ static bool mlxbf_pmc_guid_match(const guid_t *guid,
/* Helper to map the Performance Counters from the varios blocks */
static int mlxbf_pmc_map_counters(struct device *dev)
{
- uint64_t info[MLXBF_PMC_INFO_SZ];
- int i, tile_num, ret;
+ u64 info[MLXBF_PMC_INFO_SZ];
+ unsigned int tile_num, i;
+ int ret;
for (i = 0; i < pmc->total_blocks; ++i) {
- if (strstr(pmc->block_name[i], "tile")) {
- ret = sscanf(pmc->block_name[i], "tile%d", &tile_num);
- if (ret < 0)
- return ret;
+ /* Create sysfs for tiles only if block number < tile_count */
+ if (strstr(pmc->block_name[i], "tilenet")) {
+ if (sscanf(pmc->block_name[i], "tilenet%u", &tile_num) != 1)
+ continue;
+
+ if (tile_num >= pmc->tile_count)
+ continue;
+ } else if (strstr(pmc->block_name[i], "tile")) {
+ if (sscanf(pmc->block_name[i], "tile%u", &tile_num) != 1)
+ continue;
if (tile_num >= pmc->tile_count)
continue;
}
+
+ /* Create sysfs only for enabled MSS blocks */
+ if (strstr(pmc->block_name[i], "mss") &&
+ pmc->event_set == MLXBF_PMC_EVENT_SET_BF3) {
+ unsigned int mss_num;
+
+ if (sscanf(pmc->block_name[i], "mss%u", &mss_num) != 1)
+ continue;
+
+ if (!((pmc->mss_enable >> mss_num) & 0x1))
+ continue;
+ }
+
+ /* Create sysfs only for enabled EMI blocks */
+ if (strstr(pmc->block_name[i], "emi") &&
+ pmc->event_set == MLXBF_PMC_EVENT_SET_BF3) {
+ unsigned int emi_num;
+
+ if (sscanf(pmc->block_name[i], "emi%u", &emi_num) != 1)
+ continue;
+
+ if (!((pmc->mss_enable >> (emi_num / 2)) & 0x1))
+ continue;
+ }
+
+ /* Create sysfs only for enabled LLT blocks */
+ if (strstr(pmc->block_name[i], "llt_miss")) {
+ unsigned int llt_num;
+
+ if (sscanf(pmc->block_name[i], "llt_miss%u", &llt_num) != 1)
+ continue;
+
+ if (!((pmc->llt_enable >> llt_num) & 0x1))
+ continue;
+ } else if (strstr(pmc->block_name[i], "llt")) {
+ unsigned int llt_num;
+
+ if (sscanf(pmc->block_name[i], "llt%u", &llt_num) != 1)
+ continue;
+
+ if (!((pmc->llt_enable >> llt_num) & 0x1))
+ continue;
+ }
+
+ /* Create sysfs only for enabled APT blocks */
+ if (strstr(pmc->block_name[i], "apt")) {
+ unsigned int apt_num;
+
+ if (sscanf(pmc->block_name[i], "apt%u", &apt_num) != 1)
+ continue;
+
+ if (!((pmc->apt_enable >> apt_num) & 0x1))
+ continue;
+ }
+
ret = device_property_read_u64_array(dev, pmc->block_name[i],
info, MLXBF_PMC_INFO_SZ);
if (ret)
@@ -1378,6 +2249,10 @@ static int mlxbf_pmc_map_counters(struct device *dev)
return -ENOMEM;
ret = mlxbf_pmc_create_groups(dev, i);
+ if (ret == -ENOENT) {
+ dev_warn(dev, "ignoring unsupported block: '%s'\n", pmc->block_name[i]);
+ continue;
+ }
if (ret)
return ret;
}
@@ -1431,6 +2306,8 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
pmc->event_set = MLXBF_PMC_EVENT_SET_BF1;
else if (!strcmp(hid, "MLNXBFD1"))
pmc->event_set = MLXBF_PMC_EVENT_SET_BF2;
+ else if (!strcmp(hid, "MLNXBFD2"))
+ pmc->event_set = MLXBF_PMC_EVENT_SET_BF3;
else
return -ENODEV;
@@ -1444,11 +2321,23 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
if (ret != pmc->total_blocks)
return -EFAULT;
- ret = device_property_read_u32(dev, "tile_num", &pmc->tile_count);
- if (ret)
- return ret;
+ if (device_property_read_u32(dev, "tile_num", &pmc->tile_count)) {
+ if (device_property_read_u8(dev, "apt_enable", &pmc->apt_enable)) {
+ dev_warn(dev, "Number of APTs undefined, ignoring blocks\n");
+ pmc->apt_enable = 0;
+ }
+ if (device_property_read_u8(dev, "llt_enable", &pmc->llt_enable)) {
+ dev_warn(dev, "Number of LLTs undefined, ignoring blocks\n");
+ pmc->llt_enable = 0;
+ }
+ if (device_property_read_u8(dev, "mss_enable", &pmc->mss_enable)) {
+ dev_warn(dev, "Number of MSSs undefined, ignoring blocks\n");
+ pmc->mss_enable = 0;
+ }
+ }
pmc->pdev = pdev;
+ pmc->group_num = 0;
ret = mlxbf_pmc_map_counters(dev);
if (ret)
@@ -1456,6 +2345,8 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
pmc->hwmon_dev = devm_hwmon_device_register_with_groups(
dev, "bfperf", pmc, pmc->groups);
+ if (IS_ERR(pmc->hwmon_dev))
+ return PTR_ERR(pmc->hwmon_dev);
platform_set_drvdata(pdev, pmc);
return 0;
@@ -1463,6 +2354,7 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
static const struct acpi_device_id mlxbf_pmc_acpi_ids[] = { { "MLNXBFD0", 0 },
{ "MLNXBFD1", 0 },
+ { "MLNXBFD2", 0 },
{}, };
MODULE_DEVICE_TABLE(acpi, mlxbf_pmc_acpi_ids);