]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/hwtracing/intel_th/core.c
intel_th: Make the switch allocate its subdevices
[mirror_ubuntu-bionic-kernel.git] / drivers / hwtracing / intel_th / core.c
1 /*
2 * Intel(R) Trace Hub driver core
3 *
4 * Copyright (C) 2014-2015 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18 #include <linux/types.h>
19 #include <linux/module.h>
20 #include <linux/device.h>
21 #include <linux/sysfs.h>
22 #include <linux/kdev_t.h>
23 #include <linux/debugfs.h>
24 #include <linux/idr.h>
25 #include <linux/pci.h>
26 #include <linux/pm_runtime.h>
27 #include <linux/dma-mapping.h>
28
29 #include "intel_th.h"
30 #include "debug.h"
31
32 static bool host_mode __read_mostly;
33 module_param(host_mode, bool, 0444);
34
35 static DEFINE_IDA(intel_th_ida);
36
37 static int intel_th_match(struct device *dev, struct device_driver *driver)
38 {
39 struct intel_th_driver *thdrv = to_intel_th_driver(driver);
40 struct intel_th_device *thdev = to_intel_th_device(dev);
41
42 if (thdev->type == INTEL_TH_SWITCH &&
43 (!thdrv->enable || !thdrv->disable))
44 return 0;
45
46 return !strcmp(thdev->name, driver->name);
47 }
48
49 static int intel_th_child_remove(struct device *dev, void *data)
50 {
51 device_release_driver(dev);
52
53 return 0;
54 }
55
56 static int intel_th_probe(struct device *dev)
57 {
58 struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver);
59 struct intel_th_device *thdev = to_intel_th_device(dev);
60 struct intel_th_driver *hubdrv;
61 struct intel_th_device *hub = NULL;
62 int ret;
63
64 if (thdev->type == INTEL_TH_SWITCH)
65 hub = thdev;
66 else if (dev->parent)
67 hub = to_intel_th_device(dev->parent);
68
69 if (!hub || !hub->dev.driver)
70 return -EPROBE_DEFER;
71
72 hubdrv = to_intel_th_driver(hub->dev.driver);
73
74 pm_runtime_set_active(dev);
75 pm_runtime_no_callbacks(dev);
76 pm_runtime_enable(dev);
77
78 ret = thdrv->probe(to_intel_th_device(dev));
79 if (ret)
80 goto out_pm;
81
82 if (thdrv->attr_group) {
83 ret = sysfs_create_group(&thdev->dev.kobj, thdrv->attr_group);
84 if (ret)
85 goto out;
86 }
87
88 if (thdev->type == INTEL_TH_OUTPUT &&
89 !intel_th_output_assigned(thdev))
90 /* does not talk to hardware */
91 ret = hubdrv->assign(hub, thdev);
92
93 out:
94 if (ret)
95 thdrv->remove(thdev);
96
97 out_pm:
98 if (ret)
99 pm_runtime_disable(dev);
100
101 return ret;
102 }
103
104 static void intel_th_device_remove(struct intel_th_device *thdev);
105
106 static int intel_th_remove(struct device *dev)
107 {
108 struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver);
109 struct intel_th_device *thdev = to_intel_th_device(dev);
110 struct intel_th_device *hub = to_intel_th_hub(thdev);
111 int err;
112
113 if (thdev->type == INTEL_TH_SWITCH) {
114 struct intel_th *th = to_intel_th(hub);
115 int i, lowest;
116
117 /* disconnect outputs */
118 err = device_for_each_child(dev, thdev, intel_th_child_remove);
119 if (err)
120 return err;
121
122 /*
123 * Remove outputs, that is, hub's children: they are created
124 * at hub's probe time by having the hub call
125 * intel_th_output_enable() for each of them.
126 */
127 for (i = 0, lowest = -1; i < th->num_thdevs; i++) {
128 /*
129 * Move the non-output devices from higher up the
130 * th->thdev[] array to lower positions to maintain
131 * a contiguous array.
132 */
133 if (th->thdev[i]->type != INTEL_TH_OUTPUT) {
134 if (lowest >= 0) {
135 th->thdev[lowest] = th->thdev[i];
136 th->thdev[i] = NULL;
137 ++lowest;
138 }
139
140 continue;
141 }
142
143 if (lowest == -1)
144 lowest = i;
145
146 intel_th_device_remove(th->thdev[i]);
147 th->thdev[i] = NULL;
148 }
149
150 th->num_thdevs = lowest;
151 }
152
153 if (thdrv->attr_group)
154 sysfs_remove_group(&thdev->dev.kobj, thdrv->attr_group);
155
156 pm_runtime_get_sync(dev);
157
158 thdrv->remove(thdev);
159
160 if (intel_th_output_assigned(thdev)) {
161 struct intel_th_driver *hubdrv =
162 to_intel_th_driver(dev->parent->driver);
163
164 if (hub->dev.driver)
165 /* does not talk to hardware */
166 hubdrv->unassign(hub, thdev);
167 }
168
169 pm_runtime_disable(dev);
170 pm_runtime_set_active(dev);
171 pm_runtime_enable(dev);
172
173 return 0;
174 }
175
176 static struct bus_type intel_th_bus = {
177 .name = "intel_th",
178 .match = intel_th_match,
179 .probe = intel_th_probe,
180 .remove = intel_th_remove,
181 };
182
183 static void intel_th_device_free(struct intel_th_device *thdev);
184
185 static void intel_th_device_release(struct device *dev)
186 {
187 intel_th_device_free(to_intel_th_device(dev));
188 }
189
190 static struct device_type intel_th_source_device_type = {
191 .name = "intel_th_source_device",
192 .release = intel_th_device_release,
193 };
194
195 static char *intel_th_output_devnode(struct device *dev, umode_t *mode,
196 kuid_t *uid, kgid_t *gid)
197 {
198 struct intel_th_device *thdev = to_intel_th_device(dev);
199 struct intel_th *th = to_intel_th(thdev);
200 char *node;
201
202 if (thdev->id >= 0)
203 node = kasprintf(GFP_KERNEL, "intel_th%d/%s%d", th->id,
204 thdev->name, thdev->id);
205 else
206 node = kasprintf(GFP_KERNEL, "intel_th%d/%s", th->id,
207 thdev->name);
208
209 return node;
210 }
211
212 static ssize_t port_show(struct device *dev, struct device_attribute *attr,
213 char *buf)
214 {
215 struct intel_th_device *thdev = to_intel_th_device(dev);
216
217 if (thdev->output.port >= 0)
218 return scnprintf(buf, PAGE_SIZE, "%u\n", thdev->output.port);
219
220 return scnprintf(buf, PAGE_SIZE, "unassigned\n");
221 }
222
223 static DEVICE_ATTR_RO(port);
224
225 static int intel_th_output_activate(struct intel_th_device *thdev)
226 {
227 struct intel_th_driver *thdrv =
228 to_intel_th_driver_or_null(thdev->dev.driver);
229 int ret = 0;
230
231 if (!thdrv)
232 return -ENODEV;
233
234 if (!try_module_get(thdrv->driver.owner))
235 return -ENODEV;
236
237 pm_runtime_get_sync(&thdev->dev);
238
239 if (thdrv->activate)
240 ret = thdrv->activate(thdev);
241 else
242 intel_th_trace_enable(thdev);
243
244 if (ret) {
245 pm_runtime_put(&thdev->dev);
246 module_put(thdrv->driver.owner);
247 }
248
249 return ret;
250 }
251
252 static void intel_th_output_deactivate(struct intel_th_device *thdev)
253 {
254 struct intel_th_driver *thdrv =
255 to_intel_th_driver_or_null(thdev->dev.driver);
256
257 if (!thdrv)
258 return;
259
260 if (thdrv->deactivate)
261 thdrv->deactivate(thdev);
262 else
263 intel_th_trace_disable(thdev);
264
265 pm_runtime_put(&thdev->dev);
266 module_put(thdrv->driver.owner);
267 }
268
269 static ssize_t active_show(struct device *dev, struct device_attribute *attr,
270 char *buf)
271 {
272 struct intel_th_device *thdev = to_intel_th_device(dev);
273
274 return scnprintf(buf, PAGE_SIZE, "%d\n", thdev->output.active);
275 }
276
277 static ssize_t active_store(struct device *dev, struct device_attribute *attr,
278 const char *buf, size_t size)
279 {
280 struct intel_th_device *thdev = to_intel_th_device(dev);
281 unsigned long val;
282 int ret;
283
284 ret = kstrtoul(buf, 10, &val);
285 if (ret)
286 return ret;
287
288 if (!!val != thdev->output.active) {
289 if (val)
290 ret = intel_th_output_activate(thdev);
291 else
292 intel_th_output_deactivate(thdev);
293 }
294
295 return ret ? ret : size;
296 }
297
298 static DEVICE_ATTR_RW(active);
299
300 static struct attribute *intel_th_output_attrs[] = {
301 &dev_attr_port.attr,
302 &dev_attr_active.attr,
303 NULL,
304 };
305
306 ATTRIBUTE_GROUPS(intel_th_output);
307
308 static struct device_type intel_th_output_device_type = {
309 .name = "intel_th_output_device",
310 .groups = intel_th_output_groups,
311 .release = intel_th_device_release,
312 .devnode = intel_th_output_devnode,
313 };
314
315 static struct device_type intel_th_switch_device_type = {
316 .name = "intel_th_switch_device",
317 .release = intel_th_device_release,
318 };
319
320 static struct device_type *intel_th_device_type[] = {
321 [INTEL_TH_SOURCE] = &intel_th_source_device_type,
322 [INTEL_TH_OUTPUT] = &intel_th_output_device_type,
323 [INTEL_TH_SWITCH] = &intel_th_switch_device_type,
324 };
325
326 int intel_th_driver_register(struct intel_th_driver *thdrv)
327 {
328 if (!thdrv->probe || !thdrv->remove)
329 return -EINVAL;
330
331 thdrv->driver.bus = &intel_th_bus;
332
333 return driver_register(&thdrv->driver);
334 }
335 EXPORT_SYMBOL_GPL(intel_th_driver_register);
336
337 void intel_th_driver_unregister(struct intel_th_driver *thdrv)
338 {
339 driver_unregister(&thdrv->driver);
340 }
341 EXPORT_SYMBOL_GPL(intel_th_driver_unregister);
342
343 static struct intel_th_device *
344 intel_th_device_alloc(struct intel_th *th, unsigned int type, const char *name,
345 int id)
346 {
347 struct device *parent;
348 struct intel_th_device *thdev;
349
350 if (type == INTEL_TH_OUTPUT)
351 parent = &th->hub->dev;
352 else
353 parent = th->dev;
354
355 thdev = kzalloc(sizeof(*thdev) + strlen(name) + 1, GFP_KERNEL);
356 if (!thdev)
357 return NULL;
358
359 thdev->id = id;
360 thdev->type = type;
361
362 strcpy(thdev->name, name);
363 device_initialize(&thdev->dev);
364 thdev->dev.bus = &intel_th_bus;
365 thdev->dev.type = intel_th_device_type[type];
366 thdev->dev.parent = parent;
367 thdev->dev.dma_mask = parent->dma_mask;
368 thdev->dev.dma_parms = parent->dma_parms;
369 dma_set_coherent_mask(&thdev->dev, parent->coherent_dma_mask);
370 if (id >= 0)
371 dev_set_name(&thdev->dev, "%d-%s%d", th->id, name, id);
372 else
373 dev_set_name(&thdev->dev, "%d-%s", th->id, name);
374
375 return thdev;
376 }
377
378 static int intel_th_device_add_resources(struct intel_th_device *thdev,
379 struct resource *res, int nres)
380 {
381 struct resource *r;
382
383 r = kmemdup(res, sizeof(*res) * nres, GFP_KERNEL);
384 if (!r)
385 return -ENOMEM;
386
387 thdev->resource = r;
388 thdev->num_resources = nres;
389
390 return 0;
391 }
392
393 static void intel_th_device_remove(struct intel_th_device *thdev)
394 {
395 device_del(&thdev->dev);
396 put_device(&thdev->dev);
397 }
398
399 static void intel_th_device_free(struct intel_th_device *thdev)
400 {
401 kfree(thdev->resource);
402 kfree(thdev);
403 }
404
405 /*
406 * Intel(R) Trace Hub subdevices
407 */
408 static const struct intel_th_subdevice {
409 const char *name;
410 struct resource res[3];
411 unsigned nres;
412 unsigned type;
413 unsigned otype;
414 unsigned scrpd;
415 int id;
416 } intel_th_subdevices[] = {
417 {
418 .nres = 1,
419 .res = {
420 {
421 .start = REG_GTH_OFFSET,
422 .end = REG_GTH_OFFSET + REG_GTH_LENGTH - 1,
423 .flags = IORESOURCE_MEM,
424 },
425 },
426 .name = "gth",
427 .type = INTEL_TH_SWITCH,
428 .id = -1,
429 },
430 {
431 .nres = 2,
432 .res = {
433 {
434 .start = REG_MSU_OFFSET,
435 .end = REG_MSU_OFFSET + REG_MSU_LENGTH - 1,
436 .flags = IORESOURCE_MEM,
437 },
438 {
439 .start = BUF_MSU_OFFSET,
440 .end = BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1,
441 .flags = IORESOURCE_MEM,
442 },
443 },
444 .name = "msc",
445 .id = 0,
446 .type = INTEL_TH_OUTPUT,
447 .otype = GTH_MSU,
448 .scrpd = SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC0_IS_ENABLED,
449 },
450 {
451 .nres = 2,
452 .res = {
453 {
454 .start = REG_MSU_OFFSET,
455 .end = REG_MSU_OFFSET + REG_MSU_LENGTH - 1,
456 .flags = IORESOURCE_MEM,
457 },
458 {
459 .start = BUF_MSU_OFFSET,
460 .end = BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1,
461 .flags = IORESOURCE_MEM,
462 },
463 },
464 .name = "msc",
465 .id = 1,
466 .type = INTEL_TH_OUTPUT,
467 .otype = GTH_MSU,
468 .scrpd = SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC1_IS_ENABLED,
469 },
470 {
471 .nres = 2,
472 .res = {
473 {
474 .start = REG_STH_OFFSET,
475 .end = REG_STH_OFFSET + REG_STH_LENGTH - 1,
476 .flags = IORESOURCE_MEM,
477 },
478 {
479 .start = TH_MMIO_SW,
480 .end = 0,
481 .flags = IORESOURCE_MEM,
482 },
483 },
484 .id = -1,
485 .name = "sth",
486 .type = INTEL_TH_SOURCE,
487 },
488 {
489 .nres = 1,
490 .res = {
491 {
492 .start = REG_PTI_OFFSET,
493 .end = REG_PTI_OFFSET + REG_PTI_LENGTH - 1,
494 .flags = IORESOURCE_MEM,
495 },
496 },
497 .id = -1,
498 .name = "pti",
499 .type = INTEL_TH_OUTPUT,
500 .otype = GTH_PTI,
501 .scrpd = SCRPD_PTI_IS_PRIM_DEST,
502 },
503 {
504 .nres = 1,
505 .res = {
506 {
507 .start = REG_DCIH_OFFSET,
508 .end = REG_DCIH_OFFSET + REG_DCIH_LENGTH - 1,
509 .flags = IORESOURCE_MEM,
510 },
511 },
512 .id = -1,
513 .name = "dcih",
514 .type = INTEL_TH_OUTPUT,
515 },
516 };
517
518 #ifdef CONFIG_MODULES
519 static void __intel_th_request_hub_module(struct work_struct *work)
520 {
521 struct intel_th *th = container_of(work, struct intel_th,
522 request_module_work);
523
524 request_module("intel_th_%s", th->hub->name);
525 }
526
527 static int intel_th_request_hub_module(struct intel_th *th)
528 {
529 INIT_WORK(&th->request_module_work, __intel_th_request_hub_module);
530 schedule_work(&th->request_module_work);
531
532 return 0;
533 }
534
535 static void intel_th_request_hub_module_flush(struct intel_th *th)
536 {
537 flush_work(&th->request_module_work);
538 }
539 #else
540 static inline int intel_th_request_hub_module(struct intel_th *th)
541 {
542 return -EINVAL;
543 }
544
545 static inline void intel_th_request_hub_module_flush(struct intel_th *th)
546 {
547 }
548 #endif /* CONFIG_MODULES */
549
550 static struct intel_th_device *
551 intel_th_subdevice_alloc(struct intel_th *th,
552 const struct intel_th_subdevice *subdev)
553 {
554 struct intel_th_device *thdev;
555 struct resource res[3];
556 unsigned int req = 0;
557 int r, err;
558
559 thdev = intel_th_device_alloc(th, subdev->type, subdev->name,
560 subdev->id);
561 if (!thdev)
562 return ERR_PTR(-ENOMEM);
563
564
565 memcpy(res, subdev->res,
566 sizeof(struct resource) * subdev->nres);
567
568 for (r = 0; r < subdev->nres; r++) {
569 struct resource *devres = th->resource;
570 int bar = TH_MMIO_CONFIG;
571
572 /*
573 * Take .end == 0 to mean 'take the whole bar',
574 * .start then tells us which bar it is. Default to
575 * TH_MMIO_CONFIG.
576 */
577 if (!res[r].end && res[r].flags == IORESOURCE_MEM) {
578 bar = res[r].start;
579 res[r].start = 0;
580 res[r].end = resource_size(&devres[bar]) - 1;
581 }
582
583 if (res[r].flags & IORESOURCE_MEM) {
584 res[r].start += devres[bar].start;
585 res[r].end += devres[bar].start;
586
587 dev_dbg(th->dev, "%s:%d @ %pR\n",
588 subdev->name, r, &res[r]);
589 } else if (res[r].flags & IORESOURCE_IRQ) {
590 res[r].start = th->irq;
591 }
592 }
593
594 err = intel_th_device_add_resources(thdev, res, subdev->nres);
595 if (err) {
596 put_device(&thdev->dev);
597 goto fail_put_device;
598 }
599
600 if (subdev->type == INTEL_TH_OUTPUT) {
601 thdev->dev.devt = MKDEV(th->major, th->num_thdevs);
602 thdev->output.type = subdev->otype;
603 thdev->output.port = -1;
604 thdev->output.scratchpad = subdev->scrpd;
605 } else if (subdev->type == INTEL_TH_SWITCH) {
606 thdev->host_mode = host_mode;
607 th->hub = thdev;
608 }
609
610 err = device_add(&thdev->dev);
611 if (err) {
612 put_device(&thdev->dev);
613 goto fail_free_res;
614 }
615
616 /* need switch driver to be loaded to enumerate the rest */
617 if (subdev->type == INTEL_TH_SWITCH && !req) {
618 err = intel_th_request_hub_module(th);
619 if (!err)
620 req++;
621 }
622
623 return thdev;
624
625 fail_free_res:
626 kfree(thdev->resource);
627
628 fail_put_device:
629 put_device(&thdev->dev);
630
631 return ERR_PTR(err);
632 }
633
634 /**
635 * intel_th_output_enable() - find and enable a device for a given output type
636 * @th: Intel TH instance
637 * @otype: output type
638 *
639 * Go through the unallocated output devices, find the first one whos type
640 * matches @otype and instantiate it. These devices are removed when the hub
641 * device is removed, see intel_th_remove().
642 */
643 int intel_th_output_enable(struct intel_th *th, unsigned int otype)
644 {
645 struct intel_th_device *thdev;
646 int src = 0, dst = 0;
647
648 for (src = 0, dst = 0; dst <= th->num_thdevs; src++, dst++) {
649 for (; src < ARRAY_SIZE(intel_th_subdevices); src++) {
650 if (intel_th_subdevices[src].type != INTEL_TH_OUTPUT)
651 continue;
652
653 if (intel_th_subdevices[src].otype != otype)
654 continue;
655
656 break;
657 }
658
659 /* no unallocated matching subdevices */
660 if (src == ARRAY_SIZE(intel_th_subdevices))
661 return -ENODEV;
662
663 for (; dst < th->num_thdevs; dst++) {
664 if (th->thdev[dst]->type != INTEL_TH_OUTPUT)
665 continue;
666
667 if (th->thdev[dst]->output.type != otype)
668 continue;
669
670 break;
671 }
672
673 /*
674 * intel_th_subdevices[src] matches our requirements and is
675 * not matched in th::thdev[]
676 */
677 if (dst == th->num_thdevs)
678 goto found;
679 }
680
681 return -ENODEV;
682
683 found:
684 thdev = intel_th_subdevice_alloc(th, &intel_th_subdevices[src]);
685 if (IS_ERR(thdev))
686 return PTR_ERR(thdev);
687
688 th->thdev[th->num_thdevs++] = thdev;
689
690 return 0;
691 }
692 EXPORT_SYMBOL_GPL(intel_th_output_enable);
693
694 static int intel_th_populate(struct intel_th *th)
695 {
696 int src;
697
698 /* create devices for each intel_th_subdevice */
699 for (src = 0; src < ARRAY_SIZE(intel_th_subdevices); src++) {
700 const struct intel_th_subdevice *subdev =
701 &intel_th_subdevices[src];
702 struct intel_th_device *thdev;
703
704 /* only allow SOURCE and SWITCH devices in host mode */
705 if (host_mode && subdev->type == INTEL_TH_OUTPUT)
706 continue;
707
708 /*
709 * don't enable port OUTPUTs in this path; SWITCH enables them
710 * via intel_th_output_enable()
711 */
712 if (subdev->type == INTEL_TH_OUTPUT &&
713 subdev->otype != GTH_NONE)
714 continue;
715
716 thdev = intel_th_subdevice_alloc(th, subdev);
717 /* note: caller should free subdevices from th::thdev[] */
718 if (IS_ERR(thdev))
719 return PTR_ERR(thdev);
720
721 th->thdev[th->num_thdevs++] = thdev;
722 }
723
724 return 0;
725 }
726
727 static int match_devt(struct device *dev, void *data)
728 {
729 dev_t devt = (dev_t)(unsigned long)data;
730
731 return dev->devt == devt;
732 }
733
734 static int intel_th_output_open(struct inode *inode, struct file *file)
735 {
736 const struct file_operations *fops;
737 struct intel_th_driver *thdrv;
738 struct device *dev;
739 int err;
740
741 dev = bus_find_device(&intel_th_bus, NULL,
742 (void *)(unsigned long)inode->i_rdev,
743 match_devt);
744 if (!dev || !dev->driver)
745 return -ENODEV;
746
747 thdrv = to_intel_th_driver(dev->driver);
748 fops = fops_get(thdrv->fops);
749 if (!fops)
750 return -ENODEV;
751
752 replace_fops(file, fops);
753
754 file->private_data = to_intel_th_device(dev);
755
756 if (file->f_op->open) {
757 err = file->f_op->open(inode, file);
758 return err;
759 }
760
761 return 0;
762 }
763
764 static const struct file_operations intel_th_output_fops = {
765 .open = intel_th_output_open,
766 .llseek = noop_llseek,
767 };
768
769 /**
770 * intel_th_alloc() - allocate a new Intel TH device and its subdevices
771 * @dev: parent device
772 * @devres: parent's resources
773 * @ndevres: number of resources
774 * @irq: irq number
775 */
776 struct intel_th *
777 intel_th_alloc(struct device *dev, struct resource *devres,
778 unsigned int ndevres, int irq)
779 {
780 struct intel_th *th;
781 int err;
782
783 th = kzalloc(sizeof(*th), GFP_KERNEL);
784 if (!th)
785 return ERR_PTR(-ENOMEM);
786
787 th->id = ida_simple_get(&intel_th_ida, 0, 0, GFP_KERNEL);
788 if (th->id < 0) {
789 err = th->id;
790 goto err_alloc;
791 }
792
793 th->major = __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS,
794 "intel_th/output", &intel_th_output_fops);
795 if (th->major < 0) {
796 err = th->major;
797 goto err_ida;
798 }
799 th->dev = dev;
800
801 th->resource = devres;
802 th->num_resources = ndevres;
803 th->irq = irq;
804
805 dev_set_drvdata(dev, th);
806
807 pm_runtime_no_callbacks(dev);
808 pm_runtime_put(dev);
809 pm_runtime_allow(dev);
810
811 err = intel_th_populate(th);
812 if (err) {
813 /* free the subdevices and undo everything */
814 intel_th_free(th);
815 return ERR_PTR(err);
816 }
817
818 return th;
819
820 err_ida:
821 ida_simple_remove(&intel_th_ida, th->id);
822
823 err_alloc:
824 kfree(th);
825
826 return ERR_PTR(err);
827 }
828 EXPORT_SYMBOL_GPL(intel_th_alloc);
829
830 void intel_th_free(struct intel_th *th)
831 {
832 int i;
833
834 intel_th_request_hub_module_flush(th);
835
836 intel_th_device_remove(th->hub);
837 for (i = 0; i < th->num_thdevs; i++) {
838 if (th->thdev[i] != th->hub)
839 intel_th_device_remove(th->thdev[i]);
840 th->thdev[i] = NULL;
841 }
842
843 th->num_thdevs = 0;
844
845 pm_runtime_get_sync(th->dev);
846 pm_runtime_forbid(th->dev);
847
848 __unregister_chrdev(th->major, 0, TH_POSSIBLE_OUTPUTS,
849 "intel_th/output");
850
851 ida_simple_remove(&intel_th_ida, th->id);
852
853 kfree(th);
854 }
855 EXPORT_SYMBOL_GPL(intel_th_free);
856
857 /**
858 * intel_th_trace_enable() - enable tracing for an output device
859 * @thdev: output device that requests tracing be enabled
860 */
861 int intel_th_trace_enable(struct intel_th_device *thdev)
862 {
863 struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
864 struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
865
866 if (WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH))
867 return -EINVAL;
868
869 if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT))
870 return -EINVAL;
871
872 pm_runtime_get_sync(&thdev->dev);
873 hubdrv->enable(hub, &thdev->output);
874
875 return 0;
876 }
877 EXPORT_SYMBOL_GPL(intel_th_trace_enable);
878
879 /**
880 * intel_th_trace_disable() - disable tracing for an output device
881 * @thdev: output device that requests tracing be disabled
882 */
883 int intel_th_trace_disable(struct intel_th_device *thdev)
884 {
885 struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
886 struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
887
888 WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH);
889 if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT))
890 return -EINVAL;
891
892 hubdrv->disable(hub, &thdev->output);
893 pm_runtime_put(&thdev->dev);
894
895 return 0;
896 }
897 EXPORT_SYMBOL_GPL(intel_th_trace_disable);
898
899 int intel_th_set_output(struct intel_th_device *thdev,
900 unsigned int master)
901 {
902 struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
903 struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
904
905 if (!hubdrv->set_output)
906 return -ENOTSUPP;
907
908 return hubdrv->set_output(hub, master);
909 }
910 EXPORT_SYMBOL_GPL(intel_th_set_output);
911
912 static int __init intel_th_init(void)
913 {
914 intel_th_debug_init();
915
916 return bus_register(&intel_th_bus);
917 }
918 subsys_initcall(intel_th_init);
919
920 static void __exit intel_th_exit(void)
921 {
922 intel_th_debug_done();
923
924 bus_unregister(&intel_th_bus);
925 }
926 module_exit(intel_th_exit);
927
928 MODULE_LICENSE("GPL v2");
929 MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver");
930 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");