starfive_starlink_pmu.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * StarFive's StarLink PMU driver
  4. *
  5. * Copyright (C) 2023 StarFive Technology Co., Ltd.
  6. *
  7. * Author: Ji Sheng Teoh <jisheng.teoh@starfivetech.com>
  8. *
  9. */
  10. #define STARLINK_PMU_PDEV_NAME "starfive_starlink_pmu"
  11. #define pr_fmt(fmt) STARLINK_PMU_PDEV_NAME ": " fmt
  12. #include <linux/bitmap.h>
  13. #include <linux/cpu_pm.h>
  14. #include <linux/io.h>
  15. #include <linux/irq.h>
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/mod_devicetable.h>
  19. #include <linux/perf_event.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/sysfs.h>
  22. #define STARLINK_PMU_MAX_COUNTERS 64
  23. #define STARLINK_PMU_NUM_COUNTERS 16
  24. #define STARLINK_PMU_IDX_CYCLE_COUNTER 63
  25. #define STARLINK_PMU_EVENT_SELECT 0x060
  26. #define STARLINK_PMU_EVENT_COUNTER 0x160
  27. #define STARLINK_PMU_COUNTER_MASK GENMASK_ULL(63, 0)
  28. #define STARLINK_PMU_CYCLE_COUNTER 0x058
  29. #define STARLINK_PMU_CONTROL 0x040
  30. #define STARLINK_PMU_GLOBAL_ENABLE BIT_ULL(0)
  31. #define STARLINK_PMU_INTERRUPT_ENABLE 0x050
  32. #define STARLINK_PMU_COUNTER_OVERFLOW_STATUS 0x048
  33. #define STARLINK_PMU_CYCLE_OVERFLOW_MASK BIT_ULL(63)
  34. #define STARLINK_CYCLES 0x058
  35. #define CACHE_READ_REQUEST 0x04000701
  36. #define CACHE_WRITE_REQUEST 0x03000001
  37. #define CACHE_RELEASE_REQUEST 0x0003e001
  38. #define CACHE_READ_HIT 0x00901202
  39. #define CACHE_READ_MISS 0x04008002
  40. #define CACHE_WRITE_HIT 0x006c0002
  41. #define CACHE_WRITE_MISS 0x03000002
  42. #define CACHE_WRITEBACK 0x00000403
  43. #define to_starlink_pmu(p) (container_of(p, struct starlink_pmu, pmu))
  44. #define STARLINK_FORMAT_ATTR(_name, _config) \
  45. (&((struct dev_ext_attribute[]) { \
  46. { .attr = __ATTR(_name, 0444, starlink_pmu_sysfs_format_show, NULL), \
  47. .var = (void *)_config, } \
  48. })[0].attr.attr)
  49. #define STARLINK_EVENT_ATTR(_name, _id) \
  50. PMU_EVENT_ATTR_ID(_name, starlink_pmu_sysfs_event_show, _id)
  51. static int starlink_pmu_cpuhp_state;
  52. struct starlink_hw_events {
  53. struct perf_event *events[STARLINK_PMU_MAX_COUNTERS];
  54. DECLARE_BITMAP(used_mask, STARLINK_PMU_MAX_COUNTERS);
  55. };
  56. struct starlink_pmu {
  57. struct pmu pmu;
  58. struct starlink_hw_events __percpu *hw_events;
  59. struct hlist_node node;
  60. struct notifier_block starlink_pmu_pm_nb;
  61. void __iomem *pmu_base;
  62. cpumask_t cpumask;
  63. int irq;
  64. };
  65. static ssize_t
  66. starlink_pmu_sysfs_format_show(struct device *dev,
  67. struct device_attribute *attr,
  68. char *buf)
  69. {
  70. struct dev_ext_attribute *eattr = container_of(attr,
  71. struct dev_ext_attribute, attr);
  72. return sysfs_emit(buf, "%s\n", (char *)eattr->var);
  73. }
  74. static struct attribute *starlink_pmu_format_attrs[] = {
  75. STARLINK_FORMAT_ATTR(event, "config:0-31"),
  76. NULL
  77. };
  78. static const struct attribute_group starlink_pmu_format_attr_group = {
  79. .name = "format",
  80. .attrs = starlink_pmu_format_attrs,
  81. };
  82. static ssize_t
  83. starlink_pmu_sysfs_event_show(struct device *dev,
  84. struct device_attribute *attr,
  85. char *buf)
  86. {
  87. struct perf_pmu_events_attr *eattr = container_of(attr,
  88. struct perf_pmu_events_attr, attr);
  89. return sysfs_emit(buf, "event=0x%02llx\n", eattr->id);
  90. }
  91. static struct attribute *starlink_pmu_event_attrs[] = {
  92. STARLINK_EVENT_ATTR(cycles, STARLINK_CYCLES),
  93. STARLINK_EVENT_ATTR(read_request, CACHE_READ_REQUEST),
  94. STARLINK_EVENT_ATTR(write_request, CACHE_WRITE_REQUEST),
  95. STARLINK_EVENT_ATTR(release_request, CACHE_RELEASE_REQUEST),
  96. STARLINK_EVENT_ATTR(read_hit, CACHE_READ_HIT),
  97. STARLINK_EVENT_ATTR(read_miss, CACHE_READ_MISS),
  98. STARLINK_EVENT_ATTR(write_hit, CACHE_WRITE_HIT),
  99. STARLINK_EVENT_ATTR(write_miss, CACHE_WRITE_MISS),
  100. STARLINK_EVENT_ATTR(writeback, CACHE_WRITEBACK),
  101. NULL
  102. };
  103. static const struct attribute_group starlink_pmu_events_attr_group = {
  104. .name = "events",
  105. .attrs = starlink_pmu_event_attrs,
  106. };
  107. static ssize_t
  108. cpumask_show(struct device *dev, struct device_attribute *attr, char *buf)
  109. {
  110. struct starlink_pmu *starlink_pmu = to_starlink_pmu(dev_get_drvdata(dev));
  111. return cpumap_print_to_pagebuf(true, buf, &starlink_pmu->cpumask);
  112. }
  113. static DEVICE_ATTR_RO(cpumask);
  114. static struct attribute *starlink_pmu_cpumask_attrs[] = {
  115. &dev_attr_cpumask.attr,
  116. NULL
  117. };
  118. static const struct attribute_group starlink_pmu_cpumask_attr_group = {
  119. .attrs = starlink_pmu_cpumask_attrs,
  120. };
  121. static const struct attribute_group *starlink_pmu_attr_groups[] = {
  122. &starlink_pmu_format_attr_group,
  123. &starlink_pmu_events_attr_group,
  124. &starlink_pmu_cpumask_attr_group,
  125. NULL
  126. };
  127. static void starlink_pmu_set_event_period(struct perf_event *event)
  128. {
  129. struct starlink_pmu *starlink_pmu = to_starlink_pmu(event->pmu);
  130. struct hw_perf_event *hwc = &event->hw;
  131. int idx = event->hw.idx;
  132. /*
  133. * Program counter to half of it's max count to handle
  134. * cases of extreme interrupt latency.
  135. */
  136. u64 val = STARLINK_PMU_COUNTER_MASK >> 1;
  137. local64_set(&hwc->prev_count, val);
  138. if (hwc->config == STARLINK_CYCLES)
  139. writeq(val, starlink_pmu->pmu_base + STARLINK_PMU_CYCLE_COUNTER);
  140. else
  141. writeq(val, starlink_pmu->pmu_base + STARLINK_PMU_EVENT_COUNTER +
  142. idx * sizeof(u64));
  143. }
  144. static void starlink_pmu_counter_start(struct perf_event *event,
  145. struct starlink_pmu *starlink_pmu)
  146. {
  147. struct hw_perf_event *hwc = &event->hw;
  148. int idx = event->hw.idx;
  149. u64 val;
  150. /*
  151. * Enable counter overflow interrupt[63:0],
  152. * which is mapped as follow:
  153. *
  154. * event counter 0 - Bit [0]
  155. * event counter 1 - Bit [1]
  156. * ...
  157. * cycle counter - Bit [63]
  158. */
  159. val = readq(starlink_pmu->pmu_base + STARLINK_PMU_INTERRUPT_ENABLE);
  160. if (hwc->config == STARLINK_CYCLES) {
  161. /*
  162. * Cycle count has its dedicated register, and it starts
  163. * counting as soon as STARLINK_PMU_GLOBAL_ENABLE is set.
  164. */
  165. val |= STARLINK_PMU_CYCLE_OVERFLOW_MASK;
  166. } else {
  167. writeq(event->hw.config, starlink_pmu->pmu_base +
  168. STARLINK_PMU_EVENT_SELECT + idx * sizeof(u64));
  169. val |= BIT_ULL(idx);
  170. }
  171. writeq(val, starlink_pmu->pmu_base + STARLINK_PMU_INTERRUPT_ENABLE);
  172. writeq(STARLINK_PMU_GLOBAL_ENABLE, starlink_pmu->pmu_base +
  173. STARLINK_PMU_CONTROL);
  174. }
  175. static void starlink_pmu_counter_stop(struct perf_event *event,
  176. struct starlink_pmu *starlink_pmu)
  177. {
  178. struct hw_perf_event *hwc = &event->hw;
  179. int idx = event->hw.idx;
  180. u64 val;
  181. val = readq(starlink_pmu->pmu_base + STARLINK_PMU_CONTROL);
  182. val &= ~STARLINK_PMU_GLOBAL_ENABLE;
  183. writeq(val, starlink_pmu->pmu_base + STARLINK_PMU_CONTROL);
  184. val = readq(starlink_pmu->pmu_base + STARLINK_PMU_INTERRUPT_ENABLE);
  185. if (hwc->config == STARLINK_CYCLES)
  186. val &= ~STARLINK_PMU_CYCLE_OVERFLOW_MASK;
  187. else
  188. val &= ~BIT_ULL(idx);
  189. writeq(val, starlink_pmu->pmu_base + STARLINK_PMU_INTERRUPT_ENABLE);
  190. }
  191. static void starlink_pmu_update(struct perf_event *event)
  192. {
  193. struct starlink_pmu *starlink_pmu = to_starlink_pmu(event->pmu);
  194. struct hw_perf_event *hwc = &event->hw;
  195. int idx = hwc->idx;
  196. u64 prev_raw_count, new_raw_count;
  197. u64 oldval;
  198. u64 delta;
  199. do {
  200. prev_raw_count = local64_read(&hwc->prev_count);
  201. if (hwc->config == STARLINK_CYCLES)
  202. new_raw_count = readq(starlink_pmu->pmu_base +
  203. STARLINK_PMU_CYCLE_COUNTER);
  204. else
  205. new_raw_count = readq(starlink_pmu->pmu_base +
  206. STARLINK_PMU_EVENT_COUNTER +
  207. idx * sizeof(u64));
  208. oldval = local64_cmpxchg(&hwc->prev_count, prev_raw_count,
  209. new_raw_count);
  210. } while (oldval != prev_raw_count);
  211. delta = (new_raw_count - prev_raw_count) & STARLINK_PMU_COUNTER_MASK;
  212. local64_add(delta, &event->count);
  213. }
  214. static void starlink_pmu_start(struct perf_event *event, int flags)
  215. {
  216. struct starlink_pmu *starlink_pmu = to_starlink_pmu(event->pmu);
  217. struct hw_perf_event *hwc = &event->hw;
  218. if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
  219. return;
  220. if (flags & PERF_EF_RELOAD)
  221. WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
  222. hwc->state = 0;
  223. starlink_pmu_set_event_period(event);
  224. starlink_pmu_counter_start(event, starlink_pmu);
  225. perf_event_update_userpage(event);
  226. }
  227. static void starlink_pmu_stop(struct perf_event *event, int flags)
  228. {
  229. struct starlink_pmu *starlink_pmu = to_starlink_pmu(event->pmu);
  230. struct hw_perf_event *hwc = &event->hw;
  231. if (hwc->state & PERF_HES_STOPPED)
  232. return;
  233. starlink_pmu_counter_stop(event, starlink_pmu);
  234. starlink_pmu_update(event);
  235. hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
  236. }
  237. static int starlink_pmu_add(struct perf_event *event, int flags)
  238. {
  239. struct starlink_pmu *starlink_pmu = to_starlink_pmu(event->pmu);
  240. struct starlink_hw_events *hw_events =
  241. this_cpu_ptr(starlink_pmu->hw_events);
  242. struct hw_perf_event *hwc = &event->hw;
  243. unsigned long *used_mask = hw_events->used_mask;
  244. u32 n_events = STARLINK_PMU_NUM_COUNTERS;
  245. int idx;
  246. /*
  247. * Cycle counter has dedicated register to hold counter value.
  248. * Event other than cycle count has to be enabled through
  249. * event select register, and assigned with independent counter
  250. * as they appear.
  251. */
  252. if (hwc->config == STARLINK_CYCLES) {
  253. idx = STARLINK_PMU_IDX_CYCLE_COUNTER;
  254. } else {
  255. idx = find_first_zero_bit(used_mask, n_events);
  256. /* All counter are in use */
  257. if (idx < 0)
  258. return idx;
  259. set_bit(idx, used_mask);
  260. }
  261. hwc->idx = idx;
  262. hw_events->events[idx] = event;
  263. hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
  264. if (flags & PERF_EF_START)
  265. starlink_pmu_start(event, PERF_EF_RELOAD);
  266. perf_event_update_userpage(event);
  267. return 0;
  268. }
  269. static void starlink_pmu_del(struct perf_event *event, int flags)
  270. {
  271. struct starlink_pmu *starlink_pmu = to_starlink_pmu(event->pmu);
  272. struct starlink_hw_events *hw_events =
  273. this_cpu_ptr(starlink_pmu->hw_events);
  274. struct hw_perf_event *hwc = &event->hw;
  275. starlink_pmu_stop(event, PERF_EF_UPDATE);
  276. hw_events->events[hwc->idx] = NULL;
  277. clear_bit(hwc->idx, hw_events->used_mask);
  278. perf_event_update_userpage(event);
  279. }
  280. static bool starlink_pmu_validate_event_group(struct perf_event *event)
  281. {
  282. struct perf_event *leader = event->group_leader;
  283. struct perf_event *sibling;
  284. int counter = 1;
  285. /*
  286. * Ensure hardware events in the group are on the same PMU,
  287. * software events are acceptable.
  288. */
  289. if (event->group_leader->pmu != event->pmu &&
  290. !is_software_event(event->group_leader))
  291. return false;
  292. for_each_sibling_event(sibling, leader) {
  293. if (sibling->pmu != event->pmu && !is_software_event(sibling))
  294. return false;
  295. counter++;
  296. }
  297. return counter <= STARLINK_PMU_NUM_COUNTERS;
  298. }
  299. static int starlink_pmu_event_init(struct perf_event *event)
  300. {
  301. struct starlink_pmu *starlink_pmu = to_starlink_pmu(event->pmu);
  302. struct hw_perf_event *hwc = &event->hw;
  303. /*
  304. * Sampling is not supported, as counters are shared
  305. * by all CPU.
  306. */
  307. if (hwc->sample_period)
  308. return -EOPNOTSUPP;
  309. /*
  310. * Per-task and attach to a task are not supported,
  311. * as uncore events are not specific to any CPU.
  312. */
  313. if (event->cpu < 0 || event->attach_state & PERF_ATTACH_TASK)
  314. return -EOPNOTSUPP;
  315. if (!starlink_pmu_validate_event_group(event))
  316. return -EINVAL;
  317. hwc->idx = -1;
  318. hwc->config = event->attr.config;
  319. event->cpu = cpumask_first(&starlink_pmu->cpumask);
  320. return 0;
  321. }
  322. static irqreturn_t starlink_pmu_handle_irq(int irq_num, void *data)
  323. {
  324. struct starlink_pmu *starlink_pmu = data;
  325. struct starlink_hw_events *hw_events =
  326. this_cpu_ptr(starlink_pmu->hw_events);
  327. bool handled = false;
  328. int idx;
  329. u64 overflow_status;
  330. for (idx = 0; idx < STARLINK_PMU_MAX_COUNTERS; idx++) {
  331. struct perf_event *event = hw_events->events[idx];
  332. if (!event)
  333. continue;
  334. overflow_status = readq(starlink_pmu->pmu_base +
  335. STARLINK_PMU_COUNTER_OVERFLOW_STATUS);
  336. if (!(overflow_status & BIT_ULL(idx)))
  337. continue;
  338. writeq(BIT_ULL(idx), starlink_pmu->pmu_base +
  339. STARLINK_PMU_COUNTER_OVERFLOW_STATUS);
  340. starlink_pmu_update(event);
  341. starlink_pmu_set_event_period(event);
  342. handled = true;
  343. }
  344. return IRQ_RETVAL(handled);
  345. }
  346. static int starlink_setup_irqs(struct starlink_pmu *starlink_pmu,
  347. struct platform_device *pdev)
  348. {
  349. int ret, irq;
  350. irq = platform_get_irq(pdev, 0);
  351. if (irq < 0)
  352. return -EINVAL;
  353. ret = devm_request_irq(&pdev->dev, irq, starlink_pmu_handle_irq,
  354. 0, STARLINK_PMU_PDEV_NAME, starlink_pmu);
  355. if (ret)
  356. return dev_err_probe(&pdev->dev, ret, "Failed to request IRQ\n");
  357. starlink_pmu->irq = irq;
  358. return 0;
  359. }
  360. static int starlink_pmu_pm_notify(struct notifier_block *b,
  361. unsigned long cmd, void *v)
  362. {
  363. struct starlink_pmu *starlink_pmu = container_of(b, struct starlink_pmu,
  364. starlink_pmu_pm_nb);
  365. struct starlink_hw_events *hw_events =
  366. this_cpu_ptr(starlink_pmu->hw_events);
  367. bool enabled = !bitmap_empty(hw_events->used_mask, STARLINK_PMU_MAX_COUNTERS);
  368. struct perf_event *event;
  369. int idx;
  370. if (!enabled)
  371. return NOTIFY_OK;
  372. for (idx = 0; idx < STARLINK_PMU_MAX_COUNTERS; idx++) {
  373. event = hw_events->events[idx];
  374. if (!event)
  375. continue;
  376. switch (cmd) {
  377. case CPU_PM_ENTER:
  378. /* Stop and update the counter */
  379. starlink_pmu_stop(event, PERF_EF_UPDATE);
  380. break;
  381. case CPU_PM_EXIT:
  382. case CPU_PM_ENTER_FAILED:
  383. /* Restore and enable the counter */
  384. starlink_pmu_start(event, PERF_EF_RELOAD);
  385. break;
  386. default:
  387. break;
  388. }
  389. }
  390. return NOTIFY_OK;
  391. }
  392. static int starlink_pmu_pm_register(struct starlink_pmu *starlink_pmu)
  393. {
  394. if (!IS_ENABLED(CONFIG_CPU_PM))
  395. return 0;
  396. starlink_pmu->starlink_pmu_pm_nb.notifier_call = starlink_pmu_pm_notify;
  397. return cpu_pm_register_notifier(&starlink_pmu->starlink_pmu_pm_nb);
  398. }
  399. static void starlink_pmu_pm_unregister(struct starlink_pmu *starlink_pmu)
  400. {
  401. if (!IS_ENABLED(CONFIG_CPU_PM))
  402. return;
  403. cpu_pm_unregister_notifier(&starlink_pmu->starlink_pmu_pm_nb);
  404. }
  405. static void starlink_pmu_destroy(struct starlink_pmu *starlink_pmu)
  406. {
  407. starlink_pmu_pm_unregister(starlink_pmu);
  408. cpuhp_state_remove_instance(starlink_pmu_cpuhp_state,
  409. &starlink_pmu->node);
  410. }
  411. static int starlink_pmu_probe(struct platform_device *pdev)
  412. {
  413. struct starlink_pmu *starlink_pmu;
  414. struct starlink_hw_events *hw_events;
  415. struct resource *res;
  416. int cpuid, i, ret;
  417. starlink_pmu = devm_kzalloc(&pdev->dev, sizeof(*starlink_pmu), GFP_KERNEL);
  418. if (!starlink_pmu)
  419. return -ENOMEM;
  420. starlink_pmu->pmu_base =
  421. devm_platform_get_and_ioremap_resource(pdev, 0, &res);
  422. if (IS_ERR(starlink_pmu->pmu_base))
  423. return PTR_ERR(starlink_pmu->pmu_base);
  424. starlink_pmu->hw_events = alloc_percpu_gfp(struct starlink_hw_events,
  425. GFP_KERNEL);
  426. if (!starlink_pmu->hw_events) {
  427. dev_err(&pdev->dev, "Failed to allocate per-cpu PMU data\n");
  428. return -ENOMEM;
  429. }
  430. for_each_possible_cpu(cpuid) {
  431. hw_events = per_cpu_ptr(starlink_pmu->hw_events, cpuid);
  432. for (i = 0; i < STARLINK_PMU_MAX_COUNTERS; i++)
  433. hw_events->events[i] = NULL;
  434. }
  435. ret = starlink_setup_irqs(starlink_pmu, pdev);
  436. if (ret)
  437. return ret;
  438. ret = cpuhp_state_add_instance(starlink_pmu_cpuhp_state,
  439. &starlink_pmu->node);
  440. if (ret) {
  441. dev_err(&pdev->dev, "Failed to register hotplug\n");
  442. return ret;
  443. }
  444. ret = starlink_pmu_pm_register(starlink_pmu);
  445. if (ret) {
  446. cpuhp_state_remove_instance(starlink_pmu_cpuhp_state,
  447. &starlink_pmu->node);
  448. return ret;
  449. }
  450. starlink_pmu->pmu = (struct pmu) {
  451. .task_ctx_nr = perf_invalid_context,
  452. .event_init = starlink_pmu_event_init,
  453. .add = starlink_pmu_add,
  454. .del = starlink_pmu_del,
  455. .start = starlink_pmu_start,
  456. .stop = starlink_pmu_stop,
  457. .read = starlink_pmu_update,
  458. .attr_groups = starlink_pmu_attr_groups,
  459. };
  460. ret = perf_pmu_register(&starlink_pmu->pmu, STARLINK_PMU_PDEV_NAME, -1);
  461. if (ret)
  462. starlink_pmu_destroy(starlink_pmu);
  463. return ret;
  464. }
  465. static const struct of_device_id starlink_pmu_of_match[] = {
  466. { .compatible = "starfive,jh8100-starlink-pmu" },
  467. {}
  468. };
  469. MODULE_DEVICE_TABLE(of, starlink_pmu_of_match);
  470. static struct platform_driver starlink_pmu_driver = {
  471. .driver = {
  472. .name = STARLINK_PMU_PDEV_NAME,
  473. .of_match_table = starlink_pmu_of_match,
  474. .suppress_bind_attrs = true,
  475. },
  476. .probe = starlink_pmu_probe,
  477. };
  478. static int
  479. starlink_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
  480. {
  481. struct starlink_pmu *starlink_pmu = hlist_entry_safe(node,
  482. struct starlink_pmu,
  483. node);
  484. if (cpumask_empty(&starlink_pmu->cpumask))
  485. cpumask_set_cpu(cpu, &starlink_pmu->cpumask);
  486. WARN_ON(irq_set_affinity(starlink_pmu->irq, cpumask_of(cpu)));
  487. return 0;
  488. }
  489. static int
  490. starlink_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
  491. {
  492. struct starlink_pmu *starlink_pmu = hlist_entry_safe(node,
  493. struct starlink_pmu,
  494. node);
  495. unsigned int target;
  496. if (!cpumask_test_and_clear_cpu(cpu, &starlink_pmu->cpumask))
  497. return 0;
  498. target = cpumask_any_but(cpu_online_mask, cpu);
  499. if (target >= nr_cpu_ids)
  500. return 0;
  501. perf_pmu_migrate_context(&starlink_pmu->pmu, cpu, target);
  502. cpumask_set_cpu(target, &starlink_pmu->cpumask);
  503. WARN_ON(irq_set_affinity(starlink_pmu->irq, cpumask_of(target)));
  504. return 0;
  505. }
  506. static int __init starlink_pmu_init(void)
  507. {
  508. int ret;
  509. ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
  510. "soc/starfive/starlink_pmu:online",
  511. starlink_pmu_online_cpu,
  512. starlink_pmu_offline_cpu);
  513. if (ret < 0)
  514. return ret;
  515. starlink_pmu_cpuhp_state = ret;
  516. return platform_driver_register(&starlink_pmu_driver);
  517. }
  518. device_initcall(starlink_pmu_init);