1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * HiSilicon SoC UC (unified cache) uncore Hardware event counters support 4 * 5 * Copyright (C) 2023 HiSilicon Limited 6 * 7 * This code is based on the uncore PMUs like hisi_uncore_l3c_pmu. 8 */ 9 #include <linux/cpuhotplug.h> 10 #include <linux/interrupt.h> 11 #include <linux/irq.h> 12 #include <linux/list.h> 13 #include <linux/mod_devicetable.h> 14 15 #include "hisi_uncore_pmu.h" 16 17 /* Dynamic CPU hotplug state used by UC PMU */ 18 static enum cpuhp_state hisi_uc_pmu_online; 19 20 /* UC register definition */ 21 #define HISI_UC_INT_MASK_REG 0x0800 22 #define HISI_UC_INT_STS_REG 0x0808 23 #define HISI_UC_INT_CLEAR_REG 0x080c 24 #define HISI_UC_TRACETAG_CTRL_REG 0x1b2c 25 #define HISI_UC_TRACETAG_REQ_MSK GENMASK(9, 7) 26 #define HISI_UC_TRACETAG_MARK_EN BIT(0) 27 #define HISI_UC_TRACETAG_REQ_EN (HISI_UC_TRACETAG_MARK_EN | BIT(2)) 28 #define HISI_UC_TRACETAG_SRCID_EN BIT(3) 29 #define HISI_UC_SRCID_CTRL_REG 0x1b40 30 #define HISI_UC_SRCID_MSK GENMASK(14, 1) 31 #define HISI_UC_EVENT_CTRL_REG 0x1c00 32 #define HISI_UC_EVENT_TRACETAG_EN BIT(29) 33 #define HISI_UC_EVENT_URING_MSK GENMASK(28, 27) 34 #define HISI_UC_EVENT_GLB_EN BIT(26) 35 #define HISI_UC_VERSION_REG 0x1cf0 36 #define HISI_UC_EVTYPE_REGn(n) (0x1d00 + (n) * 4) 37 #define HISI_UC_EVTYPE_MASK GENMASK(7, 0) 38 #define HISI_UC_CNTR_REGn(n) (0x1e00 + (n) * 8) 39 40 #define HISI_UC_NR_COUNTERS 0x8 41 #define HISI_UC_V2_NR_EVENTS 0xFF 42 #define HISI_UC_CNTR_REG_BITS 64 43 44 #define HISI_UC_RD_REQ_TRACETAG 0x4 45 #define HISI_UC_URING_EVENT_MIN 0x47 46 #define HISI_UC_URING_EVENT_MAX 0x59 47 48 HISI_PMU_EVENT_ATTR_EXTRACTOR(rd_req_en, config1, 0, 0); 49 HISI_PMU_EVENT_ATTR_EXTRACTOR(uring_channel, config1, 5, 4); 50 HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid, config1, 19, 6); 51 HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_en, config1, 20, 20); 52 53 static int hisi_uc_pmu_check_filter(struct perf_event *event) 54 { 55 struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); 56 57 if (hisi_get_srcid_en(event) && !hisi_get_rd_req_en(event)) { 58 dev_err(uc_pmu->dev, 59 "rcid_en depends on rd_req_en being enabled!\n"); 60 return -EINVAL; 61 } 62 63 if (!hisi_get_uring_channel(event)) 64 return 0; 65 66 if ((HISI_GET_EVENTID(event) < HISI_UC_URING_EVENT_MIN) || 67 (HISI_GET_EVENTID(event) > HISI_UC_URING_EVENT_MAX)) 68 dev_warn(uc_pmu->dev, 69 "Only events: [%#x ~ %#x] support channel filtering!", 70 HISI_UC_URING_EVENT_MIN, HISI_UC_URING_EVENT_MAX); 71 72 return 0; 73 } 74 75 static void hisi_uc_pmu_config_req_tracetag(struct perf_event *event) 76 { 77 struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); 78 u32 val; 79 80 if (!hisi_get_rd_req_en(event)) 81 return; 82 83 val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 84 85 /* The request-type has been configured */ 86 if (FIELD_GET(HISI_UC_TRACETAG_REQ_MSK, val) == HISI_UC_RD_REQ_TRACETAG) 87 return; 88 89 /* Set request-type for tracetag, only read request is supported! */ 90 val &= ~HISI_UC_TRACETAG_REQ_MSK; 91 val |= FIELD_PREP(HISI_UC_TRACETAG_REQ_MSK, HISI_UC_RD_REQ_TRACETAG); 92 val |= HISI_UC_TRACETAG_REQ_EN; 93 writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 94 } 95 96 static void hisi_uc_pmu_clear_req_tracetag(struct perf_event *event) 97 { 98 struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); 99 u32 val; 100 101 if (!hisi_get_rd_req_en(event)) 102 return; 103 104 val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 105 106 /* Do nothing, the request-type tracetag has been cleaned up */ 107 if (FIELD_GET(HISI_UC_TRACETAG_REQ_MSK, val) == 0) 108 return; 109 110 /* Clear request-type */ 111 val &= ~HISI_UC_TRACETAG_REQ_MSK; 112 val &= ~HISI_UC_TRACETAG_REQ_EN; 113 writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 114 } 115 116 static void hisi_uc_pmu_config_srcid_tracetag(struct perf_event *event) 117 { 118 struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); 119 u32 val; 120 121 if (!hisi_get_srcid_en(event)) 122 return; 123 124 val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 125 126 /* Do nothing, the source id has been configured */ 127 if (FIELD_GET(HISI_UC_TRACETAG_SRCID_EN, val)) 128 return; 129 130 /* Enable source id tracetag */ 131 val |= HISI_UC_TRACETAG_SRCID_EN; 132 writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 133 134 val = readl(uc_pmu->base + HISI_UC_SRCID_CTRL_REG); 135 val &= ~HISI_UC_SRCID_MSK; 136 val |= FIELD_PREP(HISI_UC_SRCID_MSK, hisi_get_srcid(event)); 137 writel(val, uc_pmu->base + HISI_UC_SRCID_CTRL_REG); 138 139 /* Depend on request-type tracetag enabled */ 140 hisi_uc_pmu_config_req_tracetag(event); 141 } 142 143 static void hisi_uc_pmu_clear_srcid_tracetag(struct perf_event *event) 144 { 145 struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); 146 u32 val; 147 148 if (!hisi_get_srcid_en(event)) 149 return; 150 151 val = readl(uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 152 153 /* Do nothing, the source id has been cleaned up */ 154 if (FIELD_GET(HISI_UC_TRACETAG_SRCID_EN, val) == 0) 155 return; 156 157 hisi_uc_pmu_clear_req_tracetag(event); 158 159 /* Disable source id tracetag */ 160 val &= ~HISI_UC_TRACETAG_SRCID_EN; 161 writel(val, uc_pmu->base + HISI_UC_TRACETAG_CTRL_REG); 162 163 val = readl(uc_pmu->base + HISI_UC_SRCID_CTRL_REG); 164 val &= ~HISI_UC_SRCID_MSK; 165 writel(val, uc_pmu->base + HISI_UC_SRCID_CTRL_REG); 166 } 167 168 static void hisi_uc_pmu_config_uring_channel(struct perf_event *event) 169 { 170 struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); 171 u32 uring_channel = hisi_get_uring_channel(event); 172 u32 val; 173 174 /* Do nothing if not being set or is set explicitly to zero (default) */ 175 if (uring_channel == 0) 176 return; 177 178 val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 179 180 /* Do nothing, the uring_channel has been configured */ 181 if (uring_channel == FIELD_GET(HISI_UC_EVENT_URING_MSK, val)) 182 return; 183 184 val &= ~HISI_UC_EVENT_URING_MSK; 185 val |= FIELD_PREP(HISI_UC_EVENT_URING_MSK, uring_channel); 186 writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 187 } 188 189 static void hisi_uc_pmu_clear_uring_channel(struct perf_event *event) 190 { 191 struct hisi_pmu *uc_pmu = to_hisi_pmu(event->pmu); 192 u32 val; 193 194 /* Do nothing if not being set or is set explicitly to zero (default) */ 195 if (hisi_get_uring_channel(event) == 0) 196 return; 197 198 val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 199 200 /* Do nothing, the uring_channel has been cleaned up */ 201 if (FIELD_GET(HISI_UC_EVENT_URING_MSK, val) == 0) 202 return; 203 204 val &= ~HISI_UC_EVENT_URING_MSK; 205 writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 206 } 207 208 static void hisi_uc_pmu_enable_filter(struct perf_event *event) 209 { 210 if (event->attr.config1 == 0) 211 return; 212 213 hisi_uc_pmu_config_uring_channel(event); 214 hisi_uc_pmu_config_req_tracetag(event); 215 hisi_uc_pmu_config_srcid_tracetag(event); 216 } 217 218 static void hisi_uc_pmu_disable_filter(struct perf_event *event) 219 { 220 if (event->attr.config1 == 0) 221 return; 222 223 hisi_uc_pmu_clear_srcid_tracetag(event); 224 hisi_uc_pmu_clear_req_tracetag(event); 225 hisi_uc_pmu_clear_uring_channel(event); 226 } 227 228 static void hisi_uc_pmu_write_evtype(struct hisi_pmu *uc_pmu, int idx, u32 type) 229 { 230 u32 val; 231 232 /* 233 * Select the appropriate event select register. 234 * There are 2 32-bit event select registers for the 235 * 8 hardware counters, each event code is 8-bit wide. 236 */ 237 val = readl(uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4)); 238 val &= ~(HISI_UC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx)); 239 val |= (type << HISI_PMU_EVTYPE_SHIFT(idx)); 240 writel(val, uc_pmu->base + HISI_UC_EVTYPE_REGn(idx / 4)); 241 } 242 243 static void hisi_uc_pmu_start_counters(struct hisi_pmu *uc_pmu) 244 { 245 u32 val; 246 247 val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 248 val |= HISI_UC_EVENT_GLB_EN; 249 writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 250 } 251 252 static void hisi_uc_pmu_stop_counters(struct hisi_pmu *uc_pmu) 253 { 254 u32 val; 255 256 val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 257 val &= ~HISI_UC_EVENT_GLB_EN; 258 writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 259 } 260 261 static void hisi_uc_pmu_enable_counter(struct hisi_pmu *uc_pmu, 262 struct hw_perf_event *hwc) 263 { 264 u32 val; 265 266 /* Enable counter index */ 267 val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 268 val |= (1 << hwc->idx); 269 writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 270 } 271 272 static void hisi_uc_pmu_disable_counter(struct hisi_pmu *uc_pmu, 273 struct hw_perf_event *hwc) 274 { 275 u32 val; 276 277 /* Clear counter index */ 278 val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 279 val &= ~(1 << hwc->idx); 280 writel(val, uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 281 } 282 283 static u64 hisi_uc_pmu_read_counter(struct hisi_pmu *uc_pmu, 284 struct hw_perf_event *hwc) 285 { 286 return readq(uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx)); 287 } 288 289 static bool hisi_uc_pmu_get_glb_en_state(struct hisi_pmu *uc_pmu) 290 { 291 u32 val; 292 293 val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG); 294 return !!FIELD_GET(HISI_UC_EVENT_GLB_EN, val); 295 } 296 297 static void hisi_uc_pmu_write_counter_normal(struct hisi_pmu *uc_pmu, 298 struct hw_perf_event *hwc, u64 val) 299 { 300 writeq(val, uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx)); 301 } 302 303 static void hisi_uc_pmu_write_counter_quirk_v2(struct hisi_pmu *uc_pmu, 304 struct hw_perf_event *hwc, u64 val) 305 { 306 hisi_uc_pmu_start_counters(uc_pmu); 307 hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val); 308 hisi_uc_pmu_stop_counters(uc_pmu); 309 } 310 311 static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu, 312 struct hw_perf_event *hwc, u64 val) 313 { 314 bool enable = hisi_uc_pmu_get_glb_en_state(uc_pmu); 315 bool erratum = uc_pmu->identifier == HISI_PMU_V2; 316 317 /* 318 * HiSilicon UC PMU v2 suffers the erratum 162700402 that the 319 * PMU counter cannot be set due to the lack of clock under power 320 * saving mode. This will lead to error or inaccurate counts. 321 * The clock can be enabled by the PMU global enabling control. 322 * The irq handler and pmu_start() will call the function to set 323 * period. If the function under irq context, the PMU has been 324 * enabled therefore we set counter directly. Other situations 325 * the PMU is disabled, we need to enable it to turn on the 326 * counter clock to set period, and then restore PMU enable 327 * status, the counter can hold its value without a clock. 328 */ 329 if (enable || !erratum) 330 hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val); 331 else 332 hisi_uc_pmu_write_counter_quirk_v2(uc_pmu, hwc, val); 333 } 334 335 static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu, 336 struct hw_perf_event *hwc) 337 { 338 u32 val; 339 340 val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG); 341 val &= ~(1 << hwc->idx); 342 writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG); 343 } 344 345 static void hisi_uc_pmu_disable_counter_int(struct hisi_pmu *uc_pmu, 346 struct hw_perf_event *hwc) 347 { 348 u32 val; 349 350 val = readl(uc_pmu->base + HISI_UC_INT_MASK_REG); 351 val |= (1 << hwc->idx); 352 writel(val, uc_pmu->base + HISI_UC_INT_MASK_REG); 353 } 354 355 static u32 hisi_uc_pmu_get_int_status(struct hisi_pmu *uc_pmu) 356 { 357 return readl(uc_pmu->base + HISI_UC_INT_STS_REG); 358 } 359 360 static void hisi_uc_pmu_clear_int_status(struct hisi_pmu *uc_pmu, int idx) 361 { 362 writel(1 << idx, uc_pmu->base + HISI_UC_INT_CLEAR_REG); 363 } 364 365 static int hisi_uc_pmu_init_data(struct platform_device *pdev, 366 struct hisi_pmu *uc_pmu) 367 { 368 hisi_uncore_pmu_init_topology(uc_pmu, &pdev->dev); 369 370 /* 371 * Use SCCL (Super CPU Cluster) ID and CCL (CPU Cluster) ID to 372 * identify the topology information of UC PMU devices in the chip. 373 * They have some CCLs per SCCL and then 4 UC PMU per CCL. 374 */ 375 if (uc_pmu->topo.sccl_id < 0) { 376 dev_err(&pdev->dev, "Can not read uc sccl-id!\n"); 377 return -EINVAL; 378 } 379 380 if (uc_pmu->topo.ccl_id < 0) { 381 dev_err(&pdev->dev, "Can not read uc ccl-id!\n"); 382 return -EINVAL; 383 } 384 385 if (uc_pmu->topo.sub_id < 0) { 386 dev_err(&pdev->dev, "Can not read sub-id!\n"); 387 return -EINVAL; 388 } 389 390 uc_pmu->base = devm_platform_ioremap_resource(pdev, 0); 391 if (IS_ERR(uc_pmu->base)) { 392 dev_err(&pdev->dev, "ioremap failed for uc_pmu resource\n"); 393 return PTR_ERR(uc_pmu->base); 394 } 395 396 uc_pmu->identifier = readl(uc_pmu->base + HISI_UC_VERSION_REG); 397 398 return 0; 399 } 400 401 static struct attribute *hisi_uc_pmu_format_attr[] = { 402 HISI_PMU_FORMAT_ATTR(event, "config:0-7"), 403 HISI_PMU_FORMAT_ATTR(rd_req_en, "config1:0-0"), 404 HISI_PMU_FORMAT_ATTR(uring_channel, "config1:4-5"), 405 HISI_PMU_FORMAT_ATTR(srcid, "config1:6-19"), 406 HISI_PMU_FORMAT_ATTR(srcid_en, "config1:20-20"), 407 NULL 408 }; 409 410 static const struct attribute_group hisi_uc_pmu_format_group = { 411 .name = "format", 412 .attrs = hisi_uc_pmu_format_attr, 413 }; 414 415 static struct attribute *hisi_uc_pmu_events_attr[] = { 416 HISI_PMU_EVENT_ATTR(sq_time, 0x00), 417 HISI_PMU_EVENT_ATTR(pq_time, 0x01), 418 HISI_PMU_EVENT_ATTR(hbm_time, 0x02), 419 HISI_PMU_EVENT_ATTR(iq_comp_time_cring, 0x03), 420 HISI_PMU_EVENT_ATTR(iq_comp_time_uring, 0x05), 421 HISI_PMU_EVENT_ATTR(cpu_rd, 0x10), 422 HISI_PMU_EVENT_ATTR(cpu_rd64, 0x17), 423 HISI_PMU_EVENT_ATTR(cpu_rs64, 0x19), 424 HISI_PMU_EVENT_ATTR(cpu_mru, 0x1c), 425 HISI_PMU_EVENT_ATTR(cycles, 0x95), 426 HISI_PMU_EVENT_ATTR(spipe_hit, 0xb3), 427 HISI_PMU_EVENT_ATTR(hpipe_hit, 0xdb), 428 HISI_PMU_EVENT_ATTR(cring_rxdat_cnt, 0xfa), 429 HISI_PMU_EVENT_ATTR(cring_txdat_cnt, 0xfb), 430 HISI_PMU_EVENT_ATTR(uring_rxdat_cnt, 0xfc), 431 HISI_PMU_EVENT_ATTR(uring_txdat_cnt, 0xfd), 432 NULL 433 }; 434 435 static const struct attribute_group hisi_uc_pmu_events_group = { 436 .name = "events", 437 .attrs = hisi_uc_pmu_events_attr, 438 }; 439 440 static const struct attribute_group *hisi_uc_pmu_attr_groups[] = { 441 &hisi_uc_pmu_format_group, 442 &hisi_uc_pmu_events_group, 443 &hisi_pmu_cpumask_attr_group, 444 &hisi_pmu_identifier_group, 445 NULL 446 }; 447 448 static const struct hisi_uncore_ops hisi_uncore_uc_pmu_ops = { 449 .check_filter = hisi_uc_pmu_check_filter, 450 .write_evtype = hisi_uc_pmu_write_evtype, 451 .get_event_idx = hisi_uncore_pmu_get_event_idx, 452 .start_counters = hisi_uc_pmu_start_counters, 453 .stop_counters = hisi_uc_pmu_stop_counters, 454 .enable_counter = hisi_uc_pmu_enable_counter, 455 .disable_counter = hisi_uc_pmu_disable_counter, 456 .enable_counter_int = hisi_uc_pmu_enable_counter_int, 457 .disable_counter_int = hisi_uc_pmu_disable_counter_int, 458 .write_counter = hisi_uc_pmu_write_counter, 459 .read_counter = hisi_uc_pmu_read_counter, 460 .get_int_status = hisi_uc_pmu_get_int_status, 461 .clear_int_status = hisi_uc_pmu_clear_int_status, 462 .enable_filter = hisi_uc_pmu_enable_filter, 463 .disable_filter = hisi_uc_pmu_disable_filter, 464 }; 465 466 static int hisi_uc_pmu_dev_probe(struct platform_device *pdev, 467 struct hisi_pmu *uc_pmu) 468 { 469 int ret; 470 471 ret = hisi_uc_pmu_init_data(pdev, uc_pmu); 472 if (ret) 473 return ret; 474 475 ret = hisi_uncore_pmu_init_irq(uc_pmu, pdev); 476 if (ret) 477 return ret; 478 479 uc_pmu->pmu_events.attr_groups = hisi_uc_pmu_attr_groups; 480 uc_pmu->check_event = HISI_UC_EVTYPE_MASK; 481 uc_pmu->ops = &hisi_uncore_uc_pmu_ops; 482 uc_pmu->counter_bits = HISI_UC_CNTR_REG_BITS; 483 uc_pmu->num_counters = HISI_UC_NR_COUNTERS; 484 uc_pmu->dev = &pdev->dev; 485 uc_pmu->on_cpu = -1; 486 487 return 0; 488 } 489 490 static void hisi_uc_pmu_remove_cpuhp_instance(void *hotplug_node) 491 { 492 cpuhp_state_remove_instance_nocalls(hisi_uc_pmu_online, hotplug_node); 493 } 494 495 static void hisi_uc_pmu_unregister_pmu(void *pmu) 496 { 497 perf_pmu_unregister(pmu); 498 } 499 500 static int hisi_uc_pmu_probe(struct platform_device *pdev) 501 { 502 struct hisi_pmu *uc_pmu; 503 char *name; 504 int ret; 505 506 uc_pmu = devm_kzalloc(&pdev->dev, sizeof(*uc_pmu), GFP_KERNEL); 507 if (!uc_pmu) 508 return -ENOMEM; 509 510 platform_set_drvdata(pdev, uc_pmu); 511 512 ret = hisi_uc_pmu_dev_probe(pdev, uc_pmu); 513 if (ret) 514 return ret; 515 516 name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_uc%d_%d", 517 uc_pmu->topo.sccl_id, uc_pmu->topo.ccl_id, 518 uc_pmu->topo.sub_id); 519 if (!name) 520 return -ENOMEM; 521 522 ret = cpuhp_state_add_instance(hisi_uc_pmu_online, &uc_pmu->node); 523 if (ret) 524 return dev_err_probe(&pdev->dev, ret, "Error registering hotplug\n"); 525 526 ret = devm_add_action_or_reset(&pdev->dev, 527 hisi_uc_pmu_remove_cpuhp_instance, 528 &uc_pmu->node); 529 if (ret) 530 return ret; 531 532 hisi_pmu_init(uc_pmu, THIS_MODULE); 533 534 ret = perf_pmu_register(&uc_pmu->pmu, name, -1); 535 if (ret) 536 return ret; 537 538 return devm_add_action_or_reset(&pdev->dev, 539 hisi_uc_pmu_unregister_pmu, 540 &uc_pmu->pmu); 541 } 542 543 static const struct acpi_device_id hisi_uc_pmu_acpi_match[] = { 544 { "HISI0291", }, 545 {} 546 }; 547 MODULE_DEVICE_TABLE(acpi, hisi_uc_pmu_acpi_match); 548 549 static struct platform_driver hisi_uc_pmu_driver = { 550 .driver = { 551 .name = "hisi_uc_pmu", 552 .acpi_match_table = hisi_uc_pmu_acpi_match, 553 /* 554 * We have not worked out a safe bind/unbind process, 555 * Forcefully unbinding during sampling will lead to a 556 * kernel panic, so this is not supported yet. 557 */ 558 .suppress_bind_attrs = true, 559 }, 560 .probe = hisi_uc_pmu_probe, 561 }; 562 563 static int __init hisi_uc_pmu_module_init(void) 564 { 565 int ret; 566 567 ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, 568 "perf/hisi/uc:online", 569 hisi_uncore_pmu_online_cpu, 570 hisi_uncore_pmu_offline_cpu); 571 if (ret < 0) { 572 pr_err("UC PMU: Error setup hotplug, ret = %d\n", ret); 573 return ret; 574 } 575 hisi_uc_pmu_online = ret; 576 577 ret = platform_driver_register(&hisi_uc_pmu_driver); 578 if (ret) 579 cpuhp_remove_multi_state(hisi_uc_pmu_online); 580 581 return ret; 582 } 583 module_init(hisi_uc_pmu_module_init); 584 585 static void __exit hisi_uc_pmu_module_exit(void) 586 { 587 platform_driver_unregister(&hisi_uc_pmu_driver); 588 cpuhp_remove_multi_state(hisi_uc_pmu_online); 589 } 590 module_exit(hisi_uc_pmu_module_exit); 591 592 MODULE_IMPORT_NS("HISI_PMU"); 593 MODULE_DESCRIPTION("HiSilicon SoC UC uncore PMU driver"); 594 MODULE_LICENSE("GPL"); 595 MODULE_AUTHOR("Junhao He <hejunhao3@huawei.com>"); 596