1 // SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB 2 /* 3 * Mellanox BlueField Performance Monitoring Counters driver 4 * 5 * This driver provides a sysfs interface for monitoring 6 * performance statistics in BlueField SoC. 7 * 8 * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. 9 */ 10 11 #include <linux/acpi.h> 12 #include <linux/arm-smccc.h> 13 #include <linux/bitfield.h> 14 #include <linux/errno.h> 15 #include <linux/hwmon.h> 16 #include <linux/platform_device.h> 17 #include <linux/string.h> 18 #include <uapi/linux/psci.h> 19 20 #define MLXBF_PMC_WRITE_REG_32 0x82000009 21 #define MLXBF_PMC_READ_REG_32 0x8200000A 22 #define MLXBF_PMC_WRITE_REG_64 0x8200000B 23 #define MLXBF_PMC_READ_REG_64 0x8200000C 24 #define MLXBF_PMC_SIP_SVC_UID 0x8200ff01 25 #define MLXBF_PMC_SIP_SVC_VERSION 0x8200ff03 26 #define MLXBF_PMC_SVC_REQ_MAJOR 0 27 #define MLXBF_PMC_SVC_MIN_MINOR 3 28 29 #define MLXBF_PMC_SMCCC_ACCESS_VIOLATION -4 30 31 #define MLXBF_PMC_EVENT_SET_BF1 0 32 #define MLXBF_PMC_EVENT_SET_BF2 1 33 #define MLXBF_PMC_EVENT_SET_BF3 2 34 #define MLXBF_PMC_EVENT_INFO_LEN 100 35 36 #define MLXBF_PMC_MAX_BLOCKS 40 37 #define MLXBF_PMC_MAX_ATTRS 70 38 #define MLXBF_PMC_INFO_SZ 4 39 #define MLXBF_PMC_REG_SIZE 8 40 #define MLXBF_PMC_L3C_REG_SIZE 4 41 42 #define MLXBF_PMC_TYPE_CRSPACE 2 43 #define MLXBF_PMC_TYPE_COUNTER 1 44 #define MLXBF_PMC_TYPE_REGISTER 0 45 46 #define MLXBF_PMC_PERFCTL 0 47 #define MLXBF_PMC_PERFEVT 1 48 #define MLXBF_PMC_PERFACC0 4 49 50 #define MLXBF_PMC_PERFMON_CONFIG_WR_R_B BIT(0) 51 #define MLXBF_PMC_PERFMON_CONFIG_STROBE BIT(1) 52 #define MLXBF_PMC_PERFMON_CONFIG_ADDR GENMASK_ULL(4, 2) 53 #define MLXBF_PMC_PERFMON_CONFIG_WDATA GENMASK_ULL(60, 5) 54 55 #define MLXBF_PMC_PERFCTL_FM0 GENMASK_ULL(18, 16) 56 #define MLXBF_PMC_PERFCTL_MS0 GENMASK_ULL(21, 20) 57 #define MLXBF_PMC_PERFCTL_ACCM0 GENMASK_ULL(26, 24) 58 #define MLXBF_PMC_PERFCTL_AD0 BIT(27) 59 #define MLXBF_PMC_PERFCTL_ETRIG0 GENMASK_ULL(29, 28) 60 #define MLXBF_PMC_PERFCTL_EB0 BIT(30) 61 #define MLXBF_PMC_PERFCTL_EN0 BIT(31) 62 63 #define MLXBF_PMC_PERFEVT_EVTSEL GENMASK_ULL(31, 24) 64 65 #define MLXBF_PMC_L3C_PERF_CNT_CFG 0x0 66 #define MLXBF_PMC_L3C_PERF_CNT_SEL 0x10 67 #define MLXBF_PMC_L3C_PERF_CNT_SEL_1 0x14 68 #define MLXBF_PMC_L3C_PERF_CNT_LOW 0x40 69 #define MLXBF_PMC_L3C_PERF_CNT_HIGH 0x60 70 71 #define MLXBF_PMC_L3C_PERF_CNT_CFG_EN BIT(0) 72 #define MLXBF_PMC_L3C_PERF_CNT_CFG_RST BIT(1) 73 #define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0 GENMASK(5, 0) 74 #define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1 GENMASK(13, 8) 75 #define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2 GENMASK(21, 16) 76 #define MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3 GENMASK(29, 24) 77 78 #define MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4 GENMASK(5, 0) 79 80 #define MLXBF_PMC_L3C_PERF_CNT_LOW_VAL GENMASK(31, 0) 81 #define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0) 82 83 #define MLXBF_PMC_CRSPACE_PERFMON_REG0 0x0 84 #define MLXBF_PMC_CRSPACE_PERFSEL_SZ 4 85 #define MLXBF_PMC_CRSPACE_PERFSEL0 GENMASK(23, 16) 86 #define MLXBF_PMC_CRSPACE_PERFSEL1 GENMASK(7, 0) 87 #define MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ 0x2 88 #define MLXBF_PMC_CRSPACE_PERFMON_CTL(n) (n * MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ) 89 #define MLXBF_PMC_CRSPACE_PERFMON_EN BIT(30) 90 #define MLXBF_PMC_CRSPACE_PERFMON_CLR BIT(28) 91 #define MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0x4) 92 #define MLXBF_PMC_CRSPACE_PERFMON_VAL0(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0xc) 93 94 /** 95 * struct mlxbf_pmc_attribute - Structure to hold attribute and block info 96 * for each sysfs entry 97 * @dev_attr: Device attribute struct 98 * @index: index to identify counter number within a block 99 * @nr: block number to which the sysfs belongs 100 */ 101 struct mlxbf_pmc_attribute { 102 struct device_attribute dev_attr; 103 unsigned int index; 104 unsigned int nr; 105 }; 106 107 /** 108 * struct mlxbf_pmc_block_info - Structure to hold info for each HW block 109 * 110 * @mmio_base: The VA at which the PMC block is mapped 111 * @blk_size: Size of each mapped region 112 * @counters: Number of counters in the block 113 * @type: Type of counters in the block 114 * @attr_counter: Attributes for "counter" sysfs files 115 * @attr_event: Attributes for "event" sysfs files 116 * @attr_event_list: Attributes for "event_list" sysfs files 117 * @attr_enable: Attributes for "enable" sysfs files 118 * @attr_count_clock: Attributes for "count_clock" sysfs files 119 * @block_attr: All attributes needed for the block 120 * @block_attr_grp: Attribute group for the block 121 */ 122 struct mlxbf_pmc_block_info { 123 void __iomem *mmio_base; 124 size_t blk_size; 125 size_t counters; 126 unsigned int type; 127 struct mlxbf_pmc_attribute *attr_counter; 128 struct mlxbf_pmc_attribute *attr_event; 129 struct mlxbf_pmc_attribute attr_event_list; 130 struct mlxbf_pmc_attribute attr_enable; 131 struct mlxbf_pmc_attribute attr_count_clock; 132 struct attribute *block_attr[MLXBF_PMC_MAX_ATTRS]; 133 struct attribute_group block_attr_grp; 134 }; 135 136 /** 137 * struct mlxbf_pmc_context - Structure to hold PMC context info 138 * 139 * @pdev: The kernel structure representing the device 140 * @total_blocks: Total number of blocks 141 * @tile_count: Number of tiles in the system 142 * @apt_enable: Info on enabled APTs 143 * @llt_enable: Info on enabled LLTs 144 * @mss_enable: Info on enabled MSSs 145 * @group_num: Group number assigned to each valid block 146 * @hwmon_dev: Hwmon device for bfperf 147 * @block_name: Block name 148 * @block: Block info 149 * @groups: Attribute groups from each block 150 * @svc_sreg_support: Whether SMCs are used to access performance registers 151 * @sreg_tbl_perf: Secure register access table number 152 * @event_set: Event set to use 153 */ 154 struct mlxbf_pmc_context { 155 struct platform_device *pdev; 156 u32 total_blocks; 157 u32 tile_count; 158 u8 apt_enable; 159 u8 llt_enable; 160 u8 mss_enable; 161 u32 group_num; 162 struct device *hwmon_dev; 163 const char *block_name[MLXBF_PMC_MAX_BLOCKS]; 164 struct mlxbf_pmc_block_info block[MLXBF_PMC_MAX_BLOCKS]; 165 const struct attribute_group *groups[MLXBF_PMC_MAX_BLOCKS]; 166 bool svc_sreg_support; 167 u32 sreg_tbl_perf; 168 unsigned int event_set; 169 }; 170 171 /** 172 * struct mlxbf_pmc_events - Structure to hold supported events for each block 173 * @evt_num: Event number used to program counters 174 * @evt_name: Name of the event 175 */ 176 struct mlxbf_pmc_events { 177 u32 evt_num; 178 char *evt_name; 179 }; 180 181 static const struct mlxbf_pmc_events mlxbf_pmc_pcie_events[] = { 182 { 0x0, "IN_P_PKT_CNT" }, 183 { 0x10, "IN_NP_PKT_CNT" }, 184 { 0x18, "IN_C_PKT_CNT" }, 185 { 0x20, "OUT_P_PKT_CNT" }, 186 { 0x28, "OUT_NP_PKT_CNT" }, 187 { 0x30, "OUT_C_PKT_CNT" }, 188 { 0x38, "IN_P_BYTE_CNT" }, 189 { 0x40, "IN_NP_BYTE_CNT" }, 190 { 0x48, "IN_C_BYTE_CNT" }, 191 { 0x50, "OUT_P_BYTE_CNT" }, 192 { 0x58, "OUT_NP_BYTE_CNT" }, 193 { 0x60, "OUT_C_BYTE_CNT" }, 194 }; 195 196 static const struct mlxbf_pmc_events mlxbf_pmc_smgen_events[] = { 197 { 0x0, "AW_REQ" }, 198 { 0x1, "AW_BEATS" }, 199 { 0x2, "AW_TRANS" }, 200 { 0x3, "AW_RESP" }, 201 { 0x4, "AW_STL" }, 202 { 0x5, "AW_LAT" }, 203 { 0x6, "AW_REQ_TBU" }, 204 { 0x8, "AR_REQ" }, 205 { 0x9, "AR_BEATS" }, 206 { 0xa, "AR_TRANS" }, 207 { 0xb, "AR_STL" }, 208 { 0xc, "AR_LAT" }, 209 { 0xd, "AR_REQ_TBU" }, 210 { 0xe, "TBU_MISS" }, 211 { 0xf, "TX_DAT_AF" }, 212 { 0x10, "RX_DAT_AF" }, 213 { 0x11, "RETRYQ_CRED" }, 214 }; 215 216 static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = { 217 { 0x0, "DISABLE" }, 218 { 0xa0, "TPIO_DATA_BEAT" }, 219 { 0xa1, "TDMA_DATA_BEAT" }, 220 { 0xa2, "MAP_DATA_BEAT" }, 221 { 0xa3, "TXMSG_DATA_BEAT" }, 222 { 0xa4, "TPIO_DATA_PACKET" }, 223 { 0xa5, "TDMA_DATA_PACKET" }, 224 { 0xa6, "MAP_DATA_PACKET" }, 225 { 0xa7, "TXMSG_DATA_PACKET" }, 226 { 0xa8, "TDMA_RT_AF" }, 227 { 0xa9, "TDMA_PBUF_MAC_AF" }, 228 { 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" }, 229 { 0xab, "TRIO_MAP_CPL_BUF_EMPTY" }, 230 { 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" }, 231 { 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" }, 232 { 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" }, 233 { 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" }, 234 { 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" }, 235 { 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" }, 236 { 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" }, 237 { 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" }, 238 }; 239 240 static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = { 241 { 0x0, "DISABLE" }, 242 { 0xa0, "TPIO_DATA_BEAT" }, 243 { 0xa1, "TDMA_DATA_BEAT" }, 244 { 0xa2, "MAP_DATA_BEAT" }, 245 { 0xa3, "TXMSG_DATA_BEAT" }, 246 { 0xa4, "TPIO_DATA_PACKET" }, 247 { 0xa5, "TDMA_DATA_PACKET" }, 248 { 0xa6, "MAP_DATA_PACKET" }, 249 { 0xa7, "TXMSG_DATA_PACKET" }, 250 { 0xa8, "TDMA_RT_AF" }, 251 { 0xa9, "TDMA_PBUF_MAC_AF" }, 252 { 0xaa, "TRIO_MAP_WRQ_BUF_EMPTY" }, 253 { 0xab, "TRIO_MAP_CPL_BUF_EMPTY" }, 254 { 0xac, "TRIO_MAP_RDQ0_BUF_EMPTY" }, 255 { 0xad, "TRIO_MAP_RDQ1_BUF_EMPTY" }, 256 { 0xae, "TRIO_MAP_RDQ2_BUF_EMPTY" }, 257 { 0xaf, "TRIO_MAP_RDQ3_BUF_EMPTY" }, 258 { 0xb0, "TRIO_MAP_RDQ4_BUF_EMPTY" }, 259 { 0xb1, "TRIO_MAP_RDQ5_BUF_EMPTY" }, 260 { 0xb2, "TRIO_MAP_RDQ6_BUF_EMPTY" }, 261 { 0xb3, "TRIO_MAP_RDQ7_BUF_EMPTY" }, 262 { 0xb4, "TRIO_RING_TX_FLIT_CH0" }, 263 { 0xb5, "TRIO_RING_TX_FLIT_CH1" }, 264 { 0xb6, "TRIO_RING_TX_FLIT_CH2" }, 265 { 0xb7, "TRIO_RING_TX_FLIT_CH3" }, 266 { 0xb8, "TRIO_RING_TX_FLIT_CH4" }, 267 { 0xb9, "TRIO_RING_RX_FLIT_CH0" }, 268 { 0xba, "TRIO_RING_RX_FLIT_CH1" }, 269 { 0xbb, "TRIO_RING_RX_FLIT_CH2" }, 270 { 0xbc, "TRIO_RING_RX_FLIT_CH3" }, 271 }; 272 273 static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = { 274 { 0x0, "DISABLE" }, 275 { 0x100, "ECC_SINGLE_ERROR_CNT" }, 276 { 0x104, "ECC_DOUBLE_ERROR_CNT" }, 277 { 0x114, "SERR_INJ" }, 278 { 0x118, "DERR_INJ" }, 279 { 0x124, "ECC_SINGLE_ERROR_0" }, 280 { 0x164, "ECC_DOUBLE_ERROR_0" }, 281 { 0x340, "DRAM_ECC_COUNT" }, 282 { 0x344, "DRAM_ECC_INJECT" }, 283 { 0x348, "DRAM_ECC_ERROR" }, 284 }; 285 286 static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_1[] = { 287 { 0x0, "DISABLE" }, 288 { 0xc0, "RXREQ_MSS" }, 289 { 0xc1, "RXDAT_MSS" }, 290 { 0xc2, "TXRSP_MSS" }, 291 { 0xc3, "TXDAT_MSS" }, 292 }; 293 294 static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_3[] = { 295 {0, "SKYLIB_CDN_TX_FLITS"}, 296 {1, "SKYLIB_DDN_TX_FLITS"}, 297 {2, "SKYLIB_NDN_TX_FLITS"}, 298 {3, "SKYLIB_SDN_TX_FLITS"}, 299 {4, "SKYLIB_UDN_TX_FLITS"}, 300 {5, "SKYLIB_CDN_RX_FLITS"}, 301 {6, "SKYLIB_DDN_RX_FLITS"}, 302 {7, "SKYLIB_NDN_RX_FLITS"}, 303 {8, "SKYLIB_SDN_RX_FLITS"}, 304 {9, "SKYLIB_UDN_RX_FLITS"}, 305 {10, "SKYLIB_CDN_TX_STALL"}, 306 {11, "SKYLIB_DDN_TX_STALL"}, 307 {12, "SKYLIB_NDN_TX_STALL"}, 308 {13, "SKYLIB_SDN_TX_STALL"}, 309 {14, "SKYLIB_UDN_TX_STALL"}, 310 {15, "SKYLIB_CDN_RX_STALL"}, 311 {16, "SKYLIB_DDN_RX_STALL"}, 312 {17, "SKYLIB_NDN_RX_STALL"}, 313 {18, "SKYLIB_SDN_RX_STALL"}, 314 {19, "SKYLIB_UDN_RX_STALL"}, 315 {20, "SKYLIB_CHI_REQ0_TX_FLITS"}, 316 {21, "SKYLIB_CHI_DATA0_TX_FLITS"}, 317 {22, "SKYLIB_CHI_RESP0_TX_FLITS"}, 318 {23, "SKYLIB_CHI_SNP0_TX_FLITS"}, 319 {24, "SKYLIB_CHI_REQ1_TX_FLITS"}, 320 {25, "SKYLIB_CHI_DATA1_TX_FLITS"}, 321 {26, "SKYLIB_CHI_RESP1_TX_FLITS"}, 322 {27, "SKYLIB_CHI_SNP1_TX_FLITS"}, 323 {28, "SKYLIB_CHI_REQ2_TX_FLITS"}, 324 {29, "SKYLIB_CHI_DATA2_TX_FLITS"}, 325 {30, "SKYLIB_CHI_RESP2_TX_FLITS"}, 326 {31, "SKYLIB_CHI_SNP2_TX_FLITS"}, 327 {32, "SKYLIB_CHI_REQ3_TX_FLITS"}, 328 {33, "SKYLIB_CHI_DATA3_TX_FLITS"}, 329 {34, "SKYLIB_CHI_RESP3_TX_FLITS"}, 330 {35, "SKYLIB_CHI_SNP3_TX_FLITS"}, 331 {36, "SKYLIB_TLP_REQ_TX_FLITS"}, 332 {37, "SKYLIB_TLP_RESP_TX_FLITS"}, 333 {38, "SKYLIB_TLP_META_TX_FLITS"}, 334 {39, "SKYLIB_AXIS_DATA_TX_FLITS"}, 335 {40, "SKYLIB_AXIS_CRED_TX_FLITS"}, 336 {41, "SKYLIB_APB_TX_FLITS"}, 337 {42, "SKYLIB_VW_TX_FLITS"}, 338 {43, "SKYLIB_GGA_MSN_W_TX_FLITS"}, 339 {44, "SKYLIB_GGA_MSN_N_TX_FLITS"}, 340 {45, "SKYLIB_CR_REQ_TX_FLITS"}, 341 {46, "SKYLIB_CR_RESP_TX_FLITS"}, 342 {47, "SKYLIB_MSN_PRNF_TX_FLITS"}, 343 {48, "SKYLIB_DBG_DATA_TX_FLITS"}, 344 {49, "SKYLIB_DBG_CRED_TX_FLITS"}, 345 {50, "SKYLIB_CHI_REQ0_RX_FLITS"}, 346 {51, "SKYLIB_CHI_DATA0_RX_FLITS"}, 347 {52, "SKYLIB_CHI_RESP0_RX_FLITS"}, 348 {53, "SKYLIB_CHI_SNP0_RX_FLITS"}, 349 {54, "SKYLIB_CHI_REQ1_RX_FLITS"}, 350 {55, "SKYLIB_CHI_DATA1_RX_FLITS"}, 351 {56, "SKYLIB_CHI_RESP1_RX_FLITS"}, 352 {57, "SKYLIB_CHI_SNP1_RX_FLITS"}, 353 {58, "SKYLIB_CHI_REQ2_RX_FLITS"}, 354 {59, "SKYLIB_CHI_DATA2_RX_FLITS"}, 355 {60, "SKYLIB_CHI_RESP2_RX_FLITS"}, 356 {61, "SKYLIB_CHI_SNP2_RX_FLITS"}, 357 {62, "SKYLIB_CHI_REQ3_RX_FLITS"}, 358 {63, "SKYLIB_CHI_DATA3_RX_FLITS"}, 359 {64, "SKYLIB_CHI_RESP3_RX_FLITS"}, 360 {65, "SKYLIB_CHI_SNP3_RX_FLITS"}, 361 {66, "SKYLIB_TLP_REQ_RX_FLITS"}, 362 {67, "SKYLIB_TLP_RESP_RX_FLITS"}, 363 {68, "SKYLIB_TLP_META_RX_FLITS"}, 364 {69, "SKYLIB_AXIS_DATA_RX_FLITS"}, 365 {70, "SKYLIB_AXIS_CRED_RX_FLITS"}, 366 {71, "SKYLIB_APB_RX_FLITS"}, 367 {72, "SKYLIB_VW_RX_FLITS"}, 368 {73, "SKYLIB_GGA_MSN_W_RX_FLITS"}, 369 {74, "SKYLIB_GGA_MSN_N_RX_FLITS"}, 370 {75, "SKYLIB_CR_REQ_RX_FLITS"}, 371 {76, "SKYLIB_CR_RESP_RX_FLITS"}, 372 {77, "SKYLIB_MSN_PRNF_RX_FLITS"}, 373 {78, "SKYLIB_DBG_DATA_RX_FLITS"}, 374 {79, "SKYLIB_DBG_CRED_RX_FLITS"}, 375 {80, "SKYLIB_CHI_REQ0_TX_STALL"}, 376 {81, "SKYLIB_CHI_DATA0_TX_STALL"}, 377 {82, "SKYLIB_CHI_RESP0_TX_STALL"}, 378 {83, "SKYLIB_CHI_SNP0_TX_STALL"}, 379 {84, "SKYLIB_CHI_REQ1_TX_STALL"}, 380 {85, "SKYLIB_CHI_DATA1_TX_STALL"}, 381 {86, "SKYLIB_CHI_RESP1_TX_STALL"}, 382 {87, "SKYLIB_CHI_SNP1_TX_STALL"}, 383 {88, "SKYLIB_CHI_REQ2_TX_STALL"}, 384 {89, "SKYLIB_CHI_DATA2_TX_STALL"}, 385 {90, "SKYLIB_CHI_RESP2_TX_STALL"}, 386 {91, "SKYLIB_CHI_SNP2_TX_STALL"}, 387 {92, "SKYLIB_CHI_REQ3_TX_STALL"}, 388 {93, "SKYLIB_CHI_DATA3_TX_STALL"}, 389 {94, "SKYLIB_CHI_RESP3_TX_STALL"}, 390 {95, "SKYLIB_CHI_SNP3_TX_STALL"}, 391 {96, "SKYLIB_TLP_REQ_TX_STALL"}, 392 {97, "SKYLIB_TLP_RESP_TX_STALL"}, 393 {98, "SKYLIB_TLP_META_TX_STALL"}, 394 {99, "SKYLIB_AXIS_DATA_TX_STALL"}, 395 {100, "SKYLIB_AXIS_CRED_TX_STALL"}, 396 {101, "SKYLIB_APB_TX_STALL"}, 397 {102, "SKYLIB_VW_TX_STALL"}, 398 {103, "SKYLIB_GGA_MSN_W_TX_STALL"}, 399 {104, "SKYLIB_GGA_MSN_N_TX_STALL"}, 400 {105, "SKYLIB_CR_REQ_TX_STALL"}, 401 {106, "SKYLIB_CR_RESP_TX_STALL"}, 402 {107, "SKYLIB_MSN_PRNF_TX_STALL"}, 403 {108, "SKYLIB_DBG_DATA_TX_STALL"}, 404 {109, "SKYLIB_DBG_CRED_TX_STALL"}, 405 {110, "SKYLIB_CHI_REQ0_RX_STALL"}, 406 {111, "SKYLIB_CHI_DATA0_RX_STALL"}, 407 {112, "SKYLIB_CHI_RESP0_RX_STALL"}, 408 {113, "SKYLIB_CHI_SNP0_RX_STALL"}, 409 {114, "SKYLIB_CHI_REQ1_RX_STALL"}, 410 {115, "SKYLIB_CHI_DATA1_RX_STALL"}, 411 {116, "SKYLIB_CHI_RESP1_RX_STALL"}, 412 {117, "SKYLIB_CHI_SNP1_RX_STALL"}, 413 {118, "SKYLIB_CHI_REQ2_RX_STALL"}, 414 {119, "SKYLIB_CHI_DATA2_RX_STALL"}, 415 {120, "SKYLIB_CHI_RESP2_RX_STALL"}, 416 {121, "SKYLIB_CHI_SNP2_RX_STALL"}, 417 {122, "SKYLIB_CHI_REQ3_RX_STALL"}, 418 {123, "SKYLIB_CHI_DATA3_RX_STALL"}, 419 {124, "SKYLIB_CHI_RESP3_RX_STALL"}, 420 {125, "SKYLIB_CHI_SNP3_RX_STALL"}, 421 {126, "SKYLIB_TLP_REQ_RX_STALL"}, 422 {127, "SKYLIB_TLP_RESP_RX_STALL"}, 423 {128, "SKYLIB_TLP_META_RX_STALL"}, 424 {129, "SKYLIB_AXIS_DATA_RX_STALL"}, 425 {130, "SKYLIB_AXIS_CRED_RX_STALL"}, 426 {131, "SKYLIB_APB_RX_STALL"}, 427 {132, "SKYLIB_VW_RX_STALL"}, 428 {133, "SKYLIB_GGA_MSN_W_RX_STALL"}, 429 {134, "SKYLIB_GGA_MSN_N_RX_STALL"}, 430 {135, "SKYLIB_CR_REQ_RX_STALL"}, 431 {136, "SKYLIB_CR_RESP_RX_STALL"}, 432 {137, "SKYLIB_MSN_PRNF_RX_STALL"}, 433 {138, "SKYLIB_DBG_DATA_RX_STALL"}, 434 {139, "SKYLIB_DBG_CRED_RX_STALL"}, 435 {140, "SKYLIB_CDN_LOOPBACK_FLITS"}, 436 {141, "SKYLIB_DDN_LOOPBACK_FLITS"}, 437 {142, "SKYLIB_NDN_LOOPBACK_FLITS"}, 438 {143, "SKYLIB_SDN_LOOPBACK_FLITS"}, 439 {144, "SKYLIB_UDN_LOOPBACK_FLITS"}, 440 {145, "HISTOGRAM_HISTOGRAM_BIN0"}, 441 {146, "HISTOGRAM_HISTOGRAM_BIN1"}, 442 {147, "HISTOGRAM_HISTOGRAM_BIN2"}, 443 {148, "HISTOGRAM_HISTOGRAM_BIN3"}, 444 {149, "HISTOGRAM_HISTOGRAM_BIN4"}, 445 {150, "HISTOGRAM_HISTOGRAM_BIN5"}, 446 {151, "HISTOGRAM_HISTOGRAM_BIN6"}, 447 {152, "HISTOGRAM_HISTOGRAM_BIN7"}, 448 {153, "HISTOGRAM_HISTOGRAM_BIN8"}, 449 {154, "HISTOGRAM_HISTOGRAM_BIN9"}, 450 }; 451 452 static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = { 453 { 0x0, "DISABLE" }, 454 { 0x45, "HNF_REQUESTS" }, 455 { 0x46, "HNF_REJECTS" }, 456 { 0x47, "ALL_BUSY" }, 457 { 0x48, "MAF_BUSY" }, 458 { 0x49, "MAF_REQUESTS" }, 459 { 0x4a, "RNF_REQUESTS" }, 460 { 0x4b, "REQUEST_TYPE" }, 461 { 0x4c, "MEMORY_READS" }, 462 { 0x4d, "MEMORY_WRITES" }, 463 { 0x4e, "VICTIM_WRITE" }, 464 { 0x4f, "POC_FULL" }, 465 { 0x50, "POC_FAIL" }, 466 { 0x51, "POC_SUCCESS" }, 467 { 0x52, "POC_WRITES" }, 468 { 0x53, "POC_READS" }, 469 { 0x54, "FORWARD" }, 470 { 0x55, "RXREQ_HNF" }, 471 { 0x56, "RXRSP_HNF" }, 472 { 0x57, "RXDAT_HNF" }, 473 { 0x58, "TXREQ_HNF" }, 474 { 0x59, "TXRSP_HNF" }, 475 { 0x5a, "TXDAT_HNF" }, 476 { 0x5b, "TXSNP_HNF" }, 477 { 0x5c, "INDEX_MATCH" }, 478 { 0x5d, "A72_ACCESS" }, 479 { 0x5e, "IO_ACCESS" }, 480 { 0x5f, "TSO_WRITE" }, 481 { 0x60, "TSO_CONFLICT" }, 482 { 0x61, "DIR_HIT" }, 483 { 0x62, "HNF_ACCEPTS" }, 484 { 0x63, "REQ_BUF_EMPTY" }, 485 { 0x64, "REQ_BUF_IDLE_MAF" }, 486 { 0x65, "TSO_NOARB" }, 487 { 0x66, "TSO_NOARB_CYCLES" }, 488 { 0x67, "MSS_NO_CREDIT" }, 489 { 0x68, "TXDAT_NO_LCRD" }, 490 { 0x69, "TXSNP_NO_LCRD" }, 491 { 0x6a, "TXRSP_NO_LCRD" }, 492 { 0x6b, "TXREQ_NO_LCRD" }, 493 { 0x6c, "TSO_CL_MATCH" }, 494 { 0x6d, "MEMORY_READS_BYPASS" }, 495 { 0x6e, "TSO_NOARB_TIMEOUT" }, 496 { 0x6f, "ALLOCATE" }, 497 { 0x70, "VICTIM" }, 498 { 0x71, "A72_WRITE" }, 499 { 0x72, "A72_READ" }, 500 { 0x73, "IO_WRITE" }, 501 { 0x74, "IO_READ" }, 502 { 0x75, "TSO_REJECT" }, 503 { 0x80, "TXREQ_RN" }, 504 { 0x81, "TXRSP_RN" }, 505 { 0x82, "TXDAT_RN" }, 506 { 0x83, "RXSNP_RN" }, 507 { 0x84, "RXRSP_RN" }, 508 { 0x85, "RXDAT_RN" }, 509 }; 510 511 static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = { 512 { 0x0, "DISABLE" }, 513 { 0x12, "CDN_REQ" }, 514 { 0x13, "DDN_REQ" }, 515 { 0x14, "NDN_REQ" }, 516 { 0x15, "CDN_DIAG_N_OUT_OF_CRED" }, 517 { 0x16, "CDN_DIAG_S_OUT_OF_CRED" }, 518 { 0x17, "CDN_DIAG_E_OUT_OF_CRED" }, 519 { 0x18, "CDN_DIAG_W_OUT_OF_CRED" }, 520 { 0x19, "CDN_DIAG_C_OUT_OF_CRED" }, 521 { 0x1a, "CDN_DIAG_N_EGRESS" }, 522 { 0x1b, "CDN_DIAG_S_EGRESS" }, 523 { 0x1c, "CDN_DIAG_E_EGRESS" }, 524 { 0x1d, "CDN_DIAG_W_EGRESS" }, 525 { 0x1e, "CDN_DIAG_C_EGRESS" }, 526 { 0x1f, "CDN_DIAG_N_INGRESS" }, 527 { 0x20, "CDN_DIAG_S_INGRESS" }, 528 { 0x21, "CDN_DIAG_E_INGRESS" }, 529 { 0x22, "CDN_DIAG_W_INGRESS" }, 530 { 0x23, "CDN_DIAG_C_INGRESS" }, 531 { 0x24, "CDN_DIAG_CORE_SENT" }, 532 { 0x25, "DDN_DIAG_N_OUT_OF_CRED" }, 533 { 0x26, "DDN_DIAG_S_OUT_OF_CRED" }, 534 { 0x27, "DDN_DIAG_E_OUT_OF_CRED" }, 535 { 0x28, "DDN_DIAG_W_OUT_OF_CRED" }, 536 { 0x29, "DDN_DIAG_C_OUT_OF_CRED" }, 537 { 0x2a, "DDN_DIAG_N_EGRESS" }, 538 { 0x2b, "DDN_DIAG_S_EGRESS" }, 539 { 0x2c, "DDN_DIAG_E_EGRESS" }, 540 { 0x2d, "DDN_DIAG_W_EGRESS" }, 541 { 0x2e, "DDN_DIAG_C_EGRESS" }, 542 { 0x2f, "DDN_DIAG_N_INGRESS" }, 543 { 0x30, "DDN_DIAG_S_INGRESS" }, 544 { 0x31, "DDN_DIAG_E_INGRESS" }, 545 { 0x32, "DDN_DIAG_W_INGRESS" }, 546 { 0x33, "DDN_DIAG_C_INGRESS" }, 547 { 0x34, "DDN_DIAG_CORE_SENT" }, 548 { 0x35, "NDN_DIAG_N_OUT_OF_CRED" }, 549 { 0x36, "NDN_DIAG_S_OUT_OF_CRED" }, 550 { 0x37, "NDN_DIAG_E_OUT_OF_CRED" }, 551 { 0x38, "NDN_DIAG_W_OUT_OF_CRED" }, 552 { 0x39, "NDN_DIAG_C_OUT_OF_CRED" }, 553 { 0x3a, "NDN_DIAG_N_EGRESS" }, 554 { 0x3b, "NDN_DIAG_S_EGRESS" }, 555 { 0x3c, "NDN_DIAG_E_EGRESS" }, 556 { 0x3d, "NDN_DIAG_W_EGRESS" }, 557 { 0x3e, "NDN_DIAG_C_EGRESS" }, 558 { 0x3f, "NDN_DIAG_N_INGRESS" }, 559 { 0x40, "NDN_DIAG_S_INGRESS" }, 560 { 0x41, "NDN_DIAG_E_INGRESS" }, 561 { 0x42, "NDN_DIAG_W_INGRESS" }, 562 { 0x43, "NDN_DIAG_C_INGRESS" }, 563 { 0x44, "NDN_DIAG_CORE_SENT" }, 564 }; 565 566 static const struct mlxbf_pmc_events mlxbf_pmc_l3c_events[] = { 567 { 0x00, "DISABLE" }, 568 { 0x01, "CYCLES" }, 569 { 0x02, "TOTAL_RD_REQ_IN" }, 570 { 0x03, "TOTAL_WR_REQ_IN" }, 571 { 0x04, "TOTAL_WR_DBID_ACK" }, 572 { 0x05, "TOTAL_WR_DATA_IN" }, 573 { 0x06, "TOTAL_WR_COMP" }, 574 { 0x07, "TOTAL_RD_DATA_OUT" }, 575 { 0x08, "TOTAL_CDN_REQ_IN_BANK0" }, 576 { 0x09, "TOTAL_CDN_REQ_IN_BANK1" }, 577 { 0x0a, "TOTAL_DDN_REQ_IN_BANK0" }, 578 { 0x0b, "TOTAL_DDN_REQ_IN_BANK1" }, 579 { 0x0c, "TOTAL_EMEM_RD_RES_IN_BANK0" }, 580 { 0x0d, "TOTAL_EMEM_RD_RES_IN_BANK1" }, 581 { 0x0e, "TOTAL_CACHE_RD_RES_IN_BANK0" }, 582 { 0x0f, "TOTAL_CACHE_RD_RES_IN_BANK1" }, 583 { 0x10, "TOTAL_EMEM_RD_REQ_BANK0" }, 584 { 0x11, "TOTAL_EMEM_RD_REQ_BANK1" }, 585 { 0x12, "TOTAL_EMEM_WR_REQ_BANK0" }, 586 { 0x13, "TOTAL_EMEM_WR_REQ_BANK1" }, 587 { 0x14, "TOTAL_RD_REQ_OUT" }, 588 { 0x15, "TOTAL_WR_REQ_OUT" }, 589 { 0x16, "TOTAL_RD_RES_IN" }, 590 { 0x17, "HITS_BANK0" }, 591 { 0x18, "HITS_BANK1" }, 592 { 0x19, "MISSES_BANK0" }, 593 { 0x1a, "MISSES_BANK1" }, 594 { 0x1b, "ALLOCATIONS_BANK0" }, 595 { 0x1c, "ALLOCATIONS_BANK1" }, 596 { 0x1d, "EVICTIONS_BANK0" }, 597 { 0x1e, "EVICTIONS_BANK1" }, 598 { 0x1f, "DBID_REJECT" }, 599 { 0x20, "WRDB_REJECT_BANK0" }, 600 { 0x21, "WRDB_REJECT_BANK1" }, 601 { 0x22, "CMDQ_REJECT_BANK0" }, 602 { 0x23, "CMDQ_REJECT_BANK1" }, 603 { 0x24, "COB_REJECT_BANK0" }, 604 { 0x25, "COB_REJECT_BANK1" }, 605 { 0x26, "TRB_REJECT_BANK0" }, 606 { 0x27, "TRB_REJECT_BANK1" }, 607 { 0x28, "TAG_REJECT_BANK0" }, 608 { 0x29, "TAG_REJECT_BANK1" }, 609 { 0x2a, "ANY_REJECT_BANK0" }, 610 { 0x2b, "ANY_REJECT_BANK1" }, 611 }; 612 613 static const struct mlxbf_pmc_events mlxbf_pmc_llt_events[] = { 614 {0, "HNF0_CYCLES"}, 615 {1, "HNF0_REQS_RECEIVED"}, 616 {2, "HNF0_REQS_PROCESSED"}, 617 {3, "HNF0_DIR_HIT"}, 618 {4, "HNF0_DIR_MISS"}, 619 {5, "HNF0_DIR_RD_ALLOC"}, 620 {6, "HNF0_DIR_WR_ALLOC"}, 621 {7, "HNF0_DIR_VICTIM"}, 622 {8, "HNF0_CL_HAZARD"}, 623 {9, "HNF0_ALL_HAZARD"}, 624 {10, "HNF0_PIPE_STALLS"}, 625 {11, "HNF0_MEM_READS"}, 626 {12, "HNF0_MEM_WRITES"}, 627 {13, "HNF0_MEM_ACCESS"}, 628 {14, "HNF0_DCL_READ"}, 629 {15, "HNF0_DCL_INVAL"}, 630 {16, "HNF0_CHI_RXDAT"}, 631 {17, "HNF0_CHI_RXRSP"}, 632 {18, "HNF0_CHI_TXDAT"}, 633 {19, "HNF0_CHI_TXRSP"}, 634 {20, "HNF0_CHI_TXSNP"}, 635 {21, "HNF0_DCT_SNP"}, 636 {22, "HNF0_SNP_FWD_DATA"}, 637 {23, "HNF0_SNP_FWD_RSP"}, 638 {24, "HNF0_SNP_RSP"}, 639 {25, "HNF0_EXCL_FULL"}, 640 {26, "HNF0_EXCL_WRITE_F"}, 641 {27, "HNF0_EXCL_WRITE_S"}, 642 {28, "HNF0_EXCL_WRITE"}, 643 {29, "HNF0_EXCL_READ"}, 644 {30, "HNF0_REQ_BUF_EMPTY"}, 645 {31, "HNF0_ALL_MAFS_BUSY"}, 646 {32, "HNF0_TXDAT_NO_LCRD"}, 647 {33, "HNF0_TXSNP_NO_LCRD"}, 648 {34, "HNF0_TXRSP_NO_LCRD"}, 649 {35, "HNF0_TXREQ_NO_LCRD"}, 650 {36, "HNF0_WRITE"}, 651 {37, "HNF0_READ"}, 652 {38, "HNF0_ACCESS"}, 653 {39, "HNF0_MAF_N_BUSY"}, 654 {40, "HNF0_MAF_N_REQS"}, 655 {41, "HNF0_SEL_OPCODE"}, 656 {42, "HNF1_CYCLES"}, 657 {43, "HNF1_REQS_RECEIVED"}, 658 {44, "HNF1_REQS_PROCESSED"}, 659 {45, "HNF1_DIR_HIT"}, 660 {46, "HNF1_DIR_MISS"}, 661 {47, "HNF1_DIR_RD_ALLOC"}, 662 {48, "HNF1_DIR_WR_ALLOC"}, 663 {49, "HNF1_DIR_VICTIM"}, 664 {50, "HNF1_CL_HAZARD"}, 665 {51, "HNF1_ALL_HAZARD"}, 666 {52, "HNF1_PIPE_STALLS"}, 667 {53, "HNF1_MEM_READS"}, 668 {54, "HNF1_MEM_WRITES"}, 669 {55, "HNF1_MEM_ACCESS"}, 670 {56, "HNF1_DCL_READ"}, 671 {57, "HNF1_DCL_INVAL"}, 672 {58, "HNF1_CHI_RXDAT"}, 673 {59, "HNF1_CHI_RXRSP"}, 674 {60, "HNF1_CHI_TXDAT"}, 675 {61, "HNF1_CHI_TXRSP"}, 676 {62, "HNF1_CHI_TXSNP"}, 677 {63, "HNF1_DCT_SNP"}, 678 {64, "HNF1_SNP_FWD_DATA"}, 679 {65, "HNF1_SNP_FWD_RSP"}, 680 {66, "HNF1_SNP_RSP"}, 681 {67, "HNF1_EXCL_FULL"}, 682 {68, "HNF1_EXCL_WRITE_F"}, 683 {69, "HNF1_EXCL_WRITE_S"}, 684 {70, "HNF1_EXCL_WRITE"}, 685 {71, "HNF1_EXCL_READ"}, 686 {72, "HNF1_REQ_BUF_EMPTY"}, 687 {73, "HNF1_ALL_MAFS_BUSY"}, 688 {74, "HNF1_TXDAT_NO_LCRD"}, 689 {75, "HNF1_TXSNP_NO_LCRD"}, 690 {76, "HNF1_TXRSP_NO_LCRD"}, 691 {77, "HNF1_TXREQ_NO_LCRD"}, 692 {78, "HNF1_WRITE"}, 693 {79, "HNF1_READ"}, 694 {80, "HNF1_ACCESS"}, 695 {81, "HNF1_MAF_N_BUSY"}, 696 {82, "HNF1_MAF_N_REQS"}, 697 {83, "HNF1_SEL_OPCODE"}, 698 {84, "GDC_BANK0_RD_REQ"}, 699 {85, "GDC_BANK0_WR_REQ"}, 700 {86, "GDC_BANK0_ALLOCATE"}, 701 {87, "GDC_BANK0_HIT"}, 702 {88, "GDC_BANK0_MISS"}, 703 {89, "GDC_BANK0_INVALIDATE"}, 704 {90, "GDC_BANK0_EVICT"}, 705 {91, "GDC_BANK0_RD_RESP"}, 706 {92, "GDC_BANK0_WR_ACK"}, 707 {93, "GDC_BANK0_SNOOP"}, 708 {94, "GDC_BANK0_SNOOP_NORMAL"}, 709 {95, "GDC_BANK0_SNOOP_FWD"}, 710 {96, "GDC_BANK0_SNOOP_STASH"}, 711 {97, "GDC_BANK0_SNOOP_STASH_INDPND_RD"}, 712 {98, "GDC_BANK0_FOLLOWER"}, 713 {99, "GDC_BANK0_FW"}, 714 {100, "GDC_BANK0_HIT_DCL_BOTH"}, 715 {101, "GDC_BANK0_HIT_DCL_PARTIAL"}, 716 {102, "GDC_BANK0_EVICT_DCL"}, 717 {103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA0"}, 718 {104, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA1"}, 719 {105, "GDC_BANK0_ARB_STRB"}, 720 {106, "GDC_BANK0_ARB_WAIT"}, 721 {107, "GDC_BANK0_GGA_STRB"}, 722 {108, "GDC_BANK0_GGA_WAIT"}, 723 {109, "GDC_BANK0_FW_STRB"}, 724 {110, "GDC_BANK0_FW_WAIT"}, 725 {111, "GDC_BANK0_SNP_STRB"}, 726 {112, "GDC_BANK0_SNP_WAIT"}, 727 {113, "GDC_BANK0_MISS_INARB_STRB"}, 728 {114, "GDC_BANK0_MISS_INARB_WAIT"}, 729 {115, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD0"}, 730 {116, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD1"}, 731 {117, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD2"}, 732 {118, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD3"}, 733 {119, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR0"}, 734 {120, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR1"}, 735 {121, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR2"}, 736 {122, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR3"}, 737 {123, "GDC_BANK1_RD_REQ"}, 738 {124, "GDC_BANK1_WR_REQ"}, 739 {125, "GDC_BANK1_ALLOCATE"}, 740 {126, "GDC_BANK1_HIT"}, 741 {127, "GDC_BANK1_MISS"}, 742 {128, "GDC_BANK1_INVALIDATE"}, 743 {129, "GDC_BANK1_EVICT"}, 744 {130, "GDC_BANK1_RD_RESP"}, 745 {131, "GDC_BANK1_WR_ACK"}, 746 {132, "GDC_BANK1_SNOOP"}, 747 {133, "GDC_BANK1_SNOOP_NORMAL"}, 748 {134, "GDC_BANK1_SNOOP_FWD"}, 749 {135, "GDC_BANK1_SNOOP_STASH"}, 750 {136, "GDC_BANK1_SNOOP_STASH_INDPND_RD"}, 751 {137, "GDC_BANK1_FOLLOWER"}, 752 {138, "GDC_BANK1_FW"}, 753 {139, "GDC_BANK1_HIT_DCL_BOTH"}, 754 {140, "GDC_BANK1_HIT_DCL_PARTIAL"}, 755 {141, "GDC_BANK1_EVICT_DCL"}, 756 {142, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA0"}, 757 {143, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA1"}, 758 {144, "GDC_BANK1_ARB_STRB"}, 759 {145, "GDC_BANK1_ARB_WAIT"}, 760 {146, "GDC_BANK1_GGA_STRB"}, 761 {147, "GDC_BANK1_GGA_WAIT"}, 762 {148, "GDC_BANK1_FW_STRB"}, 763 {149, "GDC_BANK1_FW_WAIT"}, 764 {150, "GDC_BANK1_SNP_STRB"}, 765 {151, "GDC_BANK1_SNP_WAIT"}, 766 {152, "GDC_BANK1_MISS_INARB_STRB"}, 767 {153, "GDC_BANK1_MISS_INARB_WAIT"}, 768 {154, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD0"}, 769 {155, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD1"}, 770 {156, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD2"}, 771 {157, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD3"}, 772 {158, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR0"}, 773 {159, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR1"}, 774 {160, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR2"}, 775 {161, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR3"}, 776 {162, "HISTOGRAM_HISTOGRAM_BIN0"}, 777 {163, "HISTOGRAM_HISTOGRAM_BIN1"}, 778 {164, "HISTOGRAM_HISTOGRAM_BIN2"}, 779 {165, "HISTOGRAM_HISTOGRAM_BIN3"}, 780 {166, "HISTOGRAM_HISTOGRAM_BIN4"}, 781 {167, "HISTOGRAM_HISTOGRAM_BIN5"}, 782 {168, "HISTOGRAM_HISTOGRAM_BIN6"}, 783 {169, "HISTOGRAM_HISTOGRAM_BIN7"}, 784 {170, "HISTOGRAM_HISTOGRAM_BIN8"}, 785 {171, "HISTOGRAM_HISTOGRAM_BIN9"}, 786 }; 787 788 static const struct mlxbf_pmc_events mlxbf_pmc_llt_miss_events[] = { 789 {0, "GDC_MISS_MACHINE_RD_REQ"}, 790 {1, "GDC_MISS_MACHINE_WR_REQ"}, 791 {2, "GDC_MISS_MACHINE_SNP_REQ"}, 792 {3, "GDC_MISS_MACHINE_EVICT_REQ"}, 793 {4, "GDC_MISS_MACHINE_FW_REQ"}, 794 {5, "GDC_MISS_MACHINE_RD_RESP"}, 795 {6, "GDC_MISS_MACHINE_WR_RESP"}, 796 {7, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP"}, 797 {8, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP_TXDAT"}, 798 {9, "GDC_MISS_MACHINE_CHI_TXREQ"}, 799 {10, "GDC_MISS_MACHINE_CHI_RXRSP"}, 800 {11, "GDC_MISS_MACHINE_CHI_TXDAT"}, 801 {12, "GDC_MISS_MACHINE_CHI_RXDAT"}, 802 {13, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_0"}, 803 {14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1 "}, 804 {15, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_2"}, 805 {16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3 "}, 806 {17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0 "}, 807 {18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1 "}, 808 {19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2 "}, 809 {20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3 "}, 810 {21, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_0"}, 811 {22, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_1"}, 812 {23, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_2"}, 813 {24, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_3"}, 814 {25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0 "}, 815 {26, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_1"}, 816 {27, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_2"}, 817 {28, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_3"}, 818 {29, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_0"}, 819 {30, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_1"}, 820 {31, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_2"}, 821 {32, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_3"}, 822 {33, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_4"}, 823 {34, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_5"}, 824 {35, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_6"}, 825 {36, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_0"}, 826 {37, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_1"}, 827 {38, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_0"}, 828 {39, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_1"}, 829 {40, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_0"}, 830 {41, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_1"}, 831 {42, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_0"}, 832 {43, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_1"}, 833 {44, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_0"}, 834 {45, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_1"}, 835 {46, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_2"}, 836 {47, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_3"}, 837 {48, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_0"}, 838 {49, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_1"}, 839 {50, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_0"}, 840 {51, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_1"}, 841 {52, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_0"}, 842 {53, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_1"}, 843 {54, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_0"}, 844 {55, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_1"}, 845 {56, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_2"}, 846 {57, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_3"}, 847 {58, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_0"}, 848 {59, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_1"}, 849 {60, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_2"}, 850 {61, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_3"}, 851 {62, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_4"}, 852 {63, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_5"}, 853 {64, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_6"}, 854 {65, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_7"}, 855 {66, "HISTOGRAM_HISTOGRAM_BIN0"}, 856 {67, "HISTOGRAM_HISTOGRAM_BIN1"}, 857 {68, "HISTOGRAM_HISTOGRAM_BIN2"}, 858 {69, "HISTOGRAM_HISTOGRAM_BIN3"}, 859 {70, "HISTOGRAM_HISTOGRAM_BIN4"}, 860 {71, "HISTOGRAM_HISTOGRAM_BIN5"}, 861 {72, "HISTOGRAM_HISTOGRAM_BIN6"}, 862 {73, "HISTOGRAM_HISTOGRAM_BIN7"}, 863 {74, "HISTOGRAM_HISTOGRAM_BIN8"}, 864 {75, "HISTOGRAM_HISTOGRAM_BIN9"}, 865 }; 866 867 static const struct mlxbf_pmc_events mlxbf_pmc_clock_events[] = { 868 { 0x0, "FMON_CLK_LAST_COUNT_PLL_D1_INST0" }, 869 { 0x4, "REFERENCE_WINDOW_WIDTH_PLL_D1_INST0" }, 870 { 0x8, "FMON_CLK_LAST_COUNT_PLL_D1_INST1" }, 871 { 0xc, "REFERENCE_WINDOW_WIDTH_PLL_D1_INST1" }, 872 { 0x10, "FMON_CLK_LAST_COUNT_PLL_G1" }, 873 { 0x14, "REFERENCE_WINDOW_WIDTH_PLL_G1" }, 874 { 0x18, "FMON_CLK_LAST_COUNT_PLL_W1" }, 875 { 0x1c, "REFERENCE_WINDOW_WIDTH_PLL_W1" }, 876 { 0x20, "FMON_CLK_LAST_COUNT_PLL_T1" }, 877 { 0x24, "REFERENCE_WINDOW_WIDTH_PLL_T1" }, 878 { 0x28, "FMON_CLK_LAST_COUNT_PLL_A0" }, 879 { 0x2c, "REFERENCE_WINDOW_WIDTH_PLL_A0" }, 880 { 0x30, "FMON_CLK_LAST_COUNT_PLL_C0" }, 881 { 0x34, "REFERENCE_WINDOW_WIDTH_PLL_C0" }, 882 { 0x38, "FMON_CLK_LAST_COUNT_PLL_N1" }, 883 { 0x3c, "REFERENCE_WINDOW_WIDTH_PLL_N1" }, 884 { 0x40, "FMON_CLK_LAST_COUNT_PLL_I1" }, 885 { 0x44, "REFERENCE_WINDOW_WIDTH_PLL_I1" }, 886 { 0x48, "FMON_CLK_LAST_COUNT_PLL_R1" }, 887 { 0x4c, "REFERENCE_WINDOW_WIDTH_PLL_R1" }, 888 { 0x50, "FMON_CLK_LAST_COUNT_PLL_P1" }, 889 { 0x54, "REFERENCE_WINDOW_WIDTH_PLL_P1" }, 890 { 0x58, "FMON_CLK_LAST_COUNT_REF_100_INST0" }, 891 { 0x5c, "REFERENCE_WINDOW_WIDTH_REF_100_INST0" }, 892 { 0x60, "FMON_CLK_LAST_COUNT_REF_100_INST1" }, 893 { 0x64, "REFERENCE_WINDOW_WIDTH_REF_100_INST1" }, 894 { 0x68, "FMON_CLK_LAST_COUNT_REF_156" }, 895 { 0x6c, "REFERENCE_WINDOW_WIDTH_REF_156" }, 896 }; 897 898 static const struct mlxbf_pmc_events mlxbf_pmc_gga_events[] = { 899 { 0, "GGA_PERF_DESC_WQE_STRB" }, 900 { 5, "GGA_PERF_DESC_CQE_STRB" }, 901 { 8, "GGA_PERF_DESC_TPT_REQUEST_STRB" }, 902 { 17, "GGA_PERF_DESC_TPT_RESPONSESTRB" }, 903 { 120, "GGA_PERF_DESC_ENGINE0_IN_DATA_STRB" }, 904 { 121, "GGA_PERF_DESC_ENGINE1_IN_DATA_STRB" }, 905 { 122, "GGA_PERF_DESC_ENGINE2_IN_DATA_STRB" }, 906 { 123, "GGA_PERF_DESC_ENGINE3_IN_DATA_STRB" }, 907 { 124, "GGA_PERF_DESC_ENGINE4_IN_DATA_STRB" }, 908 { 125, "GGA_PERF_DESC_ENGINE5_IN_DATA_STRB" }, 909 { 126, "GGA_PERF_DESC_ENGINE6_IN_DATA_STRB" }, 910 { 127, "GGA_PERF_DESC_ENGINE7_IN_DATA_STRB" }, 911 { 128, "GGA_PERF_DESC_ENGINE8_IN_DATA_STRB" }, 912 { 129, "GGA_PERF_DESC_ENGINE9_IN_DATA_STRB" }, 913 { 130, "GGA_PERF_DESC_ENGINE10_IN_DATA_STRB" }, 914 { 131, "GGA_PERF_DESC_ENGINE11_IN_DATA_STRB" }, 915 { 132, "GGA_PERF_DESC_ENGINE12_IN_DATA_STRB" }, 916 { 133, "GGA_PERF_DESC_ENGINE13_IN_DATA_STRB" }, 917 { 134, "GGA_PERF_DESC_ENGINE14_IN_DATA_STRB" }, 918 { 195, "GGA_PERF_DESC_ENGINE0_OUT_DATA_STRB" }, 919 { 196, "GGA_PERF_DESC_ENGINE1_OUT_DATA_STRB" }, 920 { 197, "GGA_PERF_DESC_ENGINE2_OUT_DATA_STRB" }, 921 { 198, "GGA_PERF_DESC_ENGINE3_OUT_DATA_STRB" }, 922 { 199, "GGA_PERF_DESC_ENGINE4_OUT_DATA_STRB" }, 923 { 200, "GGA_PERF_DESC_ENGINE5_OUT_DATA_STRB" }, 924 { 201, "GGA_PERF_DESC_ENGINE6_OUT_DATA_STRB" }, 925 { 202, "GGA_PERF_DESC_ENGINE7_OUT_DATA_STRB" }, 926 { 203, "GGA_PERF_DESC_ENGINE8_OUT_DATA_STRB" }, 927 { 204, "GGA_PERF_DESC_ENGINE9_OUT_DATA_STRB" }, 928 { 205, "GGA_PERF_DESC_ENGINE10_OUT_DATA_STRB" }, 929 { 206, "GGA_PERF_DESC_ENGINE11_OUT_DATA_STRB" }, 930 { 207, "GGA_PERF_DESC_ENGINE12_OUT_DATA_STRB" }, 931 { 208, "GGA_PERF_DESC_ENGINE13_OUT_DATA_STRB" }, 932 { 209, "GGA_PERF_DESC_ENGINE14_OUT_DATA_STRB" }, 933 }; 934 935 static const struct mlxbf_pmc_events mlxbf_pmc_apt_events[] = { 936 { 0, "APT_DATA_0" }, 937 { 1, "APT_DATA_1" }, 938 { 2, "APT_DATA_2" }, 939 { 3, "APT_DATA_3" }, 940 { 4, "APT_DATA_4" }, 941 { 5, "APT_DATA_5" }, 942 { 6, "APT_DATA_6" }, 943 { 7, "APT_DATA_7" }, 944 { 8, "APT_DATA_8" }, 945 { 9, "APT_DATA_9" }, 946 { 10, "APT_DATA_10" }, 947 { 11, "APT_DATA_11" }, 948 { 12, "APT_DATA_12" }, 949 { 13, "APT_DATA_13" }, 950 { 14, "APT_DATA_14" }, 951 { 15, "APT_DATA_15" }, 952 { 16, "APT_DATA_16" }, 953 { 17, "APT_DATA_17" }, 954 { 18, "APT_DATA_18" }, 955 { 19, "APT_DATA_19" }, 956 { 20, "APT_DATA_20" }, 957 { 21, "APT_DATA_21" }, 958 }; 959 960 static const struct mlxbf_pmc_events mlxbf_pmc_emi_events[] = { 961 { 0, "MCH_WR_IN_MCH_REQ_IN_STRB" }, 962 { 10, "MCH_RD_IN_MCH_REQ_IN_STRB" }, 963 { 20, "MCH_RD_RESP_DATA_MCH_RESP_OUT_STRB" }, 964 { 98, "EMI_ARBITER_EARB2CTRL_STRB" }, 965 { 99, "EMI_ARBITER_EARB2CTRL_RAS_STRB" }, 966 { 100, "EMI_ARBITER_EARB2CTRL_CAS_STRB" }, 967 }; 968 969 static const struct mlxbf_pmc_events mlxbf_pmc_prnf_events[] = { 970 { 0, "PRNF_DMA_RD_TLP_REQ" }, 971 { 1, "PRNF_DMA_RD_ICMC_BYPASS_REQ" }, 972 { 8, "PRNF_DMA_RD_TLP_SENT_TO_CHI" }, 973 { 11, "PRNF_DMA_RD_CHI_RES" }, 974 { 17, "PRNF_DMA_RD_TLP_RES_SENT" }, 975 { 18, "PRNF_DMA_WR_WR0_SLICE_ALLOC_RO" }, 976 { 19, "PRNF_DMA_WR_WR0_SLICE_ALLOC_NRO" }, 977 { 24, "PRNF_DMA_WR_WR1_SLICE_ALLOC_RO" }, 978 { 25, "PRNF_DMA_WR_WR1_SLICE_ALLOC_NRO" }, 979 { 30, "PRNF_PIO_POSTED_REQ_PUSH" }, 980 { 31, "PRNF_PIO_POSTED_REQ_POP" }, 981 { 32, "PRNF_PIO_NP_REQ_PUSH" }, 982 { 33, "PRNF_PIO_NP_REQ_POP" }, 983 { 34, "PRNF_PIO_COMP_RO_PUSH" }, 984 { 35, "PRNF_PIO_COMP_RO_POP" }, 985 { 36, "PRNF_PIO_COMP_NRO_PUSH" }, 986 { 37, "PRNF_PIO_COMP_NRO_POP" }, 987 }; 988 989 static const struct mlxbf_pmc_events mlxbf_pmc_msn_events[] = { 990 { 46, "MSN_CORE_MMA_WQE_DONE_PUSH_STRB" }, 991 { 116, "MSN_CORE_MSN2MMA_WQE_STRB" }, 992 { 164, "MSN_CORE_WQE_TOP_TILE_WQE_STRB" }, 993 { 168, "MSN_CORE_TPT_TOP_GGA_REQ_STRB" }, 994 { 171, "MSN_CORE_TPT_TOP_MMA_REQ_STRB" }, 995 { 174, "MSN_CORE_TPT_TOP_GGA_RES_STRB" }, 996 { 177, "MSN_CORE_TPT_TOP_MMA_RES_STRB" }, 997 }; 998 999 static struct mlxbf_pmc_context *pmc; 1000 1001 /* UUID used to probe ATF service. */ 1002 static const char *mlxbf_pmc_svc_uuid_str = "89c036b4-e7d7-11e6-8797-001aca00bfc4"; 1003 1004 /* Calls an SMC to access a performance register */ 1005 static int mlxbf_pmc_secure_read(void __iomem *addr, u32 command, u64 *result) 1006 { 1007 struct arm_smccc_res res; 1008 int status, err = 0; 1009 1010 arm_smccc_smc(command, pmc->sreg_tbl_perf, (uintptr_t)addr, 0, 0, 0, 0, 1011 0, &res); 1012 1013 status = res.a0; 1014 1015 switch (status) { 1016 case PSCI_RET_NOT_SUPPORTED: 1017 err = -EINVAL; 1018 break; 1019 case MLXBF_PMC_SMCCC_ACCESS_VIOLATION: 1020 err = -EACCES; 1021 break; 1022 default: 1023 *result = res.a1; 1024 break; 1025 } 1026 1027 return err; 1028 } 1029 1030 /* Read from a performance counter */ 1031 static int mlxbf_pmc_read(void __iomem *addr, u32 command, u64 *result) 1032 { 1033 if (pmc->svc_sreg_support) 1034 return mlxbf_pmc_secure_read(addr, command, result); 1035 1036 if (command == MLXBF_PMC_READ_REG_32) 1037 *result = readl(addr); 1038 else 1039 *result = readq(addr); 1040 1041 return 0; 1042 } 1043 1044 /* Convenience function for 32-bit reads */ 1045 static int mlxbf_pmc_readl(void __iomem *addr, u32 *result) 1046 { 1047 u64 read_out; 1048 int status; 1049 1050 status = mlxbf_pmc_read(addr, MLXBF_PMC_READ_REG_32, &read_out); 1051 if (status) 1052 return status; 1053 *result = (u32)read_out; 1054 1055 return 0; 1056 } 1057 1058 /* Calls an SMC to access a performance register */ 1059 static int mlxbf_pmc_secure_write(void __iomem *addr, u32 command, u64 value) 1060 { 1061 struct arm_smccc_res res; 1062 int status, err = 0; 1063 1064 arm_smccc_smc(command, pmc->sreg_tbl_perf, value, (uintptr_t)addr, 0, 0, 1065 0, 0, &res); 1066 1067 status = res.a0; 1068 1069 switch (status) { 1070 case PSCI_RET_NOT_SUPPORTED: 1071 err = -EINVAL; 1072 break; 1073 case MLXBF_PMC_SMCCC_ACCESS_VIOLATION: 1074 err = -EACCES; 1075 break; 1076 } 1077 1078 return err; 1079 } 1080 1081 /* Write to a performance counter */ 1082 static int mlxbf_pmc_write(void __iomem *addr, int command, u64 value) 1083 { 1084 if (pmc->svc_sreg_support) 1085 return mlxbf_pmc_secure_write(addr, command, value); 1086 1087 if (command == MLXBF_PMC_WRITE_REG_32) 1088 writel(value, addr); 1089 else 1090 writeq(value, addr); 1091 1092 return 0; 1093 } 1094 1095 /* Check if the register offset is within the mapped region for the block */ 1096 static bool mlxbf_pmc_valid_range(unsigned int blk_num, u32 offset) 1097 { 1098 if ((offset >= 0) && !(offset % MLXBF_PMC_REG_SIZE) && 1099 (offset + MLXBF_PMC_REG_SIZE <= pmc->block[blk_num].blk_size)) 1100 return true; /* inside the mapped PMC space */ 1101 1102 return false; 1103 } 1104 1105 /* Get the event list corresponding to a certain block */ 1106 static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk, size_t *psize) 1107 { 1108 const struct mlxbf_pmc_events *events; 1109 size_t size; 1110 1111 if (strstr(blk, "tilenet")) { 1112 events = mlxbf_pmc_hnfnet_events; 1113 size = ARRAY_SIZE(mlxbf_pmc_hnfnet_events); 1114 } else if (strstr(blk, "tile")) { 1115 events = mlxbf_pmc_hnf_events; 1116 size = ARRAY_SIZE(mlxbf_pmc_hnf_events); 1117 } else if (strstr(blk, "triogen")) { 1118 events = mlxbf_pmc_smgen_events; 1119 size = ARRAY_SIZE(mlxbf_pmc_smgen_events); 1120 } else if (strstr(blk, "trio")) { 1121 switch (pmc->event_set) { 1122 case MLXBF_PMC_EVENT_SET_BF1: 1123 events = mlxbf_pmc_trio_events_1; 1124 size = ARRAY_SIZE(mlxbf_pmc_trio_events_1); 1125 break; 1126 case MLXBF_PMC_EVENT_SET_BF2: 1127 events = mlxbf_pmc_trio_events_2; 1128 size = ARRAY_SIZE(mlxbf_pmc_trio_events_2); 1129 break; 1130 default: 1131 events = NULL; 1132 size = 0; 1133 break; 1134 } 1135 } else if (strstr(blk, "mss")) { 1136 switch (pmc->event_set) { 1137 case MLXBF_PMC_EVENT_SET_BF1: 1138 case MLXBF_PMC_EVENT_SET_BF2: 1139 events = mlxbf_pmc_mss_events_1; 1140 size = ARRAY_SIZE(mlxbf_pmc_mss_events_1); 1141 break; 1142 case MLXBF_PMC_EVENT_SET_BF3: 1143 events = mlxbf_pmc_mss_events_3; 1144 size = ARRAY_SIZE(mlxbf_pmc_mss_events_3); 1145 break; 1146 default: 1147 events = NULL; 1148 size = 0; 1149 break; 1150 } 1151 } else if (strstr(blk, "ecc")) { 1152 events = mlxbf_pmc_ecc_events; 1153 size = ARRAY_SIZE(mlxbf_pmc_ecc_events); 1154 } else if (strstr(blk, "pcie")) { 1155 events = mlxbf_pmc_pcie_events; 1156 size = ARRAY_SIZE(mlxbf_pmc_pcie_events); 1157 } else if (strstr(blk, "l3cache")) { 1158 events = mlxbf_pmc_l3c_events; 1159 size = ARRAY_SIZE(mlxbf_pmc_l3c_events); 1160 } else if (strstr(blk, "gic")) { 1161 events = mlxbf_pmc_smgen_events; 1162 size = ARRAY_SIZE(mlxbf_pmc_smgen_events); 1163 } else if (strstr(blk, "smmu")) { 1164 events = mlxbf_pmc_smgen_events; 1165 size = ARRAY_SIZE(mlxbf_pmc_smgen_events); 1166 } else if (strstr(blk, "llt_miss")) { 1167 events = mlxbf_pmc_llt_miss_events; 1168 size = ARRAY_SIZE(mlxbf_pmc_llt_miss_events); 1169 } else if (strstr(blk, "llt")) { 1170 events = mlxbf_pmc_llt_events; 1171 size = ARRAY_SIZE(mlxbf_pmc_llt_events); 1172 } else if (strstr(blk, "clock_measure")) { 1173 events = mlxbf_pmc_clock_events; 1174 size = ARRAY_SIZE(mlxbf_pmc_clock_events); 1175 } else if (strstr(blk, "gga")) { 1176 events = mlxbf_pmc_gga_events; 1177 size = ARRAY_SIZE(mlxbf_pmc_gga_events); 1178 } else if (strstr(blk, "apt")) { 1179 events = mlxbf_pmc_apt_events; 1180 size = ARRAY_SIZE(mlxbf_pmc_apt_events); 1181 } else if (strstr(blk, "emi")) { 1182 events = mlxbf_pmc_emi_events; 1183 size = ARRAY_SIZE(mlxbf_pmc_emi_events); 1184 } else if (strstr(blk, "prnf")) { 1185 events = mlxbf_pmc_prnf_events; 1186 size = ARRAY_SIZE(mlxbf_pmc_prnf_events); 1187 } else if (strstr(blk, "msn")) { 1188 events = mlxbf_pmc_msn_events; 1189 size = ARRAY_SIZE(mlxbf_pmc_msn_events); 1190 } else { 1191 events = NULL; 1192 size = 0; 1193 } 1194 1195 if (psize) 1196 *psize = size; 1197 1198 return events; 1199 } 1200 1201 static bool mlxbf_pmc_event_supported(const char *blk) 1202 { 1203 return !!mlxbf_pmc_event_list(blk, NULL); 1204 } 1205 1206 /* Get the event number given the name */ 1207 static int mlxbf_pmc_get_event_num(const char *blk, const char *evt) 1208 { 1209 const struct mlxbf_pmc_events *events; 1210 unsigned int i; 1211 size_t size; 1212 1213 events = mlxbf_pmc_event_list(blk, &size); 1214 if (!events) 1215 return -EINVAL; 1216 1217 for (i = 0; i < size; ++i) { 1218 if (!strcmp(evt, events[i].evt_name)) 1219 return events[i].evt_num; 1220 } 1221 1222 return -ENODEV; 1223 } 1224 1225 /* Get the event number given the name */ 1226 static char *mlxbf_pmc_get_event_name(const char *blk, u32 evt) 1227 { 1228 const struct mlxbf_pmc_events *events; 1229 unsigned int i; 1230 size_t size; 1231 1232 events = mlxbf_pmc_event_list(blk, &size); 1233 if (!events) 1234 return NULL; 1235 1236 for (i = 0; i < size; ++i) { 1237 if (evt == events[i].evt_num) 1238 return events[i].evt_name; 1239 } 1240 1241 return NULL; 1242 } 1243 1244 /* Method to enable/disable/reset l3cache counters */ 1245 static int mlxbf_pmc_config_l3_counters(unsigned int blk_num, bool enable, bool reset) 1246 { 1247 u32 perfcnt_cfg = 0; 1248 1249 if (enable) 1250 perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_EN; 1251 if (reset) 1252 perfcnt_cfg |= MLXBF_PMC_L3C_PERF_CNT_CFG_RST; 1253 1254 return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1255 MLXBF_PMC_L3C_PERF_CNT_CFG, 1256 MLXBF_PMC_WRITE_REG_32, perfcnt_cfg); 1257 } 1258 1259 /* Method to handle l3cache counter programming */ 1260 static int mlxbf_pmc_program_l3_counter(unsigned int blk_num, u32 cnt_num, u32 evt) 1261 { 1262 u32 perfcnt_sel_1 = 0, perfcnt_sel = 0, *wordaddr; 1263 void __iomem *pmcaddr; 1264 int ret; 1265 1266 /* Disable all counters before programming them */ 1267 if (mlxbf_pmc_config_l3_counters(blk_num, false, false)) 1268 return -EINVAL; 1269 1270 /* Select appropriate register information */ 1271 switch (cnt_num) { 1272 case 0 ... 3: 1273 pmcaddr = pmc->block[blk_num].mmio_base + 1274 MLXBF_PMC_L3C_PERF_CNT_SEL; 1275 wordaddr = &perfcnt_sel; 1276 break; 1277 case 4: 1278 pmcaddr = pmc->block[blk_num].mmio_base + 1279 MLXBF_PMC_L3C_PERF_CNT_SEL_1; 1280 wordaddr = &perfcnt_sel_1; 1281 break; 1282 default: 1283 return -EINVAL; 1284 } 1285 1286 ret = mlxbf_pmc_readl(pmcaddr, wordaddr); 1287 if (ret) 1288 return ret; 1289 1290 switch (cnt_num) { 1291 case 0: 1292 perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0; 1293 perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0, 1294 evt); 1295 break; 1296 case 1: 1297 perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1; 1298 perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1, 1299 evt); 1300 break; 1301 case 2: 1302 perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2; 1303 perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2, 1304 evt); 1305 break; 1306 case 3: 1307 perfcnt_sel &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3; 1308 perfcnt_sel |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3, 1309 evt); 1310 break; 1311 case 4: 1312 perfcnt_sel_1 &= ~MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4; 1313 perfcnt_sel_1 |= FIELD_PREP(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4, 1314 evt); 1315 break; 1316 default: 1317 return -EINVAL; 1318 } 1319 1320 return mlxbf_pmc_write(pmcaddr, MLXBF_PMC_WRITE_REG_32, *wordaddr); 1321 } 1322 1323 /* Method to handle crspace counter programming */ 1324 static int mlxbf_pmc_program_crspace_counter(unsigned int blk_num, u32 cnt_num, u32 evt) 1325 { 1326 void __iomem *addr; 1327 u32 word; 1328 int ret; 1329 1330 addr = pmc->block[blk_num].mmio_base + 1331 ((cnt_num / 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ); 1332 ret = mlxbf_pmc_readl(addr, &word); 1333 if (ret) 1334 return ret; 1335 1336 if (cnt_num % 2) { 1337 word &= ~MLXBF_PMC_CRSPACE_PERFSEL1; 1338 word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL1, evt); 1339 } else { 1340 word &= ~MLXBF_PMC_CRSPACE_PERFSEL0; 1341 word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL0, evt); 1342 } 1343 1344 return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, word); 1345 } 1346 1347 /* Method to clear crspace counter value */ 1348 static int mlxbf_pmc_clear_crspace_counter(unsigned int blk_num, u32 cnt_num) 1349 { 1350 void __iomem *addr; 1351 1352 addr = pmc->block[blk_num].mmio_base + 1353 MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) + 1354 (cnt_num * 4); 1355 1356 return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, 0x0); 1357 } 1358 1359 /* Method to program a counter to monitor an event */ 1360 static int mlxbf_pmc_program_counter(unsigned int blk_num, u32 cnt_num, u32 evt, bool is_l3) 1361 { 1362 u64 perfctl, perfevt, perfmon_cfg; 1363 1364 if (cnt_num >= pmc->block[blk_num].counters) 1365 return -ENODEV; 1366 1367 if (is_l3) 1368 return mlxbf_pmc_program_l3_counter(blk_num, cnt_num, evt); 1369 1370 if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) 1371 return mlxbf_pmc_program_crspace_counter(blk_num, cnt_num, 1372 evt); 1373 1374 /* Configure the counter */ 1375 perfctl = FIELD_PREP(MLXBF_PMC_PERFCTL_EN0, 1); 1376 perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_EB0, 0); 1377 perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ETRIG0, 1); 1378 perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_AD0, 0); 1379 perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_ACCM0, 0); 1380 perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_MS0, 0); 1381 perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_FM0, 0); 1382 1383 perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfctl); 1384 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, 1385 MLXBF_PMC_PERFCTL); 1386 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); 1387 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); 1388 1389 if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1390 cnt_num * MLXBF_PMC_REG_SIZE, 1391 MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) 1392 return -EFAULT; 1393 1394 /* Select the event */ 1395 perfevt = FIELD_PREP(MLXBF_PMC_PERFEVT_EVTSEL, evt); 1396 1397 perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WDATA, perfevt); 1398 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, 1399 MLXBF_PMC_PERFEVT); 1400 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); 1401 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); 1402 1403 if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1404 cnt_num * MLXBF_PMC_REG_SIZE, 1405 MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) 1406 return -EFAULT; 1407 1408 /* Clear the accumulator */ 1409 perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, 1410 MLXBF_PMC_PERFACC0); 1411 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); 1412 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 1); 1413 1414 if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1415 cnt_num * MLXBF_PMC_REG_SIZE, 1416 MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) 1417 return -EFAULT; 1418 1419 return 0; 1420 } 1421 1422 /* Method to handle l3 counter reads */ 1423 static int mlxbf_pmc_read_l3_counter(unsigned int blk_num, u32 cnt_num, u64 *result) 1424 { 1425 u32 perfcnt_low = 0, perfcnt_high = 0; 1426 int status; 1427 u64 value; 1428 1429 status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1430 MLXBF_PMC_L3C_PERF_CNT_LOW + 1431 cnt_num * MLXBF_PMC_L3C_REG_SIZE, 1432 &perfcnt_low); 1433 1434 if (status) 1435 return status; 1436 1437 status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1438 MLXBF_PMC_L3C_PERF_CNT_HIGH + 1439 cnt_num * MLXBF_PMC_L3C_REG_SIZE, 1440 &perfcnt_high); 1441 1442 if (status) 1443 return status; 1444 1445 value = perfcnt_high; 1446 value = value << 32; 1447 value |= perfcnt_low; 1448 *result = value; 1449 1450 return 0; 1451 } 1452 1453 /* Method to handle crspace counter reads */ 1454 static int mlxbf_pmc_read_crspace_counter(unsigned int blk_num, u32 cnt_num, u64 *result) 1455 { 1456 int status = 0; 1457 u32 value; 1458 1459 status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1460 MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) + 1461 (cnt_num * 4), &value); 1462 if (status) 1463 return status; 1464 1465 *result = value; 1466 1467 return 0; 1468 } 1469 1470 /* Method to read the counter value */ 1471 static int mlxbf_pmc_read_counter(unsigned int blk_num, u32 cnt_num, bool is_l3, u64 *result) 1472 { 1473 u32 perfcfg_offset, perfval_offset; 1474 u64 perfmon_cfg; 1475 int status; 1476 1477 if (cnt_num >= pmc->block[blk_num].counters) 1478 return -EINVAL; 1479 1480 if (is_l3) 1481 return mlxbf_pmc_read_l3_counter(blk_num, cnt_num, result); 1482 1483 if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) 1484 return mlxbf_pmc_read_crspace_counter(blk_num, cnt_num, result); 1485 1486 perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE; 1487 perfval_offset = perfcfg_offset + 1488 pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE; 1489 1490 /* Set counter in "read" mode */ 1491 perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, 1492 MLXBF_PMC_PERFACC0); 1493 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); 1494 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); 1495 1496 status = mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, 1497 MLXBF_PMC_WRITE_REG_64, perfmon_cfg); 1498 1499 if (status) 1500 return status; 1501 1502 /* Get the counter value */ 1503 return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, 1504 MLXBF_PMC_READ_REG_64, result); 1505 } 1506 1507 /* Method to read L3 block event */ 1508 static int mlxbf_pmc_read_l3_event(unsigned int blk_num, u32 cnt_num, u64 *result) 1509 { 1510 u32 perfcnt_sel = 0, perfcnt_sel_1 = 0, *wordaddr; 1511 void __iomem *pmcaddr; 1512 u64 evt; 1513 1514 /* Select appropriate register information */ 1515 switch (cnt_num) { 1516 case 0 ... 3: 1517 pmcaddr = pmc->block[blk_num].mmio_base + 1518 MLXBF_PMC_L3C_PERF_CNT_SEL; 1519 wordaddr = &perfcnt_sel; 1520 break; 1521 case 4: 1522 pmcaddr = pmc->block[blk_num].mmio_base + 1523 MLXBF_PMC_L3C_PERF_CNT_SEL_1; 1524 wordaddr = &perfcnt_sel_1; 1525 break; 1526 default: 1527 return -EINVAL; 1528 } 1529 1530 if (mlxbf_pmc_readl(pmcaddr, wordaddr)) 1531 return -EINVAL; 1532 1533 /* Read from appropriate register field for the counter */ 1534 switch (cnt_num) { 1535 case 0: 1536 evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_0, perfcnt_sel); 1537 break; 1538 case 1: 1539 evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_1, perfcnt_sel); 1540 break; 1541 case 2: 1542 evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_2, perfcnt_sel); 1543 break; 1544 case 3: 1545 evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_CNT_3, perfcnt_sel); 1546 break; 1547 case 4: 1548 evt = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_SEL_1_CNT_4, 1549 perfcnt_sel_1); 1550 break; 1551 default: 1552 return -EINVAL; 1553 } 1554 *result = evt; 1555 1556 return 0; 1557 } 1558 1559 /* Method to read crspace block event */ 1560 static int mlxbf_pmc_read_crspace_event(unsigned int blk_num, u32 cnt_num, u64 *result) 1561 { 1562 u32 word, evt; 1563 void __iomem *addr; 1564 int ret; 1565 1566 addr = pmc->block[blk_num].mmio_base + 1567 ((cnt_num / 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ); 1568 ret = mlxbf_pmc_readl(addr, &word); 1569 if (ret) 1570 return ret; 1571 1572 if (cnt_num % 2) 1573 evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL1, word); 1574 else 1575 evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL0, word); 1576 1577 *result = evt; 1578 1579 return 0; 1580 } 1581 1582 /* Method to find the event currently being monitored by a counter */ 1583 static int mlxbf_pmc_read_event(unsigned int blk_num, u32 cnt_num, bool is_l3, u64 *result) 1584 { 1585 u32 perfcfg_offset, perfval_offset; 1586 u64 perfmon_cfg, perfevt; 1587 1588 if (cnt_num >= pmc->block[blk_num].counters) 1589 return -EINVAL; 1590 1591 if (is_l3) 1592 return mlxbf_pmc_read_l3_event(blk_num, cnt_num, result); 1593 1594 if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) 1595 return mlxbf_pmc_read_crspace_event(blk_num, cnt_num, result); 1596 1597 perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE; 1598 perfval_offset = perfcfg_offset + 1599 pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE; 1600 1601 /* Set counter in "read" mode */ 1602 perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR, 1603 MLXBF_PMC_PERFEVT); 1604 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1); 1605 perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0); 1606 1607 if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset, 1608 MLXBF_PMC_WRITE_REG_64, perfmon_cfg)) 1609 return -EFAULT; 1610 1611 /* Get the event number */ 1612 if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset, 1613 MLXBF_PMC_READ_REG_64, &perfevt)) 1614 return -EFAULT; 1615 1616 *result = FIELD_GET(MLXBF_PMC_PERFEVT_EVTSEL, perfevt); 1617 1618 return 0; 1619 } 1620 1621 /* Method to read a register */ 1622 static int mlxbf_pmc_read_reg(unsigned int blk_num, u32 offset, u64 *result) 1623 { 1624 u32 reg; 1625 1626 if ((strstr(pmc->block_name[blk_num], "ecc")) || 1627 (strstr(pmc->block_name[blk_num], "clock_measure"))) { 1628 if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + offset, 1629 ®)) 1630 return -EFAULT; 1631 1632 *result = reg; 1633 return 0; 1634 } 1635 1636 if (mlxbf_pmc_valid_range(blk_num, offset)) 1637 return mlxbf_pmc_read(pmc->block[blk_num].mmio_base + offset, 1638 MLXBF_PMC_READ_REG_64, result); 1639 1640 return -EINVAL; 1641 } 1642 1643 /* Method to write to a register */ 1644 static int mlxbf_pmc_write_reg(unsigned int blk_num, u32 offset, u64 data) 1645 { 1646 if (strstr(pmc->block_name[blk_num], "clock_measure")) 1647 return -EINVAL; 1648 1649 if (strstr(pmc->block_name[blk_num], "ecc")) { 1650 return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset, 1651 MLXBF_PMC_WRITE_REG_32, data); 1652 } 1653 1654 if (mlxbf_pmc_valid_range(blk_num, offset)) 1655 return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset, 1656 MLXBF_PMC_WRITE_REG_64, data); 1657 1658 return -EINVAL; 1659 } 1660 1661 /* Show function for "counter" sysfs files */ 1662 static ssize_t mlxbf_pmc_counter_show(struct device *dev, 1663 struct device_attribute *attr, char *buf) 1664 { 1665 struct mlxbf_pmc_attribute *attr_counter = container_of( 1666 attr, struct mlxbf_pmc_attribute, dev_attr); 1667 unsigned int blk_num, cnt_num; 1668 bool is_l3 = false; 1669 int offset; 1670 u64 value; 1671 1672 blk_num = attr_counter->nr; 1673 cnt_num = attr_counter->index; 1674 1675 if (strstr(pmc->block_name[blk_num], "l3cache")) 1676 is_l3 = true; 1677 1678 if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) || 1679 (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)) { 1680 if (mlxbf_pmc_read_counter(blk_num, cnt_num, is_l3, &value)) 1681 return -EINVAL; 1682 } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) { 1683 offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], 1684 attr->attr.name); 1685 if (offset < 0) 1686 return -EINVAL; 1687 if (mlxbf_pmc_read_reg(blk_num, offset, &value)) 1688 return -EINVAL; 1689 } else 1690 return -EINVAL; 1691 1692 return sysfs_emit(buf, "0x%llx\n", value); 1693 } 1694 1695 /* Store function for "counter" sysfs files */ 1696 static ssize_t mlxbf_pmc_counter_store(struct device *dev, 1697 struct device_attribute *attr, 1698 const char *buf, size_t count) 1699 { 1700 struct mlxbf_pmc_attribute *attr_counter = container_of( 1701 attr, struct mlxbf_pmc_attribute, dev_attr); 1702 unsigned int blk_num, cnt_num, data; 1703 bool is_l3 = false; 1704 u64 evt_num; 1705 int offset; 1706 int err; 1707 1708 blk_num = attr_counter->nr; 1709 cnt_num = attr_counter->index; 1710 1711 err = kstrtouint(buf, 0, &data); 1712 if (err < 0) 1713 return err; 1714 1715 /* Allow non-zero writes only to the ecc regs */ 1716 if (!(strstr(pmc->block_name[blk_num], "ecc")) && data) 1717 return -EINVAL; 1718 1719 /* Do not allow writes to the L3C regs */ 1720 if (strstr(pmc->block_name[blk_num], "l3cache")) 1721 return -EINVAL; 1722 1723 if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) { 1724 err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num); 1725 if (err) 1726 return err; 1727 err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num, 1728 is_l3); 1729 if (err) 1730 return err; 1731 } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) { 1732 offset = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], 1733 attr->attr.name); 1734 if (offset < 0) 1735 return -EINVAL; 1736 err = mlxbf_pmc_write_reg(blk_num, offset, data); 1737 if (err) 1738 return err; 1739 } else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) { 1740 if (sscanf(attr->attr.name, "counter%u", &cnt_num) != 1) 1741 return -EINVAL; 1742 err = mlxbf_pmc_clear_crspace_counter(blk_num, cnt_num); 1743 } else 1744 return -EINVAL; 1745 1746 return count; 1747 } 1748 1749 /* Show function for "event" sysfs files */ 1750 static ssize_t mlxbf_pmc_event_show(struct device *dev, 1751 struct device_attribute *attr, char *buf) 1752 { 1753 struct mlxbf_pmc_attribute *attr_event = container_of( 1754 attr, struct mlxbf_pmc_attribute, dev_attr); 1755 unsigned int blk_num, cnt_num; 1756 bool is_l3 = false; 1757 char *evt_name; 1758 u64 evt_num; 1759 int err; 1760 1761 blk_num = attr_event->nr; 1762 cnt_num = attr_event->index; 1763 1764 if (strstr(pmc->block_name[blk_num], "l3cache")) 1765 is_l3 = true; 1766 1767 err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num); 1768 if (err) 1769 return sysfs_emit(buf, "No event being monitored\n"); 1770 1771 evt_name = mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num); 1772 if (!evt_name) 1773 return -EINVAL; 1774 1775 return sysfs_emit(buf, "0x%llx: %s\n", evt_num, evt_name); 1776 } 1777 1778 /* Store function for "event" sysfs files */ 1779 static ssize_t mlxbf_pmc_event_store(struct device *dev, 1780 struct device_attribute *attr, 1781 const char *buf, size_t count) 1782 { 1783 struct mlxbf_pmc_attribute *attr_event = container_of( 1784 attr, struct mlxbf_pmc_attribute, dev_attr); 1785 unsigned int blk_num, cnt_num; 1786 bool is_l3 = false; 1787 int evt_num; 1788 int err; 1789 1790 blk_num = attr_event->nr; 1791 cnt_num = attr_event->index; 1792 1793 if (isalpha(buf[0])) { 1794 evt_num = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], 1795 buf); 1796 if (evt_num < 0) 1797 return -EINVAL; 1798 } else { 1799 err = kstrtouint(buf, 0, &evt_num); 1800 if (err < 0) 1801 return err; 1802 } 1803 1804 if (strstr(pmc->block_name[blk_num], "l3cache")) 1805 is_l3 = true; 1806 1807 err = mlxbf_pmc_program_counter(blk_num, cnt_num, evt_num, is_l3); 1808 if (err) 1809 return err; 1810 1811 return count; 1812 } 1813 1814 /* Show function for "event_list" sysfs files */ 1815 static ssize_t mlxbf_pmc_event_list_show(struct device *dev, 1816 struct device_attribute *attr, 1817 char *buf) 1818 { 1819 struct mlxbf_pmc_attribute *attr_event_list = container_of( 1820 attr, struct mlxbf_pmc_attribute, dev_attr); 1821 const struct mlxbf_pmc_events *events; 1822 char e_info[MLXBF_PMC_EVENT_INFO_LEN]; 1823 unsigned int blk_num, i, len = 0; 1824 size_t size; 1825 int ret = 0; 1826 1827 blk_num = attr_event_list->nr; 1828 1829 events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &size); 1830 if (!events) 1831 return -EINVAL; 1832 1833 for (i = 0, buf[0] = '\0'; i < size; ++i) { 1834 len += snprintf(e_info, sizeof(e_info), "0x%x: %s\n", 1835 events[i].evt_num, events[i].evt_name); 1836 if (len >= PAGE_SIZE) 1837 break; 1838 strcat(buf, e_info); 1839 ret = len; 1840 } 1841 1842 return ret; 1843 } 1844 1845 /* Show function for "enable" sysfs files - only for l3cache & crspace */ 1846 static ssize_t mlxbf_pmc_enable_show(struct device *dev, 1847 struct device_attribute *attr, char *buf) 1848 { 1849 struct mlxbf_pmc_attribute *attr_enable = container_of( 1850 attr, struct mlxbf_pmc_attribute, dev_attr); 1851 unsigned int blk_num, value; 1852 u32 perfcnt_cfg, word; 1853 1854 blk_num = attr_enable->nr; 1855 1856 if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) { 1857 if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1858 MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters), 1859 &word)) 1860 return -EINVAL; 1861 1862 value = FIELD_GET(MLXBF_PMC_CRSPACE_PERFMON_EN, word); 1863 } else { 1864 if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1865 MLXBF_PMC_L3C_PERF_CNT_CFG, 1866 &perfcnt_cfg)) 1867 return -EINVAL; 1868 1869 value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg); 1870 } 1871 1872 return sysfs_emit(buf, "%u\n", value); 1873 } 1874 1875 /* Store function for "enable" sysfs files - only for l3cache & crspace */ 1876 static ssize_t mlxbf_pmc_enable_store(struct device *dev, 1877 struct device_attribute *attr, 1878 const char *buf, size_t count) 1879 { 1880 struct mlxbf_pmc_attribute *attr_enable = container_of( 1881 attr, struct mlxbf_pmc_attribute, dev_attr); 1882 unsigned int en, blk_num; 1883 u32 word; 1884 int err; 1885 1886 blk_num = attr_enable->nr; 1887 1888 err = kstrtouint(buf, 0, &en); 1889 if (err < 0) 1890 return err; 1891 1892 if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) { 1893 err = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1894 MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters), 1895 &word); 1896 if (err) 1897 return -EINVAL; 1898 1899 word &= ~MLXBF_PMC_CRSPACE_PERFMON_EN; 1900 word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_EN, en); 1901 if (en) 1902 word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_CLR, 1); 1903 1904 mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1905 MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters), 1906 MLXBF_PMC_WRITE_REG_32, word); 1907 } else { 1908 if (en && en != 1) 1909 return -EINVAL; 1910 1911 err = mlxbf_pmc_config_l3_counters(blk_num, false, !!en); 1912 if (err) 1913 return err; 1914 1915 if (en == 1) { 1916 err = mlxbf_pmc_config_l3_counters(blk_num, true, false); 1917 if (err) 1918 return err; 1919 } 1920 } 1921 1922 return count; 1923 } 1924 1925 /* Show function for "count_clock" sysfs files - only for crspace */ 1926 static ssize_t mlxbf_pmc_count_clock_show(struct device *dev, 1927 struct device_attribute *attr, char *buf) 1928 { 1929 struct mlxbf_pmc_attribute *attr_count_clock = container_of( 1930 attr, struct mlxbf_pmc_attribute, dev_attr); 1931 unsigned int blk_num; 1932 u32 reg; 1933 1934 blk_num = attr_count_clock->nr; 1935 1936 if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1937 MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters), 1938 ®)) 1939 return -EINVAL; 1940 1941 return sysfs_emit(buf, "%u\n", reg); 1942 } 1943 1944 /* Store function for "count_clock" sysfs files - only for crspace */ 1945 static ssize_t mlxbf_pmc_count_clock_store(struct device *dev, 1946 struct device_attribute *attr, 1947 const char *buf, size_t count) 1948 { 1949 struct mlxbf_pmc_attribute *attr_count_clock = container_of( 1950 attr, struct mlxbf_pmc_attribute, dev_attr); 1951 unsigned int blk_num; 1952 u32 reg; 1953 int err; 1954 1955 blk_num = attr_count_clock->nr; 1956 1957 err = kstrtouint(buf, 0, ®); 1958 if (err < 0) 1959 return err; 1960 1961 mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1962 MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters), 1963 MLXBF_PMC_WRITE_REG_32, reg); 1964 1965 return count; 1966 } 1967 1968 /* Populate attributes for blocks with counters to monitor performance */ 1969 static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_num) 1970 { 1971 struct mlxbf_pmc_attribute *attr; 1972 unsigned int i = 0, j = 0; 1973 1974 if (!mlxbf_pmc_event_supported(pmc->block_name[blk_num])) 1975 return -ENOENT; 1976 1977 /* "event_list" sysfs to list events supported by the block */ 1978 attr = &pmc->block[blk_num].attr_event_list; 1979 sysfs_attr_init(&attr->dev_attr.attr); 1980 attr->dev_attr.attr.mode = 0444; 1981 attr->dev_attr.show = mlxbf_pmc_event_list_show; 1982 attr->nr = blk_num; 1983 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event_list"); 1984 if (!attr->dev_attr.attr.name) 1985 return -ENOMEM; 1986 pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr; 1987 attr = NULL; 1988 1989 /* "enable" sysfs to start/stop the counters. Only in L3C blocks */ 1990 if (strstr(pmc->block_name[blk_num], "l3cache") || 1991 ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))) { 1992 attr = &pmc->block[blk_num].attr_enable; 1993 sysfs_attr_init(&attr->dev_attr.attr); 1994 attr->dev_attr.attr.mode = 0644; 1995 attr->dev_attr.show = mlxbf_pmc_enable_show; 1996 attr->dev_attr.store = mlxbf_pmc_enable_store; 1997 attr->nr = blk_num; 1998 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, 1999 "enable"); 2000 if (!attr->dev_attr.attr.name) 2001 return -ENOMEM; 2002 pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; 2003 attr = NULL; 2004 } 2005 2006 if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) { 2007 /* Program crspace counters to count clock cycles using "count_clock" sysfs */ 2008 attr = &pmc->block[blk_num].attr_count_clock; 2009 attr->dev_attr.attr.mode = 0644; 2010 attr->dev_attr.show = mlxbf_pmc_count_clock_show; 2011 attr->dev_attr.store = mlxbf_pmc_count_clock_store; 2012 attr->nr = blk_num; 2013 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, 2014 "count_clock"); 2015 if (!attr->dev_attr.attr.name) 2016 return -ENOMEM; 2017 pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; 2018 attr = NULL; 2019 } 2020 2021 pmc->block[blk_num].attr_counter = devm_kcalloc( 2022 dev, pmc->block[blk_num].counters, 2023 sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); 2024 if (!pmc->block[blk_num].attr_counter) 2025 return -ENOMEM; 2026 2027 pmc->block[blk_num].attr_event = devm_kcalloc( 2028 dev, pmc->block[blk_num].counters, 2029 sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); 2030 if (!pmc->block[blk_num].attr_event) 2031 return -ENOMEM; 2032 2033 /* "eventX" and "counterX" sysfs to program and read counter values */ 2034 for (j = 0; j < pmc->block[blk_num].counters; ++j) { 2035 attr = &pmc->block[blk_num].attr_counter[j]; 2036 sysfs_attr_init(&attr->dev_attr.attr); 2037 attr->dev_attr.attr.mode = 0644; 2038 attr->dev_attr.show = mlxbf_pmc_counter_show; 2039 attr->dev_attr.store = mlxbf_pmc_counter_store; 2040 attr->index = j; 2041 attr->nr = blk_num; 2042 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "counter%u", j); 2043 if (!attr->dev_attr.attr.name) 2044 return -ENOMEM; 2045 pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; 2046 attr = NULL; 2047 2048 attr = &pmc->block[blk_num].attr_event[j]; 2049 sysfs_attr_init(&attr->dev_attr.attr); 2050 attr->dev_attr.attr.mode = 0644; 2051 attr->dev_attr.show = mlxbf_pmc_event_show; 2052 attr->dev_attr.store = mlxbf_pmc_event_store; 2053 attr->index = j; 2054 attr->nr = blk_num; 2055 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, "event%u", j); 2056 if (!attr->dev_attr.attr.name) 2057 return -ENOMEM; 2058 pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; 2059 attr = NULL; 2060 } 2061 2062 return 0; 2063 } 2064 2065 /* Populate attributes for blocks with registers to monitor performance */ 2066 static int mlxbf_pmc_init_perftype_reg(struct device *dev, unsigned int blk_num) 2067 { 2068 const struct mlxbf_pmc_events *events; 2069 struct mlxbf_pmc_attribute *attr; 2070 unsigned int i = 0; 2071 size_t count = 0; 2072 2073 events = mlxbf_pmc_event_list(pmc->block_name[blk_num], &count); 2074 if (!events) 2075 return -ENOENT; 2076 2077 pmc->block[blk_num].attr_event = devm_kcalloc( 2078 dev, count, sizeof(struct mlxbf_pmc_attribute), GFP_KERNEL); 2079 if (!pmc->block[blk_num].attr_event) 2080 return -ENOMEM; 2081 2082 while (count > 0) { 2083 --count; 2084 attr = &pmc->block[blk_num].attr_event[count]; 2085 sysfs_attr_init(&attr->dev_attr.attr); 2086 attr->dev_attr.attr.mode = 0644; 2087 attr->dev_attr.show = mlxbf_pmc_counter_show; 2088 attr->dev_attr.store = mlxbf_pmc_counter_store; 2089 attr->nr = blk_num; 2090 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, 2091 events[count].evt_name); 2092 if (!attr->dev_attr.attr.name) 2093 return -ENOMEM; 2094 pmc->block[blk_num].block_attr[i] = &attr->dev_attr.attr; 2095 attr = NULL; 2096 i++; 2097 } 2098 2099 return 0; 2100 } 2101 2102 /* Helper to create the bfperf sysfs sub-directories and files */ 2103 static int mlxbf_pmc_create_groups(struct device *dev, unsigned int blk_num) 2104 { 2105 int err; 2106 2107 /* Populate attributes based on counter type */ 2108 if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) || 2109 (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)) 2110 err = mlxbf_pmc_init_perftype_counter(dev, blk_num); 2111 else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) 2112 err = mlxbf_pmc_init_perftype_reg(dev, blk_num); 2113 else 2114 err = -ENOENT; 2115 2116 if (err) 2117 return err; 2118 2119 /* Add a new attribute_group for the block */ 2120 pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr; 2121 pmc->block[blk_num].block_attr_grp.name = devm_kasprintf( 2122 dev, GFP_KERNEL, pmc->block_name[blk_num]); 2123 if (!pmc->block[blk_num].block_attr_grp.name) 2124 return -ENOMEM; 2125 pmc->groups[pmc->group_num] = &pmc->block[blk_num].block_attr_grp; 2126 pmc->group_num++; 2127 2128 return 0; 2129 } 2130 2131 static bool mlxbf_pmc_guid_match(const guid_t *guid, 2132 const struct arm_smccc_res *res) 2133 { 2134 guid_t id = GUID_INIT(res->a0, res->a1, res->a1 >> 16, res->a2, 2135 res->a2 >> 8, res->a2 >> 16, res->a2 >> 24, 2136 res->a3, res->a3 >> 8, res->a3 >> 16, 2137 res->a3 >> 24); 2138 2139 return guid_equal(guid, &id); 2140 } 2141 2142 /* Helper to map the Performance Counters from the varios blocks */ 2143 static int mlxbf_pmc_map_counters(struct device *dev) 2144 { 2145 u64 info[MLXBF_PMC_INFO_SZ]; 2146 unsigned int tile_num, i; 2147 int ret; 2148 2149 for (i = 0; i < pmc->total_blocks; ++i) { 2150 /* Create sysfs for tiles only if block number < tile_count */ 2151 if (strstr(pmc->block_name[i], "tilenet")) { 2152 if (sscanf(pmc->block_name[i], "tilenet%u", &tile_num) != 1) 2153 continue; 2154 2155 if (tile_num >= pmc->tile_count) 2156 continue; 2157 } else if (strstr(pmc->block_name[i], "tile")) { 2158 if (sscanf(pmc->block_name[i], "tile%u", &tile_num) != 1) 2159 continue; 2160 2161 if (tile_num >= pmc->tile_count) 2162 continue; 2163 } 2164 2165 /* Create sysfs only for enabled MSS blocks */ 2166 if (strstr(pmc->block_name[i], "mss") && 2167 pmc->event_set == MLXBF_PMC_EVENT_SET_BF3) { 2168 unsigned int mss_num; 2169 2170 if (sscanf(pmc->block_name[i], "mss%u", &mss_num) != 1) 2171 continue; 2172 2173 if (!((pmc->mss_enable >> mss_num) & 0x1)) 2174 continue; 2175 } 2176 2177 /* Create sysfs only for enabled EMI blocks */ 2178 if (strstr(pmc->block_name[i], "emi") && 2179 pmc->event_set == MLXBF_PMC_EVENT_SET_BF3) { 2180 unsigned int emi_num; 2181 2182 if (sscanf(pmc->block_name[i], "emi%u", &emi_num) != 1) 2183 continue; 2184 2185 if (!((pmc->mss_enable >> (emi_num / 2)) & 0x1)) 2186 continue; 2187 } 2188 2189 /* Create sysfs only for enabled LLT blocks */ 2190 if (strstr(pmc->block_name[i], "llt_miss")) { 2191 unsigned int llt_num; 2192 2193 if (sscanf(pmc->block_name[i], "llt_miss%u", &llt_num) != 1) 2194 continue; 2195 2196 if (!((pmc->llt_enable >> llt_num) & 0x1)) 2197 continue; 2198 } else if (strstr(pmc->block_name[i], "llt")) { 2199 unsigned int llt_num; 2200 2201 if (sscanf(pmc->block_name[i], "llt%u", &llt_num) != 1) 2202 continue; 2203 2204 if (!((pmc->llt_enable >> llt_num) & 0x1)) 2205 continue; 2206 } 2207 2208 /* Create sysfs only for enabled APT blocks */ 2209 if (strstr(pmc->block_name[i], "apt")) { 2210 unsigned int apt_num; 2211 2212 if (sscanf(pmc->block_name[i], "apt%u", &apt_num) != 1) 2213 continue; 2214 2215 if (!((pmc->apt_enable >> apt_num) & 0x1)) 2216 continue; 2217 } 2218 2219 ret = device_property_read_u64_array(dev, pmc->block_name[i], 2220 info, MLXBF_PMC_INFO_SZ); 2221 if (ret) 2222 return ret; 2223 2224 /* 2225 * Do not remap if the proper SMC calls are supported, 2226 * since the SMC calls expect physical addresses. 2227 */ 2228 if (pmc->svc_sreg_support) 2229 pmc->block[i].mmio_base = (void __iomem *)info[0]; 2230 else 2231 pmc->block[i].mmio_base = 2232 devm_ioremap(dev, info[0], info[1]); 2233 2234 pmc->block[i].blk_size = info[1]; 2235 pmc->block[i].counters = info[2]; 2236 pmc->block[i].type = info[3]; 2237 2238 if (!pmc->block[i].mmio_base) 2239 return -ENOMEM; 2240 2241 ret = mlxbf_pmc_create_groups(dev, i); 2242 if (ret == -ENOENT) { 2243 dev_warn(dev, "ignoring unsupported block: '%s'\n", pmc->block_name[i]); 2244 continue; 2245 } 2246 if (ret) 2247 return ret; 2248 } 2249 2250 return 0; 2251 } 2252 2253 static int mlxbf_pmc_probe(struct platform_device *pdev) 2254 { 2255 struct acpi_device *acpi_dev = ACPI_COMPANION(&pdev->dev); 2256 const char *hid = acpi_device_hid(acpi_dev); 2257 struct device *dev = &pdev->dev; 2258 struct arm_smccc_res res; 2259 guid_t guid; 2260 int ret; 2261 2262 /* Ensure we have the UUID we expect for this service. */ 2263 arm_smccc_smc(MLXBF_PMC_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); 2264 guid_parse(mlxbf_pmc_svc_uuid_str, &guid); 2265 if (!mlxbf_pmc_guid_match(&guid, &res)) 2266 return -ENODEV; 2267 2268 pmc = devm_kzalloc(dev, sizeof(struct mlxbf_pmc_context), GFP_KERNEL); 2269 if (!pmc) 2270 return -ENOMEM; 2271 2272 /* 2273 * ACPI indicates whether we use SMCs to access registers or not. 2274 * If sreg_tbl_perf is not present, just assume we're not using SMCs. 2275 */ 2276 ret = device_property_read_u32(dev, "sec_reg_block", 2277 &pmc->sreg_tbl_perf); 2278 if (ret) { 2279 pmc->svc_sreg_support = false; 2280 } else { 2281 /* 2282 * Check service version to see if we actually do support the 2283 * needed SMCs. If we have the calls we need, mark support for 2284 * them in the pmc struct. 2285 */ 2286 arm_smccc_smc(MLXBF_PMC_SIP_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, 2287 &res); 2288 if (res.a0 == MLXBF_PMC_SVC_REQ_MAJOR && 2289 res.a1 >= MLXBF_PMC_SVC_MIN_MINOR) 2290 pmc->svc_sreg_support = true; 2291 else 2292 return -EINVAL; 2293 } 2294 2295 if (!strcmp(hid, "MLNXBFD0")) 2296 pmc->event_set = MLXBF_PMC_EVENT_SET_BF1; 2297 else if (!strcmp(hid, "MLNXBFD1")) 2298 pmc->event_set = MLXBF_PMC_EVENT_SET_BF2; 2299 else if (!strcmp(hid, "MLNXBFD2")) 2300 pmc->event_set = MLXBF_PMC_EVENT_SET_BF3; 2301 else 2302 return -ENODEV; 2303 2304 ret = device_property_read_u32(dev, "block_num", &pmc->total_blocks); 2305 if (ret) 2306 return ret; 2307 2308 ret = device_property_read_string_array(dev, "block_name", 2309 pmc->block_name, 2310 pmc->total_blocks); 2311 if (ret != pmc->total_blocks) 2312 return -EFAULT; 2313 2314 if (device_property_read_u32(dev, "tile_num", &pmc->tile_count)) { 2315 if (device_property_read_u8(dev, "apt_enable", &pmc->apt_enable)) { 2316 dev_warn(dev, "Number of APTs undefined, ignoring blocks\n"); 2317 pmc->apt_enable = 0; 2318 } 2319 if (device_property_read_u8(dev, "llt_enable", &pmc->llt_enable)) { 2320 dev_warn(dev, "Number of LLTs undefined, ignoring blocks\n"); 2321 pmc->llt_enable = 0; 2322 } 2323 if (device_property_read_u8(dev, "mss_enable", &pmc->mss_enable)) { 2324 dev_warn(dev, "Number of MSSs undefined, ignoring blocks\n"); 2325 pmc->mss_enable = 0; 2326 } 2327 } 2328 2329 pmc->pdev = pdev; 2330 pmc->group_num = 0; 2331 2332 ret = mlxbf_pmc_map_counters(dev); 2333 if (ret) 2334 return ret; 2335 2336 pmc->hwmon_dev = devm_hwmon_device_register_with_groups( 2337 dev, "bfperf", pmc, pmc->groups); 2338 if (IS_ERR(pmc->hwmon_dev)) 2339 return PTR_ERR(pmc->hwmon_dev); 2340 platform_set_drvdata(pdev, pmc); 2341 2342 return 0; 2343 } 2344 2345 static const struct acpi_device_id mlxbf_pmc_acpi_ids[] = { { "MLNXBFD0", 0 }, 2346 { "MLNXBFD1", 0 }, 2347 { "MLNXBFD2", 0 }, 2348 {}, }; 2349 2350 MODULE_DEVICE_TABLE(acpi, mlxbf_pmc_acpi_ids); 2351 static struct platform_driver pmc_driver = { 2352 .driver = { .name = "mlxbf-pmc", 2353 .acpi_match_table = ACPI_PTR(mlxbf_pmc_acpi_ids), }, 2354 .probe = mlxbf_pmc_probe, 2355 }; 2356 2357 module_platform_driver(pmc_driver); 2358 2359 MODULE_AUTHOR("Shravan Kumar Ramani <sramani@mellanox.com>"); 2360 MODULE_DESCRIPTION("Mellanox PMC driver"); 2361 MODULE_LICENSE("Dual BSD/GPL"); 2362