]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
intel_th: Wait until port is in reset before programming it
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>
Mon, 21 Jun 2021 15:12:46 +0000 (18:12 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Jul 2021 14:16:10 +0000 (16:16 +0200)
[ Upstream commit ab1afed701d2db7eb35c1a2526a29067a38e93d1 ]

Some devices don't drain their pipelines if we don't make sure that
the corresponding output port is in reset before programming it for
a new trace capture, resulting in bits of old trace appearing in the
new trace capture. Fix that by explicitly making sure the reset is
asserted before programming new trace capture.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Link: https://lore.kernel.org/r/20210621151246.31891-5-alexander.shishkin@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/hwtracing/intel_th/core.c
drivers/hwtracing/intel_th/gth.c
drivers/hwtracing/intel_th/intel_th.h

index 6c723b57dfc0793936e5943ba0a86b63b25703cf..be2f02e35067f8a8d3ef51a7f1a78cd9b775e541 100644 (file)
@@ -215,6 +215,22 @@ static ssize_t port_show(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR_RO(port);
 
+static void intel_th_trace_prepare(struct intel_th_device *thdev)
+{
+       struct intel_th_device *hub = to_intel_th_hub(thdev);
+       struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+
+       if (hub->type != INTEL_TH_SWITCH)
+               return;
+
+       if (thdev->type != INTEL_TH_OUTPUT)
+               return;
+
+       pm_runtime_get_sync(&thdev->dev);
+       hubdrv->prepare(hub, &thdev->output);
+       pm_runtime_put(&thdev->dev);
+}
+
 static int intel_th_output_activate(struct intel_th_device *thdev)
 {
        struct intel_th_driver *thdrv =
@@ -235,6 +251,7 @@ static int intel_th_output_activate(struct intel_th_device *thdev)
        if (ret)
                goto fail_put;
 
+       intel_th_trace_prepare(thdev);
        if (thdrv->activate)
                ret = thdrv->activate(thdev);
        else
index 5041fe7fee9edf6a1e3fdbf9747ad370fd837743..ef2751556fd77a23bee3401b52bacffe00c7515e 100644 (file)
@@ -513,6 +513,21 @@ static void gth_tscu_resync(struct gth_device *gth)
        iowrite32(reg, gth->base + REG_TSCU_TSUCTRL);
 }
 
+static void intel_th_gth_prepare(struct intel_th_device *thdev,
+                                struct intel_th_output *output)
+{
+       struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+       int count;
+
+       /*
+        * Wait until the output port is in reset before we start
+        * programming it.
+        */
+       for (count = GTH_PLE_WAITLOOP_DEPTH;
+            count && !(gth_output_get(gth, output->port) & BIT(5)); count--)
+               cpu_relax();
+}
+
 /**
  * intel_th_gth_enable() - enable tracing to an output device
  * @thdev:     GTH device
@@ -734,6 +749,7 @@ static struct intel_th_driver intel_th_gth_driver = {
        .assign         = intel_th_gth_assign,
        .unassign       = intel_th_gth_unassign,
        .set_output     = intel_th_gth_set_output,
+       .prepare        = intel_th_gth_prepare,
        .enable         = intel_th_gth_enable,
        .disable        = intel_th_gth_disable,
        .driver = {
index 780206dc9012c26c534df934b593eaa455bec780..6b5473f3c16f05e8976520d5e12eed84f79a21f5 100644 (file)
@@ -134,6 +134,7 @@ intel_th_output_assigned(struct intel_th_device *thdev)
  * @remove:    remove method
  * @assign:    match a given output type device against available outputs
  * @unassign:  deassociate an output type device from an output port
+ * @prepare:   prepare output port for tracing
  * @enable:    enable tracing for a given output device
  * @disable:   disable tracing for a given output device
  * @irq:       interrupt callback
@@ -155,6 +156,8 @@ struct intel_th_driver {
                                          struct intel_th_device *othdev);
        void                    (*unassign)(struct intel_th_device *thdev,
                                            struct intel_th_device *othdev);
+       void                    (*prepare)(struct intel_th_device *thdev,
+                                          struct intel_th_output *output);
        void                    (*enable)(struct intel_th_device *thdev,
                                          struct intel_th_output *output);
        void                    (*disable)(struct intel_th_device *thdev,