Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1334566 > unrolled thread
| Started by | Alexander Shishkin <alexander.shishkin@intel.com> |
|---|---|
| First post | 2016-02-15 17:10 +0100 |
| Last post | 2016-02-16 13:30 +0100 |
| Articles | 20 on this page of 24 — 3 participants |
Back to article view | Back to linux.kernel
[git pull] stm class/intel_th: Updates for char-misc-next Alexander Shishkin <alexander.shishkin@intel.com> - 2016-02-15 17:10 +0100
Re: [git pull] stm class/intel_th: Updates for char-misc-next Greg KH <gregkh@linuxfoundation.org> - 2016-02-15 17:50 +0100
[PATCH 07/20] intel_th: msu: Release resources on read error Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 10/20] intel_th: Use real device index in the node names Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 08/20] intel_th: sth: Sanitize packet callback's return values Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 20/20] stm class: dummy_stm: Add link callback for fault injection Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 00/20] stm class/intel_th: Updates for char-misc-next Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 12/20] stm class: Support devices with multiple instances Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 11/20] stm class: Use driver's packet callback return value Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 01/20] stm class: Use a signed return type for stm_find_master_chan Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 14/20] stm class: Add heartbeat stm source device Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 09/20] intel_th: Set root device's drvdata early Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 18/20] stm class: Fix a race in unlinking Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 13/20] stm class: dummy_stm: Create multiple devices Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 19/20] stm class: Plug stm device's unlink callback Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 04/20] intel_th: gth: Remove commented-out code Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 03/20] intel_th: Depend on HAS_IOMEM Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 15/20] stm class: Fix unlocking braino in the error path Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 16/20] stm class: Guard output assignment against concurrency Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 17/20] stm class: Fix unbalanced module/device refcounting Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 05/20] intel_th: Update scratchpad bits according to enabled output activity Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 06/20] intel_th: msu: Fix offset for wrapped block Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
[PATCH 02/20] stm class: Fix master deallocation in device unregistering Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-15 18:20 +0100
Re: [git pull] stm class/intel_th: Updates for char-misc-next Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2016-02-16 13:30 +0100
Page 1 of 2 [1] 2 Next page →
| From | Alexander Shishkin <alexander.shishkin@intel.com> |
|---|---|
| Date | 2016-02-15 17:10 +0100 |
| Subject | [git pull] stm class/intel_th: Updates for char-misc-next |
| Message-ID | <r2tSP-3jp-35@gated-at.bofh.it> |
Hi Greg,
These are patches I have queued for the next merge window. Please
consider pulling.
The following changes since commit 1b79dff672ca09a5461cc1d46ad81c62137841c5:
Merge 4.5-rc4 into char-misc-next (2016-02-14 14:25:59 -0800)
are available in the git repository at:
https://github.com/virtuoso/linux-perf.git stm-for-greg
for you to fetch changes up to fb756bc533ca533c2f415b74589b7172c3456b7c:
stm class: dummy_stm: Add link callback for fault injection (2016-02-15 15:54:37 +0200)
----------------------------------------------------------------
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
Chunyan Zhang (1):
stm class: Fix master deallocation in device unregistering
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 | 138 ++++++++++++++++++++++++++--------
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, 420 insertions(+), 80 deletions(-)
create mode 100644 drivers/hwtracing/stm/heartbeat.c
[toc] | [next] | [standalone]
| From | Greg KH <gregkh@linuxfoundation.org> |
|---|---|
| Date | 2016-02-15 17:50 +0100 |
| Message-ID | <r2uvw-3zL-21@gated-at.bofh.it> |
| In reply to | #1334566 |
On Mon, Feb 15, 2016 at 06:08:07PM +0200, Alexander Shishkin wrote: > Hi Greg, > > These are patches I have queued for the next merge window. Please > consider pulling. > > The following changes since commit 1b79dff672ca09a5461cc1d46ad81c62137841c5: > > Merge 4.5-rc4 into char-misc-next (2016-02-14 14:25:59 -0800) > > are available in the git repository at: > > https://github.com/virtuoso/linux-perf.git stm-for-greg I can't accept pull requests from github, sorry. And that isn't even a signed tag, which is also something that is required. Just send these as emails and I'll take them that way for now. thanks, greg k-h
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 07/20] intel_th: msu: Release resources on read error |
| Message-ID | <r2uYy-41S-5@gated-at.bofh.it> |
| In reply to | #1334594 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 10/20] intel_th: Use real device index in the node names |
| Message-ID | <r2uYx-41S-1@gated-at.bofh.it> |
| In reply to | #1334594 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 08/20] intel_th: sth: Sanitize packet callback's return values |
| Message-ID | <r2uYy-41S-7@gated-at.bofh.it> |
| In reply to | #1334594 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 20/20] stm class: dummy_stm: Add link callback for fault injection |
| Message-ID | <r2uYy-41S-13@gated-at.bofh.it> |
| In reply to | #1334594 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 00/20] stm class/intel_th: Updates for char-misc-next |
| Message-ID | <r2uYx-41S-3@gated-at.bofh.it> |
| In reply to | #1334594 |
Hi Greg, These are the patches I have queued for the next merge window. Please consider applying. 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 Chunyan Zhang (1): stm class: Fix master deallocation in device unregistering 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 | 138 ++++++++++++++++++++++++++-------- 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, 420 insertions(+), 80 deletions(-) create mode 100644 drivers/hwtracing/stm/heartbeat.c -- 2.7.0
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 12/20] stm class: Support devices with multiple instances |
| Message-ID | <r2uYy-41S-15@gated-at.bofh.it> |
| In reply to | #1334618 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 11/20] stm class: Use driver's packet callback return value |
| Message-ID | <r2uYy-41S-19@gated-at.bofh.it> |
| In reply to | #1334618 |
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 79cca94bfb..0db303b50e 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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 01/20] stm class: Use a signed return type for stm_find_master_chan |
| Message-ID | <r2uYy-41S-21@gated-at.bofh.it> |
| In reply to | #1334618 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 14/20] stm class: Add heartbeat stm source device |
| Message-ID | <r2uYy-41S-23@gated-at.bofh.it> |
| In reply to | #1334618 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 09/20] intel_th: Set root device's drvdata early |
| Message-ID | <r2uYy-41S-27@gated-at.bofh.it> |
| In reply to | #1334618 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 18/20] stm class: Fix a race in unlinking |
| Message-ID | <r2uYz-41S-31@gated-at.bofh.it> |
| In reply to | #1334618 |
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 f86f56d853..30181821d9 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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 13/20] stm class: dummy_stm: Create multiple devices |
| Message-ID | <r2uYz-41S-35@gated-at.bofh.it> |
| In reply to | #1334618 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 19/20] stm class: Plug stm device's unlink callback |
| Message-ID | <r2uYz-41S-43@gated-at.bofh.it> |
| In reply to | #1334618 |
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 30181821d9..de80d45d8d 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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 04/20] intel_th: gth: Remove commented-out code |
| Message-ID | <r2uYz-41S-37@gated-at.bofh.it> |
| In reply to | #1334618 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 03/20] intel_th: Depend on HAS_IOMEM |
| Message-ID | <r2uYz-41S-39@gated-at.bofh.it> |
| In reply to | #1334618 |
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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 15/20] stm class: Fix unlocking braino in the error path |
| Message-ID | <r2uYz-41S-41@gated-at.bofh.it> |
| In reply to | #1334618 |
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 0db303b50e..4a626d8990 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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 16/20] stm class: Guard output assignment against concurrency |
| Message-ID | <r2uYz-41S-47@gated-at.bofh.it> |
| In reply to | #1334618 |
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 4a626d8990..f6ade21729 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
[toc] | [prev] | [next] | [standalone]
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Date | 2016-02-15 18:20 +0100 |
| Subject | [PATCH 17/20] stm class: Fix unbalanced module/device refcounting |
| Message-ID | <r2uYz-41S-49@gated-at.bofh.it> |
| In reply to | #1334618 |
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 f6ade21729..f86f56d853 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
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web