From a0ebf519b8a2666438d999c62995618c710573e5 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@kernel.org> Date: Fri, 18 Nov 2016 14:17:31 +0200 Subject: stm class: Fix device leak in open error path Make sure to drop the reference taken by class_find_device() also on allocation errors in open(). Signed-off-by: Johan Hovold <johan@kernel.org> Fixes: 7bd1d4093c2f ("stm class: Introduce an abstraction for...") Cc: stable@vger.kernel.org # v4.6+ Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- drivers/hwtracing/stm/core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index 51f81d64ca37..a6ea387b5b00 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -361,7 +361,7 @@ static int stm_char_open(struct inode *inode, struct file *file) struct stm_file *stmf; struct device *dev; unsigned int major = imajor(inode); - int err = -ENODEV; + int err = -ENOMEM; dev = class_find_device(&stm_class, NULL, &major, major_match); if (!dev) @@ -369,8 +369,9 @@ static int stm_char_open(struct inode *inode, struct file *file) stmf = kzalloc(sizeof(*stmf), GFP_KERNEL); if (!stmf) - return -ENOMEM; + goto err_put_device; + err = -ENODEV; stm_output_init(&stmf->output); stmf->stm = to_stm_device(dev); @@ -382,9 +383,10 @@ static int stm_char_open(struct inode *inode, struct file *file) return nonseekable_open(inode, file); err_free: + kfree(stmf); +err_put_device: /* matches class_find_device() above */ put_device(dev); - kfree(stmf); return err; } -- cgit v1.2.3 From bd566189723d919e6081b494856337ef61a23f9f Mon Sep 17 00:00:00 2001 From: Alexander Shishkin <alexander.shishkin@linux.intel.com> Date: Thu, 14 Jul 2016 13:39:20 +0300 Subject: stm class: Document the stm_source interface This patch adds a description of the stm_source device class, an interface for the kernel code to send traces over STM devices. Cc: linux-api@vger.kernel.org Cc: Chunyan Zhang <zhang.chunyan@linaro.org> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- Documentation/trace/stm.txt | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/Documentation/trace/stm.txt b/Documentation/trace/stm.txt index ea035f9dbfd7..349869851463 100644 --- a/Documentation/trace/stm.txt +++ b/Documentation/trace/stm.txt @@ -69,12 +69,33 @@ stm device's channel mmio region is 64 bytes and hardware page size is width==64, you should be able to mmap() one page on this file descriptor and obtain direct access to an mmio region for 64 channels. +Examples of STM devices are Intel(R) Trace Hub [1] and Coresight STM +[2]. + +stm_source +========== + For kernel-based trace sources, there is "stm_source" device class. Devices of this class can be connected and disconnected to/from -stm devices at runtime via a sysfs attribute. +stm devices at runtime via a sysfs attribute called "stm_source_link" +by writing the name of the desired stm device there, for example: -Examples of STM devices are Intel(R) Trace Hub [1] and Coresight STM -[2]. +$ echo dummy_stm.0 > /sys/class/stm_source/console/stm_source_link + +For examples on how to use stm_source interface in the kernel, refer +to stm_console or stm_heartbeat drivers. + +stm_console +=========== + +One implementation of this interface also used in the example above is +the "stm_console" driver, which basically provides a one-way console +for kernel messages over an stm device. + +To configure the master/channel pair that will be assigned to this +console in the STP stream, create a "console" policy entry (see the +beginning of this text on how to do that). When initialized, it will +consume one channel. [1] https://software.intel.com/sites/default/files/managed/d3/3c/intel-th-developer-manual.pdf [2] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0444b/index.html -- cgit v1.2.3 From b29f6d3e59a1ff8dd5c0aeae8594801a15efcc2c Mon Sep 17 00:00:00 2001 From: Alexander Shishkin <alexander.shishkin@linux.intel.com> Date: Mon, 26 Sep 2016 15:27:05 +0300 Subject: stm class: Document stm_source channel assignment This patch adds an explanation of how and when stm_source devices are assigned STP masters and channels. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- Documentation/trace/stm.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/trace/stm.txt b/Documentation/trace/stm.txt index 349869851463..11cff47eecce 100644 --- a/Documentation/trace/stm.txt +++ b/Documentation/trace/stm.txt @@ -85,6 +85,16 @@ $ echo dummy_stm.0 > /sys/class/stm_source/console/stm_source_link For examples on how to use stm_source interface in the kernel, refer to stm_console or stm_heartbeat drivers. +Each stm_source device will need to assume a master and a range of +channels, depending on how many channels it requires. These are +allocated for the device according to the policy configuration. If +there's a node in the root of the policy directory that matches the +stm_source device's name (for example, "console"), this node will be +used to allocate master and channel numbers. If there's no such policy +node, the stm core will pick the first contiguous chunk of channels +within the first available master. Note that the node must exist +before the stm_source device is connected to its stm device. + stm_console =========== -- cgit v1.2.3 From 77c98b28ee68b9e26bd1492e547cb2e5d3fcfc94 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin <alexander.shishkin@linux.intel.com> Date: Fri, 18 Nov 2016 16:52:08 +0200 Subject: intel_th: Constify subdevices The subdevice array consists of immutable objects, make them const. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- drivers/hwtracing/intel_th/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 6f0a51a2c6ec..79e19627b99f 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -380,7 +380,7 @@ static void intel_th_device_free(struct intel_th_device *thdev) /* * Intel(R) Trace Hub subdevices */ -static struct intel_th_subdevice { +static const struct intel_th_subdevice { const char *name; struct resource res[3]; unsigned nres; -- cgit v1.2.3 From c49a75910c5ea9bbeb60a86350f232f6fcb13cc2 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin <alexander.shishkin@linux.intel.com> Date: Mon, 19 Sep 2016 17:07:47 +0300 Subject: intel_th: Support Host Debugger mode of operation This patch adds a 'host_mode' module option to enable host-driven operational mode in the driver. In this mode, the driver does not perform trace configuration or enable trace capture, but still provides all the means necessary for software trace sources to write their data to the Trace Hub. This means that the debug host takes care of all the configuration and enabling and we do not interfere. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- drivers/hwtracing/intel_th/core.c | 26 ++++++++++++++++++-------- drivers/hwtracing/intel_th/intel_th.h | 4 ++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 79e19627b99f..cdd9b3b26195 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -29,6 +29,9 @@ #include "intel_th.h" #include "debug.h" +static bool host_mode __read_mostly; +module_param(host_mode, bool, 0444); + static DEFINE_IDA(intel_th_ida); static int intel_th_match(struct device *dev, struct device_driver *driver) @@ -527,14 +530,19 @@ static int intel_th_populate(struct intel_th *th, struct resource *devres, { struct resource res[3]; unsigned int req = 0; - int i, err; + int src, dst, err; /* create devices for each intel_th_subdevice */ - for (i = 0; i < ARRAY_SIZE(intel_th_subdevices); i++) { - struct intel_th_subdevice *subdev = &intel_th_subdevices[i]; + for (src = 0, dst = 0; src < ARRAY_SIZE(intel_th_subdevices); src++) { + const struct intel_th_subdevice *subdev = + &intel_th_subdevices[src]; struct intel_th_device *thdev; int r; + /* only allow SOURCE and SWITCH devices in host mode */ + if (host_mode && subdev->type == INTEL_TH_OUTPUT) + continue; + thdev = intel_th_device_alloc(th, subdev->type, subdev->name, subdev->id); if (!thdev) { @@ -577,10 +585,12 @@ static int intel_th_populate(struct intel_th *th, struct resource *devres, } if (subdev->type == INTEL_TH_OUTPUT) { - thdev->dev.devt = MKDEV(th->major, i); + thdev->dev.devt = MKDEV(th->major, dst); thdev->output.type = subdev->otype; thdev->output.port = -1; thdev->output.scratchpad = subdev->scrpd; + } else if (subdev->type == INTEL_TH_SWITCH) { + thdev->host_mode = host_mode; } err = device_add(&thdev->dev); @@ -597,14 +607,14 @@ static int intel_th_populate(struct intel_th *th, struct resource *devres, req++; } - th->thdev[i] = thdev; + th->thdev[dst++] = thdev; } return 0; kill_subdevs: - for (i-- ; i >= 0; i--) - intel_th_device_remove(th->thdev[i]); + for (; dst >= 0; dst--) + intel_th_device_remove(th->thdev[dst]); return err; } @@ -717,7 +727,7 @@ void intel_th_free(struct intel_th *th) intel_th_request_hub_module_flush(th); for (i = 0; i < TH_SUBDEVICE_MAX; i++) - if (th->thdev[i] != th->hub) + if (th->thdev[i] && th->thdev[i] != th->hub) intel_th_device_remove(th->thdev[i]); intel_th_device_remove(th->hub); diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h index 4c195786bf1f..3096e7054f6d 100644 --- a/drivers/hwtracing/intel_th/intel_th.h +++ b/drivers/hwtracing/intel_th/intel_th.h @@ -54,6 +54,7 @@ struct intel_th_output { * @num_resources: number of resources in @resource array * @type: INTEL_TH_{SOURCE,OUTPUT,SWITCH} * @id: device instance or -1 + * @host_mode: Intel TH is controlled by an external debug host * @output: output descriptor for INTEL_TH_OUTPUT devices * @name: device name to match the driver */ @@ -64,6 +65,9 @@ struct intel_th_device { unsigned int type; int id; + /* INTEL_TH_SWITCH specific */ + bool host_mode; + /* INTEL_TH_OUTPUT specific */ struct intel_th_output output; -- cgit v1.2.3 From d4f5f545da12d876f5c49cef40a4a2922c75dd1e Mon Sep 17 00:00:00 2001 From: Alexander Shishkin <alexander.shishkin@linux.intel.com> Date: Mon, 19 Sep 2016 17:27:45 +0300 Subject: intel_th: gth: Handle host mode correctly When detecting host debugger mode either though a module option or via the scratchpad register, do not export any configuration or capture related attributes to userspace and refuse attempts by the output drivers to configure output ports. This way, GTH can still act as a hub and ensure that the other components that rely on its presence continue to function properly, namely the source devices. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- drivers/hwtracing/intel_th/gth.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c index 33e09369a491..dd32d0bad687 100644 --- a/drivers/hwtracing/intel_th/gth.c +++ b/drivers/hwtracing/intel_th/gth.c @@ -564,6 +564,9 @@ static int intel_th_gth_assign(struct intel_th_device *thdev, struct gth_device *gth = dev_get_drvdata(&thdev->dev); int i, id; + if (thdev->host_mode) + return -EBUSY; + if (othdev->type != INTEL_TH_OUTPUT) return -EINVAL; @@ -600,6 +603,9 @@ static void intel_th_gth_unassign(struct intel_th_device *thdev, struct gth_device *gth = dev_get_drvdata(&thdev->dev); int port = othdev->output.port; + if (thdev->host_mode) + return; + spin_lock(>h->gth_lock); othdev->output.port = -1; othdev->output.active = false; @@ -654,9 +660,24 @@ static int intel_th_gth_probe(struct intel_th_device *thdev) gth->base = base; spin_lock_init(>h->gth_lock); + /* + * Host mode can be signalled via SW means or via SCRPD_DEBUGGER_IN_USE + * bit. Either way, don't reset HW in this case, and don't export any + * capture configuration attributes. Also, refuse to assign output + * drivers to ports, see intel_th_gth_assign(). + */ + if (thdev->host_mode) + goto done; + ret = intel_th_gth_reset(gth); - if (ret) - return ret; + if (ret) { + if (ret != -EBUSY) + return ret; + + thdev->host_mode = true; + + goto done; + } for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++) gth->master[i] = -1; @@ -677,6 +698,7 @@ static int intel_th_gth_probe(struct intel_th_device *thdev) return -ENOMEM; } +done: dev_set_drvdata(dev, gth); return 0; -- cgit v1.2.3 From ee01aebbe2c4c196142bdb8074812dfe44830725 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin <alexander.shishkin@linux.intel.com> Date: Mon, 19 Sep 2016 18:06:25 +0300 Subject: intel_th: Document debug host mode Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- Documentation/trace/intel_th.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/trace/intel_th.txt b/Documentation/trace/intel_th.txt index f7fc5ba5df8d..f92070e7dde0 100644 --- a/Documentation/trace/intel_th.txt +++ b/Documentation/trace/intel_th.txt @@ -97,3 +97,25 @@ $ echo 0 > /sys/bus/intel_th/devices/0-msc0/active # and now you can collect the trace from the device node: $ cat /dev/intel_th0/msc0 > my_stp_trace + +Host Debugger Mode +================== + +It is possible to configure the Trace Hub and control its trace +capture from a remote debug host, which should be connected via one of +the hardware debugging interfaces, which will then be used to both +control Intel Trace Hub and transfer its trace data to the debug host. + +The driver needs to be told that such an arrangement is taking place +so that it does not touch any capture/port configuration and avoids +conflicting with the debug host's configuration accesses. The only +activity that the driver will perform in this mode is collecting +software traces to the Software Trace Hub (an stm class device). The +user is still responsible for setting up adequate master/channel +mappings that the decoder on the receiving end would recognize. + +In order to enable the host mode, set the 'host_mode' parameter of the +'intel_th' kernel module to 'y'. None of the virtual output devices +will show up on the intel_th bus. Also, trace configuration and +capture controlling attribute groups of the 'gth' device will not be +exposed. The 'sth' device will operate as usual. -- cgit v1.2.3