coresight: Expose device connections via sysfs
[linux-2.6-microblaze.git] / drivers / hwtracing / coresight / coresight-sysfs.c
index 6759f78..82afeaf 100644 (file)
@@ -122,3 +122,83 @@ void coresight_remove_sysfs_link(struct coresight_sysfs_link *info)
        info->orig->nr_links--;
        info->target->nr_links--;
 }
+
+/*
+ * coresight_make_links: Make a link for a connection from a @orig
+ * device to @target, represented by @conn.
+ *
+ *   e.g, for devOrig[output_X] -> devTarget[input_Y] is represented
+ *   as two symbolic links :
+ *
+ *     /sys/.../devOrig/out:X  -> /sys/.../devTarget/
+ *     /sys/.../devTarget/in:Y -> /sys/.../devOrig/
+ *
+ * The link names are allocated for a device where it appears. i.e, the
+ * "out" link on the master and "in" link on the slave device.
+ * The link info is stored in the connection record for avoiding
+ * the reconstruction of names for removal.
+ */
+int coresight_make_links(struct coresight_device *orig,
+                        struct coresight_connection *conn,
+                        struct coresight_device *target)
+{
+       int ret = -ENOMEM;
+       char *outs = NULL, *ins = NULL;
+       struct coresight_sysfs_link *link = NULL;
+
+       do {
+               outs = devm_kasprintf(&orig->dev, GFP_KERNEL,
+                                     "out:%d", conn->outport);
+               if (!outs)
+                       break;
+               ins = devm_kasprintf(&target->dev, GFP_KERNEL,
+                                    "in:%d", conn->child_port);
+               if (!ins)
+                       break;
+               link = devm_kzalloc(&orig->dev,
+                                   sizeof(struct coresight_sysfs_link),
+                                   GFP_KERNEL);
+               if (!link)
+                       break;
+
+               link->orig = orig;
+               link->target = target;
+               link->orig_name = outs;
+               link->target_name = ins;
+
+               ret = coresight_add_sysfs_link(link);
+               if (ret)
+                       break;
+
+               conn->link = link;
+
+               /*
+                * Install the device connection. This also indicates that
+                * the links are operational on both ends.
+                */
+               conn->child_dev = target;
+               return 0;
+       } while (0);
+
+       return ret;
+}
+
+/*
+ * coresight_remove_links: Remove the sysfs links for a given connection @conn,
+ * from @orig device to @target device. See coresight_make_links() for more
+ * details.
+ */
+void coresight_remove_links(struct coresight_device *orig,
+                           struct coresight_connection *conn)
+{
+       if (!orig || !conn->link)
+               return;
+
+       coresight_remove_sysfs_link(conn->link);
+
+       devm_kfree(&conn->child_dev->dev, conn->link->target_name);
+       devm_kfree(&orig->dev, conn->link->orig_name);
+       devm_kfree(&orig->dev, conn->link);
+       conn->link = NULL;
+       conn->child_dev = NULL;
+}