coresight: etm3x: implementing perf_enable/disable() API
[firefly-linux-kernel-4.4.55.git] / drivers / hwtracing / coresight / coresight.c
index f26589effb70157b4b53a32d03babd34c657fb78..95cccb179763cfa0585db25b1e5e688049a3b8a2 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/coresight.h>
 #include <linux/of_platform.h>
 #include <linux/delay.h>
+#include <linux/pm_runtime.h>
 
 #include "coresight-priv.h"
 
@@ -221,7 +222,7 @@ static void coresight_disable_link(struct coresight_device *csdev,
        csdev->enable = false;
 }
 
-static int coresight_enable_source(struct coresight_device *csdev)
+static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
 {
        int ret;
 
@@ -233,7 +234,7 @@ static int coresight_enable_source(struct coresight_device *csdev)
 
        if (!csdev->enable) {
                if (source_ops(csdev)->enable) {
-                       ret = source_ops(csdev)->enable(csdev);
+                       ret = source_ops(csdev)->enable(csdev, NULL, mode);
                        if (ret)
                                return ret;
                }
@@ -321,6 +322,21 @@ err:
        goto out;
 }
 
+struct coresight_device *coresight_get_sink(struct list_head *path)
+{
+       struct coresight_device *csdev;
+
+       if (!path)
+               return NULL;
+
+       csdev = list_last_entry(path, struct coresight_node, link)->csdev;
+       if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
+           csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
+               return NULL;
+
+       return csdev;
+}
+
 /**
  * _coresight_build_path - recursively build a path from a @csdev to a sink.
  * @csdev:     The device to start from.
@@ -361,7 +377,8 @@ out:
        /*
         * A path from this element to a sink has been found.  The elements
         * leading to the sink are already enqueued, all that is left to do
-        * is add a node for this element.
+        * is tell the PM runtime core we need this element and add a node
+        * for it.
         */
        node = kzalloc(sizeof(struct coresight_node), GFP_KERNEL);
        if (!node)
@@ -369,6 +386,7 @@ out:
 
        node->csdev = csdev;
        list_add(&node->link, path);
+       pm_runtime_get_sync(csdev->dev.parent);
 
        return 0;
 }
@@ -400,9 +418,13 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
  */
 void coresight_release_path(struct list_head *path)
 {
+       struct coresight_device *csdev;
        struct coresight_node *nd, *next;
 
        list_for_each_entry_safe(nd, next, path, link) {
+               csdev = nd->csdev;
+
+               pm_runtime_put_sync(csdev->dev.parent);
                list_del(&nd->link);
                kfree(nd);
        }
@@ -436,7 +458,7 @@ int coresight_enable(struct coresight_device *csdev)
        if (ret)
                goto err_path;
 
-       ret = coresight_enable_source(csdev);
+       ret = coresight_enable_source(csdev, CS_MODE_SYSFS);
        if (ret)
                goto err_source;