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