coresight: Store pointers to connections rather than an array of them
authorJames Clark <james.clark@arm.com>
Tue, 25 Apr 2023 14:35:34 +0000 (15:35 +0100)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Mon, 5 Jun 2023 14:46:46 +0000 (15:46 +0100)
This will allow the same connection object to be referenced via the
input connection list in a later commit rather than duplicating them.

Reviewed-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: James Clark <james.clark@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20230425143542.2305069-8-james.clark@arm.com
drivers/hwtracing/coresight/coresight-core.c
drivers/hwtracing/coresight/coresight-platform.c
drivers/hwtracing/coresight/coresight-priv.h
drivers/hwtracing/coresight/coresight-tmc-etr.c
include/linux/coresight.h

index 91274e7..0b73896 100644 (file)
@@ -119,7 +119,7 @@ static int coresight_find_link_inport(struct coresight_device *csdev,
        struct coresight_connection *conn;
 
        for (i = 0; i < parent->pdata->nr_outconns; i++) {
-               conn = &parent->pdata->out_conns[i];
+               conn = parent->pdata->out_conns[i];
                if (conn->dest_dev == csdev)
                        return conn->dest_port;
        }
@@ -137,7 +137,7 @@ static int coresight_find_link_outport(struct coresight_device *csdev,
        struct coresight_connection *conn;
 
        for (i = 0; i < csdev->pdata->nr_outconns; i++) {
-               conn = &csdev->pdata->out_conns[i];
+               conn = csdev->pdata->out_conns[i];
                if (conn->dest_dev == child)
                        return conn->src_port;
        }
@@ -606,7 +606,7 @@ coresight_find_enabled_sink(struct coresight_device *csdev)
        for (i = 0; i < csdev->pdata->nr_outconns; i++) {
                struct coresight_device *child_dev;
 
-               child_dev = csdev->pdata->out_conns[i].dest_dev;
+               child_dev = csdev->pdata->out_conns[i]->dest_dev;
                if (child_dev)
                        sink = coresight_find_enabled_sink(child_dev);
                if (sink)
@@ -722,7 +722,7 @@ static int coresight_grab_device(struct coresight_device *csdev)
        for (i = 0; i < csdev->pdata->nr_outconns; i++) {
                struct coresight_device *child;
 
-               child = csdev->pdata->out_conns[i].dest_dev;
+               child = csdev->pdata->out_conns[i]->dest_dev;
                if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
                        if (!coresight_get_ref(child))
                                goto err;
@@ -733,7 +733,7 @@ err:
        for (i--; i >= 0; i--) {
                struct coresight_device *child;
 
-               child = csdev->pdata->out_conns[i].dest_dev;
+               child = csdev->pdata->out_conns[i]->dest_dev;
                if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
                        coresight_put_ref(child);
        }
@@ -752,7 +752,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
        for (i = 0; i < csdev->pdata->nr_outconns; i++) {
                struct coresight_device *child;
 
-               child = csdev->pdata->out_conns[i].dest_dev;
+               child = csdev->pdata->out_conns[i]->dest_dev;
                if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
                        coresight_put_ref(child);
        }
@@ -794,7 +794,7 @@ static int _coresight_build_path(struct coresight_device *csdev,
        for (i = 0; i < csdev->pdata->nr_outconns; i++) {
                struct coresight_device *child_dev;
 
-               child_dev = csdev->pdata->out_conns[i].dest_dev;
+               child_dev = csdev->pdata->out_conns[i]->dest_dev;
                if (child_dev &&
                    _coresight_build_path(child_dev, sink, path) == 0) {
                        found = true;
@@ -964,7 +964,7 @@ coresight_find_sink(struct coresight_device *csdev, int *depth)
                struct coresight_device *child_dev, *sink = NULL;
                int child_depth = curr_depth;
 
-               child_dev = csdev->pdata->out_conns[i].dest_dev;
+               child_dev = csdev->pdata->out_conns[i]->dest_dev;
                if (child_dev)
                        sink = coresight_find_sink(child_dev, &child_depth);
 
@@ -1334,7 +1334,7 @@ static int coresight_orphan_match(struct device *dev, void *data)
         * an orphan connection whose name matches @csdev, link it.
         */
        for (i = 0; i < i_csdev->pdata->nr_outconns; i++) {
-               conn = &i_csdev->pdata->out_conns[i];
+               conn = i_csdev->pdata->out_conns[i];
 
                /* We have found at least one orphan connection */
                if (conn->dest_dev == NULL) {
@@ -1372,7 +1372,7 @@ static int coresight_fixup_device_conns(struct coresight_device *csdev)
        int i, ret = 0;
 
        for (i = 0; i < csdev->pdata->nr_outconns; i++) {
-               struct coresight_connection *conn = &csdev->pdata->out_conns[i];
+               struct coresight_connection *conn = csdev->pdata->out_conns[i];
 
                conn->dest_dev =
                        coresight_find_csdev_by_fwnode(conn->dest_fwnode);
@@ -1406,15 +1406,12 @@ static int coresight_remove_match(struct device *dev, void *data)
         * a connection whose name matches @csdev, remove it.
         */
        for (i = 0; i < iterator->pdata->nr_outconns; i++) {
-               conn = &iterator->pdata->out_conns[i];
+               conn = iterator->pdata->out_conns[i];
 
-               if (conn->dest_dev == NULL)
-                       continue;
-
-               if (csdev->dev.fwnode == conn->dest_fwnode) {
+               /* Child_dev being set signifies that the links were made */
+               if (csdev->dev.fwnode == conn->dest_fwnode && conn->dest_dev) {
                        iterator->orphan = true;
                        coresight_remove_links(iterator, conn);
-
                        conn->dest_dev = NULL;
                        /* No need to continue */
                        break;
@@ -1534,22 +1531,26 @@ void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset)
  * to the output port of this device.
  */
 void coresight_release_platform_data(struct coresight_device *csdev,
+                                    struct device *dev,
                                     struct coresight_platform_data *pdata)
 {
        int i;
-       struct coresight_connection *conns = pdata->out_conns;
+       struct coresight_connection **conns = pdata->out_conns;
 
        for (i = 0; i < pdata->nr_outconns; i++) {
                /* If we have made the links, remove them now */
-               if (csdev && conns[i].dest_dev)
-                       coresight_remove_links(csdev, &conns[i]);
+               if (csdev && conns[i]->dest_dev)
+                       coresight_remove_links(csdev, conns[i]);
                /*
                 * Drop the refcount and clear the handle as this device
                 * is going away
                 */
-               fwnode_handle_put(conns[i].dest_fwnode);
-               conns[i].dest_fwnode = NULL;
+               fwnode_handle_put(conns[i]->dest_fwnode);
+               conns[i]->dest_fwnode = NULL;
+               devm_kfree(dev, conns[i]);
        }
+       devm_kfree(dev, pdata->out_conns);
+       devm_kfree(dev, pdata);
        if (csdev)
                coresight_remove_conns_sysfs_group(csdev);
 }
@@ -1666,7 +1667,7 @@ out_unlock:
 
 err_out:
        /* Cleanup the connection information */
-       coresight_release_platform_data(NULL, desc->pdata);
+       coresight_release_platform_data(NULL, desc->dev, desc->pdata);
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(coresight_register);
@@ -1679,7 +1680,7 @@ void coresight_unregister(struct coresight_device *csdev)
                cti_assoc_ops->remove(csdev);
        coresight_remove_conns(csdev);
        coresight_clear_default_sink(csdev);
-       coresight_release_platform_data(csdev, csdev->pdata);
+       coresight_release_platform_data(csdev, csdev->dev.parent, csdev->pdata);
        device_unregister(&csdev->dev);
 }
 EXPORT_SYMBOL_GPL(coresight_unregister);
index 8c20293..9c05f78 100644 (file)
@@ -37,7 +37,7 @@ coresight_add_out_conn(struct device *dev,
         * Warn on any existing duplicate output port.
         */
        for (i = 0; i < pdata->nr_outconns; ++i) {
-               conn = &pdata->out_conns[i];
+               conn = pdata->out_conns[i];
                /* Output == -1 means ignore the port for example for helpers */
                if (conn->src_port != -1 &&
                    conn->src_port == new_conn->src_port) {
@@ -54,8 +54,19 @@ coresight_add_out_conn(struct device *dev,
        if (!pdata->out_conns)
                return ERR_PTR(-ENOMEM);
 
-       pdata->out_conns[pdata->nr_outconns - 1] = *new_conn;
-       return &pdata->out_conns[pdata->nr_outconns - 1];
+       conn = devm_kmalloc(dev, sizeof(struct coresight_connection),
+                           GFP_KERNEL);
+       if (!conn)
+               return ERR_PTR(-ENOMEM);
+
+       /*
+        * Copy the new connection into the allocation, save the pointer to the
+        * end of the connection array and also return it in case it needs to be
+        * used right away.
+        */
+       *conn = *new_conn;
+       pdata->out_conns[pdata->nr_outconns - 1] = conn;
+       return conn;
 }
 EXPORT_SYMBOL_GPL(coresight_add_out_conn);
 
@@ -863,7 +874,7 @@ coresight_get_platform_data(struct device *dev)
 error:
        if (!IS_ERR_OR_NULL(pdata))
                /* Cleanup the connection information */
-               coresight_release_platform_data(NULL, pdata);
+               coresight_release_platform_data(NULL, dev, pdata);
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(coresight_get_platform_data);
index 788ff19..65ae6d1 100644 (file)
@@ -207,6 +207,7 @@ static inline void *coresight_get_uci_data(const struct amba_id *id)
 }
 
 void coresight_release_platform_data(struct coresight_device *csdev,
+                                    struct device *dev,
                                     struct coresight_platform_data *pdata);
 struct coresight_device *
 coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode);
index 9ab77ab..e449364 100644 (file)
@@ -782,7 +782,7 @@ tmc_etr_get_catu_device(struct tmc_drvdata *drvdata)
                return NULL;
 
        for (i = 0; i < etr->pdata->nr_outconns; i++) {
-               tmp = etr->pdata->out_conns[i].dest_dev;
+               tmp = etr->pdata->out_conns[i]->dest_dev;
                if (tmp && coresight_is_catu_device(tmp))
                        return tmp;
        }
index 12fdbd0..abf36a3 100644 (file)
@@ -104,14 +104,15 @@ union coresight_dev_subtype {
  *
  * @nr_inconns: Number of elements for the input connections.
  * @nr_outconns: Number of elements for the output connections.
- * @out_conns: Array of nr_outconns connections from this component.
+ * @out_conns: Array of nr_outconns pointers to connections from this
+ *            component.
  */
 struct coresight_platform_data {
        int high_inport;
        int high_outport;
        int nr_inconns;
        int nr_outconns;
-       struct coresight_connection *out_conns;
+       struct coresight_connection **out_conns;
 };
 
 /**