Re: [PATCH v5 10/13] coresight: Make refcount a property of the connection

From: Mike Leach
Date: Wed Apr 12 2023 - 11:58:20 EST


On Tue, 4 Apr 2023 at 16:52, James Clark <james.clark@xxxxxxx> wrote:
>
> This removes the need to do an additional lookup for the total number
> of ports used and also removes the need to allocate an array of
> refcounts which is just another representation of a connection array.
>
> This was only used for link type devices, for regular devices a single
> refcount on the coresight device is used.
>
> There is a both an input and output refcount in case two link type
> devices are connected together so that they don't overwrite each other's
> counts.
>
> Signed-off-by: James Clark <james.clark@xxxxxxx>
> ---
> drivers/hwtracing/coresight/coresight-core.c | 116 ++++++------------
> drivers/hwtracing/coresight/coresight-etb10.c | 10 +-
> .../hwtracing/coresight/coresight-funnel.c | 26 ++--
> .../hwtracing/coresight/coresight-platform.c | 109 +---------------
> .../coresight/coresight-replicator.c | 23 ++--
> .../hwtracing/coresight/coresight-tmc-etf.c | 24 ++--
> .../hwtracing/coresight/coresight-tmc-etr.c | 12 +-
> drivers/hwtracing/coresight/coresight-tpda.c | 23 ++--
> drivers/hwtracing/coresight/coresight-tpiu.c | 4 +-
> drivers/hwtracing/coresight/ultrasoc-smb.c | 8 +-
> include/linux/coresight.h | 14 ++-
> 11 files changed, 126 insertions(+), 243 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index a0a0ea2c626b..939b7fb751b5 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -112,40 +112,24 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
> }
> EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
>
> -static int coresight_find_link_inport(struct coresight_device *csdev,
> - struct coresight_device *parent)
> +static struct coresight_connection *
> +coresight_find_out_connection(struct coresight_device *src_dev,
> + struct coresight_device *dest_dev)
> {
> int i;
> struct coresight_connection *conn;
>
> - for (i = 0; i < parent->pdata->nr_outconns; i++) {
> - conn = parent->pdata->out_conns[i];
> - if (conn->dest_dev == csdev)
> - return conn->dest_port;
> + for (i = 0; i < src_dev->pdata->nr_outconns; i++) {
> + conn = src_dev->pdata->out_conns[i];
> + if (conn->dest_dev == dest_dev)
> + return conn;
> }
>
> - dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
> - dev_name(&parent->dev), dev_name(&csdev->dev));
> + dev_err(&src_dev->dev,
> + "couldn't find output connection, src_dev: %s, dest_dev: %s\n",
> + dev_name(&src_dev->dev), dev_name(&dest_dev->dev));
>
> - return -ENODEV;
> -}
> -
> -static int coresight_find_link_outport(struct coresight_device *csdev,
> - struct coresight_device *child)
> -{
> - int i;
> - struct coresight_connection *conn;
> -
> - for (i = 0; i < csdev->pdata->nr_outconns; i++) {
> - conn = csdev->pdata->out_conns[i];
> - if (conn->dest_dev == child)
> - return conn->src_port;
> - }
> -
> - dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
> - dev_name(&csdev->dev), dev_name(&child->dev));
> -
> - return -ENODEV;
> + return ERR_PTR(-ENODEV);
> }
>
> static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
> @@ -352,24 +336,24 @@ static int coresight_enable_link(struct coresight_device *csdev,
> {
> int ret = 0;
> int link_subtype;
> - int inport, outport;
> + struct coresight_connection *inconn, *outconn;
>
> if (!parent || !child)
> return -EINVAL;
>
> - inport = coresight_find_link_inport(csdev, parent);
> - outport = coresight_find_link_outport(csdev, child);
> + inconn = coresight_find_out_connection(parent, csdev);
> + outconn = coresight_find_out_connection(csdev, child);
> link_subtype = csdev->subtype.link_subtype;
>
> - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && inport < 0)
> - return inport;
> - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
> - return outport;
> + if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR(inconn))
> + return PTR_ERR(inconn);
> + if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn))
> + return PTR_ERR(outconn);
>
> if (link_ops(csdev)->enable) {
> ret = coresight_control_assoc_ectdev(csdev, true);
> if (!ret) {
> - ret = link_ops(csdev)->enable(csdev, inport, outport);
> + ret = link_ops(csdev)->enable(csdev, inconn, outconn);
> if (ret)
> coresight_control_assoc_ectdev(csdev, false);
> }
> @@ -385,33 +369,36 @@ static void coresight_disable_link(struct coresight_device *csdev,
> struct coresight_device *parent,
> struct coresight_device *child)
> {
> - int i, nr_conns;
> + int i;
> int link_subtype;
> - int inport, outport;
> + struct coresight_connection *inconn, *outconn;
>
> if (!parent || !child)
> return;
>
> - inport = coresight_find_link_inport(csdev, parent);
> - outport = coresight_find_link_outport(csdev, child);
> + inconn = coresight_find_out_connection(parent, csdev);
> + outconn = coresight_find_out_connection(csdev, child);
> link_subtype = csdev->subtype.link_subtype;
>
> - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
> - nr_conns = csdev->pdata->high_inport;
> - } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
> - nr_conns = csdev->pdata->high_outport;
> - } else {
> - nr_conns = 1;
> - }
> -
> if (link_ops(csdev)->disable) {
> - link_ops(csdev)->disable(csdev, inport, outport);
> + link_ops(csdev)->disable(csdev, inconn, outconn);
> coresight_control_assoc_ectdev(csdev, false);
> }
>
> - for (i = 0; i < nr_conns; i++)
> - if (atomic_read(&csdev->refcnt[i]) != 0)
> + if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
> + for (i = 0; i < csdev->pdata->nr_inconns; i++)
> + if (atomic_read(&csdev->pdata->in_conns[i]->dest_refcnt) !=
> + 0)
> + return;
> + } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
> + for (i = 0; i < csdev->pdata->nr_outconns; i++)
> + if (atomic_read(&csdev->pdata->out_conns[i]->src_refcnt) !=
> + 0)
> + return;
> + } else {
> + if (atomic_read(&csdev->refcnt) != 0)
> return;
> + }
>
> csdev->enable = false;
> }
> @@ -435,7 +422,7 @@ static int coresight_enable_source(struct coresight_device *csdev,
> csdev->enable = true;
> }
>
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
>
> return 0;
> }
> @@ -450,7 +437,7 @@ static int coresight_enable_source(struct coresight_device *csdev,
> */
> static bool coresight_disable_source(struct coresight_device *csdev)
> {
> - if (atomic_dec_return(csdev->refcnt) == 0) {
> + if (atomic_dec_return(&csdev->refcnt) == 0) {
> if (source_ops(csdev)->disable)
> source_ops(csdev)->disable(csdev, NULL);
> coresight_control_assoc_ectdev(csdev, false);
> @@ -1094,7 +1081,7 @@ int coresight_enable(struct coresight_device *csdev)
> * source is already enabled.
> */
> if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE)
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> goto out;
> }
>
> @@ -1308,7 +1295,6 @@ static void coresight_device_release(struct device *dev)
> struct coresight_device *csdev = to_coresight_device(dev);
>
> fwnode_handle_put(csdev->dev.fwnode);
> - kfree(csdev->refcnt);
> kfree(csdev);
> }
>
> @@ -1537,9 +1523,6 @@ void coresight_release_platform_data(struct coresight_device *csdev,
> struct coresight_device *coresight_register(struct coresight_desc *desc)
> {
> int ret;
> - int link_subtype;
> - int nr_refcnts = 1;
> - atomic_t *refcnts = NULL;
> struct coresight_device *csdev;
> bool registered = false;
>
> @@ -1549,25 +1532,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
> goto err_out;
> }
>
> - if (desc->type == CORESIGHT_DEV_TYPE_LINK ||
> - desc->type == CORESIGHT_DEV_TYPE_LINKSINK) {
> - link_subtype = desc->subtype.link_subtype;
> -
> - if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
> - nr_refcnts = desc->pdata->high_inport;
> - else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
> - nr_refcnts = desc->pdata->high_outport;
> - }
> -
> - refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
> - if (!refcnts) {
> - ret = -ENOMEM;
> - kfree(csdev);
> - goto err_out;
> - }
> -
> - csdev->refcnt = refcnts;
> -
> csdev->pdata = desc->pdata;
>
> csdev->type = desc->type;
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index eb99c445015a..fa80039e0821 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
> drvdata->mode = CS_MODE_SYSFS;
> }
>
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> out:
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> return ret;
> @@ -199,7 +199,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
> * use for this session.
> */
> if (drvdata->pid == pid) {
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> goto out;
> }
>
> @@ -217,7 +217,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
> /* Associate with monitored process. */
> drvdata->pid = pid;
> drvdata->mode = CS_MODE_PERF;
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> }
>
> out:
> @@ -356,7 +356,7 @@ static int etb_disable(struct coresight_device *csdev)
>
> spin_lock_irqsave(&drvdata->spinlock, flags);
>
> - if (atomic_dec_return(csdev->refcnt)) {
> + if (atomic_dec_return(&csdev->refcnt)) {
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> return -EBUSY;
> }
> @@ -447,7 +447,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
> spin_lock_irqsave(&drvdata->spinlock, flags);
>
> /* Don't do anything if another tracer is using this sink */
> - if (atomic_read(csdev->refcnt) != 1)
> + if (atomic_read(&csdev->refcnt) != 1)
> goto out;
>
> __etb_disable_hw(drvdata);
> diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
> index b363dd6bc510..b8e150e45b27 100644
> --- a/drivers/hwtracing/coresight/coresight-funnel.c
> +++ b/drivers/hwtracing/coresight/coresight-funnel.c
> @@ -74,8 +74,9 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
> return rc;
> }
>
> -static int funnel_enable(struct coresight_device *csdev, int inport,
> - int outport)
> +static int funnel_enable(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> int rc = 0;
> struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> @@ -83,18 +84,19 @@ static int funnel_enable(struct coresight_device *csdev, int inport,
> bool first_enable = false;
>
> spin_lock_irqsave(&drvdata->spinlock, flags);
> - if (atomic_read(&csdev->refcnt[inport]) == 0) {
> + if (atomic_read(&in->dest_refcnt) == 0) {
> if (drvdata->base)
> - rc = dynamic_funnel_enable_hw(drvdata, inport);
> + rc = dynamic_funnel_enable_hw(drvdata, in->dest_port);
> if (!rc)
> first_enable = true;
> }
> if (!rc)
> - atomic_inc(&csdev->refcnt[inport]);
> + atomic_inc(&in->dest_refcnt);
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
>
> if (first_enable)
> - dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", inport);
> + dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n",
> + in->dest_port);
> return rc;
> }
>
> @@ -117,23 +119,25 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
> CS_LOCK(drvdata->base);
> }
>
> -static void funnel_disable(struct coresight_device *csdev, int inport,
> - int outport)
> +static void funnel_disable(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> unsigned long flags;
> bool last_disable = false;
>
> spin_lock_irqsave(&drvdata->spinlock, flags);
> - if (atomic_dec_return(&csdev->refcnt[inport]) == 0) {
> + if (atomic_dec_return(&in->dest_refcnt) == 0) {
> if (drvdata->base)
> - dynamic_funnel_disable_hw(drvdata, inport);
> + dynamic_funnel_disable_hw(drvdata, in->dest_port);
> last_disable = true;
> }
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
>
> if (last_disable)
> - dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n", inport);
> + dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n",
> + in->dest_port);
> }
>
> static const struct coresight_ops_link funnel_link_ops = {
> diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> index 257ad48925a1..3e2e135cb8f6 100644
> --- a/drivers/hwtracing/coresight/coresight-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-platform.c
> @@ -146,41 +146,6 @@ static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
> return of_property_read_bool(ep, "slave-mode");
> }
>
> -static void of_coresight_get_ports_legacy(const struct device_node *node,
> - int *nr_inconns, int *nr_outconns)
> -{
> - struct device_node *ep = NULL;
> - struct of_endpoint endpoint;
> - int in = 0, out = 0;
> -
> - /*
> - * Avoid warnings in of_graph_get_next_endpoint()
> - * if the device doesn't have any graph connections
> - */
> - if (!of_graph_is_present(node))
> - return;
> - do {
> - ep = of_graph_get_next_endpoint(node, ep);
> - if (!ep)
> - break;
> -
> - if (of_graph_parse_endpoint(ep, &endpoint))
> - continue;
> -
> - if (of_coresight_legacy_ep_is_input(ep)) {
> - in = (endpoint.port + 1 > in) ?
> - endpoint.port + 1 : in;
> - } else {
> - out = (endpoint.port + 1) > out ?
> - endpoint.port + 1 : out;
> - }
> -
> - } while (ep);
> -
> - *nr_inconns = in;
> - *nr_outconns = out;
> -}
> -
> static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
> {
> struct device_node *parent = of_graph_get_port_parent(ep);
> @@ -196,59 +161,12 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
> return parent;
> }
>
> -static inline struct device_node *
> -of_coresight_get_input_ports_node(const struct device_node *node)
> -{
> - return of_get_child_by_name(node, "in-ports");
> -}
> -
> static inline struct device_node *
> of_coresight_get_output_ports_node(const struct device_node *node)
> {
> return of_get_child_by_name(node, "out-ports");
> }
>
> -static inline int
> -of_coresight_count_ports(struct device_node *port_parent)
> -{
> - int i = 0;
> - struct device_node *ep = NULL;
> - struct of_endpoint endpoint;
> -
> - while ((ep = of_graph_get_next_endpoint(port_parent, ep))) {
> - /* Defer error handling to parsing */
> - if (of_graph_parse_endpoint(ep, &endpoint))
> - continue;
> - if (endpoint.port + 1 > i)
> - i = endpoint.port + 1;
> - }
> -
> - return i;
> -}
> -
> -static void of_coresight_get_ports(const struct device_node *node,
> - int *nr_inconns, int *nr_outconns)
> -{
> - struct device_node *input_ports = NULL, *output_ports = NULL;
> -
> - input_ports = of_coresight_get_input_ports_node(node);
> - output_ports = of_coresight_get_output_ports_node(node);
> -
> - if (input_ports || output_ports) {
> - if (input_ports) {
> - *nr_inconns = of_coresight_count_ports(input_ports);
> - of_node_put(input_ports);
> - }
> - if (output_ports) {
> - *nr_outconns = of_coresight_count_ports(output_ports);
> - of_node_put(output_ports);
> - }
> - } else {
> - /* Fall back to legacy DT bindings parsing */
> - of_coresight_get_ports_legacy(node, nr_inconns, nr_outconns);
> - }
> -}
> -
> static int of_coresight_get_cpu(struct device *dev)
> {
> int cpu;
> @@ -351,13 +269,6 @@ static int of_get_coresight_platform_data(struct device *dev,
> bool legacy_binding = false;
> struct device_node *node = dev->of_node;
>
> - /* Get the number of input and output port for this component */
> - of_coresight_get_ports(node, &pdata->high_inport, &pdata->high_outport);
> -
> - /* If there are no output connections, we are done */
> - if (!pdata->high_outport)
> - return 0;
> -
> parent = of_coresight_get_output_ports_node(node);
> /*
> * If the DT uses obsoleted bindings, the ports are listed
> @@ -365,6 +276,12 @@ static int of_get_coresight_platform_data(struct device *dev,
> * ports.
> */
> if (!parent) {
> + /*
> + * Avoid warnings in of_graph_get_next_endpoint()
> + * if the device doesn't have any graph connections
> + */
> + if (!of_graph_is_present(node))
> + return 0;
> legacy_binding = true;
> parent = node;
> dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n");
> @@ -751,7 +668,6 @@ static int acpi_coresight_parse_graph(struct device *dev,
> struct coresight_connection conn, zero_conn = {};
> struct coresight_connection *new_conn;
>
> - pdata->nr_inconns = pdata->nr_outconns = 0;
> graph = acpi_get_coresight_graph(adev);
> if (!graph)
> return -ENOENT;
> @@ -770,22 +686,9 @@ static int acpi_coresight_parse_graph(struct device *dev,
> return dir;
>
> if (dir == ACPI_CORESIGHT_LINK_MASTER) {
> - if (conn.src_port >= pdata->high_outport)
> - pdata->high_outport = conn.src_port + 1;
> new_conn = coresight_add_out_conn(dev, pdata, &conn);
> if (IS_ERR(new_conn))
> return PTR_ERR(new_conn);
> - } else {
> - WARN_ON(pdata->high_inport == conn.dest_port + 1);
> - /*
> - * We do not track input port connections for a device.
> - * However we need the highest port number described,
> - * which can be recorded now and reuse this connection
> - * record for an output connection. Hence, do not move
> - * the ptr for input connections
> - */
> - if (conn.dest_port >= pdata->high_inport)
> - pdata->high_inport = conn.dest_port + 1;
> }
> }
>
> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
> index 4dd50546d7e4..b6be73034996 100644
> --- a/drivers/hwtracing/coresight/coresight-replicator.c
> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
> @@ -114,8 +114,9 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
> return rc;
> }
>
> -static int replicator_enable(struct coresight_device *csdev, int inport,
> - int outport)
> +static int replicator_enable(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> int rc = 0;
> struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> @@ -123,15 +124,15 @@ static int replicator_enable(struct coresight_device *csdev, int inport,
> bool first_enable = false;
>
> spin_lock_irqsave(&drvdata->spinlock, flags);
> - if (atomic_read(&csdev->refcnt[outport]) == 0) {
> + if (atomic_read(&out->src_refcnt) == 0) {
> if (drvdata->base)
> - rc = dynamic_replicator_enable(drvdata, inport,
> - outport);
> + rc = dynamic_replicator_enable(drvdata, in->dest_port,
> + out->src_port);
> if (!rc)
> first_enable = true;
> }
> if (!rc)
> - atomic_inc(&csdev->refcnt[outport]);
> + atomic_inc(&out->src_refcnt);
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
>
> if (first_enable)
> @@ -168,17 +169,19 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
> CS_LOCK(drvdata->base);
> }
>
> -static void replicator_disable(struct coresight_device *csdev, int inport,
> - int outport)
> +static void replicator_disable(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> unsigned long flags;
> bool last_disable = false;
>
> spin_lock_irqsave(&drvdata->spinlock, flags);
> - if (atomic_dec_return(&csdev->refcnt[outport]) == 0) {
> + if (atomic_dec_return(&out->src_refcnt) == 0) {
> if (drvdata->base)
> - dynamic_replicator_disable(drvdata, inport, outport);
> + dynamic_replicator_disable(drvdata, in->dest_port,
> + out->src_port);
> last_disable = true;
> }
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> index 14d3c1472455..79d8c64eac49 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> @@ -206,7 +206,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
> * touched.
> */
> if (drvdata->mode == CS_MODE_SYSFS) {
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> goto out;
> }
>
> @@ -229,7 +229,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
> ret = tmc_etb_enable_hw(drvdata);
> if (!ret) {
> drvdata->mode = CS_MODE_SYSFS;
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> } else {
> /* Free up the buffer if we failed to enable */
> used = false;
> @@ -284,7 +284,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
> * use for this session.
> */
> if (drvdata->pid == pid) {
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> break;
> }
>
> @@ -293,7 +293,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
> /* Associate with monitored process. */
> drvdata->pid = pid;
> drvdata->mode = CS_MODE_PERF;
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> }
> } while (0);
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> @@ -338,7 +338,7 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
> return -EBUSY;
> }
>
> - if (atomic_dec_return(csdev->refcnt)) {
> + if (atomic_dec_return(&csdev->refcnt)) {
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> return -EBUSY;
> }
> @@ -357,7 +357,8 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
> }
>
> static int tmc_enable_etf_link(struct coresight_device *csdev,
> - int inport, int outport)
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> int ret = 0;
> unsigned long flags;
> @@ -370,7 +371,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
> return -EBUSY;
> }
>
> - if (atomic_read(&csdev->refcnt[0]) == 0) {
> + if (atomic_read(&csdev->refcnt) == 0) {
> ret = tmc_etf_enable_hw(drvdata);
> if (!ret) {
> drvdata->mode = CS_MODE_SYSFS;
> @@ -378,7 +379,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
> }
> }
> if (!ret)
> - atomic_inc(&csdev->refcnt[0]);
> + atomic_inc(&csdev->refcnt);
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
>
> if (first_enable)
> @@ -387,7 +388,8 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
> }
>
> static void tmc_disable_etf_link(struct coresight_device *csdev,
> - int inport, int outport)
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> unsigned long flags;
> struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> @@ -399,7 +401,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
> return;
> }
>
> - if (atomic_dec_return(&csdev->refcnt[0]) == 0) {
> + if (atomic_dec_return(&csdev->refcnt) == 0) {
> tmc_etf_disable_hw(drvdata);
> drvdata->mode = CS_MODE_DISABLED;
> last_disable = true;
> @@ -487,7 +489,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
> spin_lock_irqsave(&drvdata->spinlock, flags);
>
> /* Don't do anything if another tracer is using this sink */
> - if (atomic_read(csdev->refcnt) != 1)
> + if (atomic_read(&csdev->refcnt) != 1)
> goto out;
>
> CS_UNLOCK(drvdata->base);
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 1bbe5410a23d..689ba6abc70b 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -1209,7 +1209,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
> * touched, even if the buffer size has changed.
> */
> if (drvdata->mode == CS_MODE_SYSFS) {
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> goto out;
> }
>
> @@ -1226,7 +1226,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
> ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
> if (!ret) {
> drvdata->mode = CS_MODE_SYSFS;
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> }
> out:
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> @@ -1535,7 +1535,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
> spin_lock_irqsave(&drvdata->spinlock, flags);
>
> /* Don't do anything if another tracer is using this sink */
> - if (atomic_read(csdev->refcnt) != 1) {
> + if (atomic_read(&csdev->refcnt) != 1) {
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> goto out;
> }
> @@ -1647,7 +1647,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
> * use for this session.
> */
> if (drvdata->pid == pid) {
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> goto unlock_out;
> }
>
> @@ -1657,7 +1657,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
> drvdata->pid = pid;
> drvdata->mode = CS_MODE_PERF;
> drvdata->perf_buf = etr_perf->etr_buf;
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> }
>
> unlock_out:
> @@ -1690,7 +1690,7 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
> return -EBUSY;
> }
>
> - if (atomic_dec_return(csdev->refcnt)) {
> + if (atomic_dec_return(&csdev->refcnt)) {
> spin_unlock_irqrestore(&drvdata->spinlock, flags);
> return -EBUSY;
> }
> diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
> index f712e112ecff..8d2b9d29237d 100644
> --- a/drivers/hwtracing/coresight/coresight-tpda.c
> +++ b/drivers/hwtracing/coresight/coresight-tpda.c
> @@ -54,18 +54,20 @@ static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
> CS_LOCK(drvdata->base);
> }
>
> -static int tpda_enable(struct coresight_device *csdev, int inport, int outport)
> +static int tpda_enable(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>
> spin_lock(&drvdata->spinlock);
> - if (atomic_read(&csdev->refcnt[inport]) == 0)
> - __tpda_enable(drvdata, inport);
> + if (atomic_read(&in->dest_refcnt) == 0)
> + __tpda_enable(drvdata, in->dest_port);
>
> - atomic_inc(&csdev->refcnt[inport]);
> + atomic_inc(&in->dest_refcnt);
> spin_unlock(&drvdata->spinlock);
>
> - dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", inport);
> + dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
> return 0;
> }
>
> @@ -82,18 +84,19 @@ static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
> CS_LOCK(drvdata->base);
> }
>
> -static void tpda_disable(struct coresight_device *csdev, int inport,
> - int outport)
> +static void tpda_disable(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out)
> {
> struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>
> spin_lock(&drvdata->spinlock);
> - if (atomic_dec_return(&csdev->refcnt[inport]) == 0)
> - __tpda_disable(drvdata, inport);
> + if (atomic_dec_return(&in->dest_refcnt) == 0)
> + __tpda_disable(drvdata, in->dest_port);
>
> spin_unlock(&drvdata->spinlock);
>
> - dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", inport);
> + dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
> }
>
> static const struct coresight_ops_link tpda_link_ops = {
> diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
> index b0179f761c98..59eac93fd6bb 100644
> --- a/drivers/hwtracing/coresight/coresight-tpiu.c
> +++ b/drivers/hwtracing/coresight/coresight-tpiu.c
> @@ -73,7 +73,7 @@ static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode,
> void *__unused)
> {
> tpiu_enable_hw(&csdev->access);
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
> dev_dbg(&csdev->dev, "TPIU enabled\n");
> return 0;
> }
> @@ -96,7 +96,7 @@ static void tpiu_disable_hw(struct csdev_access *csa)
>
> static int tpiu_disable(struct coresight_device *csdev)
> {
> - if (atomic_dec_return(csdev->refcnt))
> + if (atomic_dec_return(&csdev->refcnt))
> return -EBUSY;
>
> tpiu_disable_hw(&csdev->access);
> diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
> index a2ced0b3c3cd..e9a32a97fbee 100644
> --- a/drivers/hwtracing/coresight/ultrasoc-smb.c
> +++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
> @@ -106,7 +106,7 @@ static int smb_open(struct inode *inode, struct file *file)
> goto out;
> }
>
> - if (atomic_read(drvdata->csdev->refcnt)) {
> + if (atomic_read(&drvdata->csdev->refcnt)) {
> ret = -EBUSY;
> goto out;
> }
> @@ -290,7 +290,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
> if (ret)
> goto out;
>
> - atomic_inc(csdev->refcnt);
> + atomic_inc(&csdev->refcnt);
>
> dev_dbg(&csdev->dev, "Ultrasoc SMB enabled\n");
> out:
> @@ -311,7 +311,7 @@ static int smb_disable(struct coresight_device *csdev)
> goto out;
> }
>
> - if (atomic_dec_return(csdev->refcnt)) {
> + if (atomic_dec_return(&csdev->refcnt)) {
> ret = -EBUSY;
> goto out;
> }
> @@ -411,7 +411,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev,
> mutex_lock(&drvdata->mutex);
>
> /* Don't do anything if another tracer is using this sink. */
> - if (atomic_read(csdev->refcnt) != 1)
> + if (atomic_read(&csdev->refcnt) != 1)
> goto out;
>
> smb_disable_hw(drvdata);
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index e9c52c5ca7f3..b97edd24f3ec 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -111,8 +111,6 @@ union coresight_dev_subtype {
> * unloaded the connection leaves an empty slot.
> */
> struct coresight_platform_data {
> - int high_inport;
> - int high_outport;
> int nr_inconns;
> int nr_outconns;
> struct coresight_connection **out_conns;
> @@ -205,6 +203,8 @@ struct coresight_connection {
> struct coresight_device *dest_dev;
> struct coresight_sysfs_link *link;
> struct coresight_device *src_dev;
> + atomic_t src_refcnt;
> + atomic_t dest_refcnt;
> };
>
> /**
> @@ -256,7 +256,7 @@ struct coresight_device {
> const struct coresight_ops *ops;
> struct csdev_access access;
> struct device dev;
> - atomic_t *refcnt;
> + atomic_t refcnt;
> bool orphan;
> bool enable; /* true only if configured as part of a path */
> /* sink specific fields */
> @@ -341,8 +341,12 @@ struct coresight_ops_sink {
> * @disable: disables flow between iport and oport.
> */
> struct coresight_ops_link {
> - int (*enable)(struct coresight_device *csdev, int iport, int oport);
> - void (*disable)(struct coresight_device *csdev, int iport, int oport);
> + int (*enable)(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out);
> + void (*disable)(struct coresight_device *csdev,
> + struct coresight_connection *in,
> + struct coresight_connection *out);
> };
>
> /**
> --
> 2.34.1
>

Reviewed-by: Mike Leach <mike.leach@xxxxxxxxxx>

--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK