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
, const struct device_driver
*driver
)
31 const 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 void 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
);
104 if (thdev
->type
== INTEL_TH_SWITCH
) {
105 struct intel_th
*th
= to_intel_th(hub
);
111 * intel_th_child_remove returns 0 unconditionally, so there is
112 * no need to check the return value of device_for_each_child.
114 device_for_each_child(dev
, thdev
, intel_th_child_remove
);
117 * Remove outputs, that is, hub's children: they are created
118 * at hub's probe time by having the hub call
119 * intel_th_output_enable() for each of them.
121 for (i
= 0, lowest
= -1; i
< th
->num_thdevs
; i
++) {
123 * Move the non-output devices from higher up the
124 * th->thdev[] array to lower positions to maintain
125 * a contiguous array.
127 if (th
->thdev
[i
]->type
!= INTEL_TH_OUTPUT
) {
129 th
->thdev
[lowest
] = th
->thdev
[i
];
140 intel_th_device_remove(th
->thdev
[i
]);
145 th
->num_thdevs
= lowest
;
148 if (thdrv
->attr_group
)
149 sysfs_remove_group(&thdev
->dev
.kobj
, thdrv
->attr_group
);
151 pm_runtime_get_sync(dev
);
153 thdrv
->remove(thdev
);
155 if (intel_th_output_assigned(thdev
)) {
156 struct intel_th_driver
*hubdrv
=
157 to_intel_th_driver(dev
->parent
->driver
);
160 /* does not talk to hardware */
161 hubdrv
->unassign(hub
, thdev
);
164 pm_runtime_disable(dev
);
165 pm_runtime_set_active(dev
);
166 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 const 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(const struct device
*dev
, umode_t
*mode
,
189 kuid_t
*uid
, kgid_t
*gid
)
191 const struct intel_th_device
*thdev
= to_intel_th_device(dev
);
192 const 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 void intel_th_trace_prepare(struct intel_th_device
*thdev
)
220 struct intel_th_device
*hub
= to_intel_th_hub(thdev
);
221 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
223 if (hub
->type
!= INTEL_TH_SWITCH
)
226 if (thdev
->type
!= INTEL_TH_OUTPUT
)
229 pm_runtime_get_sync(&thdev
->dev
);
230 hubdrv
->prepare(hub
, &thdev
->output
);
231 pm_runtime_put(&thdev
->dev
);
234 static int intel_th_output_activate(struct intel_th_device
*thdev
)
236 struct intel_th_driver
*thdrv
=
237 to_intel_th_driver_or_null(thdev
->dev
.driver
);
238 struct intel_th
*th
= to_intel_th(thdev
);
244 if (!try_module_get(thdrv
->driver
.owner
))
247 pm_runtime_get_sync(&thdev
->dev
);
250 ret
= th
->activate(th
);
254 intel_th_trace_prepare(thdev
);
256 ret
= thdrv
->activate(thdev
);
258 intel_th_trace_enable(thdev
);
261 goto fail_deactivate
;
270 pm_runtime_put(&thdev
->dev
);
271 module_put(thdrv
->driver
.owner
);
276 static void intel_th_output_deactivate(struct intel_th_device
*thdev
)
278 struct intel_th_driver
*thdrv
=
279 to_intel_th_driver_or_null(thdev
->dev
.driver
);
280 struct intel_th
*th
= to_intel_th(thdev
);
285 if (thdrv
->deactivate
)
286 thdrv
->deactivate(thdev
);
288 intel_th_trace_disable(thdev
);
293 pm_runtime_put(&thdev
->dev
);
294 module_put(thdrv
->driver
.owner
);
297 static ssize_t
active_show(struct device
*dev
, struct device_attribute
*attr
,
300 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
302 return scnprintf(buf
, PAGE_SIZE
, "%d\n", thdev
->output
.active
);
305 static ssize_t
active_store(struct device
*dev
, struct device_attribute
*attr
,
306 const char *buf
, size_t size
)
308 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
312 ret
= kstrtoul(buf
, 10, &val
);
316 if (!!val
!= thdev
->output
.active
) {
318 ret
= intel_th_output_activate(thdev
);
320 intel_th_output_deactivate(thdev
);
323 return ret
? ret
: size
;
326 static DEVICE_ATTR_RW(active
);
328 static struct attribute
*intel_th_output_attrs
[] = {
330 &dev_attr_active
.attr
,
334 ATTRIBUTE_GROUPS(intel_th_output
);
336 static const struct device_type intel_th_output_device_type
= {
337 .name
= "intel_th_output_device",
338 .groups
= intel_th_output_groups
,
339 .release
= intel_th_device_release
,
340 .devnode
= intel_th_output_devnode
,
343 static const struct device_type intel_th_switch_device_type
= {
344 .name
= "intel_th_switch_device",
345 .release
= intel_th_device_release
,
348 static const struct device_type
*intel_th_device_type
[] = {
349 [INTEL_TH_SOURCE
] = &intel_th_source_device_type
,
350 [INTEL_TH_OUTPUT
] = &intel_th_output_device_type
,
351 [INTEL_TH_SWITCH
] = &intel_th_switch_device_type
,
354 int intel_th_driver_register(struct intel_th_driver
*thdrv
)
356 if (!thdrv
->probe
|| !thdrv
->remove
)
359 thdrv
->driver
.bus
= &intel_th_bus
;
361 return driver_register(&thdrv
->driver
);
363 EXPORT_SYMBOL_GPL(intel_th_driver_register
);
365 void intel_th_driver_unregister(struct intel_th_driver
*thdrv
)
367 driver_unregister(&thdrv
->driver
);
369 EXPORT_SYMBOL_GPL(intel_th_driver_unregister
);
371 static struct intel_th_device
*
372 intel_th_device_alloc(struct intel_th
*th
, unsigned int type
, const char *name
,
375 struct device
*parent
;
376 struct intel_th_device
*thdev
;
378 if (type
== INTEL_TH_OUTPUT
)
379 parent
= &th
->hub
->dev
;
383 thdev
= kzalloc(sizeof(*thdev
) + strlen(name
) + 1, GFP_KERNEL
);
390 strcpy(thdev
->name
, name
);
391 device_initialize(&thdev
->dev
);
392 thdev
->dev
.bus
= &intel_th_bus
;
393 thdev
->dev
.type
= intel_th_device_type
[type
];
394 thdev
->dev
.parent
= parent
;
395 thdev
->dev
.dma_mask
= parent
->dma_mask
;
396 thdev
->dev
.dma_parms
= parent
->dma_parms
;
397 dma_set_coherent_mask(&thdev
->dev
, parent
->coherent_dma_mask
);
399 dev_set_name(&thdev
->dev
, "%d-%s%d", th
->id
, name
, id
);
401 dev_set_name(&thdev
->dev
, "%d-%s", th
->id
, name
);
406 static int intel_th_device_add_resources(struct intel_th_device
*thdev
,
407 struct resource
*res
, int nres
)
411 r
= kmemdup(res
, sizeof(*res
) * nres
, GFP_KERNEL
);
416 thdev
->num_resources
= nres
;
421 static void intel_th_device_remove(struct intel_th_device
*thdev
)
423 device_del(&thdev
->dev
);
424 put_device(&thdev
->dev
);
427 static void intel_th_device_free(struct intel_th_device
*thdev
)
429 kfree(thdev
->resource
);
434 * Intel(R) Trace Hub subdevices
436 static const struct intel_th_subdevice
{
438 struct resource res
[3];
445 } intel_th_subdevices
[] = {
450 /* Handle TSCU and CTS from GTH driver */
451 .start
= REG_GTH_OFFSET
,
452 .end
= REG_CTS_OFFSET
+ REG_CTS_LENGTH
- 1,
453 .flags
= IORESOURCE_MEM
,
457 .type
= INTEL_TH_SWITCH
,
464 .start
= REG_MSU_OFFSET
,
465 .end
= REG_MSU_OFFSET
+ REG_MSU_LENGTH
- 1,
466 .flags
= IORESOURCE_MEM
,
469 .start
= BUF_MSU_OFFSET
,
470 .end
= BUF_MSU_OFFSET
+ BUF_MSU_LENGTH
- 1,
471 .flags
= IORESOURCE_MEM
,
476 .type
= INTEL_TH_OUTPUT
,
479 .scrpd
= SCRPD_MEM_IS_PRIM_DEST
| SCRPD_MSC0_IS_ENABLED
,
485 .start
= REG_MSU_OFFSET
,
486 .end
= REG_MSU_OFFSET
+ REG_MSU_LENGTH
- 1,
487 .flags
= IORESOURCE_MEM
,
490 .start
= BUF_MSU_OFFSET
,
491 .end
= BUF_MSU_OFFSET
+ BUF_MSU_LENGTH
- 1,
492 .flags
= IORESOURCE_MEM
,
497 .type
= INTEL_TH_OUTPUT
,
500 .scrpd
= SCRPD_MEM_IS_PRIM_DEST
| SCRPD_MSC1_IS_ENABLED
,
506 .start
= REG_STH_OFFSET
,
507 .end
= REG_STH_OFFSET
+ REG_STH_LENGTH
- 1,
508 .flags
= IORESOURCE_MEM
,
513 .flags
= IORESOURCE_MEM
,
518 .type
= INTEL_TH_SOURCE
,
524 .start
= REG_STH_OFFSET
,
525 .end
= REG_STH_OFFSET
+ REG_STH_LENGTH
- 1,
526 .flags
= IORESOURCE_MEM
,
529 .start
= TH_MMIO_RTIT
,
531 .flags
= IORESOURCE_MEM
,
536 .type
= INTEL_TH_SOURCE
,
542 .start
= REG_PTI_OFFSET
,
543 .end
= REG_PTI_OFFSET
+ REG_PTI_LENGTH
- 1,
544 .flags
= IORESOURCE_MEM
,
549 .type
= INTEL_TH_OUTPUT
,
551 .scrpd
= SCRPD_PTI_IS_PRIM_DEST
,
557 .start
= REG_PTI_OFFSET
,
558 .end
= REG_PTI_OFFSET
+ REG_PTI_LENGTH
- 1,
559 .flags
= IORESOURCE_MEM
,
564 .type
= INTEL_TH_OUTPUT
,
566 .scrpd
= SCRPD_PTI_IS_PRIM_DEST
,
572 .start
= REG_DCIH_OFFSET
,
573 .end
= REG_DCIH_OFFSET
+ REG_DCIH_LENGTH
- 1,
574 .flags
= IORESOURCE_MEM
,
579 .type
= INTEL_TH_OUTPUT
,
583 #ifdef CONFIG_MODULES
584 static void __intel_th_request_hub_module(struct work_struct
*work
)
586 struct intel_th
*th
= container_of(work
, struct intel_th
,
587 request_module_work
);
589 request_module("intel_th_%s", th
->hub
->name
);
592 static int intel_th_request_hub_module(struct intel_th
*th
)
594 INIT_WORK(&th
->request_module_work
, __intel_th_request_hub_module
);
595 schedule_work(&th
->request_module_work
);
600 static void intel_th_request_hub_module_flush(struct intel_th
*th
)
602 flush_work(&th
->request_module_work
);
605 static inline int intel_th_request_hub_module(struct intel_th
*th
)
610 static inline void intel_th_request_hub_module_flush(struct intel_th
*th
)
613 #endif /* CONFIG_MODULES */
615 static struct intel_th_device
*
616 intel_th_subdevice_alloc(struct intel_th
*th
,
617 const struct intel_th_subdevice
*subdev
)
619 struct intel_th_device
*thdev
;
620 struct resource res
[3];
621 unsigned int req
= 0;
624 thdev
= intel_th_device_alloc(th
, subdev
->type
, subdev
->name
,
627 return ERR_PTR(-ENOMEM
);
629 thdev
->drvdata
= th
->drvdata
;
631 memcpy(res
, subdev
->res
,
632 sizeof(struct resource
) * subdev
->nres
);
634 for (r
= 0; r
< subdev
->nres
; r
++) {
635 struct resource
*devres
= th
->resource
;
636 int bar
= TH_MMIO_CONFIG
;
639 * Take .end == 0 to mean 'take the whole bar',
640 * .start then tells us which bar it is. Default to
643 if (!res
[r
].end
&& res
[r
].flags
== IORESOURCE_MEM
) {
646 if (bar
>= th
->num_resources
)
647 goto fail_put_device
;
649 res
[r
].end
= resource_size(&devres
[bar
]) - 1;
652 if (res
[r
].flags
& IORESOURCE_MEM
) {
653 res
[r
].start
+= devres
[bar
].start
;
654 res
[r
].end
+= devres
[bar
].start
;
656 dev_dbg(th
->dev
, "%s:%d @ %pR\n",
657 subdev
->name
, r
, &res
[r
]);
658 } else if (res
[r
].flags
& IORESOURCE_IRQ
) {
660 * Only pass on the IRQ if we have useful interrupts:
661 * the ones that can be configured via MINTCTL.
663 if (INTEL_TH_CAP(th
, has_mintctl
) && th
->irq
!= -1)
664 res
[r
].start
= th
->irq
;
668 err
= intel_th_device_add_resources(thdev
, res
, subdev
->nres
);
670 goto fail_put_device
;
672 if (subdev
->type
== INTEL_TH_OUTPUT
) {
674 thdev
->dev
.devt
= MKDEV(th
->major
, th
->num_thdevs
);
675 thdev
->output
.type
= subdev
->otype
;
676 thdev
->output
.port
= -1;
677 thdev
->output
.scratchpad
= subdev
->scrpd
;
678 } else if (subdev
->type
== INTEL_TH_SWITCH
) {
680 INTEL_TH_CAP(th
, host_mode_only
) ? true : host_mode
;
684 err
= device_add(&thdev
->dev
);
688 /* need switch driver to be loaded to enumerate the rest */
689 if (subdev
->type
== INTEL_TH_SWITCH
&& !req
) {
690 err
= intel_th_request_hub_module(th
);
698 kfree(thdev
->resource
);
701 put_device(&thdev
->dev
);
707 * intel_th_output_enable() - find and enable a device for a given output type
708 * @th: Intel TH instance
709 * @otype: output type
711 * Go through the unallocated output devices, find the first one whos type
712 * matches @otype and instantiate it. These devices are removed when the hub
713 * device is removed, see intel_th_remove().
715 int intel_th_output_enable(struct intel_th
*th
, unsigned int otype
)
717 struct intel_th_device
*thdev
;
718 int src
= 0, dst
= 0;
720 for (src
= 0, dst
= 0; dst
<= th
->num_thdevs
; src
++, dst
++) {
721 for (; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
722 if (intel_th_subdevices
[src
].type
!= INTEL_TH_OUTPUT
)
725 if (intel_th_subdevices
[src
].otype
!= otype
)
731 /* no unallocated matching subdevices */
732 if (src
== ARRAY_SIZE(intel_th_subdevices
))
735 for (; dst
< th
->num_thdevs
; dst
++) {
736 if (th
->thdev
[dst
]->type
!= INTEL_TH_OUTPUT
)
739 if (th
->thdev
[dst
]->output
.type
!= otype
)
746 * intel_th_subdevices[src] matches our requirements and is
747 * not matched in th::thdev[]
749 if (dst
== th
->num_thdevs
)
756 thdev
= intel_th_subdevice_alloc(th
, &intel_th_subdevices
[src
]);
758 return PTR_ERR(thdev
);
760 th
->thdev
[th
->num_thdevs
++] = thdev
;
764 EXPORT_SYMBOL_GPL(intel_th_output_enable
);
766 static int intel_th_populate(struct intel_th
*th
)
770 /* create devices for each intel_th_subdevice */
771 for (src
= 0; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
772 const struct intel_th_subdevice
*subdev
=
773 &intel_th_subdevices
[src
];
774 struct intel_th_device
*thdev
;
776 /* only allow SOURCE and SWITCH devices in host mode */
777 if ((INTEL_TH_CAP(th
, host_mode_only
) || host_mode
) &&
778 subdev
->type
== INTEL_TH_OUTPUT
)
782 * don't enable port OUTPUTs in this path; SWITCH enables them
783 * via intel_th_output_enable()
785 if (subdev
->type
== INTEL_TH_OUTPUT
&&
786 subdev
->otype
!= GTH_NONE
)
789 thdev
= intel_th_subdevice_alloc(th
, subdev
);
790 /* note: caller should free subdevices from th::thdev[] */
792 /* ENODEV for individual subdevices is allowed */
793 if (PTR_ERR(thdev
) == -ENODEV
)
796 return PTR_ERR(thdev
);
799 th
->thdev
[th
->num_thdevs
++] = thdev
;
805 static int intel_th_output_open(struct inode
*inode
, struct file
*file
)
807 const struct file_operations
*fops
;
808 struct intel_th_driver
*thdrv
;
812 dev
= bus_find_device_by_devt(&intel_th_bus
, inode
->i_rdev
);
813 if (!dev
|| !dev
->driver
)
816 thdrv
= to_intel_th_driver(dev
->driver
);
817 fops
= fops_get(thdrv
->fops
);
821 replace_fops(file
, fops
);
823 file
->private_data
= to_intel_th_device(dev
);
825 if (file
->f_op
->open
) {
826 err
= file
->f_op
->open(inode
, file
);
833 static const struct file_operations intel_th_output_fops
= {
834 .open
= intel_th_output_open
,
835 .llseek
= noop_llseek
,
838 static irqreturn_t
intel_th_irq(int irq
, void *data
)
840 struct intel_th
*th
= data
;
841 irqreturn_t ret
= IRQ_NONE
;
842 struct intel_th_driver
*d
;
845 for (i
= 0; i
< th
->num_thdevs
; i
++) {
846 if (th
->thdev
[i
]->type
!= INTEL_TH_OUTPUT
)
849 d
= to_intel_th_driver(th
->thdev
[i
]->dev
.driver
);
851 ret
|= d
->irq(th
->thdev
[i
]);
858 * intel_th_alloc() - allocate a new Intel TH device and its subdevices
859 * @dev: parent device
860 * @devres: resources indexed by th_mmio_idx
864 intel_th_alloc(struct device
*dev
, const struct intel_th_drvdata
*drvdata
,
865 struct resource
*devres
, unsigned int ndevres
)
867 int err
, r
, nr_mmios
= 0;
870 th
= kzalloc(sizeof(*th
), GFP_KERNEL
);
872 return ERR_PTR(-ENOMEM
);
874 th
->id
= ida_alloc(&intel_th_ida
, GFP_KERNEL
);
880 th
->major
= __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS
,
881 "intel_th/output", &intel_th_output_fops
);
888 th
->drvdata
= drvdata
;
890 for (r
= 0; r
< ndevres
; r
++)
891 switch (devres
[r
].flags
& IORESOURCE_TYPE_BITS
) {
893 th
->resource
[nr_mmios
++] = devres
[r
];
896 err
= devm_request_irq(dev
, devres
[r
].start
,
897 intel_th_irq
, IRQF_SHARED
,
903 th
->irq
= devres
[r
].start
;
907 dev_warn(dev
, "Unknown resource type %lx\n",
912 th
->num_resources
= nr_mmios
;
914 dev_set_drvdata(dev
, th
);
916 pm_runtime_no_callbacks(dev
);
918 pm_runtime_allow(dev
);
920 err
= intel_th_populate(th
);
922 /* free the subdevices and undo everything */
930 __unregister_chrdev(th
->major
, 0, TH_POSSIBLE_OUTPUTS
,
934 ida_free(&intel_th_ida
, th
->id
);
941 EXPORT_SYMBOL_GPL(intel_th_alloc
);
943 void intel_th_free(struct intel_th
*th
)
947 intel_th_request_hub_module_flush(th
);
949 intel_th_device_remove(th
->hub
);
950 for (i
= 0; i
< th
->num_thdevs
; i
++) {
951 if (th
->thdev
[i
] != th
->hub
)
952 intel_th_device_remove(th
->thdev
[i
]);
958 for (i
= 0; i
< th
->num_irqs
; i
++)
959 devm_free_irq(th
->dev
, th
->irq
+ i
, th
);
961 pm_runtime_get_sync(th
->dev
);
962 pm_runtime_forbid(th
->dev
);
964 __unregister_chrdev(th
->major
, 0, TH_POSSIBLE_OUTPUTS
,
967 ida_free(&intel_th_ida
, th
->id
);
971 EXPORT_SYMBOL_GPL(intel_th_free
);
974 * intel_th_trace_enable() - enable tracing for an output device
975 * @thdev: output device that requests tracing be enabled
977 int intel_th_trace_enable(struct intel_th_device
*thdev
)
979 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
980 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
982 if (WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
))
985 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
988 pm_runtime_get_sync(&thdev
->dev
);
989 hubdrv
->enable(hub
, &thdev
->output
);
993 EXPORT_SYMBOL_GPL(intel_th_trace_enable
);
996 * intel_th_trace_switch() - execute a switch sequence
997 * @thdev: output device that requests tracing switch
999 int intel_th_trace_switch(struct intel_th_device
*thdev
)
1001 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
1002 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
1004 if (WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
))
1007 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
1010 hubdrv
->trig_switch(hub
, &thdev
->output
);
1014 EXPORT_SYMBOL_GPL(intel_th_trace_switch
);
1017 * intel_th_trace_disable() - disable tracing for an output device
1018 * @thdev: output device that requests tracing be disabled
1020 int intel_th_trace_disable(struct intel_th_device
*thdev
)
1022 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
1023 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
1025 WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
);
1026 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
1029 hubdrv
->disable(hub
, &thdev
->output
);
1030 pm_runtime_put(&thdev
->dev
);
1034 EXPORT_SYMBOL_GPL(intel_th_trace_disable
);
1036 int intel_th_set_output(struct intel_th_device
*thdev
,
1037 unsigned int master
)
1039 struct intel_th_device
*hub
= to_intel_th_hub(thdev
);
1040 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
1043 /* In host mode, this is up to the external debugger, do nothing. */
1048 * hub is instantiated together with the source device that
1049 * calls here, so guaranteed to be present.
1051 hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
1052 if (!hubdrv
|| !try_module_get(hubdrv
->driver
.owner
))
1055 if (!hubdrv
->set_output
) {
1060 ret
= hubdrv
->set_output(hub
, master
);
1063 module_put(hubdrv
->driver
.owner
);
1066 EXPORT_SYMBOL_GPL(intel_th_set_output
);
1068 static int __init
intel_th_init(void)
1070 intel_th_debug_init();
1072 return bus_register(&intel_th_bus
);
1074 subsys_initcall(intel_th_init
);
1076 static void __exit
intel_th_exit(void)
1078 intel_th_debug_done();
1080 bus_unregister(&intel_th_bus
);
1082 module_exit(intel_th_exit
);
1084 MODULE_LICENSE("GPL v2");
1085 MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver");
1086 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");