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
]);
150 th
->num_thdevs
= lowest
;
153 if (thdrv
->attr_group
)
154 sysfs_remove_group(&thdev
->dev
.kobj
, thdrv
->attr_group
);
156 pm_runtime_get_sync(dev
);
158 thdrv
->remove(thdev
);
160 if (intel_th_output_assigned(thdev
)) {
161 struct intel_th_driver
*hubdrv
=
162 to_intel_th_driver(dev
->parent
->driver
);
165 /* does not talk to hardware */
166 hubdrv
->unassign(hub
, thdev
);
169 pm_runtime_disable(dev
);
170 pm_runtime_set_active(dev
);
171 pm_runtime_enable(dev
);
176 static struct bus_type intel_th_bus
= {
178 .match
= intel_th_match
,
179 .probe
= intel_th_probe
,
180 .remove
= intel_th_remove
,
183 static void intel_th_device_free(struct intel_th_device
*thdev
);
185 static void intel_th_device_release(struct device
*dev
)
187 intel_th_device_free(to_intel_th_device(dev
));
190 static struct device_type intel_th_source_device_type
= {
191 .name
= "intel_th_source_device",
192 .release
= intel_th_device_release
,
195 static char *intel_th_output_devnode(struct device
*dev
, umode_t
*mode
,
196 kuid_t
*uid
, kgid_t
*gid
)
198 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
199 struct intel_th
*th
= to_intel_th(thdev
);
203 node
= kasprintf(GFP_KERNEL
, "intel_th%d/%s%d", th
->id
,
204 thdev
->name
, thdev
->id
);
206 node
= kasprintf(GFP_KERNEL
, "intel_th%d/%s", th
->id
,
212 static ssize_t
port_show(struct device
*dev
, struct device_attribute
*attr
,
215 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
217 if (thdev
->output
.port
>= 0)
218 return scnprintf(buf
, PAGE_SIZE
, "%u\n", thdev
->output
.port
);
220 return scnprintf(buf
, PAGE_SIZE
, "unassigned\n");
223 static DEVICE_ATTR_RO(port
);
225 static int intel_th_output_activate(struct intel_th_device
*thdev
)
227 struct intel_th_driver
*thdrv
=
228 to_intel_th_driver_or_null(thdev
->dev
.driver
);
234 if (!try_module_get(thdrv
->driver
.owner
))
237 pm_runtime_get_sync(&thdev
->dev
);
240 ret
= thdrv
->activate(thdev
);
242 intel_th_trace_enable(thdev
);
245 pm_runtime_put(&thdev
->dev
);
246 module_put(thdrv
->driver
.owner
);
252 static void intel_th_output_deactivate(struct intel_th_device
*thdev
)
254 struct intel_th_driver
*thdrv
=
255 to_intel_th_driver_or_null(thdev
->dev
.driver
);
260 if (thdrv
->deactivate
)
261 thdrv
->deactivate(thdev
);
263 intel_th_trace_disable(thdev
);
265 pm_runtime_put(&thdev
->dev
);
266 module_put(thdrv
->driver
.owner
);
269 static ssize_t
active_show(struct device
*dev
, struct device_attribute
*attr
,
272 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
274 return scnprintf(buf
, PAGE_SIZE
, "%d\n", thdev
->output
.active
);
277 static ssize_t
active_store(struct device
*dev
, struct device_attribute
*attr
,
278 const char *buf
, size_t size
)
280 struct intel_th_device
*thdev
= to_intel_th_device(dev
);
284 ret
= kstrtoul(buf
, 10, &val
);
288 if (!!val
!= thdev
->output
.active
) {
290 ret
= intel_th_output_activate(thdev
);
292 intel_th_output_deactivate(thdev
);
295 return ret
? ret
: size
;
298 static DEVICE_ATTR_RW(active
);
300 static struct attribute
*intel_th_output_attrs
[] = {
302 &dev_attr_active
.attr
,
306 ATTRIBUTE_GROUPS(intel_th_output
);
308 static struct device_type intel_th_output_device_type
= {
309 .name
= "intel_th_output_device",
310 .groups
= intel_th_output_groups
,
311 .release
= intel_th_device_release
,
312 .devnode
= intel_th_output_devnode
,
315 static struct device_type intel_th_switch_device_type
= {
316 .name
= "intel_th_switch_device",
317 .release
= intel_th_device_release
,
320 static struct device_type
*intel_th_device_type
[] = {
321 [INTEL_TH_SOURCE
] = &intel_th_source_device_type
,
322 [INTEL_TH_OUTPUT
] = &intel_th_output_device_type
,
323 [INTEL_TH_SWITCH
] = &intel_th_switch_device_type
,
326 int intel_th_driver_register(struct intel_th_driver
*thdrv
)
328 if (!thdrv
->probe
|| !thdrv
->remove
)
331 thdrv
->driver
.bus
= &intel_th_bus
;
333 return driver_register(&thdrv
->driver
);
335 EXPORT_SYMBOL_GPL(intel_th_driver_register
);
337 void intel_th_driver_unregister(struct intel_th_driver
*thdrv
)
339 driver_unregister(&thdrv
->driver
);
341 EXPORT_SYMBOL_GPL(intel_th_driver_unregister
);
343 static struct intel_th_device
*
344 intel_th_device_alloc(struct intel_th
*th
, unsigned int type
, const char *name
,
347 struct device
*parent
;
348 struct intel_th_device
*thdev
;
350 if (type
== INTEL_TH_OUTPUT
)
351 parent
= &th
->hub
->dev
;
355 thdev
= kzalloc(sizeof(*thdev
) + strlen(name
) + 1, GFP_KERNEL
);
362 strcpy(thdev
->name
, name
);
363 device_initialize(&thdev
->dev
);
364 thdev
->dev
.bus
= &intel_th_bus
;
365 thdev
->dev
.type
= intel_th_device_type
[type
];
366 thdev
->dev
.parent
= parent
;
367 thdev
->dev
.dma_mask
= parent
->dma_mask
;
368 thdev
->dev
.dma_parms
= parent
->dma_parms
;
369 dma_set_coherent_mask(&thdev
->dev
, parent
->coherent_dma_mask
);
371 dev_set_name(&thdev
->dev
, "%d-%s%d", th
->id
, name
, id
);
373 dev_set_name(&thdev
->dev
, "%d-%s", th
->id
, name
);
378 static int intel_th_device_add_resources(struct intel_th_device
*thdev
,
379 struct resource
*res
, int nres
)
383 r
= kmemdup(res
, sizeof(*res
) * nres
, GFP_KERNEL
);
388 thdev
->num_resources
= nres
;
393 static void intel_th_device_remove(struct intel_th_device
*thdev
)
395 device_del(&thdev
->dev
);
396 put_device(&thdev
->dev
);
399 static void intel_th_device_free(struct intel_th_device
*thdev
)
401 kfree(thdev
->resource
);
406 * Intel(R) Trace Hub subdevices
408 static const struct intel_th_subdevice
{
410 struct resource res
[3];
416 } intel_th_subdevices
[] = {
421 .start
= REG_GTH_OFFSET
,
422 .end
= REG_GTH_OFFSET
+ REG_GTH_LENGTH
- 1,
423 .flags
= IORESOURCE_MEM
,
427 .type
= INTEL_TH_SWITCH
,
434 .start
= REG_MSU_OFFSET
,
435 .end
= REG_MSU_OFFSET
+ REG_MSU_LENGTH
- 1,
436 .flags
= IORESOURCE_MEM
,
439 .start
= BUF_MSU_OFFSET
,
440 .end
= BUF_MSU_OFFSET
+ BUF_MSU_LENGTH
- 1,
441 .flags
= IORESOURCE_MEM
,
446 .type
= INTEL_TH_OUTPUT
,
448 .scrpd
= SCRPD_MEM_IS_PRIM_DEST
| SCRPD_MSC0_IS_ENABLED
,
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_MSC1_IS_ENABLED
,
474 .start
= REG_STH_OFFSET
,
475 .end
= REG_STH_OFFSET
+ REG_STH_LENGTH
- 1,
476 .flags
= IORESOURCE_MEM
,
481 .flags
= IORESOURCE_MEM
,
486 .type
= INTEL_TH_SOURCE
,
492 .start
= REG_PTI_OFFSET
,
493 .end
= REG_PTI_OFFSET
+ REG_PTI_LENGTH
- 1,
494 .flags
= IORESOURCE_MEM
,
499 .type
= INTEL_TH_OUTPUT
,
501 .scrpd
= SCRPD_PTI_IS_PRIM_DEST
,
507 .start
= REG_DCIH_OFFSET
,
508 .end
= REG_DCIH_OFFSET
+ REG_DCIH_LENGTH
- 1,
509 .flags
= IORESOURCE_MEM
,
514 .type
= INTEL_TH_OUTPUT
,
518 #ifdef CONFIG_MODULES
519 static void __intel_th_request_hub_module(struct work_struct
*work
)
521 struct intel_th
*th
= container_of(work
, struct intel_th
,
522 request_module_work
);
524 request_module("intel_th_%s", th
->hub
->name
);
527 static int intel_th_request_hub_module(struct intel_th
*th
)
529 INIT_WORK(&th
->request_module_work
, __intel_th_request_hub_module
);
530 schedule_work(&th
->request_module_work
);
535 static void intel_th_request_hub_module_flush(struct intel_th
*th
)
537 flush_work(&th
->request_module_work
);
540 static inline int intel_th_request_hub_module(struct intel_th
*th
)
545 static inline void intel_th_request_hub_module_flush(struct intel_th
*th
)
548 #endif /* CONFIG_MODULES */
550 static struct intel_th_device
*
551 intel_th_subdevice_alloc(struct intel_th
*th
,
552 const struct intel_th_subdevice
*subdev
)
554 struct intel_th_device
*thdev
;
555 struct resource res
[3];
556 unsigned int req
= 0;
559 thdev
= intel_th_device_alloc(th
, subdev
->type
, subdev
->name
,
562 return ERR_PTR(-ENOMEM
);
565 memcpy(res
, subdev
->res
,
566 sizeof(struct resource
) * subdev
->nres
);
568 for (r
= 0; r
< subdev
->nres
; r
++) {
569 struct resource
*devres
= th
->resource
;
570 int bar
= TH_MMIO_CONFIG
;
573 * Take .end == 0 to mean 'take the whole bar',
574 * .start then tells us which bar it is. Default to
577 if (!res
[r
].end
&& res
[r
].flags
== IORESOURCE_MEM
) {
580 res
[r
].end
= resource_size(&devres
[bar
]) - 1;
583 if (res
[r
].flags
& IORESOURCE_MEM
) {
584 res
[r
].start
+= devres
[bar
].start
;
585 res
[r
].end
+= devres
[bar
].start
;
587 dev_dbg(th
->dev
, "%s:%d @ %pR\n",
588 subdev
->name
, r
, &res
[r
]);
589 } else if (res
[r
].flags
& IORESOURCE_IRQ
) {
590 res
[r
].start
= th
->irq
;
594 err
= intel_th_device_add_resources(thdev
, res
, subdev
->nres
);
596 put_device(&thdev
->dev
);
597 goto fail_put_device
;
600 if (subdev
->type
== INTEL_TH_OUTPUT
) {
601 thdev
->dev
.devt
= MKDEV(th
->major
, th
->num_thdevs
);
602 thdev
->output
.type
= subdev
->otype
;
603 thdev
->output
.port
= -1;
604 thdev
->output
.scratchpad
= subdev
->scrpd
;
605 } else if (subdev
->type
== INTEL_TH_SWITCH
) {
606 thdev
->host_mode
= host_mode
;
610 err
= device_add(&thdev
->dev
);
612 put_device(&thdev
->dev
);
616 /* need switch driver to be loaded to enumerate the rest */
617 if (subdev
->type
== INTEL_TH_SWITCH
&& !req
) {
618 err
= intel_th_request_hub_module(th
);
626 kfree(thdev
->resource
);
629 put_device(&thdev
->dev
);
635 * intel_th_output_enable() - find and enable a device for a given output type
636 * @th: Intel TH instance
637 * @otype: output type
639 * Go through the unallocated output devices, find the first one whos type
640 * matches @otype and instantiate it. These devices are removed when the hub
641 * device is removed, see intel_th_remove().
643 int intel_th_output_enable(struct intel_th
*th
, unsigned int otype
)
645 struct intel_th_device
*thdev
;
646 int src
= 0, dst
= 0;
648 for (src
= 0, dst
= 0; dst
<= th
->num_thdevs
; src
++, dst
++) {
649 for (; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
650 if (intel_th_subdevices
[src
].type
!= INTEL_TH_OUTPUT
)
653 if (intel_th_subdevices
[src
].otype
!= otype
)
659 /* no unallocated matching subdevices */
660 if (src
== ARRAY_SIZE(intel_th_subdevices
))
663 for (; dst
< th
->num_thdevs
; dst
++) {
664 if (th
->thdev
[dst
]->type
!= INTEL_TH_OUTPUT
)
667 if (th
->thdev
[dst
]->output
.type
!= otype
)
674 * intel_th_subdevices[src] matches our requirements and is
675 * not matched in th::thdev[]
677 if (dst
== th
->num_thdevs
)
684 thdev
= intel_th_subdevice_alloc(th
, &intel_th_subdevices
[src
]);
686 return PTR_ERR(thdev
);
688 th
->thdev
[th
->num_thdevs
++] = thdev
;
692 EXPORT_SYMBOL_GPL(intel_th_output_enable
);
694 static int intel_th_populate(struct intel_th
*th
)
698 /* create devices for each intel_th_subdevice */
699 for (src
= 0; src
< ARRAY_SIZE(intel_th_subdevices
); src
++) {
700 const struct intel_th_subdevice
*subdev
=
701 &intel_th_subdevices
[src
];
702 struct intel_th_device
*thdev
;
704 /* only allow SOURCE and SWITCH devices in host mode */
705 if (host_mode
&& subdev
->type
== INTEL_TH_OUTPUT
)
709 * don't enable port OUTPUTs in this path; SWITCH enables them
710 * via intel_th_output_enable()
712 if (subdev
->type
== INTEL_TH_OUTPUT
&&
713 subdev
->otype
!= GTH_NONE
)
716 thdev
= intel_th_subdevice_alloc(th
, subdev
);
717 /* note: caller should free subdevices from th::thdev[] */
719 return PTR_ERR(thdev
);
721 th
->thdev
[th
->num_thdevs
++] = thdev
;
727 static int match_devt(struct device
*dev
, void *data
)
729 dev_t devt
= (dev_t
)(unsigned long)data
;
731 return dev
->devt
== devt
;
734 static int intel_th_output_open(struct inode
*inode
, struct file
*file
)
736 const struct file_operations
*fops
;
737 struct intel_th_driver
*thdrv
;
741 dev
= bus_find_device(&intel_th_bus
, NULL
,
742 (void *)(unsigned long)inode
->i_rdev
,
744 if (!dev
|| !dev
->driver
)
747 thdrv
= to_intel_th_driver(dev
->driver
);
748 fops
= fops_get(thdrv
->fops
);
752 replace_fops(file
, fops
);
754 file
->private_data
= to_intel_th_device(dev
);
756 if (file
->f_op
->open
) {
757 err
= file
->f_op
->open(inode
, file
);
764 static const struct file_operations intel_th_output_fops
= {
765 .open
= intel_th_output_open
,
766 .llseek
= noop_llseek
,
770 * intel_th_alloc() - allocate a new Intel TH device and its subdevices
771 * @dev: parent device
772 * @devres: parent's resources
773 * @ndevres: number of resources
777 intel_th_alloc(struct device
*dev
, struct resource
*devres
,
778 unsigned int ndevres
, int irq
)
783 th
= kzalloc(sizeof(*th
), GFP_KERNEL
);
785 return ERR_PTR(-ENOMEM
);
787 th
->id
= ida_simple_get(&intel_th_ida
, 0, 0, GFP_KERNEL
);
793 th
->major
= __register_chrdev(0, 0, TH_POSSIBLE_OUTPUTS
,
794 "intel_th/output", &intel_th_output_fops
);
801 th
->resource
= devres
;
802 th
->num_resources
= ndevres
;
805 dev_set_drvdata(dev
, th
);
807 pm_runtime_no_callbacks(dev
);
809 pm_runtime_allow(dev
);
811 err
= intel_th_populate(th
);
813 /* free the subdevices and undo everything */
821 ida_simple_remove(&intel_th_ida
, th
->id
);
828 EXPORT_SYMBOL_GPL(intel_th_alloc
);
830 void intel_th_free(struct intel_th
*th
)
834 intel_th_request_hub_module_flush(th
);
836 intel_th_device_remove(th
->hub
);
837 for (i
= 0; i
< th
->num_thdevs
; i
++) {
838 if (th
->thdev
[i
] != th
->hub
)
839 intel_th_device_remove(th
->thdev
[i
]);
845 pm_runtime_get_sync(th
->dev
);
846 pm_runtime_forbid(th
->dev
);
848 __unregister_chrdev(th
->major
, 0, TH_POSSIBLE_OUTPUTS
,
851 ida_simple_remove(&intel_th_ida
, th
->id
);
855 EXPORT_SYMBOL_GPL(intel_th_free
);
858 * intel_th_trace_enable() - enable tracing for an output device
859 * @thdev: output device that requests tracing be enabled
861 int intel_th_trace_enable(struct intel_th_device
*thdev
)
863 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
864 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
866 if (WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
))
869 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
872 pm_runtime_get_sync(&thdev
->dev
);
873 hubdrv
->enable(hub
, &thdev
->output
);
877 EXPORT_SYMBOL_GPL(intel_th_trace_enable
);
880 * intel_th_trace_disable() - disable tracing for an output device
881 * @thdev: output device that requests tracing be disabled
883 int intel_th_trace_disable(struct intel_th_device
*thdev
)
885 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
886 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
888 WARN_ON_ONCE(hub
->type
!= INTEL_TH_SWITCH
);
889 if (WARN_ON_ONCE(thdev
->type
!= INTEL_TH_OUTPUT
))
892 hubdrv
->disable(hub
, &thdev
->output
);
893 pm_runtime_put(&thdev
->dev
);
897 EXPORT_SYMBOL_GPL(intel_th_trace_disable
);
899 int intel_th_set_output(struct intel_th_device
*thdev
,
902 struct intel_th_device
*hub
= to_intel_th_device(thdev
->dev
.parent
);
903 struct intel_th_driver
*hubdrv
= to_intel_th_driver(hub
->dev
.driver
);
905 if (!hubdrv
->set_output
)
908 return hubdrv
->set_output(hub
, master
);
910 EXPORT_SYMBOL_GPL(intel_th_set_output
);
912 static int __init
intel_th_init(void)
914 intel_th_debug_init();
916 return bus_register(&intel_th_bus
);
918 subsys_initcall(intel_th_init
);
920 static void __exit
intel_th_exit(void)
922 intel_th_debug_done();
924 bus_unregister(&intel_th_bus
);
926 module_exit(intel_th_exit
);
928 MODULE_LICENSE("GPL v2");
929 MODULE_DESCRIPTION("Intel(R) Trace Hub controller driver");
930 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");