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