Merge tag 'char-misc-4.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[sfrench/cifs-2.6.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 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>");