2 * Intel(R) Trace Hub driver core
4 * Copyright (C) 2014-2015 Intel Corporation.
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.
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
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
32 static bool host_mode __read_mostly
;
33 module_param(host_mode
, bool, 0444);
35 static DEFINE_IDA(intel_th_ida
);
37 static int intel_th_match(struct device
*dev
, struct device_driver
*driver
)
39 struct intel_th_driver
*thdrv
= to_intel_th_driver(driver
);
40 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
42 if (thdev
->type
== INTEL_TH_SWITCH
&&
43 (!thdrv
->enable
|| !thdrv
->disable
))
46 return !strcmp(thdev
->name
, driver
->name
);
49 static int intel_th_child_remove(struct device
*dev
, void *data
)
51 device_release_driver(dev
);
56 static int intel_th_probe(struct device
*dev
)
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
;
64 if (thdev
->type
== INTEL_TH_SWITCH
)
67 hub
= to_intel_th_device(dev
->parent
);
69 if (!hub
|| !hub
->dev
.driver
)
72 hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
74 pm_runtime_set_active(dev
);
75 pm_runtime_no_callbacks(dev
);
76 pm_runtime_enable(dev
);
78 ret
= thdrv
->probe(to_intel_th_device(dev
));
82 if (thdrv
->attr_group
) {
83 ret
= sysfs_create_group(&thdev
->dev
.kobj
, thdrv
->attr_group
);
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
);
99 pm_runtime_disable(dev
);
104 static void intel_th_device_remove(struct intel_th_device
*thdev
);
106 static int intel_th_remove(struct device
*dev
)
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
);
113 if (thdev
->type
== INTEL_TH_SWITCH
) {
114 struct intel_th
*th
= to_intel_th(hub
);
117 /* disconnect outputs */
118 err
= device_for_each_child(dev
, thdev
, intel_th_child_remove
);
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.
127 for (i
= 0, lowest
= -1; i
< th
->num_thdevs
; i
++) {
129 * Move the non-output devices from higher up the
130 * th->thdev[] array to lower positions to maintain
131 * a contiguous array.
133 if (th
->thdev
[i
]->type
!= INTEL_TH_OUTPUT
) {
135 th
->thdev
[lowest
] = th
->thdev
[i
];
146 intel_th_device_remove(th
->thdev
[i
]);
151 th
->num_thdevs
= lowest
;
154 if (thdrv
->attr_group
)
155 sysfs_remove_group(&thdev
->dev
.kobj
, thdrv
->attr_group
);
157 pm_runtime_get_sync(dev
);
159 thdrv
->remove(thdev
);
161 if (intel_th_output_assigned(thdev
)) {
162 struct intel_th_driver
*hubdrv
=
163 to_intel_th_driver(dev
->parent
->driver
);
166 /* does not talk to hardware */
167 hubdrv
->unassign(hub
, thdev
);
170 pm_runtime_disable(dev
);
171 pm_runtime_set_active(dev
);
172 pm_runtime_enable(dev
);
177 static struct bus_type intel_th_bus
= {
179 .match
= intel_th_match
,
180 .probe
= intel_th_probe
,
181 .remove
= intel_th_remove
,
184 static void intel_th_device_free(struct intel_th_device
*thdev
);
186 static void intel_th_device_release(struct device
*dev
)
188 intel_th_device_free(to_intel_th_device(dev
));
191 static struct device_type intel_th_source_device_type
= {
192 .name
= "intel_th_source_device",
193 .release
= intel_th_device_release
,
196 static char *intel_th_output_devnode(struct device
*dev
, umode_t
*mode
,
197 kuid_t
*uid
, kgid_t
*gid
)
199 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
200 struct intel_th
*th
= to_intel_th(thdev
);
204 node
= kasprintf(GFP_KERNEL
, "intel_th%d/%s%d", th
->id
,
205 thdev
->name
, thdev
->id
);
207 node
= kasprintf(GFP_KERNEL
, "intel_th%d/%s", th
->id
,
213 static ssize_t
port_show(struct device
*dev
, struct device_attribute
*attr
,
216 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
218 if (thdev
->output
.port
>= 0)
219 return scnprintf(buf
, PAGE_SIZE
, "%u\n", thdev
->output
.port
);
221 return scnprintf(buf
, PAGE_SIZE
, "unassigned\n");
224 static DEVICE_ATTR_RO(port
);
226 static int intel_th_output_activate(struct intel_th_device
*thdev
)
228 struct intel_th_driver
*thdrv
=
229 to_intel_th_driver_or_null(thdev
->dev
.driver
);
230 struct intel_th
*th
= to_intel_th(thdev
);
236 if (!try_module_get(thdrv
->driver
.owner
))
239 pm_runtime_get_sync(&thdev
->dev
);
242 ret
= th
->activate(th
);
247 ret
= thdrv
->activate(thdev
);
249 intel_th_trace_enable(thdev
);
252 goto fail_deactivate
;
261 pm_runtime_put(&thdev
->dev
);
262 module_put(thdrv
->driver
.owner
);
267 static void intel_th_output_deactivate(struct intel_th_device
*thdev
)
269 struct intel_th_driver
*thdrv
=
270 to_intel_th_driver_or_null(thdev
->dev
.driver
);
271 struct intel_th
*th
= to_intel_th(thdev
);
276 if (thdrv
->deactivate
)
277 thdrv
->deactivate(thdev
);
279 intel_th_trace_disable(thdev
);
284 pm_runtime_put(&thdev
->dev
);
285 module_put(thdrv
->driver
.owner
);
288 static ssize_t
active_show(struct device
*dev
, struct device_attribute
*attr
,
291 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
293 return scnprintf(buf
, PAGE_SIZE
, "%d\n", thdev
->output
.active
);
296 static ssize_t
active_store(struct device
*dev
, struct device_attribute
*attr
,
297 const char *buf
, size_t size
)
299 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
303 ret
= kstrtoul(buf
, 10, &val
);
307 if (!!val
!= thdev
->output
.active
) {
309 ret
= intel_th_output_activate(thdev
);
311 intel_th_output_deactivate(thdev
);
314 return ret
? ret
: size
;
317 static DEVICE_ATTR_RW(active
);
319 static struct attribute
*intel_th_output_attrs
[] = {
321 &dev_attr_active
.attr
,
325 ATTRIBUTE_GROUPS(intel_th_output
);
327 static struct device_type intel_th_output_device_type
= {
328 .name
= "intel_th_output_device",
329 .groups
= intel_th_output_groups
,
330 .release
= intel_th_device_release
,
331 .devnode
= intel_th_output_devnode
,
334 static struct device_type intel_th_switch_device_type
= {
335 .name
= "intel_th_switch_device",
336 .release
= intel_th_device_release
,
339 static struct device_type
*intel_th_device_type
[] = {
340 [INTEL_TH_SOURCE
] = &intel_th_source_device_type
,
341 [INTEL_TH_OUTPUT
] = &intel_th_output_device_type
,
342 [INTEL_TH_SWITCH
] = &intel_th_switch_device_type
,
345 int intel_th_driver_register(struct intel_th_driver
*thdrv
)
347 if (!thdrv
->probe
|| !thdrv
->remove
)
350 thdrv
->driver
.bus
= &intel_th_bus
;
352 return driver_register(&thdrv
->driver
);
354 EXPORT_SYMBOL_GPL(intel_th_driver_register
);
356 void intel_th_driver_unregister(struct intel_th_driver
*thdrv
)
358 driver_unregister(&thdrv
->driver
);
360 EXPORT_SYMBOL_GPL(intel_th_driver_unregister
);
362 static struct intel_th_device
*
363 intel_th_device_alloc(struct intel_th
*th
, unsigned int type
, const char *name
,
366 struct device
*parent
;
367 struct intel_th_device
*thdev
;
369 if (type
== INTEL_TH_OUTPUT
)
370 parent
= &th
->hub
->dev
;
374 thdev
= kzalloc(sizeof(*thdev
) + strlen(name
) + 1, GFP_KERNEL
);
381 strcpy(thdev
->name
, name
);
382 device_initialize(&thdev
->dev
);
383 thdev
->dev
.bus
= &intel_th_bus
;
384 thdev
->dev
.type
= intel_th_device_type
[type
];
385 thdev
->dev
.parent
= parent
;
386 thdev
->dev
.dma_mask
= parent
->dma_mask
;
387 thdev
->dev
.dma_parms
= parent
->dma_parms
;
388 dma_set_coherent_mask(&thdev
->dev
, parent
->coherent_dma_mask
);
390 dev_set_name(&thdev
->dev
, "%d-%s%d", th
->id
, name
, id
);
392 dev_set_name(&thdev
->dev
, "%d-%s", th
->id
, name
);
397 static int intel_th_device_add_resources(struct intel_th_device
*thdev
,
398 struct resource
*res
, int nres
)
402 r
= kmemdup(res
, sizeof(*res
) * nres
, GFP_KERNEL
);
407 thdev
->num_resources
= nres
;
412 static void intel_th_device_remove(struct intel_th_device
*thdev
)
414 device_del(&thdev
->dev
);
415 put_device(&thdev
->dev
);
418 static void intel_th_device_free(struct intel_th_device
*thdev
)
420 kfree(thdev
->resource
);
425 * Intel(R) Trace Hub subdevices
427 static const struct intel_th_subdevice
{
429 struct resource res
[3];
435 } intel_th_subdevices
[] = {
440 /* Handle TSCU from GTH driver */
441 .start
= REG_GTH_OFFSET
,
442 .end
= REG_TSCU_OFFSET
+ REG_TSCU_LENGTH
- 1,
443 .flags
= IORESOURCE_MEM
,
447 .type
= INTEL_TH_SWITCH
,
454 .start
= REG_MSU_OFFSET
,
455 .end
= REG_MSU_OFFSET
+ REG_MSU_LENGTH
- 1,
456 .flags
= IORESOURCE_MEM
,
459 .start
= BUF_MSU_OFFSET
,
460 .end
= BUF_MSU_OFFSET
+ BUF_MSU_LENGTH
- 1,
461 .flags
= IORESOURCE_MEM
,
466 .type
= INTEL_TH_OUTPUT
,
468 .scrpd
= SCRPD_MEM_IS_PRIM_DEST
| SCRPD_MSC0_IS_ENABLED
,
474 .start
= REG_MSU_OFFSET
,
475 .end
= REG_MSU_OFFSET
+ REG_MSU_LENGTH
- 1,
476 .flags
= IORESOURCE_MEM
,
479 .start
= BUF_MSU_OFFSET
,
480 .end
= BUF_MSU_OFFSET
+ BUF_MSU_LENGTH
- 1,
481 .flags
= IORESOURCE_MEM
,
486 .type
= INTEL_TH_OUTPUT
,
488 .scrpd
= SCRPD_MEM_IS_PRIM_DEST
| SCRPD_MSC1_IS_ENABLED
,
494 .start
= REG_STH_OFFSET
,
495 .end
= REG_STH_OFFSET
+ REG_STH_LENGTH
- 1,
496 .flags
= IORESOURCE_MEM
,
501 .flags
= IORESOURCE_MEM
,
506 .type
= INTEL_TH_SOURCE
,
512 .start
= REG_PTI_OFFSET
,
513 .end
= REG_PTI_OFFSET
+ REG_PTI_LENGTH
- 1,
514 .flags
= IORESOURCE_MEM
,
519 .type
= INTEL_TH_OUTPUT
,
521 .scrpd
= SCRPD_PTI_IS_PRIM_DEST
,
527 .start
= REG_PTI_OFFSET
,
528 .end
= REG_PTI_OFFSET
+ REG_PTI_LENGTH
- 1,
529 .flags
= IORESOURCE_MEM
,
534 .type
= INTEL_TH_OUTPUT
,
536 .scrpd
= SCRPD_PTI_IS_PRIM_DEST
,
542 .start
= REG_DCIH_OFFSET
,
543 .end
= REG_DCIH_OFFSET
+ REG_DCIH_LENGTH
- 1,
544 .flags
= IORESOURCE_MEM
,
549 .type
= INTEL_TH_OUTPUT
,
553 #ifdef CONFIG_MODULES
554 static void __intel_th_request_hub_module(struct work_struct
*work
)
556 struct intel_th
*th
= container_of(work
, struct intel_th
,
557 request_module_work
);
559 request_module("intel_th_%s", th
->hub
->name
);
562 static int intel_th_request_hub_module(struct intel_th
*th
)
564 INIT_WORK(&th
->request_module_work
, __intel_th_request_hub_module
);
565 schedule_work(&th
->request_module_work
);
570 static void intel_th_request_hub_module_flush(struct intel_th
*th
)
572 flush_work(&th
->request_module_work
);
575 static inline int intel_th_request_hub_module(struct intel_th
*th
)
580 static inline void intel_th_request_hub_module_flush(struct intel_th
*th
)
583 #endif /* CONFIG_MODULES */
585 static struct intel_th_device
*
586 intel_th_subdevice_alloc(struct intel_th
*th
,
587 const struct intel_th_subdevice
*subdev
)
589 struct intel_th_device
*thdev
;
590 struct resource res
[3];
591 unsigned int req
= 0;
594 thdev
= intel_th_device_alloc(th
, subdev
->type
, subdev
->name
,
597 return ERR_PTR(-ENOMEM
);
599 thdev
->drvdata
= th
->drvdata
;
601 memcpy(res
, subdev
->res
,
602 sizeof(struct resource
) * subdev
->nres
);
604 for (r
= 0; r
< subdev
->nres
; r
++) {
605 struct resource
*devres
= th
->resource
;
606 int bar
= TH_MMIO_CONFIG
;
609 * Take .end == 0 to mean 'take the whole bar',
610 * .start then tells us which bar it is. Default to
613 if (!res
[r
].end
&& res
[r
].flags
== IORESOURCE_MEM
) {
616 res
[r
].end
= resource_size(&devres
[bar
]) - 1;
619 if (res
[r
].flags
& IORESOURCE_MEM
) {
620 res
[r
].start
+= devres
[bar
].start
;
621 res
[r
].end
+= devres
[bar
].start
;
623 dev_dbg(th
->dev
, "%s:%d @ %pR\n",
624 subdev
->name
, r
, &res
[r
]);
625 } else if (res
[r
].flags
& IORESOURCE_IRQ
) {
626 res
[r
].start
= th
->irq
;
630 err
= intel_th_device_add_resources(thdev
, res
, subdev
->nres
);
632 put_device(&thdev
->dev
);
633 goto fail_put_device
;
636 if (subdev
->type
== INTEL_TH_OUTPUT
) {
637 thdev
->dev
.devt
= MKDEV(th
->major
, th
->num_thdevs
);
638 thdev
->output
.type
= subdev
->otype
;
639 thdev
->output
.port
= -1;
640 thdev
->output
.scratchpad
= subdev
->scrpd
;
641 } else if (subdev
->type
== INTEL_TH_SWITCH
) {
642 thdev
->host_mode
= host_mode
;
646 err
= device_add(&thdev
->dev
);
648 put_device(&thdev
->dev
);
652 /* need switch driver to be loaded to enumerate the rest */
653 if (subdev
->type
== INTEL_TH_SWITCH
&& !req
) {
654 err
= intel_th_request_hub_module(th
);
662 kfree(thdev
->resource
);
665 put_device(&thdev
->dev
);
671 * intel_th_output_enable() - find and enable a device for a given output type
672 * @th: Intel TH instance
673 * @otype: output type
675 * Go through the unallocated output devices, find the first one whos type
676 * matches @otype and instantiate it. These devices are removed when the hub
677 * device is removed, see intel_th_remove().
679 int intel_th_output_enable(struct intel_th
*th
, unsigned int otype
)
681 struct intel_th_device
*thdev
;
682 int src
= 0, dst
= 0;
684 for (src
= 0, dst
= 0; dst
<= th
->num_thdevs
; src
++, dst
++) {
685 for (; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
686 if (intel_th_subdevices
[src
].type
!= INTEL_TH_OUTPUT
)
689 if (intel_th_subdevices
[src
].otype
!= otype
)
695 /* no unallocated matching subdevices */
696 if (src
== ARRAY_SIZE(intel_th_subdevices
))
699 for (; dst
< th
->num_thdevs
; dst
++) {
700 if (th
->thdev
[dst
]->type
!= INTEL_TH_OUTPUT
)
703 if (th
->thdev
[dst
]->output
.type
!= otype
)
710 * intel_th_subdevices[src] matches our requirements and is
711 * not matched in th::thdev[]
713 if (dst
== th
->num_thdevs
)
720 thdev
= intel_th_subdevice_alloc(th
, &intel_th_subdevices
[src
]);
722 return PTR_ERR(thdev
);
724 th
->thdev
[th
->num_thdevs
++] = thdev
;
728 EXPORT_SYMBOL_GPL(intel_th_output_enable
);
730 static int intel_th_populate(struct intel_th
*th
)
734 /* create devices for each intel_th_subdevice */
735 for (src
= 0; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
736 const struct intel_th_subdevice
*subdev
=
737 &intel_th_subdevices
[src
];
738 struct intel_th_device
*thdev
;
740 /* only allow SOURCE and SWITCH devices in host mode */
741 if (host_mode
&& subdev
->type
== INTEL_TH_OUTPUT
)
745 * don't enable port OUTPUTs in this path; SWITCH enables them
746 * via intel_th_output_enable()
748 if (subdev
->type
== INTEL_TH_OUTPUT
&&
749 subdev
->otype
!= GTH_NONE
)
752 thdev
= intel_th_subdevice_alloc(th
, subdev
);
753 /* note: caller should free subdevices from th::thdev[] */
755 return PTR_ERR(thdev
);
757 th
->thdev
[th
->num_thdevs
++] = thdev
;
763 static int match_devt(struct device
*dev
, void *data
)
765 dev_t devt
= (dev_t
)(unsigned long)data
;
767 return dev
->devt
== devt
;
770 static int intel_th_output_open(struct inode
*inode
, struct file
*file
)
772 const struct file_operations
*fops
;
773 struct intel_th_driver
*thdrv
;
777 dev
= bus_find_device(&intel_th_bus
, NULL
,
778 (void *)(unsigned long)inode
->i_rdev
,
780 if (!dev
|| !dev
->driver
)
783 thdrv
= to_intel_th_driver(dev
->driver
);
784 fops
= fops_get(thdrv
->fops
);
788 replace_fops(file
, fops
);
790 file
->private_data
= to_intel_th_device(dev
);
792 if (file
->f_op
->open
) {
793 err
= file
->f_op
->open(inode
, file
);
800 static const struct file_operations intel_th_output_fops
= {
801 .open
= intel_th_output_open
,
802 .llseek
= noop_llseek
,
806 * intel_th_alloc() - allocate a new Intel TH device and its subdevices
807 * @dev: parent device
808 * @devres: parent's resources
809 * @ndevres: number of resources
813 intel_th_alloc(struct device
*dev
, struct intel_th_drvdata
*drvdata
,
814 struct resource
*devres
, unsigned int ndevres
, int irq
)
819 th
= kzalloc(sizeof(*th
), GFP_KERNEL
);
821 return ERR_PTR(-ENOMEM
);
823 th
->id
= ida_simple_get(&intel_th_ida
, 0, 0, GFP_KERNEL
);
829 th
->major
= __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS
,
830 "intel_th/output", &intel_th_output_fops
);
836 th
->drvdata
= drvdata
;
838 th
->resource
= devres
;
839 th
->num_resources
= ndevres
;
842 dev_set_drvdata(dev
, th
);
844 pm_runtime_no_callbacks(dev
);
846 pm_runtime_allow(dev
);
848 err
= intel_th_populate(th
);
850 /* free the subdevices and undo everything */
858 ida_simple_remove(&intel_th_ida
, th
->id
);
865 EXPORT_SYMBOL_GPL(intel_th_alloc
);
867 void intel_th_free(struct intel_th
*th
)
871 intel_th_request_hub_module_flush(th
);
873 intel_th_device_remove(th
->hub
);
874 for (i
= 0; i
< th
->num_thdevs
; i
++) {
875 if (th
->thdev
[i
] != th
->hub
)
876 intel_th_device_remove(th
->thdev
[i
]);
882 pm_runtime_get_sync(th
->dev
);
883 pm_runtime_forbid(th
->dev
);
885 __unregister_chrdev(th
->major
, 0, TH_POSSIBLE_OUTPUTS
,
888 ida_simple_remove(&intel_th_ida
, th
->id
);
892 EXPORT_SYMBOL_GPL(intel_th_free
);
895 * intel_th_trace_enable() - enable tracing for an output device
896 * @thdev: output device that requests tracing be enabled
898 int intel_th_trace_enable(struct intel_th_device
*thdev
)
900 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
901 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
903 if (WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
))
906 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
909 pm_runtime_get_sync(&thdev
->dev
);
910 hubdrv
->enable(hub
, &thdev
->output
);
914 EXPORT_SYMBOL_GPL(intel_th_trace_enable
);
917 * intel_th_trace_disable() - disable tracing for an output device
918 * @thdev: output device that requests tracing be disabled
920 int intel_th_trace_disable(struct intel_th_device
*thdev
)
922 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
923 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
925 WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
);
926 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
929 hubdrv
->disable(hub
, &thdev
->output
);
930 pm_runtime_put(&thdev
->dev
);
934 EXPORT_SYMBOL_GPL(intel_th_trace_disable
);
936 int intel_th_set_output(struct intel_th_device
*thdev
,
939 struct intel_th_device
*hub
= to_intel_th_hub(thdev
);
940 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
942 if (!hubdrv
->set_output
)
945 return hubdrv
->set_output(hub
, master
);
947 EXPORT_SYMBOL_GPL(intel_th_set_output
);
949 static int __init
intel_th_init(void)
951 intel_th_debug_init();
953 return bus_register(&intel_th_bus
);
955 subsys_initcall(intel_th_init
);
957 static void __exit
intel_th_exit(void)
959 intel_th_debug_done();
961 bus_unregister(&intel_th_bus
);
963 module_exit(intel_th_exit
);
965 MODULE_LICENSE("GPL v2");
966 MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver");
967 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");