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