xref: /openbmc/linux/drivers/hwtracing/intel_th/core.c (revision 4ed91d48259d9ddd378424d008f2e6559f7e78f8)
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 int intel_th_remove(struct device *dev)
105 {
106 	struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver);
107 	struct intel_th_device *thdev = to_intel_th_device(dev);
108 	struct intel_th_device *hub = to_intel_th_device(dev->parent);
109 	int err;
110 
111 	if (thdev->type == INTEL_TH_SWITCH) {
112 		err = device_for_each_child(dev, thdev, intel_th_child_remove);
113 		if (err)
114 			return err;
115 	}
116 
117 	if (thdrv->attr_group)
118 		sysfs_remove_group(&thdev->dev.kobj, thdrv->attr_group);
119 
120 	pm_runtime_get_sync(dev);
121 
122 	thdrv->remove(thdev);
123 
124 	if (intel_th_output_assigned(thdev)) {
125 		struct intel_th_driver *hubdrv =
126 			to_intel_th_driver(dev->parent->driver);
127 
128 		if (hub->dev.driver)
129 			/* does not talk to hardware */
130 			hubdrv->unassign(hub, thdev);
131 	}
132 
133 	pm_runtime_disable(dev);
134 	pm_runtime_set_active(dev);
135 	pm_runtime_enable(dev);
136 
137 	return 0;
138 }
139 
140 static struct bus_type intel_th_bus = {
141 	.name		= "intel_th",
142 	.dev_attrs	= NULL,
143 	.match		= intel_th_match,
144 	.probe		= intel_th_probe,
145 	.remove		= intel_th_remove,
146 };
147 
148 static void intel_th_device_free(struct intel_th_device *thdev);
149 
150 static void intel_th_device_release(struct device *dev)
151 {
152 	intel_th_device_free(to_intel_th_device(dev));
153 }
154 
155 static struct device_type intel_th_source_device_type = {
156 	.name		= "intel_th_source_device",
157 	.release	= intel_th_device_release,
158 };
159 
160 static struct intel_th *to_intel_th(struct intel_th_device *thdev)
161 {
162 	/*
163 	 * subdevice tree is flat: if this one is not a switch, its
164 	 * parent must be
165 	 */
166 	if (thdev->type != INTEL_TH_SWITCH)
167 		thdev = to_intel_th_hub(thdev);
168 
169 	if (WARN_ON_ONCE(!thdev || thdev->type != INTEL_TH_SWITCH))
170 		return NULL;
171 
172 	return dev_get_drvdata(thdev->dev.parent);
173 }
174 
175 static char *intel_th_output_devnode(struct device *dev, umode_t *mode,
176 				     kuid_t *uid, kgid_t *gid)
177 {
178 	struct intel_th_device *thdev = to_intel_th_device(dev);
179 	struct intel_th *th = to_intel_th(thdev);
180 	char *node;
181 
182 	if (thdev->id >= 0)
183 		node = kasprintf(GFP_KERNEL, "intel_th%d/%s%d", th->id,
184 				 thdev->name, thdev->id);
185 	else
186 		node = kasprintf(GFP_KERNEL, "intel_th%d/%s", th->id,
187 				 thdev->name);
188 
189 	return node;
190 }
191 
192 static ssize_t port_show(struct device *dev, struct device_attribute *attr,
193 			 char *buf)
194 {
195 	struct intel_th_device *thdev = to_intel_th_device(dev);
196 
197 	if (thdev->output.port >= 0)
198 		return scnprintf(buf, PAGE_SIZE, "%u\n", thdev->output.port);
199 
200 	return scnprintf(buf, PAGE_SIZE, "unassigned\n");
201 }
202 
203 static DEVICE_ATTR_RO(port);
204 
205 static int intel_th_output_activate(struct intel_th_device *thdev)
206 {
207 	struct intel_th_driver *thdrv =
208 		to_intel_th_driver_or_null(thdev->dev.driver);
209 	int ret = 0;
210 
211 	if (!thdrv)
212 		return -ENODEV;
213 
214 	if (!try_module_get(thdrv->driver.owner))
215 		return -ENODEV;
216 
217 	pm_runtime_get_sync(&thdev->dev);
218 
219 	if (thdrv->activate)
220 		ret = thdrv->activate(thdev);
221 	else
222 		intel_th_trace_enable(thdev);
223 
224 	if (ret)
225 		pm_runtime_put(&thdev->dev);
226 
227 	return ret;
228 }
229 
230 static void intel_th_output_deactivate(struct intel_th_device *thdev)
231 {
232 	struct intel_th_driver *thdrv =
233 		to_intel_th_driver_or_null(thdev->dev.driver);
234 
235 	if (!thdrv)
236 		return;
237 
238 	if (thdrv->deactivate)
239 		thdrv->deactivate(thdev);
240 	else
241 		intel_th_trace_disable(thdev);
242 
243 	pm_runtime_put(&thdev->dev);
244 	module_put(thdrv->driver.owner);
245 }
246 
247 static ssize_t active_show(struct device *dev, struct device_attribute *attr,
248 			   char *buf)
249 {
250 	struct intel_th_device *thdev = to_intel_th_device(dev);
251 
252 	return scnprintf(buf, PAGE_SIZE, "%d\n", thdev->output.active);
253 }
254 
255 static ssize_t active_store(struct device *dev, struct device_attribute *attr,
256 			    const char *buf, size_t size)
257 {
258 	struct intel_th_device *thdev = to_intel_th_device(dev);
259 	unsigned long val;
260 	int ret;
261 
262 	ret = kstrtoul(buf, 10, &val);
263 	if (ret)
264 		return ret;
265 
266 	if (!!val != thdev->output.active) {
267 		if (val)
268 			ret = intel_th_output_activate(thdev);
269 		else
270 			intel_th_output_deactivate(thdev);
271 	}
272 
273 	return ret ? ret : size;
274 }
275 
276 static DEVICE_ATTR_RW(active);
277 
278 static struct attribute *intel_th_output_attrs[] = {
279 	&dev_attr_port.attr,
280 	&dev_attr_active.attr,
281 	NULL,
282 };
283 
284 ATTRIBUTE_GROUPS(intel_th_output);
285 
286 static struct device_type intel_th_output_device_type = {
287 	.name		= "intel_th_output_device",
288 	.groups		= intel_th_output_groups,
289 	.release	= intel_th_device_release,
290 	.devnode	= intel_th_output_devnode,
291 };
292 
293 static struct device_type intel_th_switch_device_type = {
294 	.name		= "intel_th_switch_device",
295 	.release	= intel_th_device_release,
296 };
297 
298 static struct device_type *intel_th_device_type[] = {
299 	[INTEL_TH_SOURCE]	= &intel_th_source_device_type,
300 	[INTEL_TH_OUTPUT]	= &intel_th_output_device_type,
301 	[INTEL_TH_SWITCH]	= &intel_th_switch_device_type,
302 };
303 
304 int intel_th_driver_register(struct intel_th_driver *thdrv)
305 {
306 	if (!thdrv->probe || !thdrv->remove)
307 		return -EINVAL;
308 
309 	thdrv->driver.bus = &intel_th_bus;
310 
311 	return driver_register(&thdrv->driver);
312 }
313 EXPORT_SYMBOL_GPL(intel_th_driver_register);
314 
315 void intel_th_driver_unregister(struct intel_th_driver *thdrv)
316 {
317 	driver_unregister(&thdrv->driver);
318 }
319 EXPORT_SYMBOL_GPL(intel_th_driver_unregister);
320 
321 static struct intel_th_device *
322 intel_th_device_alloc(struct intel_th *th, unsigned int type, const char *name,
323 		      int id)
324 {
325 	struct device *parent;
326 	struct intel_th_device *thdev;
327 
328 	if (type == INTEL_TH_SWITCH)
329 		parent = th->dev;
330 	else
331 		parent = &th->hub->dev;
332 
333 	thdev = kzalloc(sizeof(*thdev) + strlen(name) + 1, GFP_KERNEL);
334 	if (!thdev)
335 		return NULL;
336 
337 	thdev->id = id;
338 	thdev->type = type;
339 
340 	strcpy(thdev->name, name);
341 	device_initialize(&thdev->dev);
342 	thdev->dev.bus = &intel_th_bus;
343 	thdev->dev.type = intel_th_device_type[type];
344 	thdev->dev.parent = parent;
345 	thdev->dev.dma_mask = parent->dma_mask;
346 	thdev->dev.dma_parms = parent->dma_parms;
347 	dma_set_coherent_mask(&thdev->dev, parent->coherent_dma_mask);
348 	if (id >= 0)
349 		dev_set_name(&thdev->dev, "%d-%s%d", th->id, name, id);
350 	else
351 		dev_set_name(&thdev->dev, "%d-%s", th->id, name);
352 
353 	return thdev;
354 }
355 
356 static int intel_th_device_add_resources(struct intel_th_device *thdev,
357 					 struct resource *res, int nres)
358 {
359 	struct resource *r;
360 
361 	r = kmemdup(res, sizeof(*res) * nres, GFP_KERNEL);
362 	if (!r)
363 		return -ENOMEM;
364 
365 	thdev->resource = r;
366 	thdev->num_resources = nres;
367 
368 	return 0;
369 }
370 
371 static void intel_th_device_remove(struct intel_th_device *thdev)
372 {
373 	device_del(&thdev->dev);
374 	put_device(&thdev->dev);
375 }
376 
377 static void intel_th_device_free(struct intel_th_device *thdev)
378 {
379 	kfree(thdev->resource);
380 	kfree(thdev);
381 }
382 
383 /*
384  * Intel(R) Trace Hub subdevices
385  */
386 static const struct intel_th_subdevice {
387 	const char		*name;
388 	struct resource		res[3];
389 	unsigned		nres;
390 	unsigned		type;
391 	unsigned		otype;
392 	unsigned		scrpd;
393 	int			id;
394 } intel_th_subdevices[TH_SUBDEVICE_MAX] = {
395 	{
396 		.nres	= 1,
397 		.res	= {
398 			{
399 				.start	= REG_GTH_OFFSET,
400 				.end	= REG_GTH_OFFSET + REG_GTH_LENGTH - 1,
401 				.flags	= IORESOURCE_MEM,
402 			},
403 		},
404 		.name	= "gth",
405 		.type	= INTEL_TH_SWITCH,
406 		.id	= -1,
407 	},
408 	{
409 		.nres	= 2,
410 		.res	= {
411 			{
412 				.start	= REG_MSU_OFFSET,
413 				.end	= REG_MSU_OFFSET + REG_MSU_LENGTH - 1,
414 				.flags	= IORESOURCE_MEM,
415 			},
416 			{
417 				.start	= BUF_MSU_OFFSET,
418 				.end	= BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1,
419 				.flags	= IORESOURCE_MEM,
420 			},
421 		},
422 		.name	= "msc",
423 		.id	= 0,
424 		.type	= INTEL_TH_OUTPUT,
425 		.otype	= GTH_MSU,
426 		.scrpd	= SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC0_IS_ENABLED,
427 	},
428 	{
429 		.nres	= 2,
430 		.res	= {
431 			{
432 				.start	= REG_MSU_OFFSET,
433 				.end	= REG_MSU_OFFSET + REG_MSU_LENGTH - 1,
434 				.flags	= IORESOURCE_MEM,
435 			},
436 			{
437 				.start	= BUF_MSU_OFFSET,
438 				.end	= BUF_MSU_OFFSET + BUF_MSU_LENGTH - 1,
439 				.flags	= IORESOURCE_MEM,
440 			},
441 		},
442 		.name	= "msc",
443 		.id	= 1,
444 		.type	= INTEL_TH_OUTPUT,
445 		.otype	= GTH_MSU,
446 		.scrpd	= SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC1_IS_ENABLED,
447 	},
448 	{
449 		.nres	= 2,
450 		.res	= {
451 			{
452 				.start	= REG_STH_OFFSET,
453 				.end	= REG_STH_OFFSET + REG_STH_LENGTH - 1,
454 				.flags	= IORESOURCE_MEM,
455 			},
456 			{
457 				.start	= TH_MMIO_SW,
458 				.end	= 0,
459 				.flags	= IORESOURCE_MEM,
460 			},
461 		},
462 		.id	= -1,
463 		.name	= "sth",
464 		.type	= INTEL_TH_SOURCE,
465 	},
466 	{
467 		.nres	= 1,
468 		.res	= {
469 			{
470 				.start	= REG_PTI_OFFSET,
471 				.end	= REG_PTI_OFFSET + REG_PTI_LENGTH - 1,
472 				.flags	= IORESOURCE_MEM,
473 			},
474 		},
475 		.id	= -1,
476 		.name	= "pti",
477 		.type	= INTEL_TH_OUTPUT,
478 		.otype	= GTH_PTI,
479 		.scrpd	= SCRPD_PTI_IS_PRIM_DEST,
480 	},
481 	{
482 		.nres	= 1,
483 		.res	= {
484 			{
485 				.start	= REG_DCIH_OFFSET,
486 				.end	= REG_DCIH_OFFSET + REG_DCIH_LENGTH - 1,
487 				.flags	= IORESOURCE_MEM,
488 			},
489 		},
490 		.id	= -1,
491 		.name	= "dcih",
492 		.type	= INTEL_TH_OUTPUT,
493 	},
494 };
495 
496 #ifdef CONFIG_MODULES
497 static void __intel_th_request_hub_module(struct work_struct *work)
498 {
499 	struct intel_th *th = container_of(work, struct intel_th,
500 					   request_module_work);
501 
502 	request_module("intel_th_%s", th->hub->name);
503 }
504 
505 static int intel_th_request_hub_module(struct intel_th *th)
506 {
507 	INIT_WORK(&th->request_module_work, __intel_th_request_hub_module);
508 	schedule_work(&th->request_module_work);
509 
510 	return 0;
511 }
512 
513 static void intel_th_request_hub_module_flush(struct intel_th *th)
514 {
515 	flush_work(&th->request_module_work);
516 }
517 #else
518 static inline int intel_th_request_hub_module(struct intel_th *th)
519 {
520 	return -EINVAL;
521 }
522 
523 static inline void intel_th_request_hub_module_flush(struct intel_th *th)
524 {
525 }
526 #endif /* CONFIG_MODULES */
527 
528 static int intel_th_populate(struct intel_th *th, struct resource *devres,
529 			     unsigned int ndevres, int irq)
530 {
531 	struct resource res[3];
532 	unsigned int req = 0;
533 	int src, dst, err;
534 
535 	/* create devices for each intel_th_subdevice */
536 	for (src = 0, dst = 0; src < ARRAY_SIZE(intel_th_subdevices); src++) {
537 		const struct intel_th_subdevice *subdev =
538 			&intel_th_subdevices[src];
539 		struct intel_th_device *thdev;
540 		int r;
541 
542 		/* only allow SOURCE and SWITCH devices in host mode */
543 		if (host_mode && subdev->type == INTEL_TH_OUTPUT)
544 			continue;
545 
546 		thdev = intel_th_device_alloc(th, subdev->type, subdev->name,
547 					      subdev->id);
548 		if (!thdev) {
549 			err = -ENOMEM;
550 			goto kill_subdevs;
551 		}
552 
553 		memcpy(res, subdev->res,
554 		       sizeof(struct resource) * subdev->nres);
555 
556 		for (r = 0; r < subdev->nres; r++) {
557 			int bar = TH_MMIO_CONFIG;
558 
559 			/*
560 			 * Take .end == 0 to mean 'take the whole bar',
561 			 * .start then tells us which bar it is. Default to
562 			 * TH_MMIO_CONFIG.
563 			 */
564 			if (!res[r].end && res[r].flags == IORESOURCE_MEM) {
565 				bar = res[r].start;
566 				res[r].start = 0;
567 				res[r].end = resource_size(&devres[bar]) - 1;
568 			}
569 
570 			if (res[r].flags & IORESOURCE_MEM) {
571 				res[r].start	+= devres[bar].start;
572 				res[r].end	+= devres[bar].start;
573 
574 				dev_dbg(th->dev, "%s:%d @ %pR\n",
575 					subdev->name, r, &res[r]);
576 			} else if (res[r].flags & IORESOURCE_IRQ) {
577 				res[r].start	= irq;
578 			}
579 		}
580 
581 		err = intel_th_device_add_resources(thdev, res, subdev->nres);
582 		if (err) {
583 			put_device(&thdev->dev);
584 			goto kill_subdevs;
585 		}
586 
587 		if (subdev->type == INTEL_TH_OUTPUT) {
588 			thdev->dev.devt = MKDEV(th->major, dst);
589 			thdev->output.type = subdev->otype;
590 			thdev->output.port = -1;
591 			thdev->output.scratchpad = subdev->scrpd;
592 		} else if (subdev->type == INTEL_TH_SWITCH) {
593 			thdev->host_mode = host_mode;
594 		}
595 
596 		err = device_add(&thdev->dev);
597 		if (err) {
598 			put_device(&thdev->dev);
599 			goto kill_subdevs;
600 		}
601 
602 		/* need switch driver to be loaded to enumerate the rest */
603 		if (subdev->type == INTEL_TH_SWITCH && !req) {
604 			th->hub = thdev;
605 			err = intel_th_request_hub_module(th);
606 			if (!err)
607 				req++;
608 		}
609 
610 		th->thdev[dst++] = thdev;
611 	}
612 
613 	return 0;
614 
615 kill_subdevs:
616 	for (; dst >= 0; dst--)
617 		intel_th_device_remove(th->thdev[dst]);
618 
619 	return err;
620 }
621 
622 static int match_devt(struct device *dev, void *data)
623 {
624 	dev_t devt = (dev_t)(unsigned long)data;
625 
626 	return dev->devt == devt;
627 }
628 
629 static int intel_th_output_open(struct inode *inode, struct file *file)
630 {
631 	const struct file_operations *fops;
632 	struct intel_th_driver *thdrv;
633 	struct device *dev;
634 	int err;
635 
636 	dev = bus_find_device(&intel_th_bus, NULL,
637 			      (void *)(unsigned long)inode->i_rdev,
638 			      match_devt);
639 	if (!dev || !dev->driver)
640 		return -ENODEV;
641 
642 	thdrv = to_intel_th_driver(dev->driver);
643 	fops = fops_get(thdrv->fops);
644 	if (!fops)
645 		return -ENODEV;
646 
647 	replace_fops(file, fops);
648 
649 	file->private_data = to_intel_th_device(dev);
650 
651 	if (file->f_op->open) {
652 		err = file->f_op->open(inode, file);
653 		return err;
654 	}
655 
656 	return 0;
657 }
658 
659 static const struct file_operations intel_th_output_fops = {
660 	.open	= intel_th_output_open,
661 	.llseek	= noop_llseek,
662 };
663 
664 /**
665  * intel_th_alloc() - allocate a new Intel TH device and its subdevices
666  * @dev:	parent device
667  * @devres:	parent's resources
668  * @ndevres:	number of resources
669  * @irq:	irq number
670  */
671 struct intel_th *
672 intel_th_alloc(struct device *dev, struct resource *devres,
673 	       unsigned int ndevres, int irq)
674 {
675 	struct intel_th *th;
676 	int err;
677 
678 	th = kzalloc(sizeof(*th), GFP_KERNEL);
679 	if (!th)
680 		return ERR_PTR(-ENOMEM);
681 
682 	th->id = ida_simple_get(&intel_th_ida, 0, 0, GFP_KERNEL);
683 	if (th->id < 0) {
684 		err = th->id;
685 		goto err_alloc;
686 	}
687 
688 	th->major = __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS,
689 				      "intel_th/output", &intel_th_output_fops);
690 	if (th->major < 0) {
691 		err = th->major;
692 		goto err_ida;
693 	}
694 	th->dev = dev;
695 
696 	dev_set_drvdata(dev, th);
697 
698 	pm_runtime_no_callbacks(dev);
699 	pm_runtime_put(dev);
700 	pm_runtime_allow(dev);
701 
702 	err = intel_th_populate(th, devres, ndevres, irq);
703 	if (err)
704 		goto err_chrdev;
705 
706 	return th;
707 
708 err_chrdev:
709 	pm_runtime_forbid(dev);
710 
711 	__unregister_chrdev(th->major, 0, TH_POSSIBLE_OUTPUTS,
712 			    "intel_th/output");
713 
714 err_ida:
715 	ida_simple_remove(&intel_th_ida, th->id);
716 
717 err_alloc:
718 	kfree(th);
719 
720 	return ERR_PTR(err);
721 }
722 EXPORT_SYMBOL_GPL(intel_th_alloc);
723 
724 void intel_th_free(struct intel_th *th)
725 {
726 	int i;
727 
728 	intel_th_request_hub_module_flush(th);
729 	for (i = 0; i < TH_SUBDEVICE_MAX; i++)
730 		if (th->thdev[i] && th->thdev[i] != th->hub)
731 			intel_th_device_remove(th->thdev[i]);
732 
733 	intel_th_device_remove(th->hub);
734 
735 	pm_runtime_get_sync(th->dev);
736 	pm_runtime_forbid(th->dev);
737 
738 	__unregister_chrdev(th->major, 0, TH_POSSIBLE_OUTPUTS,
739 			    "intel_th/output");
740 
741 	ida_simple_remove(&intel_th_ida, th->id);
742 
743 	kfree(th);
744 }
745 EXPORT_SYMBOL_GPL(intel_th_free);
746 
747 /**
748  * intel_th_trace_enable() - enable tracing for an output device
749  * @thdev:	output device that requests tracing be enabled
750  */
751 int intel_th_trace_enable(struct intel_th_device *thdev)
752 {
753 	struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
754 	struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
755 
756 	if (WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH))
757 		return -EINVAL;
758 
759 	if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT))
760 		return -EINVAL;
761 
762 	pm_runtime_get_sync(&thdev->dev);
763 	hubdrv->enable(hub, &thdev->output);
764 
765 	return 0;
766 }
767 EXPORT_SYMBOL_GPL(intel_th_trace_enable);
768 
769 /**
770  * intel_th_trace_disable() - disable tracing for an output device
771  * @thdev:	output device that requests tracing be disabled
772  */
773 int intel_th_trace_disable(struct intel_th_device *thdev)
774 {
775 	struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
776 	struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
777 
778 	WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH);
779 	if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT))
780 		return -EINVAL;
781 
782 	hubdrv->disable(hub, &thdev->output);
783 	pm_runtime_put(&thdev->dev);
784 
785 	return 0;
786 }
787 EXPORT_SYMBOL_GPL(intel_th_trace_disable);
788 
789 int intel_th_set_output(struct intel_th_device *thdev,
790 			unsigned int master)
791 {
792 	struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent);
793 	struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
794 
795 	if (!hubdrv->set_output)
796 		return -ENOTSUPP;
797 
798 	return hubdrv->set_output(hub, master);
799 }
800 EXPORT_SYMBOL_GPL(intel_th_set_output);
801 
802 static int __init intel_th_init(void)
803 {
804 	intel_th_debug_init();
805 
806 	return bus_register(&intel_th_bus);
807 }
808 subsys_initcall(intel_th_init);
809 
810 static void __exit intel_th_exit(void)
811 {
812 	intel_th_debug_done();
813 
814 	bus_unregister(&intel_th_bus);
815 }
816 module_exit(intel_th_exit);
817 
818 MODULE_LICENSE("GPL v2");
819 MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver");
820 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
821