| From 69ff1e92cce7e625ac1fad896b66bbdd55e97787 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 20 Sep 2018 13:18:10 -0600 |
| Subject: coresight: dynamic-replicator: Handle multiple connections |
| |
| From: Suzuki K Poulose <suzuki.poulose@arm.com> |
| |
| [ Upstream commit 30af4fb619e5126cb3152072e687b377fc9398d6 ] |
| |
| When a replicator port is enabled, we block the traffic |
| on the other port and route all traffic to the new enabled |
| port. If there are two active trace sessions each targeting |
| the two different paths from the replicator, the second session |
| will disable the first session and route all the data to the |
| second path. |
| ETR |
| / |
| e.g, replicator |
| \ |
| ETB |
| |
| If CPU0 is operated in sysfs mode to ETR and CPU1 is operated |
| in perf mode to ETB, depending on the order in which the |
| replicator is enabled one device is blocked. |
| |
| Ideally we need trace-id for the session to make the |
| right choice. That implies we need a trace-id allocation |
| logic for the coresight subsystem and use that to route |
| the traffic. The short term solution is to only manage |
| the "target port" and leave the other port untouched. |
| That leaves both the paths unaffected, except that some |
| unwanted traffic may be pushed to the paths (if the Trace-IDs |
| are not far enough), which is still fine and can be filtered |
| out while processing rather than silently blocking the data. |
| |
| Cc: Mathieu Poirier <mathieu.poirier@linaro.org> |
| Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> |
| Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../coresight/coresight-dynamic-replicator.c | 64 ++++++++++++++----- |
| 1 file changed, 47 insertions(+), 17 deletions(-) |
| |
| diff --git a/drivers/hwtracing/coresight/coresight-dynamic-replicator.c b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c |
| index f6d0571ab9dd5..d31f1d8758b24 100644 |
| --- a/drivers/hwtracing/coresight/coresight-dynamic-replicator.c |
| +++ b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c |
| @@ -34,26 +34,42 @@ struct replicator_state { |
| struct coresight_device *csdev; |
| }; |
| |
| +/* |
| + * replicator_reset : Reset the replicator configuration to sane values. |
| + */ |
| +static void replicator_reset(struct replicator_state *drvdata) |
| +{ |
| + CS_UNLOCK(drvdata->base); |
| + |
| + writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); |
| + writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1); |
| + |
| + CS_LOCK(drvdata->base); |
| +} |
| + |
| static int replicator_enable(struct coresight_device *csdev, int inport, |
| int outport) |
| { |
| + u32 reg; |
| struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent); |
| |
| + switch (outport) { |
| + case 0: |
| + reg = REPLICATOR_IDFILTER0; |
| + break; |
| + case 1: |
| + reg = REPLICATOR_IDFILTER1; |
| + break; |
| + default: |
| + WARN_ON(1); |
| + return -EINVAL; |
| + } |
| + |
| CS_UNLOCK(drvdata->base); |
| |
| - /* |
| - * Ensure that the other port is disabled |
| - * 0x00 - passing through the replicator unimpeded |
| - * 0xff - disable (or impede) the flow of ATB data |
| - */ |
| - if (outport == 0) { |
| - writel_relaxed(0x00, drvdata->base + REPLICATOR_IDFILTER0); |
| - writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1); |
| - } else { |
| - writel_relaxed(0x00, drvdata->base + REPLICATOR_IDFILTER1); |
| - writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); |
| - } |
| |
| + /* Ensure that the outport is enabled. */ |
| + writel_relaxed(0x00, drvdata->base + reg); |
| CS_LOCK(drvdata->base); |
| |
| dev_info(drvdata->dev, "REPLICATOR enabled\n"); |
| @@ -63,15 +79,25 @@ static int replicator_enable(struct coresight_device *csdev, int inport, |
| static void replicator_disable(struct coresight_device *csdev, int inport, |
| int outport) |
| { |
| + u32 reg; |
| struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent); |
| |
| + switch (outport) { |
| + case 0: |
| + reg = REPLICATOR_IDFILTER0; |
| + break; |
| + case 1: |
| + reg = REPLICATOR_IDFILTER1; |
| + break; |
| + default: |
| + WARN_ON(1); |
| + return; |
| + } |
| + |
| CS_UNLOCK(drvdata->base); |
| |
| /* disable the flow of ATB data through port */ |
| - if (outport == 0) |
| - writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); |
| - else |
| - writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1); |
| + writel_relaxed(0xff, drvdata->base + reg); |
| |
| CS_LOCK(drvdata->base); |
| |
| @@ -156,7 +182,11 @@ static int replicator_probe(struct amba_device *adev, const struct amba_id *id) |
| desc.groups = replicator_groups; |
| drvdata->csdev = coresight_register(&desc); |
| |
| - return PTR_ERR_OR_ZERO(drvdata->csdev); |
| + if (!IS_ERR(drvdata->csdev)) { |
| + replicator_reset(drvdata); |
| + return 0; |
| + } |
| + return PTR_ERR(drvdata->csdev); |
| } |
| |
| #ifdef CONFIG_PM |
| -- |
| 2.20.1 |
| |