1 // SPDX-License-Identifier: GPL-2.0
3 * Intel(R) Trace Hub driver core
5 * Copyright (C) 2014-2015 Intel Corporation.
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/types.h>
11 #include <linux/module.h>
12 #include <linux/device.h>
13 #include <linux/sysfs.h>
14 #include <linux/kdev_t.h>
15 #include <linux/debugfs.h>
16 #include <linux/idr.h>
17 #include <linux/pci.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/dma-mapping.h>
24 static bool host_mode __read_mostly
;
25 module_param(host_mode
, bool, 0444);
27 static DEFINE_IDA(intel_th_ida
);
29 static int intel_th_match(struct device
*dev
, struct device_driver
*driver
)
31 struct intel_th_driver
*thdrv
= to_intel_th_driver(driver
);
32 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
34 if (thdev
->type
== INTEL_TH_SWITCH
&&
35 (!thdrv
->enable
|| !thdrv
->disable
))
38 return !strcmp(thdev
->name
, driver
->name
);
41 static int intel_th_child_remove(struct device
*dev
, void *data
)
43 device_release_driver(dev
);
48 static int intel_th_probe(struct device
*dev
)
50 struct intel_th_driver
*thdrv
= to_intel_th_driver(dev
->driver
);
51 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
52 struct intel_th_driver
*hubdrv
;
53 struct intel_th_device
*hub
= NULL
;
56 if (thdev
->type
== INTEL_TH_SWITCH
)
59 hub
= to_intel_th_device(dev
->parent
);
61 if (!hub
|| !hub
->dev
.driver
)
64 hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
66 pm_runtime_set_active(dev
);
67 pm_runtime_no_callbacks(dev
);
68 pm_runtime_enable(dev
);
70 ret
= thdrv
->probe(to_intel_th_device(dev
));
74 if (thdrv
->attr_group
) {
75 ret
= sysfs_create_group(&thdev
->dev
.kobj
, thdrv
->attr_group
);
80 if (thdev
->type
== INTEL_TH_OUTPUT
&&
81 !intel_th_output_assigned(thdev
))
82 /* does not talk to hardware */
83 ret
= hubdrv
->assign(hub
, thdev
);
91 pm_runtime_disable(dev
);
96 static void intel_th_device_remove(struct intel_th_device
*thdev
);
98 static int intel_th_remove(struct device
*dev
)
100 struct intel_th_driver
*thdrv
= to_intel_th_driver(dev
->driver
);
101 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
102 struct intel_th_device
*hub
= to_intel_th_hub(thdev
);
105 if (thdev
->type
== INTEL_TH_SWITCH
) {
106 struct intel_th
*th
= to_intel_th(hub
);
109 /* disconnect outputs */
110 err
= device_for_each_child(dev
, thdev
, intel_th_child_remove
);
115 * Remove outputs, that is, hub's children: they are created
116 * at hub's probe time by having the hub call
117 * intel_th_output_enable() for each of them.
119 for (i
= 0, lowest
= -1; i
< th
->num_thdevs
; i
++) {
121 * Move the non-output devices from higher up the
122 * th->thdev[] array to lower positions to maintain
123 * a contiguous array.
125 if (th
->thdev
[i
]->type
!= INTEL_TH_OUTPUT
) {
127 th
->thdev
[lowest
] = th
->thdev
[i
];
138 intel_th_device_remove(th
->thdev
[i
]);
143 th
->num_thdevs
= lowest
;
146 if (thdrv
->attr_group
)
147 sysfs_remove_group(&thdev
->dev
.kobj
, thdrv
->attr_group
);
149 pm_runtime_get_sync(dev
);
151 thdrv
->remove(thdev
);
153 if (intel_th_output_assigned(thdev
)) {
154 struct intel_th_driver
*hubdrv
=
155 to_intel_th_driver(dev
->parent
->driver
);
158 /* does not talk to hardware */
159 hubdrv
->unassign(hub
, thdev
);
162 pm_runtime_disable(dev
);
163 pm_runtime_set_active(dev
);
164 pm_runtime_enable(dev
);
169 static struct bus_type intel_th_bus
= {
171 .match
= intel_th_match
,
172 .probe
= intel_th_probe
,
173 .remove
= intel_th_remove
,
176 static void intel_th_device_free(struct intel_th_device
*thdev
);
178 static void intel_th_device_release(struct device
*dev
)
180 intel_th_device_free(to_intel_th_device(dev
));
183 static struct device_type intel_th_source_device_type
= {
184 .name
= "intel_th_source_device",
185 .release
= intel_th_device_release
,
188 static char *intel_th_output_devnode(struct device
*dev
, umode_t
*mode
,
189 kuid_t
*uid
, kgid_t
*gid
)
191 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
192 struct intel_th
*th
= to_intel_th(thdev
);
196 node
= kasprintf(GFP_KERNEL
, "intel_th%d/%s%d", th
->id
,
197 thdev
->name
, thdev
->id
);
199 node
= kasprintf(GFP_KERNEL
, "intel_th%d/%s", th
->id
,
205 static ssize_t
port_show(struct device
*dev
, struct device_attribute
*attr
,
208 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
210 if (thdev
->output
.port
>= 0)
211 return scnprintf(buf
, PAGE_SIZE
, "%u\n", thdev
->output
.port
);
213 return scnprintf(buf
, PAGE_SIZE
, "unassigned\n");
216 static DEVICE_ATTR_RO(port
);
218 static int intel_th_output_activate(struct intel_th_device
*thdev
)
220 struct intel_th_driver
*thdrv
=
221 to_intel_th_driver_or_null(thdev
->dev
.driver
);
222 struct intel_th
*th
= to_intel_th(thdev
);
228 if (!try_module_get(thdrv
->driver
.owner
))
231 pm_runtime_get_sync(&thdev
->dev
);
234 ret
= th
->activate(th
);
239 ret
= thdrv
->activate(thdev
);
241 intel_th_trace_enable(thdev
);
244 goto fail_deactivate
;
253 pm_runtime_put(&thdev
->dev
);
254 module_put(thdrv
->driver
.owner
);
259 static void intel_th_output_deactivate(struct intel_th_device
*thdev
)
261 struct intel_th_driver
*thdrv
=
262 to_intel_th_driver_or_null(thdev
->dev
.driver
);
263 struct intel_th
*th
= to_intel_th(thdev
);
268 if (thdrv
->deactivate
)
269 thdrv
->deactivate(thdev
);
271 intel_th_trace_disable(thdev
);
276 pm_runtime_put(&thdev
->dev
);
277 module_put(thdrv
->driver
.owner
);
280 static ssize_t
active_show(struct device
*dev
, struct device_attribute
*attr
,
283 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
285 return scnprintf(buf
, PAGE_SIZE
, "%d\n", thdev
->output
.active
);
288 static ssize_t
active_store(struct device
*dev
, struct device_attribute
*attr
,
289 const char *buf
, size_t size
)
291 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
295 ret
= kstrtoul(buf
, 10, &val
);
299 if (!!val
!= thdev
->output
.active
) {
301 ret
= intel_th_output_activate(thdev
);
303 intel_th_output_deactivate(thdev
);
306 return ret
? ret
: size
;
309 static DEVICE_ATTR_RW(active
);
311 static struct attribute
*intel_th_output_attrs
[] = {
313 &dev_attr_active
.attr
,
317 ATTRIBUTE_GROUPS(intel_th_output
);
319 static struct device_type intel_th_output_device_type
= {
320 .name
= "intel_th_output_device",
321 .groups
= intel_th_output_groups
,
322 .release
= intel_th_device_release
,
323 .devnode
= intel_th_output_devnode
,
326 static struct device_type intel_th_switch_device_type
= {
327 .name
= "intel_th_switch_device",
328 .release
= intel_th_device_release
,
331 static struct device_type
*intel_th_device_type
[] = {
332 [INTEL_TH_SOURCE
] = &intel_th_source_device_type
,
333 [INTEL_TH_OUTPUT
] = &intel_th_output_device_type
,
334 [INTEL_TH_SWITCH
] = &intel_th_switch_device_type
,
337 int intel_th_driver_register(struct intel_th_driver
*thdrv
)
339 if (!thdrv
->probe
|| !thdrv
->remove
)
342 thdrv
->driver
.bus
= &intel_th_bus
;
344 return driver_register(&thdrv
->driver
);
346 EXPORT_SYMBOL_GPL(intel_th_driver_register
);
348 void intel_th_driver_unregister(struct intel_th_driver
*thdrv
)
350 driver_unregister(&thdrv
->driver
);
352 EXPORT_SYMBOL_GPL(intel_th_driver_unregister
);
354 static struct intel_th_device
*
355 intel_th_device_alloc(struct intel_th
*th
, unsigned int type
, const char *name
,
358 struct device
*parent
;
359 struct intel_th_device
*thdev
;
361 if (type
== INTEL_TH_OUTPUT
)
362 parent
= &th
->hub
->dev
;
366 thdev
= kzalloc(sizeof(*thdev
) + strlen(name
) + 1, GFP_KERNEL
);
373 strcpy(thdev
->name
, name
);
374 device_initialize(&thdev
->dev
);
375 thdev
->dev
.bus
= &intel_th_bus
;
376 thdev
->dev
.type
= intel_th_device_type
[type
];
377 thdev
->dev
.parent
= parent
;
378 thdev
->dev
.dma_mask
= parent
->dma_mask
;
379 thdev
->dev
.dma_parms
= parent
->dma_parms
;
380 dma_set_coherent_mask(&thdev
->dev
, parent
->coherent_dma_mask
);
382 dev_set_name(&thdev
->dev
, "%d-%s%d", th
->id
, name
, id
);
384 dev_set_name(&thdev
->dev
, "%d-%s", th
->id
, name
);
389 static int intel_th_device_add_resources(struct intel_th_device
*thdev
,
390 struct resource
*res
, int nres
)
394 r
= kmemdup(res
, sizeof(*res
) * nres
, GFP_KERNEL
);
399 thdev
->num_resources
= nres
;
404 static void intel_th_device_remove(struct intel_th_device
*thdev
)
406 device_del(&thdev
->dev
);
407 put_device(&thdev
->dev
);
410 static void intel_th_device_free(struct intel_th_device
*thdev
)
412 kfree(thdev
->resource
);
417 * Intel(R) Trace Hub subdevices
419 static const struct intel_th_subdevice
{
421 struct resource res
[3];
428 } intel_th_subdevices
[] = {
433 /* Handle TSCU and CTS from GTH driver */
434 .start
= REG_GTH_OFFSET
,
435 .end
= REG_CTS_OFFSET
+ REG_CTS_LENGTH
- 1,
436 .flags
= IORESOURCE_MEM
,
440 .type
= INTEL_TH_SWITCH
,
447 .start
= REG_MSU_OFFSET
,
448 .end
= REG_MSU_OFFSET
+ REG_MSU_LENGTH
- 1,
449 .flags
= IORESOURCE_MEM
,
452 .start
= BUF_MSU_OFFSET
,
453 .end
= BUF_MSU_OFFSET
+ BUF_MSU_LENGTH
- 1,
454 .flags
= IORESOURCE_MEM
,
459 .type
= INTEL_TH_OUTPUT
,
462 .scrpd
= SCRPD_MEM_IS_PRIM_DEST
| SCRPD_MSC0_IS_ENABLED
,
468 .start
= REG_MSU_OFFSET
,
469 .end
= REG_MSU_OFFSET
+ REG_MSU_LENGTH
- 1,
470 .flags
= IORESOURCE_MEM
,
473 .start
= BUF_MSU_OFFSET
,
474 .end
= BUF_MSU_OFFSET
+ BUF_MSU_LENGTH
- 1,
475 .flags
= IORESOURCE_MEM
,
480 .type
= INTEL_TH_OUTPUT
,
483 .scrpd
= SCRPD_MEM_IS_PRIM_DEST
| SCRPD_MSC1_IS_ENABLED
,
489 .start
= REG_STH_OFFSET
,
490 .end
= REG_STH_OFFSET
+ REG_STH_LENGTH
- 1,
491 .flags
= IORESOURCE_MEM
,
496 .flags
= IORESOURCE_MEM
,
501 .type
= INTEL_TH_SOURCE
,
507 .start
= REG_STH_OFFSET
,
508 .end
= REG_STH_OFFSET
+ REG_STH_LENGTH
- 1,
509 .flags
= IORESOURCE_MEM
,
512 .start
= TH_MMIO_RTIT
,
514 .flags
= IORESOURCE_MEM
,
519 .type
= INTEL_TH_SOURCE
,
525 .start
= REG_PTI_OFFSET
,
526 .end
= REG_PTI_OFFSET
+ REG_PTI_LENGTH
- 1,
527 .flags
= IORESOURCE_MEM
,
532 .type
= INTEL_TH_OUTPUT
,
534 .scrpd
= SCRPD_PTI_IS_PRIM_DEST
,
540 .start
= REG_PTI_OFFSET
,
541 .end
= REG_PTI_OFFSET
+ REG_PTI_LENGTH
- 1,
542 .flags
= IORESOURCE_MEM
,
547 .type
= INTEL_TH_OUTPUT
,
549 .scrpd
= SCRPD_PTI_IS_PRIM_DEST
,
555 .start
= REG_DCIH_OFFSET
,
556 .end
= REG_DCIH_OFFSET
+ REG_DCIH_LENGTH
- 1,
557 .flags
= IORESOURCE_MEM
,
562 .type
= INTEL_TH_OUTPUT
,
566 #ifdef CONFIG_MODULES
567 static void __intel_th_request_hub_module(struct work_struct
*work
)
569 struct intel_th
*th
= container_of(work
, struct intel_th
,
570 request_module_work
);
572 request_module("intel_th_%s", th
->hub
->name
);
575 static int intel_th_request_hub_module(struct intel_th
*th
)
577 INIT_WORK(&th
->request_module_work
, __intel_th_request_hub_module
);
578 schedule_work(&th
->request_module_work
);
583 static void intel_th_request_hub_module_flush(struct intel_th
*th
)
585 flush_work(&th
->request_module_work
);
588 static inline int intel_th_request_hub_module(struct intel_th
*th
)
593 static inline void intel_th_request_hub_module_flush(struct intel_th
*th
)
596 #endif /* CONFIG_MODULES */
598 static struct intel_th_device
*
599 intel_th_subdevice_alloc(struct intel_th
*th
,
600 const struct intel_th_subdevice
*subdev
)
602 struct intel_th_device
*thdev
;
603 struct resource res
[3];
604 unsigned int req
= 0;
607 thdev
= intel_th_device_alloc(th
, subdev
->type
, subdev
->name
,
610 return ERR_PTR(-ENOMEM
);
612 thdev
->drvdata
= th
->drvdata
;
614 memcpy(res
, subdev
->res
,
615 sizeof(struct resource
) * subdev
->nres
);
617 for (r
= 0; r
< subdev
->nres
; r
++) {
618 struct resource
*devres
= th
->resource
;
619 int bar
= TH_MMIO_CONFIG
;
622 * Take .end == 0 to mean 'take the whole bar',
623 * .start then tells us which bar it is. Default to
626 if (!res
[r
].end
&& res
[r
].flags
== IORESOURCE_MEM
) {
629 if (bar
>= th
->num_resources
)
630 goto fail_put_device
;
632 res
[r
].end
= resource_size(&devres
[bar
]) - 1;
635 if (res
[r
].flags
& IORESOURCE_MEM
) {
636 res
[r
].start
+= devres
[bar
].start
;
637 res
[r
].end
+= devres
[bar
].start
;
639 dev_dbg(th
->dev
, "%s:%d @ %pR\n",
640 subdev
->name
, r
, &res
[r
]);
641 } else if (res
[r
].flags
& IORESOURCE_IRQ
) {
643 * Only pass on the IRQ if we have useful interrupts:
644 * the ones that can be configured via MINTCTL.
646 if (INTEL_TH_CAP(th
, has_mintctl
) && th
->irq
!= -1)
647 res
[r
].start
= th
->irq
;
651 err
= intel_th_device_add_resources(thdev
, res
, subdev
->nres
);
653 goto fail_put_device
;
655 if (subdev
->type
== INTEL_TH_OUTPUT
) {
657 thdev
->dev
.devt
= MKDEV(th
->major
, th
->num_thdevs
);
658 thdev
->output
.type
= subdev
->otype
;
659 thdev
->output
.port
= -1;
660 thdev
->output
.scratchpad
= subdev
->scrpd
;
661 } else if (subdev
->type
== INTEL_TH_SWITCH
) {
663 INTEL_TH_CAP(th
, host_mode_only
) ? true : host_mode
;
667 err
= device_add(&thdev
->dev
);
671 /* need switch driver to be loaded to enumerate the rest */
672 if (subdev
->type
== INTEL_TH_SWITCH
&& !req
) {
673 err
= intel_th_request_hub_module(th
);
681 kfree(thdev
->resource
);
684 put_device(&thdev
->dev
);
690 * intel_th_output_enable() - find and enable a device for a given output type
691 * @th: Intel TH instance
692 * @otype: output type
694 * Go through the unallocated output devices, find the first one whos type
695 * matches @otype and instantiate it. These devices are removed when the hub
696 * device is removed, see intel_th_remove().
698 int intel_th_output_enable(struct intel_th
*th
, unsigned int otype
)
700 struct intel_th_device
*thdev
;
701 int src
= 0, dst
= 0;
703 for (src
= 0, dst
= 0; dst
<= th
->num_thdevs
; src
++, dst
++) {
704 for (; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
705 if (intel_th_subdevices
[src
].type
!= INTEL_TH_OUTPUT
)
708 if (intel_th_subdevices
[src
].otype
!= otype
)
714 /* no unallocated matching subdevices */
715 if (src
== ARRAY_SIZE(intel_th_subdevices
))
718 for (; dst
< th
->num_thdevs
; dst
++) {
719 if (th
->thdev
[dst
]->type
!= INTEL_TH_OUTPUT
)
722 if (th
->thdev
[dst
]->output
.type
!= otype
)
729 * intel_th_subdevices[src] matches our requirements and is
730 * not matched in th::thdev[]
732 if (dst
== th
->num_thdevs
)
739 thdev
= intel_th_subdevice_alloc(th
, &intel_th_subdevices
[src
]);
741 return PTR_ERR(thdev
);
743 th
->thdev
[th
->num_thdevs
++] = thdev
;
747 EXPORT_SYMBOL_GPL(intel_th_output_enable
);
749 static int intel_th_populate(struct intel_th
*th
)
753 /* create devices for each intel_th_subdevice */
754 for (src
= 0; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
755 const struct intel_th_subdevice
*subdev
=
756 &intel_th_subdevices
[src
];
757 struct intel_th_device
*thdev
;
759 /* only allow SOURCE and SWITCH devices in host mode */
760 if ((INTEL_TH_CAP(th
, host_mode_only
) || host_mode
) &&
761 subdev
->type
== INTEL_TH_OUTPUT
)
765 * don't enable port OUTPUTs in this path; SWITCH enables them
766 * via intel_th_output_enable()
768 if (subdev
->type
== INTEL_TH_OUTPUT
&&
769 subdev
->otype
!= GTH_NONE
)
772 thdev
= intel_th_subdevice_alloc(th
, subdev
);
773 /* note: caller should free subdevices from th::thdev[] */
775 /* ENODEV for individual subdevices is allowed */
776 if (PTR_ERR(thdev
) == -ENODEV
)
779 return PTR_ERR(thdev
);
782 th
->thdev
[th
->num_thdevs
++] = thdev
;
788 static int intel_th_output_open(struct inode
*inode
, struct file
*file
)
790 const struct file_operations
*fops
;
791 struct intel_th_driver
*thdrv
;
795 dev
= bus_find_device_by_devt(&intel_th_bus
, inode
->i_rdev
);
796 if (!dev
|| !dev
->driver
)
799 thdrv
= to_intel_th_driver(dev
->driver
);
800 fops
= fops_get(thdrv
->fops
);
804 replace_fops(file
, fops
);
806 file
->private_data
= to_intel_th_device(dev
);
808 if (file
->f_op
->open
) {
809 err
= file
->f_op
->open(inode
, file
);
816 static const struct file_operations intel_th_output_fops
= {
817 .open
= intel_th_output_open
,
818 .llseek
= noop_llseek
,
821 static irqreturn_t
intel_th_irq(int irq
, void *data
)
823 struct intel_th
*th
= data
;
824 irqreturn_t ret
= IRQ_NONE
;
825 struct intel_th_driver
*d
;
828 for (i
= 0; i
< th
->num_thdevs
; i
++) {
829 if (th
->thdev
[i
]->type
!= INTEL_TH_OUTPUT
)
832 d
= to_intel_th_driver(th
->thdev
[i
]->dev
.driver
);
834 ret
|= d
->irq(th
->thdev
[i
]);
841 * intel_th_alloc() - allocate a new Intel TH device and its subdevices
842 * @dev: parent device
843 * @devres: resources indexed by th_mmio_idx
847 intel_th_alloc(struct device
*dev
, struct intel_th_drvdata
*drvdata
,
848 struct resource
*devres
, unsigned int ndevres
)
850 int err
, r
, nr_mmios
= 0;
853 th
= kzalloc(sizeof(*th
), GFP_KERNEL
);
855 return ERR_PTR(-ENOMEM
);
857 th
->id
= ida_simple_get(&intel_th_ida
, 0, 0, GFP_KERNEL
);
863 th
->major
= __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS
,
864 "intel_th/output", &intel_th_output_fops
);
871 th
->drvdata
= drvdata
;
873 for (r
= 0; r
< ndevres
; r
++)
874 switch (devres
[r
].flags
& IORESOURCE_TYPE_BITS
) {
876 th
->resource
[nr_mmios
++] = devres
[r
];
879 err
= devm_request_irq(dev
, devres
[r
].start
,
880 intel_th_irq
, IRQF_SHARED
,
886 th
->irq
= devres
[r
].start
;
890 dev_warn(dev
, "Unknown resource type %lx\n",
895 th
->num_resources
= nr_mmios
;
897 dev_set_drvdata(dev
, th
);
899 pm_runtime_no_callbacks(dev
);
901 pm_runtime_allow(dev
);
903 err
= intel_th_populate(th
);
905 /* free the subdevices and undo everything */
913 __unregister_chrdev(th
->major
, 0, TH_POSSIBLE_OUTPUTS
,
917 ida_simple_remove(&intel_th_ida
, th
->id
);
924 EXPORT_SYMBOL_GPL(intel_th_alloc
);
926 void intel_th_free(struct intel_th
*th
)
930 intel_th_request_hub_module_flush(th
);
932 intel_th_device_remove(th
->hub
);
933 for (i
= 0; i
< th
->num_thdevs
; i
++) {
934 if (th
->thdev
[i
] != th
->hub
)
935 intel_th_device_remove(th
->thdev
[i
]);
941 for (i
= 0; i
< th
->num_irqs
; i
++)
942 devm_free_irq(th
->dev
, th
->irq
+ i
, th
);
944 pm_runtime_get_sync(th
->dev
);
945 pm_runtime_forbid(th
->dev
);
947 __unregister_chrdev(th
->major
, 0, TH_POSSIBLE_OUTPUTS
,
950 ida_simple_remove(&intel_th_ida
, th
->id
);
954 EXPORT_SYMBOL_GPL(intel_th_free
);
957 * intel_th_trace_enable() - enable tracing for an output device
958 * @thdev: output device that requests tracing be enabled
960 int intel_th_trace_enable(struct intel_th_device
*thdev
)
962 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
963 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
965 if (WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
))
968 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
971 pm_runtime_get_sync(&thdev
->dev
);
972 hubdrv
->enable(hub
, &thdev
->output
);
976 EXPORT_SYMBOL_GPL(intel_th_trace_enable
);
979 * intel_th_trace_switch() - execute a switch sequence
980 * @thdev: output device that requests tracing switch
982 int intel_th_trace_switch(struct intel_th_device
*thdev
)
984 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
985 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
987 if (WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
))
990 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
993 hubdrv
->trig_switch(hub
, &thdev
->output
);
997 EXPORT_SYMBOL_GPL(intel_th_trace_switch
);
1000 * intel_th_trace_disable() - disable tracing for an output device
1001 * @thdev: output device that requests tracing be disabled
1003 int intel_th_trace_disable(struct intel_th_device
*thdev
)
1005 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
1006 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
1008 WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
);
1009 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
1012 hubdrv
->disable(hub
, &thdev
->output
);
1013 pm_runtime_put(&thdev
->dev
);
1017 EXPORT_SYMBOL_GPL(intel_th_trace_disable
);
1019 int intel_th_set_output(struct intel_th_device
*thdev
,
1020 unsigned int master
)
1022 struct intel_th_device
*hub
= to_intel_th_hub(thdev
);
1023 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
1026 /* In host mode, this is up to the external debugger, do nothing. */
1031 * hub is instantiated together with the source device that
1032 * calls here, so guaranteed to be present.
1034 hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
1035 if (!hubdrv
|| !try_module_get(hubdrv
->driver
.owner
))
1038 if (!hubdrv
->set_output
) {
1043 ret
= hubdrv
->set_output(hub
, master
);
1046 module_put(hubdrv
->driver
.owner
);
1049 EXPORT_SYMBOL_GPL(intel_th_set_output
);
1051 static int __init
intel_th_init(void)
1053 intel_th_debug_init();
1055 return bus_register(&intel_th_bus
);
1057 subsys_initcall(intel_th_init
);
1059 static void __exit
intel_th_exit(void)
1061 intel_th_debug_done();
1063 bus_unregister(&intel_th_bus
);
1065 module_exit(intel_th_exit
);
1067 MODULE_LICENSE("GPL v2");
1068 MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver");
1069 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");