1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2012, The Linux Foundation. All rights reserved. |
4 | */ |
5 | |
6 | #include <linux/build_bug.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/init.h> |
9 | #include <linux/types.h> |
10 | #include <linux/device.h> |
11 | #include <linux/io.h> |
12 | #include <linux/err.h> |
13 | #include <linux/export.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/stringhash.h> |
16 | #include <linux/mutex.h> |
17 | #include <linux/clk.h> |
18 | #include <linux/coresight.h> |
19 | #include <linux/property.h> |
20 | #include <linux/delay.h> |
21 | #include <linux/pm_runtime.h> |
22 | |
23 | #include "coresight-etm-perf.h" |
24 | #include "coresight-priv.h" |
25 | #include "coresight-syscfg.h" |
26 | |
27 | /* |
28 | * Mutex used to lock all sysfs enable and disable actions and loading and |
29 | * unloading devices by the Coresight core. |
30 | */ |
31 | DEFINE_MUTEX(coresight_mutex); |
32 | static DEFINE_PER_CPU(struct coresight_device *, csdev_sink); |
33 | |
34 | /** |
35 | * struct coresight_node - elements of a path, from source to sink |
36 | * @csdev: Address of an element. |
37 | * @link: hook to the list. |
38 | */ |
39 | struct coresight_node { |
40 | struct coresight_device *csdev; |
41 | struct list_head link; |
42 | }; |
43 | |
44 | /* |
45 | * When losing synchronisation a new barrier packet needs to be inserted at the |
46 | * beginning of the data collected in a buffer. That way the decoder knows that |
47 | * it needs to look for another sync sequence. |
48 | */ |
49 | const u32 coresight_barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; |
50 | EXPORT_SYMBOL_GPL(coresight_barrier_pkt); |
51 | |
52 | static const struct cti_assoc_op *cti_assoc_ops; |
53 | |
54 | void coresight_set_cti_ops(const struct cti_assoc_op *cti_op) |
55 | { |
56 | cti_assoc_ops = cti_op; |
57 | } |
58 | EXPORT_SYMBOL_GPL(coresight_set_cti_ops); |
59 | |
60 | void coresight_remove_cti_ops(void) |
61 | { |
62 | cti_assoc_ops = NULL; |
63 | } |
64 | EXPORT_SYMBOL_GPL(coresight_remove_cti_ops); |
65 | |
66 | void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev) |
67 | { |
68 | per_cpu(csdev_sink, cpu) = csdev; |
69 | } |
70 | EXPORT_SYMBOL_GPL(coresight_set_percpu_sink); |
71 | |
72 | struct coresight_device *coresight_get_percpu_sink(int cpu) |
73 | { |
74 | return per_cpu(csdev_sink, cpu); |
75 | } |
76 | EXPORT_SYMBOL_GPL(coresight_get_percpu_sink); |
77 | |
78 | static struct coresight_connection * |
79 | coresight_find_out_connection(struct coresight_device *src_dev, |
80 | struct coresight_device *dest_dev) |
81 | { |
82 | int i; |
83 | struct coresight_connection *conn; |
84 | |
85 | for (i = 0; i < src_dev->pdata->nr_outconns; i++) { |
86 | conn = src_dev->pdata->out_conns[i]; |
87 | if (conn->dest_dev == dest_dev) |
88 | return conn; |
89 | } |
90 | |
91 | dev_err(&src_dev->dev, |
92 | "couldn't find output connection, src_dev: %s, dest_dev: %s\n" , |
93 | dev_name(&src_dev->dev), dev_name(&dest_dev->dev)); |
94 | |
95 | return ERR_PTR(error: -ENODEV); |
96 | } |
97 | |
98 | static inline u32 coresight_read_claim_tags(struct coresight_device *csdev) |
99 | { |
100 | return csdev_access_relaxed_read32(csa: &csdev->access, CORESIGHT_CLAIMCLR); |
101 | } |
102 | |
103 | static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev) |
104 | { |
105 | return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED; |
106 | } |
107 | |
108 | static inline bool coresight_is_claimed_any(struct coresight_device *csdev) |
109 | { |
110 | return coresight_read_claim_tags(csdev) != 0; |
111 | } |
112 | |
113 | static inline void coresight_set_claim_tags(struct coresight_device *csdev) |
114 | { |
115 | csdev_access_relaxed_write32(csa: &csdev->access, CORESIGHT_CLAIM_SELF_HOSTED, |
116 | CORESIGHT_CLAIMSET); |
117 | isb(); |
118 | } |
119 | |
120 | static inline void coresight_clear_claim_tags(struct coresight_device *csdev) |
121 | { |
122 | csdev_access_relaxed_write32(csa: &csdev->access, CORESIGHT_CLAIM_SELF_HOSTED, |
123 | CORESIGHT_CLAIMCLR); |
124 | isb(); |
125 | } |
126 | |
127 | /* |
128 | * coresight_claim_device_unlocked : Claim the device for self-hosted usage |
129 | * to prevent an external tool from touching this device. As per PSCI |
130 | * standards, section "Preserving the execution context" => "Debug and Trace |
131 | * save and Restore", DBGCLAIM[1] is reserved for Self-hosted debug/trace and |
132 | * DBGCLAIM[0] is reserved for external tools. |
133 | * |
134 | * Called with CS_UNLOCKed for the component. |
135 | * Returns : 0 on success |
136 | */ |
137 | int coresight_claim_device_unlocked(struct coresight_device *csdev) |
138 | { |
139 | if (WARN_ON(!csdev)) |
140 | return -EINVAL; |
141 | |
142 | if (coresight_is_claimed_any(csdev)) |
143 | return -EBUSY; |
144 | |
145 | coresight_set_claim_tags(csdev); |
146 | if (coresight_is_claimed_self_hosted(csdev)) |
147 | return 0; |
148 | /* There was a race setting the tags, clean up and fail */ |
149 | coresight_clear_claim_tags(csdev); |
150 | return -EBUSY; |
151 | } |
152 | EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked); |
153 | |
154 | int coresight_claim_device(struct coresight_device *csdev) |
155 | { |
156 | int rc; |
157 | |
158 | if (WARN_ON(!csdev)) |
159 | return -EINVAL; |
160 | |
161 | CS_UNLOCK(addr: csdev->access.base); |
162 | rc = coresight_claim_device_unlocked(csdev); |
163 | CS_LOCK(addr: csdev->access.base); |
164 | |
165 | return rc; |
166 | } |
167 | EXPORT_SYMBOL_GPL(coresight_claim_device); |
168 | |
169 | /* |
170 | * coresight_disclaim_device_unlocked : Clear the claim tags for the device. |
171 | * Called with CS_UNLOCKed for the component. |
172 | */ |
173 | void coresight_disclaim_device_unlocked(struct coresight_device *csdev) |
174 | { |
175 | |
176 | if (WARN_ON(!csdev)) |
177 | return; |
178 | |
179 | if (coresight_is_claimed_self_hosted(csdev)) |
180 | coresight_clear_claim_tags(csdev); |
181 | else |
182 | /* |
183 | * The external agent may have not honoured our claim |
184 | * and has manipulated it. Or something else has seriously |
185 | * gone wrong in our driver. |
186 | */ |
187 | WARN_ON_ONCE(1); |
188 | } |
189 | EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked); |
190 | |
191 | void coresight_disclaim_device(struct coresight_device *csdev) |
192 | { |
193 | if (WARN_ON(!csdev)) |
194 | return; |
195 | |
196 | CS_UNLOCK(addr: csdev->access.base); |
197 | coresight_disclaim_device_unlocked(csdev); |
198 | CS_LOCK(addr: csdev->access.base); |
199 | } |
200 | EXPORT_SYMBOL_GPL(coresight_disclaim_device); |
201 | |
202 | /* |
203 | * Add a helper as an output device. This function takes the @coresight_mutex |
204 | * because it's assumed that it's called from the helper device, outside of the |
205 | * core code where the mutex would already be held. Don't add new calls to this |
206 | * from inside the core code, instead try to add the new helper to the DT and |
207 | * ACPI where it will be picked up and linked automatically. |
208 | */ |
209 | void coresight_add_helper(struct coresight_device *csdev, |
210 | struct coresight_device *helper) |
211 | { |
212 | int i; |
213 | struct coresight_connection conn = {}; |
214 | struct coresight_connection *new_conn; |
215 | |
216 | mutex_lock(&coresight_mutex); |
217 | conn.dest_fwnode = fwnode_handle_get(dev_fwnode(&helper->dev)); |
218 | conn.dest_dev = helper; |
219 | conn.dest_port = conn.src_port = -1; |
220 | conn.src_dev = csdev; |
221 | |
222 | /* |
223 | * Check for duplicates because this is called every time a helper |
224 | * device is re-loaded. Existing connections will get re-linked |
225 | * automatically. |
226 | */ |
227 | for (i = 0; i < csdev->pdata->nr_outconns; ++i) |
228 | if (csdev->pdata->out_conns[i]->dest_fwnode == conn.dest_fwnode) |
229 | goto unlock; |
230 | |
231 | new_conn = coresight_add_out_conn(dev: csdev->dev.parent, pdata: csdev->pdata, |
232 | new_conn: &conn); |
233 | if (!IS_ERR(ptr: new_conn)) |
234 | coresight_add_in_conn(conn: new_conn); |
235 | |
236 | unlock: |
237 | mutex_unlock(lock: &coresight_mutex); |
238 | } |
239 | EXPORT_SYMBOL_GPL(coresight_add_helper); |
240 | |
241 | static int coresight_enable_sink(struct coresight_device *csdev, |
242 | enum cs_mode mode, void *data) |
243 | { |
244 | return sink_ops(csdev)->enable(csdev, mode, data); |
245 | } |
246 | |
247 | static void coresight_disable_sink(struct coresight_device *csdev) |
248 | { |
249 | sink_ops(csdev)->disable(csdev); |
250 | } |
251 | |
252 | static int coresight_enable_link(struct coresight_device *csdev, |
253 | struct coresight_device *parent, |
254 | struct coresight_device *child) |
255 | { |
256 | int link_subtype; |
257 | struct coresight_connection *inconn, *outconn; |
258 | |
259 | if (!parent || !child) |
260 | return -EINVAL; |
261 | |
262 | inconn = coresight_find_out_connection(src_dev: parent, dest_dev: csdev); |
263 | outconn = coresight_find_out_connection(src_dev: csdev, dest_dev: child); |
264 | link_subtype = csdev->subtype.link_subtype; |
265 | |
266 | if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR(ptr: inconn)) |
267 | return PTR_ERR(ptr: inconn); |
268 | if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(ptr: outconn)) |
269 | return PTR_ERR(ptr: outconn); |
270 | |
271 | return link_ops(csdev)->enable(csdev, inconn, outconn); |
272 | } |
273 | |
274 | static void coresight_disable_link(struct coresight_device *csdev, |
275 | struct coresight_device *parent, |
276 | struct coresight_device *child) |
277 | { |
278 | struct coresight_connection *inconn, *outconn; |
279 | |
280 | if (!parent || !child) |
281 | return; |
282 | |
283 | inconn = coresight_find_out_connection(src_dev: parent, dest_dev: csdev); |
284 | outconn = coresight_find_out_connection(src_dev: csdev, dest_dev: child); |
285 | |
286 | link_ops(csdev)->disable(csdev, inconn, outconn); |
287 | } |
288 | |
289 | static bool coresight_is_helper(struct coresight_device *csdev) |
290 | { |
291 | return csdev->type == CORESIGHT_DEV_TYPE_HELPER; |
292 | } |
293 | |
294 | static int coresight_enable_helper(struct coresight_device *csdev, |
295 | enum cs_mode mode, void *data) |
296 | { |
297 | return helper_ops(csdev)->enable(csdev, mode, data); |
298 | } |
299 | |
300 | static void coresight_disable_helper(struct coresight_device *csdev) |
301 | { |
302 | helper_ops(csdev)->disable(csdev, NULL); |
303 | } |
304 | |
305 | static void coresight_disable_helpers(struct coresight_device *csdev) |
306 | { |
307 | int i; |
308 | struct coresight_device *helper; |
309 | |
310 | for (i = 0; i < csdev->pdata->nr_outconns; ++i) { |
311 | helper = csdev->pdata->out_conns[i]->dest_dev; |
312 | if (helper && coresight_is_helper(csdev: helper)) |
313 | coresight_disable_helper(csdev: helper); |
314 | } |
315 | } |
316 | |
317 | /* |
318 | * Helper function to call source_ops(csdev)->disable and also disable the |
319 | * helpers. |
320 | * |
321 | * There is an imbalance between coresight_enable_path() and |
322 | * coresight_disable_path(). Enabling also enables the source's helpers as part |
323 | * of the path, but disabling always skips the first item in the path (which is |
324 | * the source), so sources and their helpers don't get disabled as part of that |
325 | * function and we need the extra step here. |
326 | */ |
327 | void coresight_disable_source(struct coresight_device *csdev, void *data) |
328 | { |
329 | source_ops(csdev)->disable(csdev, data); |
330 | coresight_disable_helpers(csdev); |
331 | } |
332 | EXPORT_SYMBOL_GPL(coresight_disable_source); |
333 | |
334 | /* |
335 | * coresight_disable_path_from : Disable components in the given path beyond |
336 | * @nd in the list. If @nd is NULL, all the components, except the SOURCE are |
337 | * disabled. |
338 | */ |
339 | static void coresight_disable_path_from(struct list_head *path, |
340 | struct coresight_node *nd) |
341 | { |
342 | u32 type; |
343 | struct coresight_device *csdev, *parent, *child; |
344 | |
345 | if (!nd) |
346 | nd = list_first_entry(path, struct coresight_node, link); |
347 | |
348 | list_for_each_entry_continue(nd, path, link) { |
349 | csdev = nd->csdev; |
350 | type = csdev->type; |
351 | |
352 | /* |
353 | * ETF devices are tricky... They can be a link or a sink, |
354 | * depending on how they are configured. If an ETF has been |
355 | * selected as a sink it will be configured as a sink, otherwise |
356 | * go ahead with the link configuration. |
357 | */ |
358 | if (type == CORESIGHT_DEV_TYPE_LINKSINK) |
359 | type = (csdev == coresight_get_sink(path)) ? |
360 | CORESIGHT_DEV_TYPE_SINK : |
361 | CORESIGHT_DEV_TYPE_LINK; |
362 | |
363 | switch (type) { |
364 | case CORESIGHT_DEV_TYPE_SINK: |
365 | coresight_disable_sink(csdev); |
366 | break; |
367 | case CORESIGHT_DEV_TYPE_SOURCE: |
368 | /* |
369 | * We skip the first node in the path assuming that it |
370 | * is the source. So we don't expect a source device in |
371 | * the middle of a path. |
372 | */ |
373 | WARN_ON(1); |
374 | break; |
375 | case CORESIGHT_DEV_TYPE_LINK: |
376 | parent = list_prev_entry(nd, link)->csdev; |
377 | child = list_next_entry(nd, link)->csdev; |
378 | coresight_disable_link(csdev, parent, child); |
379 | break; |
380 | default: |
381 | break; |
382 | } |
383 | |
384 | /* Disable all helpers adjacent along the path last */ |
385 | coresight_disable_helpers(csdev); |
386 | } |
387 | } |
388 | |
389 | void coresight_disable_path(struct list_head *path) |
390 | { |
391 | coresight_disable_path_from(path, NULL); |
392 | } |
393 | EXPORT_SYMBOL_GPL(coresight_disable_path); |
394 | |
395 | static int coresight_enable_helpers(struct coresight_device *csdev, |
396 | enum cs_mode mode, void *data) |
397 | { |
398 | int i, ret = 0; |
399 | struct coresight_device *helper; |
400 | |
401 | for (i = 0; i < csdev->pdata->nr_outconns; ++i) { |
402 | helper = csdev->pdata->out_conns[i]->dest_dev; |
403 | if (!helper || !coresight_is_helper(csdev: helper)) |
404 | continue; |
405 | |
406 | ret = coresight_enable_helper(csdev: helper, mode, data); |
407 | if (ret) |
408 | return ret; |
409 | } |
410 | |
411 | return 0; |
412 | } |
413 | |
414 | int coresight_enable_path(struct list_head *path, enum cs_mode mode, |
415 | void *sink_data) |
416 | { |
417 | int ret = 0; |
418 | u32 type; |
419 | struct coresight_node *nd; |
420 | struct coresight_device *csdev, *parent, *child; |
421 | |
422 | list_for_each_entry_reverse(nd, path, link) { |
423 | csdev = nd->csdev; |
424 | type = csdev->type; |
425 | |
426 | /* Enable all helpers adjacent to the path first */ |
427 | ret = coresight_enable_helpers(csdev, mode, data: sink_data); |
428 | if (ret) |
429 | goto err; |
430 | /* |
431 | * ETF devices are tricky... They can be a link or a sink, |
432 | * depending on how they are configured. If an ETF has been |
433 | * selected as a sink it will be configured as a sink, otherwise |
434 | * go ahead with the link configuration. |
435 | */ |
436 | if (type == CORESIGHT_DEV_TYPE_LINKSINK) |
437 | type = (csdev == coresight_get_sink(path)) ? |
438 | CORESIGHT_DEV_TYPE_SINK : |
439 | CORESIGHT_DEV_TYPE_LINK; |
440 | |
441 | switch (type) { |
442 | case CORESIGHT_DEV_TYPE_SINK: |
443 | ret = coresight_enable_sink(csdev, mode, data: sink_data); |
444 | /* |
445 | * Sink is the first component turned on. If we |
446 | * failed to enable the sink, there are no components |
447 | * that need disabling. Disabling the path here |
448 | * would mean we could disrupt an existing session. |
449 | */ |
450 | if (ret) |
451 | goto out; |
452 | break; |
453 | case CORESIGHT_DEV_TYPE_SOURCE: |
454 | /* sources are enabled from either sysFS or Perf */ |
455 | break; |
456 | case CORESIGHT_DEV_TYPE_LINK: |
457 | parent = list_prev_entry(nd, link)->csdev; |
458 | child = list_next_entry(nd, link)->csdev; |
459 | ret = coresight_enable_link(csdev, parent, child); |
460 | if (ret) |
461 | goto err; |
462 | break; |
463 | default: |
464 | goto err; |
465 | } |
466 | } |
467 | |
468 | out: |
469 | return ret; |
470 | err: |
471 | coresight_disable_path_from(path, nd); |
472 | goto out; |
473 | } |
474 | |
475 | struct coresight_device *coresight_get_sink(struct list_head *path) |
476 | { |
477 | struct coresight_device *csdev; |
478 | |
479 | if (!path) |
480 | return NULL; |
481 | |
482 | csdev = list_last_entry(path, struct coresight_node, link)->csdev; |
483 | if (csdev->type != CORESIGHT_DEV_TYPE_SINK && |
484 | csdev->type != CORESIGHT_DEV_TYPE_LINKSINK) |
485 | return NULL; |
486 | |
487 | return csdev; |
488 | } |
489 | |
490 | static int coresight_sink_by_id(struct device *dev, const void *data) |
491 | { |
492 | struct coresight_device *csdev = to_coresight_device(dev); |
493 | unsigned long hash; |
494 | |
495 | if (csdev->type == CORESIGHT_DEV_TYPE_SINK || |
496 | csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { |
497 | |
498 | if (!csdev->ea) |
499 | return 0; |
500 | /* |
501 | * See function etm_perf_add_symlink_sink() to know where |
502 | * this comes from. |
503 | */ |
504 | hash = (unsigned long)csdev->ea->var; |
505 | |
506 | if ((u32)hash == *(u32 *)data) |
507 | return 1; |
508 | } |
509 | |
510 | return 0; |
511 | } |
512 | |
513 | /** |
514 | * coresight_get_sink_by_id - returns the sink that matches the id |
515 | * @id: Id of the sink to match |
516 | * |
517 | * The name of a sink is unique, whether it is found on the AMBA bus or |
518 | * otherwise. As such the hash of that name can easily be used to identify |
519 | * a sink. |
520 | */ |
521 | struct coresight_device *coresight_get_sink_by_id(u32 id) |
522 | { |
523 | struct device *dev = NULL; |
524 | |
525 | dev = bus_find_device(bus: &coresight_bustype, NULL, data: &id, |
526 | match: coresight_sink_by_id); |
527 | |
528 | return dev ? to_coresight_device(dev) : NULL; |
529 | } |
530 | |
531 | /** |
532 | * coresight_get_ref- Helper function to increase reference count to module |
533 | * and device. |
534 | * |
535 | * @csdev: The coresight device to get a reference on. |
536 | * |
537 | * Return true in successful case and power up the device. |
538 | * Return false when failed to get reference of module. |
539 | */ |
540 | static inline bool coresight_get_ref(struct coresight_device *csdev) |
541 | { |
542 | struct device *dev = csdev->dev.parent; |
543 | |
544 | /* Make sure the driver can't be removed */ |
545 | if (!try_module_get(module: dev->driver->owner)) |
546 | return false; |
547 | /* Make sure the device can't go away */ |
548 | get_device(dev); |
549 | pm_runtime_get_sync(dev); |
550 | return true; |
551 | } |
552 | |
553 | /** |
554 | * coresight_put_ref- Helper function to decrease reference count to module |
555 | * and device. Power off the device. |
556 | * |
557 | * @csdev: The coresight device to decrement a reference from. |
558 | */ |
559 | static inline void coresight_put_ref(struct coresight_device *csdev) |
560 | { |
561 | struct device *dev = csdev->dev.parent; |
562 | |
563 | pm_runtime_put(dev); |
564 | put_device(dev); |
565 | module_put(module: dev->driver->owner); |
566 | } |
567 | |
568 | /* |
569 | * coresight_grab_device - Power up this device and any of the helper |
570 | * devices connected to it for trace operation. Since the helper devices |
571 | * don't appear on the trace path, they should be handled along with the |
572 | * master device. |
573 | */ |
574 | static int coresight_grab_device(struct coresight_device *csdev) |
575 | { |
576 | int i; |
577 | |
578 | for (i = 0; i < csdev->pdata->nr_outconns; i++) { |
579 | struct coresight_device *child; |
580 | |
581 | child = csdev->pdata->out_conns[i]->dest_dev; |
582 | if (child && coresight_is_helper(csdev: child)) |
583 | if (!coresight_get_ref(csdev: child)) |
584 | goto err; |
585 | } |
586 | if (coresight_get_ref(csdev)) |
587 | return 0; |
588 | err: |
589 | for (i--; i >= 0; i--) { |
590 | struct coresight_device *child; |
591 | |
592 | child = csdev->pdata->out_conns[i]->dest_dev; |
593 | if (child && coresight_is_helper(csdev: child)) |
594 | coresight_put_ref(csdev: child); |
595 | } |
596 | return -ENODEV; |
597 | } |
598 | |
599 | /* |
600 | * coresight_drop_device - Release this device and any of the helper |
601 | * devices connected to it. |
602 | */ |
603 | static void coresight_drop_device(struct coresight_device *csdev) |
604 | { |
605 | int i; |
606 | |
607 | coresight_put_ref(csdev); |
608 | for (i = 0; i < csdev->pdata->nr_outconns; i++) { |
609 | struct coresight_device *child; |
610 | |
611 | child = csdev->pdata->out_conns[i]->dest_dev; |
612 | if (child && coresight_is_helper(csdev: child)) |
613 | coresight_put_ref(csdev: child); |
614 | } |
615 | } |
616 | |
617 | /** |
618 | * _coresight_build_path - recursively build a path from a @csdev to a sink. |
619 | * @csdev: The device to start from. |
620 | * @sink: The final sink we want in this path. |
621 | * @path: The list to add devices to. |
622 | * |
623 | * The tree of Coresight device is traversed until @sink is found. |
624 | * From there the sink is added to the list along with all the devices that led |
625 | * to that point - the end result is a list from source to sink. In that list |
626 | * the source is the first device and the sink the last one. |
627 | */ |
628 | static int _coresight_build_path(struct coresight_device *csdev, |
629 | struct coresight_device *sink, |
630 | struct list_head *path) |
631 | { |
632 | int i, ret; |
633 | bool found = false; |
634 | struct coresight_node *node; |
635 | |
636 | /* The sink has been found. Enqueue the element */ |
637 | if (csdev == sink) |
638 | goto out; |
639 | |
640 | if (coresight_is_percpu_source(csdev) && coresight_is_percpu_sink(csdev: sink) && |
641 | sink == per_cpu(csdev_sink, source_ops(csdev)->cpu_id(csdev))) { |
642 | if (_coresight_build_path(csdev: sink, sink, path) == 0) { |
643 | found = true; |
644 | goto out; |
645 | } |
646 | } |
647 | |
648 | /* Not a sink - recursively explore each port found on this element */ |
649 | for (i = 0; i < csdev->pdata->nr_outconns; i++) { |
650 | struct coresight_device *child_dev; |
651 | |
652 | child_dev = csdev->pdata->out_conns[i]->dest_dev; |
653 | if (child_dev && |
654 | _coresight_build_path(csdev: child_dev, sink, path) == 0) { |
655 | found = true; |
656 | break; |
657 | } |
658 | } |
659 | |
660 | if (!found) |
661 | return -ENODEV; |
662 | |
663 | out: |
664 | /* |
665 | * A path from this element to a sink has been found. The elements |
666 | * leading to the sink are already enqueued, all that is left to do |
667 | * is tell the PM runtime core we need this element and add a node |
668 | * for it. |
669 | */ |
670 | ret = coresight_grab_device(csdev); |
671 | if (ret) |
672 | return ret; |
673 | |
674 | node = kzalloc(size: sizeof(struct coresight_node), GFP_KERNEL); |
675 | if (!node) |
676 | return -ENOMEM; |
677 | |
678 | node->csdev = csdev; |
679 | list_add(new: &node->link, head: path); |
680 | |
681 | return 0; |
682 | } |
683 | |
684 | struct list_head *coresight_build_path(struct coresight_device *source, |
685 | struct coresight_device *sink) |
686 | { |
687 | struct list_head *path; |
688 | int rc; |
689 | |
690 | if (!sink) |
691 | return ERR_PTR(error: -EINVAL); |
692 | |
693 | path = kzalloc(size: sizeof(struct list_head), GFP_KERNEL); |
694 | if (!path) |
695 | return ERR_PTR(error: -ENOMEM); |
696 | |
697 | INIT_LIST_HEAD(list: path); |
698 | |
699 | rc = _coresight_build_path(csdev: source, sink, path); |
700 | if (rc) { |
701 | kfree(objp: path); |
702 | return ERR_PTR(error: rc); |
703 | } |
704 | |
705 | return path; |
706 | } |
707 | |
708 | /** |
709 | * coresight_release_path - release a previously built path. |
710 | * @path: the path to release. |
711 | * |
712 | * Go through all the elements of a path and 1) removed it from the list and |
713 | * 2) free the memory allocated for each node. |
714 | */ |
715 | void coresight_release_path(struct list_head *path) |
716 | { |
717 | struct coresight_device *csdev; |
718 | struct coresight_node *nd, *next; |
719 | |
720 | list_for_each_entry_safe(nd, next, path, link) { |
721 | csdev = nd->csdev; |
722 | |
723 | coresight_drop_device(csdev); |
724 | list_del(entry: &nd->link); |
725 | kfree(objp: nd); |
726 | } |
727 | |
728 | kfree(objp: path); |
729 | } |
730 | |
731 | /* return true if the device is a suitable type for a default sink */ |
732 | static inline bool coresight_is_def_sink_type(struct coresight_device *csdev) |
733 | { |
734 | /* sink & correct subtype */ |
735 | if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) || |
736 | (csdev->type == CORESIGHT_DEV_TYPE_LINKSINK)) && |
737 | (csdev->subtype.sink_subtype >= CORESIGHT_DEV_SUBTYPE_SINK_BUFFER)) |
738 | return true; |
739 | return false; |
740 | } |
741 | |
742 | /** |
743 | * coresight_select_best_sink - return the best sink for use as default from |
744 | * the two provided. |
745 | * |
746 | * @sink: current best sink. |
747 | * @depth: search depth where current sink was found. |
748 | * @new_sink: new sink for comparison with current sink. |
749 | * @new_depth: search depth where new sink was found. |
750 | * |
751 | * Sinks prioritised according to coresight_dev_subtype_sink, with only |
752 | * subtypes CORESIGHT_DEV_SUBTYPE_SINK_BUFFER or higher being used. |
753 | * |
754 | * Where two sinks of equal priority are found, the sink closest to the |
755 | * source is used (smallest search depth). |
756 | * |
757 | * return @new_sink & update @depth if better than @sink, else return @sink. |
758 | */ |
759 | static struct coresight_device * |
760 | coresight_select_best_sink(struct coresight_device *sink, int *depth, |
761 | struct coresight_device *new_sink, int new_depth) |
762 | { |
763 | bool update = false; |
764 | |
765 | if (!sink) { |
766 | /* first found at this level */ |
767 | update = true; |
768 | } else if (new_sink->subtype.sink_subtype > |
769 | sink->subtype.sink_subtype) { |
770 | /* found better sink */ |
771 | update = true; |
772 | } else if ((new_sink->subtype.sink_subtype == |
773 | sink->subtype.sink_subtype) && |
774 | (*depth > new_depth)) { |
775 | /* found same but closer sink */ |
776 | update = true; |
777 | } |
778 | |
779 | if (update) |
780 | *depth = new_depth; |
781 | return update ? new_sink : sink; |
782 | } |
783 | |
784 | /** |
785 | * coresight_find_sink - recursive function to walk trace connections from |
786 | * source to find a suitable default sink. |
787 | * |
788 | * @csdev: source / current device to check. |
789 | * @depth: [in] search depth of calling dev, [out] depth of found sink. |
790 | * |
791 | * This will walk the connection path from a source (ETM) till a suitable |
792 | * sink is encountered and return that sink to the original caller. |
793 | * |
794 | * If current device is a plain sink return that & depth, otherwise recursively |
795 | * call child connections looking for a sink. Select best possible using |
796 | * coresight_select_best_sink. |
797 | * |
798 | * return best sink found, or NULL if not found at this node or child nodes. |
799 | */ |
800 | static struct coresight_device * |
801 | coresight_find_sink(struct coresight_device *csdev, int *depth) |
802 | { |
803 | int i, curr_depth = *depth + 1, found_depth = 0; |
804 | struct coresight_device *found_sink = NULL; |
805 | |
806 | if (coresight_is_def_sink_type(csdev)) { |
807 | found_depth = curr_depth; |
808 | found_sink = csdev; |
809 | if (csdev->type == CORESIGHT_DEV_TYPE_SINK) |
810 | goto return_def_sink; |
811 | /* look past LINKSINK for something better */ |
812 | } |
813 | |
814 | /* |
815 | * Not a sink we want - or possible child sink may be better. |
816 | * recursively explore each port found on this element. |
817 | */ |
818 | for (i = 0; i < csdev->pdata->nr_outconns; i++) { |
819 | struct coresight_device *child_dev, *sink = NULL; |
820 | int child_depth = curr_depth; |
821 | |
822 | child_dev = csdev->pdata->out_conns[i]->dest_dev; |
823 | if (child_dev) |
824 | sink = coresight_find_sink(csdev: child_dev, depth: &child_depth); |
825 | |
826 | if (sink) |
827 | found_sink = coresight_select_best_sink(sink: found_sink, |
828 | depth: &found_depth, |
829 | new_sink: sink, |
830 | new_depth: child_depth); |
831 | } |
832 | |
833 | return_def_sink: |
834 | /* return found sink and depth */ |
835 | if (found_sink) |
836 | *depth = found_depth; |
837 | return found_sink; |
838 | } |
839 | |
840 | /** |
841 | * coresight_find_default_sink: Find a sink suitable for use as a |
842 | * default sink. |
843 | * |
844 | * @csdev: starting source to find a connected sink. |
845 | * |
846 | * Walks connections graph looking for a suitable sink to enable for the |
847 | * supplied source. Uses CoreSight device subtypes and distance from source |
848 | * to select the best sink. |
849 | * |
850 | * If a sink is found, then the default sink for this device is set and |
851 | * will be automatically used in future. |
852 | * |
853 | * Used in cases where the CoreSight user (perf / sysfs) has not selected a |
854 | * sink. |
855 | */ |
856 | struct coresight_device * |
857 | coresight_find_default_sink(struct coresight_device *csdev) |
858 | { |
859 | int depth = 0; |
860 | |
861 | /* look for a default sink if we have not found for this device */ |
862 | if (!csdev->def_sink) { |
863 | if (coresight_is_percpu_source(csdev)) |
864 | csdev->def_sink = per_cpu(csdev_sink, source_ops(csdev)->cpu_id(csdev)); |
865 | if (!csdev->def_sink) |
866 | csdev->def_sink = coresight_find_sink(csdev, depth: &depth); |
867 | } |
868 | return csdev->def_sink; |
869 | } |
870 | |
871 | static int coresight_remove_sink_ref(struct device *dev, void *data) |
872 | { |
873 | struct coresight_device *sink = data; |
874 | struct coresight_device *source = to_coresight_device(dev); |
875 | |
876 | if (source->def_sink == sink) |
877 | source->def_sink = NULL; |
878 | return 0; |
879 | } |
880 | |
881 | /** |
882 | * coresight_clear_default_sink: Remove all default sink references to the |
883 | * supplied sink. |
884 | * |
885 | * If supplied device is a sink, then check all the bus devices and clear |
886 | * out all the references to this sink from the coresight_device def_sink |
887 | * parameter. |
888 | * |
889 | * @csdev: coresight sink - remove references to this from all sources. |
890 | */ |
891 | static void coresight_clear_default_sink(struct coresight_device *csdev) |
892 | { |
893 | if ((csdev->type == CORESIGHT_DEV_TYPE_SINK) || |
894 | (csdev->type == CORESIGHT_DEV_TYPE_LINKSINK)) { |
895 | bus_for_each_dev(bus: &coresight_bustype, NULL, data: csdev, |
896 | fn: coresight_remove_sink_ref); |
897 | } |
898 | } |
899 | |
900 | static void coresight_device_release(struct device *dev) |
901 | { |
902 | struct coresight_device *csdev = to_coresight_device(dev); |
903 | |
904 | fwnode_handle_put(fwnode: csdev->dev.fwnode); |
905 | kfree(objp: csdev); |
906 | } |
907 | |
908 | static int coresight_orphan_match(struct device *dev, void *data) |
909 | { |
910 | int i, ret = 0; |
911 | bool still_orphan = false; |
912 | struct coresight_device *dst_csdev = data; |
913 | struct coresight_device *src_csdev = to_coresight_device(dev); |
914 | struct coresight_connection *conn; |
915 | bool fixup_self = (src_csdev == dst_csdev); |
916 | |
917 | /* Move on to another component if no connection is orphan */ |
918 | if (!src_csdev->orphan) |
919 | return 0; |
920 | /* |
921 | * Circle through all the connections of that component. If we find |
922 | * an orphan connection whose name matches @dst_csdev, link it. |
923 | */ |
924 | for (i = 0; i < src_csdev->pdata->nr_outconns; i++) { |
925 | conn = src_csdev->pdata->out_conns[i]; |
926 | |
927 | /* Skip the port if it's already connected. */ |
928 | if (conn->dest_dev) |
929 | continue; |
930 | |
931 | /* |
932 | * If we are at the "new" device, which triggered this search, |
933 | * we must find the remote device from the fwnode in the |
934 | * connection. |
935 | */ |
936 | if (fixup_self) |
937 | dst_csdev = coresight_find_csdev_by_fwnode( |
938 | r_fwnode: conn->dest_fwnode); |
939 | |
940 | /* Does it match this newly added device? */ |
941 | if (dst_csdev && conn->dest_fwnode == dst_csdev->dev.fwnode) { |
942 | ret = coresight_make_links(orig: src_csdev, conn, target: dst_csdev); |
943 | if (ret) |
944 | return ret; |
945 | |
946 | /* |
947 | * Install the device connection. This also indicates that |
948 | * the links are operational on both ends. |
949 | */ |
950 | conn->dest_dev = dst_csdev; |
951 | conn->src_dev = src_csdev; |
952 | |
953 | ret = coresight_add_in_conn(conn); |
954 | if (ret) |
955 | return ret; |
956 | } else { |
957 | /* This component still has an orphan */ |
958 | still_orphan = true; |
959 | } |
960 | } |
961 | |
962 | src_csdev->orphan = still_orphan; |
963 | |
964 | /* |
965 | * Returning '0' in case we didn't encounter any error, |
966 | * ensures that all known component on the bus will be checked. |
967 | */ |
968 | return 0; |
969 | } |
970 | |
971 | static int coresight_fixup_orphan_conns(struct coresight_device *csdev) |
972 | { |
973 | return bus_for_each_dev(bus: &coresight_bustype, NULL, |
974 | data: csdev, fn: coresight_orphan_match); |
975 | } |
976 | |
977 | /* coresight_remove_conns - Remove other device's references to this device */ |
978 | static void coresight_remove_conns(struct coresight_device *csdev) |
979 | { |
980 | int i, j; |
981 | struct coresight_connection *conn; |
982 | |
983 | /* |
984 | * Remove the input connection references from the destination device |
985 | * for each output connection. |
986 | */ |
987 | for (i = 0; i < csdev->pdata->nr_outconns; i++) { |
988 | conn = csdev->pdata->out_conns[i]; |
989 | if (!conn->dest_dev) |
990 | continue; |
991 | |
992 | for (j = 0; j < conn->dest_dev->pdata->nr_inconns; ++j) |
993 | if (conn->dest_dev->pdata->in_conns[j] == conn) { |
994 | conn->dest_dev->pdata->in_conns[j] = NULL; |
995 | break; |
996 | } |
997 | } |
998 | |
999 | /* |
1000 | * For all input connections, remove references to this device. |
1001 | * Connection objects are shared so modifying this device's input |
1002 | * connections affects the other device's output connection. |
1003 | */ |
1004 | for (i = 0; i < csdev->pdata->nr_inconns; ++i) { |
1005 | conn = csdev->pdata->in_conns[i]; |
1006 | /* Input conns array is sparse */ |
1007 | if (!conn) |
1008 | continue; |
1009 | |
1010 | conn->src_dev->orphan = true; |
1011 | coresight_remove_links(orig: conn->src_dev, conn); |
1012 | conn->dest_dev = NULL; |
1013 | } |
1014 | } |
1015 | |
1016 | /** |
1017 | * coresight_timeout - loop until a bit has changed to a specific register |
1018 | * state. |
1019 | * @csa: coresight device access for the device |
1020 | * @offset: Offset of the register from the base of the device. |
1021 | * @position: the position of the bit of interest. |
1022 | * @value: the value the bit should have. |
1023 | * |
1024 | * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if |
1025 | * TIMEOUT_US has elapsed, which ever happens first. |
1026 | */ |
1027 | int coresight_timeout(struct csdev_access *csa, u32 offset, |
1028 | int position, int value) |
1029 | { |
1030 | int i; |
1031 | u32 val; |
1032 | |
1033 | for (i = TIMEOUT_US; i > 0; i--) { |
1034 | val = csdev_access_read32(csa, offset); |
1035 | /* waiting on the bit to go from 0 to 1 */ |
1036 | if (value) { |
1037 | if (val & BIT(position)) |
1038 | return 0; |
1039 | /* waiting on the bit to go from 1 to 0 */ |
1040 | } else { |
1041 | if (!(val & BIT(position))) |
1042 | return 0; |
1043 | } |
1044 | |
1045 | /* |
1046 | * Delay is arbitrary - the specification doesn't say how long |
1047 | * we are expected to wait. Extra check required to make sure |
1048 | * we don't wait needlessly on the last iteration. |
1049 | */ |
1050 | if (i - 1) |
1051 | udelay(1); |
1052 | } |
1053 | |
1054 | return -EAGAIN; |
1055 | } |
1056 | EXPORT_SYMBOL_GPL(coresight_timeout); |
1057 | |
1058 | u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset) |
1059 | { |
1060 | return csdev_access_relaxed_read32(csa: &csdev->access, offset); |
1061 | } |
1062 | |
1063 | u32 coresight_read32(struct coresight_device *csdev, u32 offset) |
1064 | { |
1065 | return csdev_access_read32(csa: &csdev->access, offset); |
1066 | } |
1067 | |
1068 | void coresight_relaxed_write32(struct coresight_device *csdev, |
1069 | u32 val, u32 offset) |
1070 | { |
1071 | csdev_access_relaxed_write32(csa: &csdev->access, val, offset); |
1072 | } |
1073 | |
1074 | void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset) |
1075 | { |
1076 | csdev_access_write32(csa: &csdev->access, val, offset); |
1077 | } |
1078 | |
1079 | u64 coresight_relaxed_read64(struct coresight_device *csdev, u32 offset) |
1080 | { |
1081 | return csdev_access_relaxed_read64(csa: &csdev->access, offset); |
1082 | } |
1083 | |
1084 | u64 coresight_read64(struct coresight_device *csdev, u32 offset) |
1085 | { |
1086 | return csdev_access_read64(csa: &csdev->access, offset); |
1087 | } |
1088 | |
1089 | void coresight_relaxed_write64(struct coresight_device *csdev, |
1090 | u64 val, u32 offset) |
1091 | { |
1092 | csdev_access_relaxed_write64(csa: &csdev->access, val, offset); |
1093 | } |
1094 | |
1095 | void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset) |
1096 | { |
1097 | csdev_access_write64(csa: &csdev->access, val, offset); |
1098 | } |
1099 | |
1100 | /* |
1101 | * coresight_release_platform_data: Release references to the devices connected |
1102 | * to the output port of this device. |
1103 | */ |
1104 | void coresight_release_platform_data(struct coresight_device *csdev, |
1105 | struct device *dev, |
1106 | struct coresight_platform_data *pdata) |
1107 | { |
1108 | int i; |
1109 | struct coresight_connection **conns = pdata->out_conns; |
1110 | |
1111 | for (i = 0; i < pdata->nr_outconns; i++) { |
1112 | /* If we have made the links, remove them now */ |
1113 | if (csdev && conns[i]->dest_dev) |
1114 | coresight_remove_links(orig: csdev, conn: conns[i]); |
1115 | /* |
1116 | * Drop the refcount and clear the handle as this device |
1117 | * is going away |
1118 | */ |
1119 | fwnode_handle_put(fwnode: conns[i]->dest_fwnode); |
1120 | conns[i]->dest_fwnode = NULL; |
1121 | devm_kfree(dev, p: conns[i]); |
1122 | } |
1123 | devm_kfree(dev, p: pdata->out_conns); |
1124 | devm_kfree(dev, p: pdata->in_conns); |
1125 | devm_kfree(dev, p: pdata); |
1126 | if (csdev) |
1127 | coresight_remove_conns_sysfs_group(csdev); |
1128 | } |
1129 | |
1130 | struct coresight_device *coresight_register(struct coresight_desc *desc) |
1131 | { |
1132 | int ret; |
1133 | struct coresight_device *csdev; |
1134 | bool registered = false; |
1135 | |
1136 | csdev = kzalloc(size: sizeof(*csdev), GFP_KERNEL); |
1137 | if (!csdev) { |
1138 | ret = -ENOMEM; |
1139 | goto err_out; |
1140 | } |
1141 | |
1142 | csdev->pdata = desc->pdata; |
1143 | |
1144 | csdev->type = desc->type; |
1145 | csdev->subtype = desc->subtype; |
1146 | csdev->ops = desc->ops; |
1147 | csdev->access = desc->access; |
1148 | csdev->orphan = true; |
1149 | |
1150 | csdev->dev.type = &coresight_dev_type[desc->type]; |
1151 | csdev->dev.groups = desc->groups; |
1152 | csdev->dev.parent = desc->dev; |
1153 | csdev->dev.release = coresight_device_release; |
1154 | csdev->dev.bus = &coresight_bustype; |
1155 | /* |
1156 | * Hold the reference to our parent device. This will be |
1157 | * dropped only in coresight_device_release(). |
1158 | */ |
1159 | csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev)); |
1160 | dev_set_name(dev: &csdev->dev, name: "%s" , desc->name); |
1161 | |
1162 | /* |
1163 | * Make sure the device registration and the connection fixup |
1164 | * are synchronised, so that we don't see uninitialised devices |
1165 | * on the coresight bus while trying to resolve the connections. |
1166 | */ |
1167 | mutex_lock(&coresight_mutex); |
1168 | |
1169 | ret = device_register(dev: &csdev->dev); |
1170 | if (ret) { |
1171 | put_device(dev: &csdev->dev); |
1172 | /* |
1173 | * All resources are free'd explicitly via |
1174 | * coresight_device_release(), triggered from put_device(). |
1175 | */ |
1176 | goto out_unlock; |
1177 | } |
1178 | |
1179 | if (csdev->type == CORESIGHT_DEV_TYPE_SINK || |
1180 | csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { |
1181 | ret = etm_perf_add_symlink_sink(csdev); |
1182 | |
1183 | if (ret) { |
1184 | device_unregister(dev: &csdev->dev); |
1185 | /* |
1186 | * As with the above, all resources are free'd |
1187 | * explicitly via coresight_device_release() triggered |
1188 | * from put_device(), which is in turn called from |
1189 | * function device_unregister(). |
1190 | */ |
1191 | goto out_unlock; |
1192 | } |
1193 | } |
1194 | /* Device is now registered */ |
1195 | registered = true; |
1196 | |
1197 | ret = coresight_create_conns_sysfs_group(csdev); |
1198 | if (!ret) |
1199 | ret = coresight_fixup_orphan_conns(csdev); |
1200 | |
1201 | out_unlock: |
1202 | mutex_unlock(lock: &coresight_mutex); |
1203 | /* Success */ |
1204 | if (!ret) { |
1205 | if (cti_assoc_ops && cti_assoc_ops->add) |
1206 | cti_assoc_ops->add(csdev); |
1207 | return csdev; |
1208 | } |
1209 | |
1210 | /* Unregister the device if needed */ |
1211 | if (registered) { |
1212 | coresight_unregister(csdev); |
1213 | return ERR_PTR(error: ret); |
1214 | } |
1215 | |
1216 | err_out: |
1217 | /* Cleanup the connection information */ |
1218 | coresight_release_platform_data(NULL, dev: desc->dev, pdata: desc->pdata); |
1219 | return ERR_PTR(error: ret); |
1220 | } |
1221 | EXPORT_SYMBOL_GPL(coresight_register); |
1222 | |
1223 | void coresight_unregister(struct coresight_device *csdev) |
1224 | { |
1225 | etm_perf_del_symlink_sink(csdev); |
1226 | /* Remove references of that device in the topology */ |
1227 | if (cti_assoc_ops && cti_assoc_ops->remove) |
1228 | cti_assoc_ops->remove(csdev); |
1229 | coresight_remove_conns(csdev); |
1230 | coresight_clear_default_sink(csdev); |
1231 | coresight_release_platform_data(csdev, dev: csdev->dev.parent, pdata: csdev->pdata); |
1232 | device_unregister(dev: &csdev->dev); |
1233 | } |
1234 | EXPORT_SYMBOL_GPL(coresight_unregister); |
1235 | |
1236 | |
1237 | /* |
1238 | * coresight_search_device_idx - Search the fwnode handle of a device |
1239 | * in the given dev_idx list. Must be called with the coresight_mutex held. |
1240 | * |
1241 | * Returns the index of the entry, when found. Otherwise, -ENOENT. |
1242 | */ |
1243 | static inline int coresight_search_device_idx(struct coresight_dev_list *dict, |
1244 | struct fwnode_handle *fwnode) |
1245 | { |
1246 | int i; |
1247 | |
1248 | for (i = 0; i < dict->nr_idx; i++) |
1249 | if (dict->fwnode_list[i] == fwnode) |
1250 | return i; |
1251 | return -ENOENT; |
1252 | } |
1253 | |
1254 | static bool coresight_compare_type(enum coresight_dev_type type_a, |
1255 | union coresight_dev_subtype subtype_a, |
1256 | enum coresight_dev_type type_b, |
1257 | union coresight_dev_subtype subtype_b) |
1258 | { |
1259 | if (type_a != type_b) |
1260 | return false; |
1261 | |
1262 | switch (type_a) { |
1263 | case CORESIGHT_DEV_TYPE_SINK: |
1264 | return subtype_a.sink_subtype == subtype_b.sink_subtype; |
1265 | case CORESIGHT_DEV_TYPE_LINK: |
1266 | return subtype_a.link_subtype == subtype_b.link_subtype; |
1267 | case CORESIGHT_DEV_TYPE_LINKSINK: |
1268 | return subtype_a.link_subtype == subtype_b.link_subtype && |
1269 | subtype_a.sink_subtype == subtype_b.sink_subtype; |
1270 | case CORESIGHT_DEV_TYPE_SOURCE: |
1271 | return subtype_a.source_subtype == subtype_b.source_subtype; |
1272 | case CORESIGHT_DEV_TYPE_HELPER: |
1273 | return subtype_a.helper_subtype == subtype_b.helper_subtype; |
1274 | default: |
1275 | return false; |
1276 | } |
1277 | } |
1278 | |
1279 | struct coresight_device * |
1280 | coresight_find_input_type(struct coresight_platform_data *pdata, |
1281 | enum coresight_dev_type type, |
1282 | union coresight_dev_subtype subtype) |
1283 | { |
1284 | int i; |
1285 | struct coresight_connection *conn; |
1286 | |
1287 | for (i = 0; i < pdata->nr_inconns; ++i) { |
1288 | conn = pdata->in_conns[i]; |
1289 | if (conn && |
1290 | coresight_compare_type(type_a: type, subtype_a: subtype, type_b: conn->src_dev->type, |
1291 | subtype_b: conn->src_dev->subtype)) |
1292 | return conn->src_dev; |
1293 | } |
1294 | return NULL; |
1295 | } |
1296 | EXPORT_SYMBOL_GPL(coresight_find_input_type); |
1297 | |
1298 | struct coresight_device * |
1299 | coresight_find_output_type(struct coresight_platform_data *pdata, |
1300 | enum coresight_dev_type type, |
1301 | union coresight_dev_subtype subtype) |
1302 | { |
1303 | int i; |
1304 | struct coresight_connection *conn; |
1305 | |
1306 | for (i = 0; i < pdata->nr_outconns; ++i) { |
1307 | conn = pdata->out_conns[i]; |
1308 | if (conn->dest_dev && |
1309 | coresight_compare_type(type_a: type, subtype_a: subtype, type_b: conn->dest_dev->type, |
1310 | subtype_b: conn->dest_dev->subtype)) |
1311 | return conn->dest_dev; |
1312 | } |
1313 | return NULL; |
1314 | } |
1315 | EXPORT_SYMBOL_GPL(coresight_find_output_type); |
1316 | |
1317 | bool coresight_loses_context_with_cpu(struct device *dev) |
1318 | { |
1319 | return fwnode_property_present(dev_fwnode(dev), |
1320 | propname: "arm,coresight-loses-context-with-cpu" ); |
1321 | } |
1322 | EXPORT_SYMBOL_GPL(coresight_loses_context_with_cpu); |
1323 | |
1324 | /* |
1325 | * coresight_alloc_device_name - Get an index for a given device in the |
1326 | * device index list specific to a driver. An index is allocated for a |
1327 | * device and is tracked with the fwnode_handle to prevent allocating |
1328 | * duplicate indices for the same device (e.g, if we defer probing of |
1329 | * a device due to dependencies), in case the index is requested again. |
1330 | */ |
1331 | char *coresight_alloc_device_name(struct coresight_dev_list *dict, |
1332 | struct device *dev) |
1333 | { |
1334 | int idx; |
1335 | char *name = NULL; |
1336 | struct fwnode_handle **list; |
1337 | |
1338 | mutex_lock(&coresight_mutex); |
1339 | |
1340 | idx = coresight_search_device_idx(dict, dev_fwnode(dev)); |
1341 | if (idx < 0) { |
1342 | /* Make space for the new entry */ |
1343 | idx = dict->nr_idx; |
1344 | list = krealloc_array(p: dict->fwnode_list, |
1345 | new_n: idx + 1, new_size: sizeof(*dict->fwnode_list), |
1346 | GFP_KERNEL); |
1347 | if (ZERO_OR_NULL_PTR(list)) { |
1348 | idx = -ENOMEM; |
1349 | goto done; |
1350 | } |
1351 | |
1352 | list[idx] = dev_fwnode(dev); |
1353 | dict->fwnode_list = list; |
1354 | dict->nr_idx = idx + 1; |
1355 | } |
1356 | |
1357 | name = devm_kasprintf(dev, GFP_KERNEL, fmt: "%s%d" , dict->pfx, idx); |
1358 | done: |
1359 | mutex_unlock(lock: &coresight_mutex); |
1360 | return name; |
1361 | } |
1362 | EXPORT_SYMBOL_GPL(coresight_alloc_device_name); |
1363 | |
1364 | const struct bus_type coresight_bustype = { |
1365 | .name = "coresight" , |
1366 | }; |
1367 | |
1368 | static int __init coresight_init(void) |
1369 | { |
1370 | int ret; |
1371 | |
1372 | ret = bus_register(bus: &coresight_bustype); |
1373 | if (ret) |
1374 | return ret; |
1375 | |
1376 | ret = etm_perf_init(); |
1377 | if (ret) |
1378 | goto exit_bus_unregister; |
1379 | |
1380 | /* initialise the coresight syscfg API */ |
1381 | ret = cscfg_init(); |
1382 | if (!ret) |
1383 | return 0; |
1384 | |
1385 | etm_perf_exit(); |
1386 | exit_bus_unregister: |
1387 | bus_unregister(bus: &coresight_bustype); |
1388 | return ret; |
1389 | } |
1390 | |
1391 | static void __exit coresight_exit(void) |
1392 | { |
1393 | cscfg_exit(); |
1394 | etm_perf_exit(); |
1395 | bus_unregister(bus: &coresight_bustype); |
1396 | } |
1397 | |
1398 | module_init(coresight_init); |
1399 | module_exit(coresight_exit); |
1400 | |
1401 | MODULE_LICENSE("GPL v2" ); |
1402 | MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>" ); |
1403 | MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>" ); |
1404 | MODULE_DESCRIPTION("Arm CoreSight tracer driver" ); |
1405 | |