public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue
@ 2016-02-12 17:00 Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 01/19] stm class: Use a signed return type for stm_find_master_chan Alexander Shishkin
                   ` (18 more replies)
  0 siblings, 19 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

Hi everybody,

These are the patches that I have in my queue right now, on top of
Greg's char-misc/char-misc-next branch. Questions, concerns,
objections, please let me know. Otherwise I would like to send it to
Greg for the next merge window.

Alexander Shishkin (16):
  intel_th: Depend on HAS_IOMEM
  intel_th: gth: Remove commented-out code
  intel_th: Update scratchpad bits according to enabled output activity
  intel_th: sth: Sanitize packet callback's return values
  intel_th: Set root device's drvdata early
  intel_th: Use real device index in the node names
  stm class: Use driver's packet callback return value
  stm class: Support devices with multiple instances
  stm class: dummy_stm: Create multiple devices
  stm class: Add heartbeat stm source device
  stm class: Fix unlocking braino in the error path
  stm class: Guard output assignment against concurrency
  stm class: Fix unbalanced module/device refcounting
  stm class: Fix a race in unlinking
  stm class: Plug stm device's unlink callback
  stm class: dummy_stm: Add link callback for fault injection

Laurent FERT (2):
  intel_th: msu: Fix offset for wrapped block
  intel_th: msu: Release resources on read error

Lucas Tanure (1):
  stm class: Use a signed return type for stm_find_master_chan

 drivers/hwtracing/intel_th/Kconfig    |   2 +-
 drivers/hwtracing/intel_th/core.c     |  30 +++++++-
 drivers/hwtracing/intel_th/gth.c      |  32 ++++----
 drivers/hwtracing/intel_th/gth.h      |   3 -
 drivers/hwtracing/intel_th/intel_th.h |  41 ++++++++++
 drivers/hwtracing/intel_th/msu.c      |   9 +--
 drivers/hwtracing/intel_th/pci.c      |   2 -
 drivers/hwtracing/intel_th/sth.c      |  11 ++-
 drivers/hwtracing/stm/Kconfig         |  11 +++
 drivers/hwtracing/stm/Makefile        |   2 +
 drivers/hwtracing/stm/core.c          | 136 ++++++++++++++++++++++++++--------
 drivers/hwtracing/stm/dummy_stm.c     |  71 +++++++++++++++---
 drivers/hwtracing/stm/heartbeat.c     | 130 ++++++++++++++++++++++++++++++++
 drivers/hwtracing/stm/policy.c        |   7 +-
 drivers/hwtracing/stm/stm.h           |   1 +
 include/linux/stm.h                   |  10 +++
 16 files changed, 419 insertions(+), 79 deletions(-)
 create mode 100644 drivers/hwtracing/stm/heartbeat.c

-- 
2.7.0

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 01/19] stm class: Use a signed return type for stm_find_master_chan
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 02/19] intel_th: Depend on HAS_IOMEM Alexander Shishkin
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Lucas Tanure, Alexander Shishkin

From: Lucas Tanure <tanure@linux.com>

The return type "unsigned int" was used by the stm_find_master_chan function
despite of the aspect that it will eventually return a negative error code.

Done with the help of Coccinelle.

Signed-off-by: Lucas Tanure <tanure@linux.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index aef8ddb244..cdec240bd6 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -233,7 +233,7 @@ static int find_free_channels(unsigned long *bitmap, unsigned int start,
 	return -1;
 }
 
-static unsigned int
+static int
 stm_find_master_chan(struct stm_device *stm, unsigned int width,
 		     unsigned int *mstart, unsigned int mend,
 		     unsigned int *cstart, unsigned int cend)
@@ -293,7 +293,7 @@ static int stm_output_assign(struct stm_device *stm, unsigned int width,
 		goto unlock;
 
 	ret = stm_find_master_chan(stm, width, &midx, mend, &cidx, cend);
-	if (ret)
+	if (ret < 0)
 		goto unlock;
 
 	output->master = midx;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 02/19] intel_th: Depend on HAS_IOMEM
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 01/19] stm class: Use a signed return type for stm_find_master_chan Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 03/19] intel_th: gth: Remove commented-out code Alexander Shishkin
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

This driver requires io memory to operate, so don't even consider it
for NO_IOMEM architectures.

Reported-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwtracing/intel_th/Kconfig b/drivers/hwtracing/intel_th/Kconfig
index 90b0844093..1b412f8a56 100644
--- a/drivers/hwtracing/intel_th/Kconfig
+++ b/drivers/hwtracing/intel_th/Kconfig
@@ -1,6 +1,6 @@
 config INTEL_TH
 	tristate "Intel(R) Trace Hub controller"
-	depends on HAS_DMA
+	depends on HAS_DMA && HAS_IOMEM
 	help
 	  Intel(R) Trace Hub (TH) is a set of hardware blocks (subdevices) that
 	  produce, switch and output trace data from multiple hardware and
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 03/19] intel_th: gth: Remove commented-out code
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 01/19] stm class: Use a signed return type for stm_find_master_chan Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 02/19] intel_th: Depend on HAS_IOMEM Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 04/19] intel_th: Update scratchpad bits according to enabled output activity Alexander Shishkin
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

There's a commented-out function in the GTH driver that's a leftover
from previous versions of the driver, where we tried to inherit the
pre-existing configuration, which didn't prove to be a sound idea.

This patch removes the function. No functional changes.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/gth.c | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c
index 2dc5378ccd..e4c9811c1f 100644
--- a/drivers/hwtracing/intel_th/gth.c
+++ b/drivers/hwtracing/intel_th/gth.c
@@ -146,24 +146,6 @@ gth_master_set(struct gth_device *gth, unsigned int master, int port)
 	iowrite32(val, gth->base + reg);
 }
 
-/*static int gth_master_get(struct gth_device *gth, unsigned int master)
-{
-	unsigned int reg = REG_GTH_SWDEST0 + ((master >> 1) & ~3u);
-	unsigned int shift = (master & 0x7) * 4;
-	u32 val;
-
-	if (master >= 256) {
-		reg = REG_GTH_GSWTDEST;
-		shift = 0;
-	}
-
-	val = ioread32(gth->base + reg);
-	val &= (0xf << shift);
-	val >>= shift;
-
-	return val ? val & 0x7 : -1;
-	}*/
-
 static ssize_t master_attr_show(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 04/19] intel_th: Update scratchpad bits according to enabled output activity
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (2 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 03/19] intel_th: gth: Remove commented-out code Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 05/19] intel_th: msu: Fix offset for wrapped block Alexander Shishkin
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

Intel TH implements a scratchpad register to indicate to the firmware
and external debuggers what trace configuration is enabled so that
everybody plays nicely together. The register is a bit field and the
bit assignment convention is described in the developer's manual.

This patch enables the driver to automatically set scratchpad register
bits according to the output configuration that's enabled.

Based on work by Yann Fouassier.

Signed-off-by: Yann Fouassier <yann.fouassier@intel.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/core.c     |  5 +++++
 drivers/hwtracing/intel_th/gth.c      | 14 +++++++++++-
 drivers/hwtracing/intel_th/gth.h      |  3 ---
 drivers/hwtracing/intel_th/intel_th.h | 41 +++++++++++++++++++++++++++++++++++
 4 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 165d3001c3..b8b9895da5 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -319,6 +319,7 @@ static struct intel_th_subdevice {
 	unsigned		nres;
 	unsigned		type;
 	unsigned		otype;
+	unsigned		scrpd;
 	int			id;
 } intel_th_subdevices[TH_SUBDEVICE_MAX] = {
 	{
@@ -352,6 +353,7 @@ static struct intel_th_subdevice {
 		.id	= 0,
 		.type	= INTEL_TH_OUTPUT,
 		.otype	= GTH_MSU,
+		.scrpd	= SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC0_IS_ENABLED,
 	},
 	{
 		.nres	= 2,
@@ -371,6 +373,7 @@ static struct intel_th_subdevice {
 		.id	= 1,
 		.type	= INTEL_TH_OUTPUT,
 		.otype	= GTH_MSU,
+		.scrpd	= SCRPD_MEM_IS_PRIM_DEST | SCRPD_MSC1_IS_ENABLED,
 	},
 	{
 		.nres	= 2,
@@ -403,6 +406,7 @@ static struct intel_th_subdevice {
 		.name	= "pti",
 		.type	= INTEL_TH_OUTPUT,
 		.otype	= GTH_PTI,
+		.scrpd	= SCRPD_PTI_IS_PRIM_DEST,
 	},
 	{
 		.nres	= 1,
@@ -477,6 +481,7 @@ static int intel_th_populate(struct intel_th *th, struct resource *devres,
 			thdev->dev.devt = MKDEV(th->major, i);
 			thdev->output.type = subdev->otype;
 			thdev->output.port = -1;
+			thdev->output.scratchpad = subdev->scrpd;
 		}
 
 		err = device_add(&thdev->dev);
diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c
index e4c9811c1f..9beea0b542 100644
--- a/drivers/hwtracing/intel_th/gth.c
+++ b/drivers/hwtracing/intel_th/gth.c
@@ -286,6 +286,10 @@ static int intel_th_gth_reset(struct gth_device *gth)
 	if (scratchpad & SCRPD_DEBUGGER_IN_USE)
 		return -EBUSY;
 
+	/* Always save/restore STH and TU registers in S0ix entry/exit */
+	scratchpad |= SCRPD_STH_IS_ENABLED | SCRPD_TRIGGER_IS_ENABLED;
+	iowrite32(scratchpad, gth->base + REG_GTH_SCRPD0);
+
 	/* output ports */
 	for (port = 0; port < 8; port++) {
 		if (gth_output_parm_get(gth, port, TH_OUTPUT_PARM(port)) ==
@@ -488,6 +492,10 @@ static void intel_th_gth_disable(struct intel_th_device *thdev,
 	if (!count)
 		dev_dbg(&thdev->dev, "timeout waiting for GTH[%d] PLE\n",
 			output->port);
+
+	reg = ioread32(gth->base + REG_GTH_SCRPD0);
+	reg &= ~output->scratchpad;
+	iowrite32(reg, gth->base + REG_GTH_SCRPD0);
 }
 
 /**
@@ -502,7 +510,7 @@ static void intel_th_gth_enable(struct intel_th_device *thdev,
 				struct intel_th_output *output)
 {
 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
-	u32 scr = 0xfc0000;
+	u32 scr = 0xfc0000, scrpd;
 	int master;
 
 	spin_lock(&gth->gth_lock);
@@ -517,6 +525,10 @@ static void intel_th_gth_enable(struct intel_th_device *thdev,
 	output->active = true;
 	spin_unlock(&gth->gth_lock);
 
+	scrpd = ioread32(gth->base + REG_GTH_SCRPD0);
+	scrpd |= output->scratchpad;
+	iowrite32(scrpd, gth->base + REG_GTH_SCRPD0);
+
 	iowrite32(scr, gth->base + REG_GTH_SCR);
 	iowrite32(0, gth->base + REG_GTH_SCR2);
 }
diff --git a/drivers/hwtracing/intel_th/gth.h b/drivers/hwtracing/intel_th/gth.h
index 3b714b7a61..56f0d26205 100644
--- a/drivers/hwtracing/intel_th/gth.h
+++ b/drivers/hwtracing/intel_th/gth.h
@@ -57,9 +57,6 @@ enum {
 	REG_GTH_SCRPD3		= 0xec, /* ScratchPad[3] */
 };
 
-/* Externall debugger is using Intel TH */
-#define SCRPD_DEBUGGER_IN_USE	BIT(24)
-
 /* waiting for Pipeline Empty bit(s) to assert for GTH */
 #define GTH_PLE_WAITLOOP_DEPTH	10000
 
diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h
index 57fd72b20f..eedd09332d 100644
--- a/drivers/hwtracing/intel_th/intel_th.h
+++ b/drivers/hwtracing/intel_th/intel_th.h
@@ -30,6 +30,7 @@ enum {
  * struct intel_th_output - descriptor INTEL_TH_OUTPUT type devices
  * @port:	output port number, assigned by the switch
  * @type:	GTH_{MSU,CTP,PTI}
+ * @scratchpad:	scratchpad bits to flag when this output is enabled
  * @multiblock:	true for multiblock output configuration
  * @active:	true when this output is enabled
  *
@@ -41,6 +42,7 @@ enum {
 struct intel_th_output {
 	int		port;
 	unsigned int	type;
+	unsigned int	scratchpad;
 	bool		multiblock;
 	bool		active;
 };
@@ -241,4 +243,43 @@ enum {
 	GTH_PTI = 4,	/* MIPI-PTI */
 };
 
+/*
+ * Scratchpad bits: tell firmware and external debuggers
+ * what we are up to.
+ */
+enum {
+	/* Memory is the primary destination */
+	SCRPD_MEM_IS_PRIM_DEST		= BIT(0),
+	/* XHCI DbC is the primary destination */
+	SCRPD_DBC_IS_PRIM_DEST		= BIT(1),
+	/* PTI is the primary destination */
+	SCRPD_PTI_IS_PRIM_DEST		= BIT(2),
+	/* BSSB is the primary destination */
+	SCRPD_BSSB_IS_PRIM_DEST		= BIT(3),
+	/* PTI is the alternate destination */
+	SCRPD_PTI_IS_ALT_DEST		= BIT(4),
+	/* BSSB is the alternate destination */
+	SCRPD_BSSB_IS_ALT_DEST		= BIT(5),
+	/* DeepSx exit occurred */
+	SCRPD_DEEPSX_EXIT		= BIT(6),
+	/* S4 exit occurred */
+	SCRPD_S4_EXIT			= BIT(7),
+	/* S5 exit occurred */
+	SCRPD_S5_EXIT			= BIT(8),
+	/* MSU controller 0/1 is enabled */
+	SCRPD_MSC0_IS_ENABLED		= BIT(9),
+	SCRPD_MSC1_IS_ENABLED		= BIT(10),
+	/* Sx exit occurred */
+	SCRPD_SX_EXIT			= BIT(11),
+	/* Trigger Unit is enabled */
+	SCRPD_TRIGGER_IS_ENABLED	= BIT(12),
+	SCRPD_ODLA_IS_ENABLED		= BIT(13),
+	SCRPD_SOCHAP_IS_ENABLED		= BIT(14),
+	SCRPD_STH_IS_ENABLED		= BIT(15),
+	SCRPD_DCIH_IS_ENABLED		= BIT(16),
+	SCRPD_VER_IS_ENABLED		= BIT(17),
+	/* External debugger is using Intel TH */
+	SCRPD_DEBUGGER_IN_USE		= BIT(24),
+};
+
 #endif
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 05/19] intel_th: msu: Fix offset for wrapped block
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (3 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 04/19] intel_th: Update scratchpad bits according to enabled output activity Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 06/19] intel_th: msu: Release resources on read error Alexander Shishkin
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

From: Laurent FERT <laurent.fert@intel.com>

Fix offset for the second pass on the wrapped block when iterating over
memory in multi-block mode, otherwise wrong part of the block will get
copied.

Signed-off-by: Laurent FERT <laurent.fert@intel.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/msu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
index 70ca27e456..3c793bbf6a 100644
--- a/drivers/hwtracing/intel_th/msu.c
+++ b/drivers/hwtracing/intel_th/msu.c
@@ -408,7 +408,7 @@ msc_buffer_iterate(struct msc_iter *iter, size_t size, void *data,
 		 * Second time (wrap_count==1), it's just like any other block,
 		 * containing data in the range of [MSC_BDESC..data_bytes].
 		 */
-		if (iter->block == iter->start_block && iter->wrap_count) {
+		if (iter->block == iter->start_block && iter->wrap_count == 2) {
 			tocopy = DATA_IN_PAGE - data_bytes;
 			src += data_bytes;
 		}
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 06/19] intel_th: msu: Release resources on read error
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (4 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 05/19] intel_th: msu: Fix offset for wrapped block Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 07/19] intel_th: sth: Sanitize packet callback's return values Alexander Shishkin
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

From: Laurent FERT <laurent.fert@intel.com>

Right now, reading from msc character device will leak its's user count
on read error.

This patch makes sure resources are released when there is no data left
to read from the buffer.

Signed-off-by: Laurent FERT <laurent.fert@intel.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/msu.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
index 3c793bbf6a..d9d6022c5a 100644
--- a/drivers/hwtracing/intel_th/msu.c
+++ b/drivers/hwtracing/intel_th/msu.c
@@ -1112,12 +1112,11 @@ static ssize_t intel_th_msc_read(struct file *file, char __user *buf,
 		size = msc->nr_pages << PAGE_SHIFT;
 
 	if (!size)
-		return 0;
+		goto put_count;
 
-	if (off >= size) {
-		len = 0;
+	if (off >= size)
 		goto put_count;
-	}
+
 	if (off + len >= size)
 		len = size - off;
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 07/19] intel_th: sth: Sanitize packet callback's return values
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (5 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 06/19] intel_th: msu: Release resources on read error Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 08/19] intel_th: Set root device's drvdata early Alexander Shishkin
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

According to the stm class interface, the packet callback should return
an error if it is asked to generate packets that it doesn't support.
When it succeeds, it should return number of bytes consumed from its
payload. Currently, for FLAG packet it mistakenly returns 1.

This patch addresses these issues.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/sth.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/intel_th/sth.c b/drivers/hwtracing/intel_th/sth.c
index 56101c33e1..e1aee61dd7 100644
--- a/drivers/hwtracing/intel_th/sth.c
+++ b/drivers/hwtracing/intel_th/sth.c
@@ -94,10 +94,13 @@ static ssize_t sth_stm_packet(struct stm_data *stm_data, unsigned int master,
 	case STP_PACKET_TRIG:
 		if (flags & STP_PACKET_TIMESTAMPED)
 			reg += 4;
-		iowrite8(*payload, sth->base + reg);
+		writeb_relaxed(*payload, sth->base + reg);
 		break;
 
 	case STP_PACKET_MERR:
+		if (size > 4)
+			size = 4;
+
 		sth_iowrite(&out->MERR, payload, size);
 		break;
 
@@ -107,8 +110,8 @@ static ssize_t sth_stm_packet(struct stm_data *stm_data, unsigned int master,
 		else
 			outp = (u64 __iomem *)&out->FLAG;
 
-		size = 1;
-		sth_iowrite(outp, payload, size);
+		size = 0;
+		writeb_relaxed(0, outp);
 		break;
 
 	case STP_PACKET_USER:
@@ -129,6 +132,8 @@ static ssize_t sth_stm_packet(struct stm_data *stm_data, unsigned int master,
 
 		sth_iowrite(outp, payload, size);
 		break;
+	default:
+		return -ENOTSUPP;
 	}
 
 	return size;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 08/19] intel_th: Set root device's drvdata early
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (6 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 07/19] intel_th: sth: Sanitize packet callback's return values Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 09/19] intel_th: Use real device index in the node names Alexander Shishkin
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

Already during the subdevice initialization time, devices will need
to reference Intel TH controller descriptor structure.

This patch moves setting the drvdata from the pci glue to intel_th
core, before subdevices are populated.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/core.c | 2 ++
 drivers/hwtracing/intel_th/pci.c  | 2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index b8b9895da5..6df3cd9774 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -584,6 +584,8 @@ intel_th_alloc(struct device *dev, struct resource *devres,
 	}
 	th->dev = dev;
 
+	dev_set_drvdata(dev, th);
+
 	err = intel_th_populate(th, devres, ndevres, irq);
 	if (err)
 		goto err_chrdev;
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
index 09017073d7..bca7a2ac00 100644
--- a/drivers/hwtracing/intel_th/pci.c
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -46,8 +46,6 @@ static int intel_th_pci_probe(struct pci_dev *pdev,
 	if (IS_ERR(th))
 		return PTR_ERR(th);
 
-	pci_set_drvdata(pdev, th);
-
 	return 0;
 }
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 09/19] intel_th: Use real device index in the node names
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (7 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 08/19] intel_th: Set root device's drvdata early Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 10/19] stm class: Use driver's packet callback return value Alexander Shishkin
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

Most of the intel_th core supports multiple co-existing TH devices,
except for output device nodes, where intel_th device id is hardcoded
to be zero.

Fix this by fetching the actual intel_th device id from the parent
device's drvdata.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/intel_th/core.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 6df3cd9774..4272f2ce5f 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -124,17 +124,34 @@ static struct device_type intel_th_source_device_type = {
 	.release	= intel_th_device_release,
 };
 
+static struct intel_th *to_intel_th(struct intel_th_device *thdev)
+{
+	/*
+	 * subdevice tree is flat: if this one is not a switch, its
+	 * parent must be
+	 */
+	if (thdev->type != INTEL_TH_SWITCH)
+		thdev = to_intel_th_hub(thdev);
+
+	if (WARN_ON_ONCE(!thdev || thdev->type != INTEL_TH_SWITCH))
+		return NULL;
+
+	return dev_get_drvdata(thdev->dev.parent);
+}
+
 static char *intel_th_output_devnode(struct device *dev, umode_t *mode,
 				     kuid_t *uid, kgid_t *gid)
 {
 	struct intel_th_device *thdev = to_intel_th_device(dev);
+	struct intel_th *th = to_intel_th(thdev);
 	char *node;
 
 	if (thdev->id >= 0)
-		node = kasprintf(GFP_KERNEL, "intel_th%d/%s%d", 0, thdev->name,
-				 thdev->id);
+		node = kasprintf(GFP_KERNEL, "intel_th%d/%s%d", th->id,
+				 thdev->name, thdev->id);
 	else
-		node = kasprintf(GFP_KERNEL, "intel_th%d/%s", 0, thdev->name);
+		node = kasprintf(GFP_KERNEL, "intel_th%d/%s", th->id,
+				 thdev->name);
 
 	return node;
 }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 10/19] stm class: Use driver's packet callback return value
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (8 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 09/19] intel_th: Use real device index in the node names Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 11/19] stm class: Support devices with multiple instances Alexander Shishkin
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

STM drivers provide a callback to generate/send individual STP packets;
it also tells the stm core how many bytes of payload it has consumed.
However, we would also need to use the negative space of this return
value to communicate errors that occur during the packet generation,
in which case the stm core will have to take appropriate action.

For now, we need to account for the possibility that the stm driver may
not support certain combinations of packet type/flags, in which case
it is expected to signal an error.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/core.c | 19 ++++++++++++-------
 include/linux/stm.h          |  7 +++++++
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index cdec240bd6..385db65994 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -380,8 +380,8 @@ static int stm_file_assign(struct stm_file *stmf, char *id, unsigned int width)
 	return ret;
 }
 
-static void stm_write(struct stm_data *data, unsigned int master,
-		      unsigned int channel, const char *buf, size_t count)
+static ssize_t stm_write(struct stm_data *data, unsigned int master,
+			  unsigned int channel, const char *buf, size_t count)
 {
 	unsigned int flags = STP_PACKET_TIMESTAMPED;
 	const unsigned char *p = buf, nil = 0;
@@ -393,9 +393,14 @@ static void stm_write(struct stm_data *data, unsigned int master,
 		sz = data->packet(data, master, channel, STP_PACKET_DATA, flags,
 				  sz, p);
 		flags = 0;
+
+		if (sz < 0)
+			break;
 	}
 
 	data->packet(data, master, channel, STP_PACKET_FLAG, 0, 0, &nil);
+
+	return pos;
 }
 
 static ssize_t stm_char_write(struct file *file, const char __user *buf,
@@ -433,8 +438,8 @@ static ssize_t stm_char_write(struct file *file, const char __user *buf,
 		return -EFAULT;
 	}
 
-	stm_write(stm->data, stmf->output.master, stmf->output.channel, kbuf,
-		  count);
+	count = stm_write(stm->data, stmf->output.master, stmf->output.channel,
+			  kbuf, count);
 
 	kfree(kbuf);
 
@@ -996,9 +1001,9 @@ int stm_source_write(struct stm_source_data *data, unsigned int chan,
 
 	stm = srcu_dereference(src->link, &stm_source_srcu);
 	if (stm)
-		stm_write(stm->data, src->output.master,
-			  src->output.channel + chan,
-			  buf, count);
+		count = stm_write(stm->data, src->output.master,
+				  src->output.channel + chan,
+				  buf, count);
 	else
 		count = -ENODEV;
 
diff --git a/include/linux/stm.h b/include/linux/stm.h
index 9d0083d364..ab8ceca4f5 100644
--- a/include/linux/stm.h
+++ b/include/linux/stm.h
@@ -67,6 +67,13 @@ struct stm_device;
  * description. That is, the lowest master that can be allocated to software
  * writers is @sw_start and data from this writer will appear is @sw_start
  * master in the STP stream.
+ *
+ * The @packet callback should adhere to the following rules:
+ *   1) it must return the number of bytes it consumed from the payload;
+ *   2) therefore, if it sent a packet that does not have payload (like FLAG),
+ *      it must return zero;
+ *   3) if it does not support the requested packet type/flag combination,
+ *      it must return -ENOTSUPP.
  */
 struct stm_data {
 	const char		*name;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 11/19] stm class: Support devices with multiple instances
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (9 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 10/19] stm class: Use driver's packet callback return value Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 12/19] stm class: dummy_stm: Create multiple devices Alexander Shishkin
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

By convention, the name of the stm policy directory in configfs consists of
the device name to which it applies and the actual policy name, separated
by a dot. Now, some devices already have dots in their names that separate
name of the actual device from its instance identifier. Such devices will
result in two (or more, who can tell) dots in the policy directory name.

Existing policy code, however, will treat the first dot as the one that
separates device name from policy name, therefore failing the above case.

This patch makes the last dot in the directory name be the separator, thus
prohibiting dots from being used in policy names.

Suggested-by: Chunyan Zhang <zhang.chunyan@linaro.org>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/policy.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/stm/policy.c b/drivers/hwtracing/stm/policy.c
index 94d3abfb73..1db189657b 100644
--- a/drivers/hwtracing/stm/policy.c
+++ b/drivers/hwtracing/stm/policy.c
@@ -332,10 +332,11 @@ stp_policies_make(struct config_group *group, const char *name)
 
 	/*
 	 * node must look like <device_name>.<policy_name>, where
-	 * <device_name> is the name of an existing stm device and
-	 * <policy_name> is an arbitrary string
+	 * <device_name> is the name of an existing stm device; may
+	 *               contain dots;
+	 * <policy_name> is an arbitrary string; may not contain dots
 	 */
-	p = strchr(devname, '.');
+	p = strrchr(devname, '.');
 	if (!p) {
 		kfree(devname);
 		return ERR_PTR(-EINVAL);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 12/19] stm class: dummy_stm: Create multiple devices
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (10 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 11/19] stm class: Support devices with multiple instances Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 13/19] stm class: Add heartbeat stm source device Alexander Shishkin
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

STM framework should be able to handle multiple STM devices at a time,
each one with its own master allocation policy.

This patch changes dummy_stm driver to create multiple STM sinks to
help testing the framework.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/dummy_stm.c | 57 ++++++++++++++++++++++++++++++++-------
 1 file changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/hwtracing/stm/dummy_stm.c b/drivers/hwtracing/stm/dummy_stm.c
index 3709bef0b2..4ff5961cd3 100644
--- a/drivers/hwtracing/stm/dummy_stm.c
+++ b/drivers/hwtracing/stm/dummy_stm.c
@@ -40,22 +40,61 @@ dummy_stm_packet(struct stm_data *stm_data, unsigned int master,
 	return size;
 }
 
-static struct stm_data dummy_stm = {
-	.name		= "dummy_stm",
-	.sw_start	= 0x0000,
-	.sw_end		= 0xffff,
-	.sw_nchannels	= 0xffff,
-	.packet		= dummy_stm_packet,
-};
+#define DUMMY_STM_MAX 32
+
+static struct stm_data dummy_stm[DUMMY_STM_MAX];
+
+static int nr_dummies = 4;
+
+module_param(nr_dummies, int, 0600);
+
+static unsigned int dummy_stm_nr;
 
 static int dummy_stm_init(void)
 {
-	return stm_register_device(NULL, &dummy_stm, THIS_MODULE);
+	int i, ret = -ENOMEM, __nr_dummies = ACCESS_ONCE(nr_dummies);
+
+	if (__nr_dummies < 0 || __nr_dummies > DUMMY_STM_MAX)
+		return -EINVAL;
+
+	for (i = 0; i < __nr_dummies; i++) {
+		dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
+		if (!dummy_stm[i].name)
+			goto fail_unregister;
+
+		dummy_stm[i].sw_start		= 0x0000;
+		dummy_stm[i].sw_end		= 0xffff;
+		dummy_stm[i].sw_nchannels	= 0xffff;
+		dummy_stm[i].packet		= dummy_stm_packet;
+
+		ret = stm_register_device(NULL, &dummy_stm[i], THIS_MODULE);
+		if (ret)
+			goto fail_free;
+	}
+
+	dummy_stm_nr = __nr_dummies;
+
+	return 0;
+
+fail_unregister:
+	for (i--; i >= 0; i--) {
+		stm_unregister_device(&dummy_stm[i]);
+fail_free:
+		kfree(dummy_stm[i].name);
+	}
+
+	return ret;
+
 }
 
 static void dummy_stm_exit(void)
 {
-	stm_unregister_device(&dummy_stm);
+	int i;
+
+	for (i = 0; i < dummy_stm_nr; i++) {
+		stm_unregister_device(&dummy_stm[i]);
+		kfree(dummy_stm[i].name);
+	}
 }
 
 module_init(dummy_stm_init);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 13/19] stm class: Add heartbeat stm source device
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (11 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 12/19] stm class: dummy_stm: Create multiple devices Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 14/19] stm class: Fix unlocking braino in the error path Alexander Shishkin
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

Heartbeat stm source may have multiple instances (for connecting to
different stm devices). Each instance will send a periodic test message
over its stm device when it is linked. This can be used for testing stm
class framework, stm device drivers or as a heartbeat over the stm link.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/Kconfig     |  11 ++++
 drivers/hwtracing/stm/Makefile    |   2 +
 drivers/hwtracing/stm/heartbeat.c | 130 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 143 insertions(+)
 create mode 100644 drivers/hwtracing/stm/heartbeat.c

diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig
index e0ac753955..847a39b353 100644
--- a/drivers/hwtracing/stm/Kconfig
+++ b/drivers/hwtracing/stm/Kconfig
@@ -28,4 +28,15 @@ config STM_SOURCE_CONSOLE
 	  If you want to send kernel console messages over STM devices,
 	  say Y.
 
+config STM_SOURCE_HEARTBEAT
+	tristate "Heartbeat over STM devices"
+	help
+	  This is a kernel space trace source that sends periodic
+	  heartbeat messages to trace hosts over STM devices. It is
+	  also useful for testing stm class drivers and the stm class
+	  framework itself.
+
+	  If you want to send heartbeat messages over STM devices,
+	  say Y.
+
 endif
diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile
index f9312c38dd..a9ce3d487e 100644
--- a/drivers/hwtracing/stm/Makefile
+++ b/drivers/hwtracing/stm/Makefile
@@ -5,5 +5,7 @@ stm_core-y		:= core.o policy.o
 obj-$(CONFIG_STM_DUMMY)	+= dummy_stm.o
 
 obj-$(CONFIG_STM_SOURCE_CONSOLE)	+= stm_console.o
+obj-$(CONFIG_STM_SOURCE_HEARTBEAT)	+= stm_heartbeat.o
 
 stm_console-y		:= console.o
+stm_heartbeat-y		:= heartbeat.o
diff --git a/drivers/hwtracing/stm/heartbeat.c b/drivers/hwtracing/stm/heartbeat.c
new file mode 100644
index 0000000000..0133571b50
--- /dev/null
+++ b/drivers/hwtracing/stm/heartbeat.c
@@ -0,0 +1,130 @@
+/*
+ * Simple heartbeat STM source driver
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * Heartbeat STM source will send repetitive messages over STM devices to a
+ * trace host.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/hrtimer.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+
+#define STM_HEARTBEAT_MAX	32
+
+static int nr_devs = 4;
+static int interval_ms = 10;
+
+module_param(nr_devs, int, 0600);
+module_param(interval_ms, int, 0600);
+
+static struct stm_heartbeat {
+	struct stm_source_data	data;
+	struct hrtimer		hrtimer;
+	unsigned int		active;
+} stm_heartbeat[STM_HEARTBEAT_MAX];
+
+static unsigned int nr_instances;
+
+static const char str[] = "heartbeat stm source driver is here to serve you";
+
+static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr)
+{
+	struct stm_heartbeat *heartbeat = container_of(hr, struct stm_heartbeat,
+						       hrtimer);
+
+	stm_source_write(&heartbeat->data, 0, str, sizeof str);
+	if (heartbeat->active)
+		hrtimer_forward_now(hr, ms_to_ktime(interval_ms));
+
+	return heartbeat->active ? HRTIMER_RESTART : HRTIMER_NORESTART;
+}
+
+static int stm_heartbeat_link(struct stm_source_data *data)
+{
+	struct stm_heartbeat *heartbeat =
+		container_of(data, struct stm_heartbeat, data);
+
+	heartbeat->active = 1;
+	hrtimer_start(&heartbeat->hrtimer, ms_to_ktime(interval_ms),
+		      HRTIMER_MODE_ABS);
+
+	return 0;
+}
+
+static void stm_heartbeat_unlink(struct stm_source_data *data)
+{
+	struct stm_heartbeat *heartbeat =
+		container_of(data, struct stm_heartbeat, data);
+
+	heartbeat->active = 0;
+	hrtimer_cancel(&heartbeat->hrtimer);
+}
+
+static int stm_heartbeat_init(void)
+{
+	int i, ret = -ENOMEM, __nr_instances = ACCESS_ONCE(nr_devs);
+
+	if (__nr_instances < 0 || __nr_instances > STM_HEARTBEAT_MAX)
+		return -EINVAL;
+
+	for (i = 0; i < __nr_instances; i++) {
+		stm_heartbeat[i].data.name =
+			kasprintf(GFP_KERNEL, "heartbeat.%d", i);
+		if (!stm_heartbeat[i].data.name)
+			goto fail_unregister;
+
+		stm_heartbeat[i].data.nr_chans	= 1;
+		stm_heartbeat[i].data.link		= stm_heartbeat_link;
+		stm_heartbeat[i].data.unlink	= stm_heartbeat_unlink;
+		hrtimer_init(&stm_heartbeat[i].hrtimer, CLOCK_MONOTONIC,
+			     HRTIMER_MODE_ABS);
+		stm_heartbeat[i].hrtimer.function =
+			stm_heartbeat_hrtimer_handler;
+
+		ret = stm_source_register_device(NULL, &stm_heartbeat[i].data);
+		if (ret)
+			goto fail_free;
+	}
+
+	nr_instances = __nr_instances;
+
+	return 0;
+
+fail_unregister:
+	for (i--; i >= 0; i--) {
+		stm_source_unregister_device(&stm_heartbeat[i].data);
+fail_free:
+		kfree(stm_heartbeat[i].data.name);
+	}
+
+	return ret;
+}
+
+static void stm_heartbeat_exit(void)
+{
+	int i;
+
+	for (i = 0; i < nr_instances; i++) {
+		stm_source_unregister_device(&stm_heartbeat[i].data);
+		kfree(stm_heartbeat[i].data.name);
+	}
+}
+
+module_init(stm_heartbeat_init);
+module_exit(stm_heartbeat_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("stm_heartbeat driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 14/19] stm class: Fix unlocking braino in the error path
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (12 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 13/19] stm class: Add heartbeat stm source device Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 15/19] stm class: Guard output assignment against concurrency Alexander Shishkin
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

If an illegal attempt is made to unlink stm source device from an
stm device, the stm device's link spinlock mistakenly remains locked.
While this really shouldn't happen (there's a warning in place), the
locking should remain in order so that we can still recover from this
situation if it indeed does happen.

This patch unifies the unlocking in the exit path of
__stm_source_link_drop() to fix this.

Reported-by: Laurent Fert <laurent.fert@intel.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/core.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 385db65994..fb5a6a582b 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -816,10 +816,8 @@ static void __stm_source_link_drop(struct stm_source_device *src,
 	spin_lock(&stm->link_lock);
 	spin_lock(&src->link_lock);
 	link = srcu_dereference_check(src->link, &stm_source_srcu, 1);
-	if (WARN_ON_ONCE(link != stm)) {
-		spin_unlock(&src->link_lock);
-		return;
-	}
+	if (WARN_ON_ONCE(link != stm))
+		goto unlock;
 
 	stm_output_free(link, &src->output);
 	list_del_init(&src->link_entry);
@@ -827,6 +825,7 @@ static void __stm_source_link_drop(struct stm_source_device *src,
 	stm_put_device(link);
 	rcu_assign_pointer(src->link, NULL);
 
+unlock:
 	spin_unlock(&src->link_lock);
 	spin_unlock(&stm->link_lock);
 }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 15/19] stm class: Guard output assignment against concurrency
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (13 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 14/19] stm class: Fix unlocking braino in the error path Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 16/19] stm class: Fix unbalanced module/device refcounting Alexander Shishkin
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

It is possible to concurrently assign the same output (a character
device writer or an stm_source device) to different stm devices,
which sets off a strategically placed warning in stm_output_assign().

To avoid this, use a spinlock to serialize (un)assignments between
outputs and stm devices.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/core.c | 17 +++++++++++++++++
 drivers/hwtracing/stm/stm.h  |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index fb5a6a582b..6a254ce4b9 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -185,6 +185,9 @@ static void stm_output_claim(struct stm_device *stm, struct stm_output *output)
 {
 	struct stp_master *master = stm_master(stm, output->master);
 
+	lockdep_assert_held(&stm->mc_lock);
+	lockdep_assert_held(&output->lock);
+
 	if (WARN_ON_ONCE(master->nr_free < output->nr_chans))
 		return;
 
@@ -199,6 +202,9 @@ stm_output_disclaim(struct stm_device *stm, struct stm_output *output)
 {
 	struct stp_master *master = stm_master(stm, output->master);
 
+	lockdep_assert_held(&stm->mc_lock);
+	lockdep_assert_held(&output->lock);
+
 	bitmap_release_region(&master->chan_map[0], output->channel,
 			      ilog2(output->nr_chans));
 
@@ -288,6 +294,7 @@ static int stm_output_assign(struct stm_device *stm, unsigned int width,
 	}
 
 	spin_lock(&stm->mc_lock);
+	spin_lock(&output->lock);
 	/* output is already assigned -- shouldn't happen */
 	if (WARN_ON_ONCE(output->nr_chans))
 		goto unlock;
@@ -304,6 +311,7 @@ static int stm_output_assign(struct stm_device *stm, unsigned int width,
 
 	ret = 0;
 unlock:
+	spin_unlock(&output->lock);
 	spin_unlock(&stm->mc_lock);
 
 	return ret;
@@ -312,11 +320,18 @@ unlock:
 static void stm_output_free(struct stm_device *stm, struct stm_output *output)
 {
 	spin_lock(&stm->mc_lock);
+	spin_lock(&output->lock);
 	if (output->nr_chans)
 		stm_output_disclaim(stm, output);
+	spin_unlock(&output->lock);
 	spin_unlock(&stm->mc_lock);
 }
 
+static void stm_output_init(struct stm_output *output)
+{
+	spin_lock_init(&output->lock);
+}
+
 static int major_match(struct device *dev, const void *data)
 {
 	unsigned int major = *(unsigned int *)data;
@@ -339,6 +354,7 @@ static int stm_char_open(struct inode *inode, struct file *file)
 	if (!stmf)
 		return -ENOMEM;
 
+	stm_output_init(&stmf->output);
 	stmf->stm = to_stm_device(dev);
 
 	if (!try_module_get(stmf->stm->owner))
@@ -952,6 +968,7 @@ int stm_source_register_device(struct device *parent,
 	if (err)
 		goto err;
 
+	stm_output_init(&src->output);
 	spin_lock_init(&src->link_lock);
 	INIT_LIST_HEAD(&src->link_entry);
 	src->data = data;
diff --git a/drivers/hwtracing/stm/stm.h b/drivers/hwtracing/stm/stm.h
index 97ee022414..4e8c692626 100644
--- a/drivers/hwtracing/stm/stm.h
+++ b/drivers/hwtracing/stm/stm.h
@@ -57,6 +57,7 @@ struct stm_device {
 	container_of((_d), struct stm_device, dev)
 
 struct stm_output {
+	spinlock_t		lock;
 	unsigned int		master;
 	unsigned int		channel;
 	unsigned int		nr_chans;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 16/19] stm class: Fix unbalanced module/device refcounting
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (14 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 15/19] stm class: Guard output assignment against concurrency Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 17/19] stm class: Fix a race in unlinking Alexander Shishkin
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

STM code takes references to the stm device and its module for the
duration of the character device's existence or the stm_source link.
Dropping these references is not well balanced everywhere, which may
lead to leaks.

This patch balances the acquisition and releasing of these two
references and annotates each site so that it's easier to verify
correctness by reading the code.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/core.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 6a254ce4b9..0144ded45b 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -113,6 +113,7 @@ struct stm_device *stm_find_device(const char *buf)
 
 	stm = to_stm_device(dev);
 	if (!try_module_get(stm->owner)) {
+		/* matches class_find_device() above */
 		put_device(dev);
 		return NULL;
 	}
@@ -125,7 +126,7 @@ struct stm_device *stm_find_device(const char *buf)
  * @stm:	stm device, previously acquired by stm_find_device()
  *
  * This drops the module reference and device reference taken by
- * stm_find_device().
+ * stm_find_device() or stm_char_open().
  */
 void stm_put_device(struct stm_device *stm)
 {
@@ -365,6 +366,8 @@ static int stm_char_open(struct inode *inode, struct file *file)
 	return nonseekable_open(inode, file);
 
 err_free:
+	/* matches class_find_device() above */
+	put_device(dev);
 	kfree(stmf);
 
 	return err;
@@ -375,6 +378,11 @@ static int stm_char_release(struct inode *inode, struct file *file)
 	struct stm_file *stmf = file->private_data;
 
 	stm_output_free(stmf->stm, &stmf->output);
+
+	/*
+	 * matches the stm_char_open()'s
+	 * class_find_device() + try_module_get()
+	 */
 	stm_put_device(stmf->stm);
 	kfree(stmf);
 
@@ -539,10 +547,8 @@ static int stm_char_policy_set_ioctl(struct stm_file *stmf, void __user *arg)
 		ret = stm->data->link(stm->data, stmf->output.master,
 				      stmf->output.channel);
 
-	if (ret) {
+	if (ret)
 		stm_output_free(stmf->stm, &stmf->output);
-		stm_put_device(stmf->stm);
-	}
 
 err_free:
 	kfree(id);
@@ -679,6 +685,7 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
 	return 0;
 
 err_device:
+	/* matches device_initialize() above */
 	put_device(&stm->dev);
 err_free:
 	kfree(stm);
@@ -791,7 +798,6 @@ static int stm_source_link_add(struct stm_source_device *src,
 
 fail_free_output:
 	stm_output_free(stm, &src->output);
-	stm_put_device(stm);
 
 fail_detach:
 	mutex_lock(&stm->link_mutex);
@@ -905,8 +911,10 @@ static ssize_t stm_source_link_store(struct device *dev,
 		return -EINVAL;
 
 	err = stm_source_link_add(src, link);
-	if (err)
+	if (err) {
+		/* matches the stm_find_device() above */
 		stm_put_device(link);
+	}
 
 	return err ? : count;
 }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 17/19] stm class: Fix a race in unlinking
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (15 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 16/19] stm class: Fix unbalanced module/device refcounting Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 18/19] stm class: Plug stm device's unlink callback Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 19/19] stm class: dummy_stm: Add link callback for fault injection Alexander Shishkin
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

There is a window in stm_source_link_drop(), during which the source's
link may change before locks are acquired. When this happens, it throws
a warning, since this is not an expected scenario.

This patch handles the race in such a way that if the link appears to
have changed by the time we took the locks, it will release them and
repeat the whole unlinking procedure from the beginning, unless the
other contender beat us to it.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/core.c | 54 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 42 insertions(+), 12 deletions(-)

diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 0144ded45b..43a4761695 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -694,18 +694,26 @@ err_free:
 }
 EXPORT_SYMBOL_GPL(stm_register_device);
 
-static void __stm_source_link_drop(struct stm_source_device *src,
-				   struct stm_device *stm);
+static int __stm_source_link_drop(struct stm_source_device *src,
+				  struct stm_device *stm);
 
 void stm_unregister_device(struct stm_data *stm_data)
 {
 	struct stm_device *stm = stm_data->stm;
 	struct stm_source_device *src, *iter;
-	int i;
+	int i, ret;
 
 	mutex_lock(&stm->link_mutex);
 	list_for_each_entry_safe(src, iter, &stm->link_list, link_entry) {
-		__stm_source_link_drop(src, stm);
+		ret = __stm_source_link_drop(src, stm);
+		/*
+		 * src <-> stm link must not change under the same
+		 * stm::link_mutex, so complain loudly if it has;
+		 * also in this situation ret!=0 means this src is
+		 * not connected to this stm and it should be otherwise
+		 * safe to proceed with the tear-down of stm.
+		 */
+		WARN_ON_ONCE(ret);
 	}
 	mutex_unlock(&stm->link_mutex);
 
@@ -824,22 +832,28 @@ fail_detach:
  *
  * Caller must hold stm::link_mutex.
  */
-static void __stm_source_link_drop(struct stm_source_device *src,
-				   struct stm_device *stm)
+static int __stm_source_link_drop(struct stm_source_device *src,
+				  struct stm_device *stm)
 {
 	struct stm_device *link;
+	int ret = 0;
 
 	lockdep_assert_held(&stm->link_mutex);
 
-	if (src->data->unlink)
-		src->data->unlink(src->data);
-
 	/* for stm::link_list modification, we hold both mutex and spinlock */
 	spin_lock(&stm->link_lock);
 	spin_lock(&src->link_lock);
 	link = srcu_dereference_check(src->link, &stm_source_srcu, 1);
-	if (WARN_ON_ONCE(link != stm))
+
+	/*
+	 * The linked device may have changed since we last looked, because
+	 * we weren't holding the src::link_lock back then; if this is the
+	 * case, tell the caller to retry.
+	 */
+	if (link != stm) {
+		ret = -EAGAIN;
 		goto unlock;
+	}
 
 	stm_output_free(link, &src->output);
 	list_del_init(&src->link_entry);
@@ -850,6 +864,11 @@ static void __stm_source_link_drop(struct stm_source_device *src,
 unlock:
 	spin_unlock(&src->link_lock);
 	spin_unlock(&stm->link_lock);
+
+	if (!ret && src->data->unlink)
+		src->data->unlink(src->data);
+
+	return ret;
 }
 
 /**
@@ -865,18 +884,29 @@ unlock:
 static void stm_source_link_drop(struct stm_source_device *src)
 {
 	struct stm_device *stm;
-	int idx;
+	int idx, ret;
 
+retry:
 	idx = srcu_read_lock(&stm_source_srcu);
+	/*
+	 * The stm device will be valid for the duration of this
+	 * read section, but the link may change before we grab
+	 * the src::link_lock in __stm_source_link_drop().
+	 */
 	stm = srcu_dereference(src->link, &stm_source_srcu);
 
+	ret = 0;
 	if (stm) {
 		mutex_lock(&stm->link_mutex);
-		__stm_source_link_drop(src, stm);
+		ret = __stm_source_link_drop(src, stm);
 		mutex_unlock(&stm->link_mutex);
 	}
 
 	srcu_read_unlock(&stm_source_srcu, idx);
+
+	/* if it did change, retry */
+	if (ret == -EAGAIN)
+		goto retry;
 }
 
 static ssize_t stm_source_link_show(struct device *dev,
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 18/19] stm class: Plug stm device's unlink callback
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (16 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 17/19] stm class: Fix a race in unlinking Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  2016-02-12 17:00 ` [QUEUED v20160212 19/19] stm class: dummy_stm: Add link callback for fault injection Alexander Shishkin
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

STM device's unlink callback is never actually called from anywhere in
the stm class code.

This patch adds calls to stm driver's unlink method after the unlinking
has succeeded.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/core.c | 23 +++++++++++++++++++----
 include/linux/stm.h          |  3 +++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 43a4761695..70deef51a3 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -376,14 +376,19 @@ err_free:
 static int stm_char_release(struct inode *inode, struct file *file)
 {
 	struct stm_file *stmf = file->private_data;
+	struct stm_device *stm = stmf->stm;
+
+	if (stm->data->unlink)
+		stm->data->unlink(stm->data, stmf->output.master,
+				  stmf->output.channel);
 
-	stm_output_free(stmf->stm, &stmf->output);
+	stm_output_free(stm, &stmf->output);
 
 	/*
 	 * matches the stm_char_open()'s
 	 * class_find_device() + try_module_get()
 	 */
-	stm_put_device(stmf->stm);
+	stm_put_device(stm);
 	kfree(stmf);
 
 	return 0;
@@ -865,8 +870,18 @@ unlock:
 	spin_unlock(&src->link_lock);
 	spin_unlock(&stm->link_lock);
 
-	if (!ret && src->data->unlink)
-		src->data->unlink(src->data);
+	/*
+	 * Call the unlink callbacks for both source and stm, when we know
+	 * that we have actually performed the unlinking.
+	 */
+	if (!ret) {
+		if (src->data->unlink)
+			src->data->unlink(src->data);
+
+		if (stm->data->unlink)
+			stm->data->unlink(stm->data, src->output.master,
+					  src->output.channel);
+	}
 
 	return ret;
 }
diff --git a/include/linux/stm.h b/include/linux/stm.h
index ab8ceca4f5..1a79ed8e43 100644
--- a/include/linux/stm.h
+++ b/include/linux/stm.h
@@ -74,6 +74,9 @@ struct stm_device;
  *      it must return zero;
  *   3) if it does not support the requested packet type/flag combination,
  *      it must return -ENOTSUPP.
+ *
+ * The @unlink callback is called when there are no more active writers so
+ * that the master/channel can be quiesced.
  */
 struct stm_data {
 	const char		*name;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [QUEUED v20160212 19/19] stm class: dummy_stm: Add link callback for fault injection
  2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
                   ` (17 preceding siblings ...)
  2016-02-12 17:00 ` [QUEUED v20160212 18/19] stm class: Plug stm device's unlink callback Alexander Shishkin
@ 2016-02-12 17:00 ` Alexander Shishkin
  18 siblings, 0 replies; 20+ messages in thread
From: Alexander Shishkin @ 2016-02-12 17:00 UTC (permalink / raw)
  To: Greg KH
  Cc: Mathieu Poirier, Chunyan Zhang, laurent.fert, yann.fouassier,
	linux-kernel, Alexander Shishkin

STM device's link callback has the power to abort master/channel
assignment by returning a negative error code. Use this in dummy
stm device to optionally abort assigning certain channel IDs.
This is useful as fault injection into the stm class core, for
testing purposes.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 drivers/hwtracing/stm/dummy_stm.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/hwtracing/stm/dummy_stm.c b/drivers/hwtracing/stm/dummy_stm.c
index 4ff5961cd3..310adf57e7 100644
--- a/drivers/hwtracing/stm/dummy_stm.c
+++ b/drivers/hwtracing/stm/dummy_stm.c
@@ -50,6 +50,19 @@ module_param(nr_dummies, int, 0600);
 
 static unsigned int dummy_stm_nr;
 
+static unsigned int fail_mode;
+
+module_param(fail_mode, int, 0600);
+
+static int dummy_stm_link(struct stm_data *data, unsigned int master,
+			  unsigned int channel)
+{
+	if (fail_mode && (channel & fail_mode))
+		return -EINVAL;
+
+	return 0;
+}
+
 static int dummy_stm_init(void)
 {
 	int i, ret = -ENOMEM, __nr_dummies = ACCESS_ONCE(nr_dummies);
@@ -66,6 +79,7 @@ static int dummy_stm_init(void)
 		dummy_stm[i].sw_end		= 0xffff;
 		dummy_stm[i].sw_nchannels	= 0xffff;
 		dummy_stm[i].packet		= dummy_stm_packet;
+		dummy_stm[i].link		= dummy_stm_link;
 
 		ret = stm_register_device(NULL, &dummy_stm[i], THIS_MODULE);
 		if (ret)
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2016-02-12 17:14 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-12 17:00 [QUEUED v20160212 00/19] stm class/intel_th: Patches in my queue Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 01/19] stm class: Use a signed return type for stm_find_master_chan Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 02/19] intel_th: Depend on HAS_IOMEM Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 03/19] intel_th: gth: Remove commented-out code Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 04/19] intel_th: Update scratchpad bits according to enabled output activity Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 05/19] intel_th: msu: Fix offset for wrapped block Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 06/19] intel_th: msu: Release resources on read error Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 07/19] intel_th: sth: Sanitize packet callback's return values Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 08/19] intel_th: Set root device's drvdata early Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 09/19] intel_th: Use real device index in the node names Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 10/19] stm class: Use driver's packet callback return value Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 11/19] stm class: Support devices with multiple instances Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 12/19] stm class: dummy_stm: Create multiple devices Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 13/19] stm class: Add heartbeat stm source device Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 14/19] stm class: Fix unlocking braino in the error path Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 15/19] stm class: Guard output assignment against concurrency Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 16/19] stm class: Fix unbalanced module/device refcounting Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 17/19] stm class: Fix a race in unlinking Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 18/19] stm class: Plug stm device's unlink callback Alexander Shishkin
2016-02-12 17:00 ` [QUEUED v20160212 19/19] stm class: dummy_stm: Add link callback for fault injection Alexander Shishkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox