[PATCH 1/9 v2] coresight: add CoreSight core layer framework

Daniel Thompson daniel.thompson at linaro.org
Wed Jul 2 02:38:01 PDT 2014


On 27/06/14 19:04, mathieu.poirier at linaro.org wrote:
> diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
> new file mode 100644
> index 0000000..fdd4d08
> --- /dev/null
> +++ b/drivers/coresight/Kconfig
> @@ -0,0 +1,10 @@
> +menuconfig CORESIGHT
> +	bool "CoreSight Tracing Support"
> +	select ARM_AMBA
> +	help
> +	  This framework provides an interface for the CoreSight debug and
> +	  trace drivers to register themselves with. It's intended to build
> +	  up a topological view of the CoreSight components and configure
> +	  the right series of components on user input via sysfs. It also

I don't understand this sentence. It makes is sound like user input is
needed somehow.

> diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
> new file mode 100644
> index 0000000..da1ebbb
> --- /dev/null
> +++ b/drivers/coresight/coresight-priv.h
> @@ -0,0 +1,69 @@
> +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CORESIGHT_PRIV_H
> +#define _CORESIGHT_PRIV_H
> +
> +#include <linux/bitops.h>
> +#include <linux/io.h>
> +#include <linux/coresight.h>
> +
> +/*
> + * Coresight management registers (0xF00-0xFCC)
> + * 0xFA0 - 0xFA4: Management	registers in PFTv1.0
> + *		  Trace		registers in PFTv1.1
> + */
> +#define CORESIGHT_ITCTRL	(0xF00)
> +#define CORESIGHT_CLAIMSET	(0xFA0)
> +#define CORESIGHT_CLAIMCLR	(0xFA4)
> +#define CORESIGHT_LAR		(0xFB0)
> +#define CORESIGHT_LSR		(0xFB4)
> +#define CORESIGHT_AUTHSTATUS	(0xFB8)
> +#define CORESIGHT_DEVID		(0xFC8)
> +#define CORESIGHT_DEVTYPE	(0xFCC)
> +
> +#define TIMEOUT_US		(100)
> +
> +#define BM(lsb, msb)		((BIT(msb) - BIT(lsb)) + BIT(msb))

Isn't this what GENMASK() already does?

> +#define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
> +#define BVAL(val, n)		((val & BIT(n)) >> n)

BVAL() is obfuscation and should be removed.

As an example (taken from one of the patches that consumes this macro):

+	for (i = TIMEOUT_US;
+	     BVAL(cs_readl(drvdata->base, ETB_FFCR), ETB_FFCR_BIT) != 0
+	     && i > 0; i--)
+		udelay(1);

Is not really as readable as:

+	for (i = TIMEOUT_US;
+	     cs_readl(drvdata->base, ETB_FFCR) & ETB_FFCR_BIT && i > 0;
+	     i--)
+		udelay(1);

Within the whole patchset it is only every usedIt is only ever used call
site looks more or less like this:


> +#define cs_writel(addr, val, off)	__raw_writel((val), addr + off)
> +#define cs_readl(addr, off)		__raw_readl(addr + off)

Out of interest, would readl/writel_relaxed() more appropriate?


> +
> +static inline void CS_LOCK(void __iomem *addr)
> +{
> +	do {
> +		/* wait for things to settle */
> +		mb();
> +		cs_writel(addr, 0x0, CORESIGHT_LAR);
> +	} while (0);
> +}
> +
> +static inline void CS_UNLOCK(void __iomem *addr)
> +{
> +	do {
> +		cs_writel(addr, CORESIGHT_UNLOCK, CORESIGHT_LAR);
> +		/* make sure eveyone has seen this */
> +		mb();
> +	} while (0);
> +}
> +
> +#ifdef CONFIG_CORESIGHT_SOURCE_ETM
> +extern unsigned int etm_readl_cp14(u32 off);
> +extern void etm_writel_cp14(u32 val, u32 off);
> +#else
> +static inline unsigned int etm_readl_cp14(u32 off) { return 0; }
> +static inline void etm_writel_cp14(u32 val, u32 off) {}
> +#endif
> +
> +#endif
> diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
> new file mode 100644
> index 0000000..6218d86
> --- /dev/null
> +++ b/drivers/coresight/coresight.c
> @@ -0,0 +1,680 @@
> +/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/types.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include <linux/export.h>
> +#include <linux/slab.h>
> +#include <linux/semaphore.h>
> +#include <linux/clk.h>
> +#include <linux/coresight.h>
> +#include <linux/of_platform.h>
> +#include <linux/debugfs.h>
> +
> +#include "coresight-priv.h"
> +
> +#define NO_SINK		(-1)
> +
> +struct dentry *cs_debugfs_parent = NULL;
> +
> +static int curr_sink = NO_SINK;
> +static LIST_HEAD(coresight_orph_conns);
> +static LIST_HEAD(coresight_devs);
> +static DEFINE_SEMAPHORE(coresight_mutex);

Why is coresight_mutex a semaphore?


> +static int coresight_find_link_inport(struct coresight_device *csdev)
> +{
> +	int i;
> +	struct coresight_device *parent;
> +	struct coresight_connection *conn;
> +
> +	parent = container_of(csdev->path_link.next, struct coresight_device,
> +			     path_link);
> +	for (i = 0; i < parent->nr_conns; i++) {
> +		conn = &parent->conns[i];
> +		if (conn->child_dev == csdev)
> +			return conn->child_port;
> +	}
> +
> +	pr_err("coresight: couldn't find inport, parent: %d, child: %d\n",
> +	       parent->id, csdev->id);
> +	return 0;
> +}
> +
> +static int coresight_find_link_outport(struct coresight_device *csdev)
> +{
> +	int i;
> +	struct coresight_device *child;
> +	struct coresight_connection *conn;
> +
> +	child = container_of(csdev->path_link.prev, struct coresight_device,
> +			      path_link);
> +	for (i = 0; i < csdev->nr_conns; i++) {
> +		conn = &csdev->conns[i];
> +		if (conn->child_dev == child)
> +			return conn->outport;
> +	}
> +
> +	pr_err("coresight: couldn't find outport, parent: %d, child: %d\n",
> +	       csdev->id, child->id);
> +	return 0;
> +}
> +
> +static int coresight_enable_sink(struct coresight_device *csdev)
> +{
> +	int ret;
> +
> +	if (csdev->refcnt.sink_refcnt == 0) {
> +		if (csdev->ops->sink_ops->enable) {
> +			ret = csdev->ops->sink_ops->enable(csdev);
> +			if (ret)
> +				goto err;
> +			csdev->enable = true;
> +		}
> +	}
> +	csdev->refcnt.sink_refcnt++;
> +
> +	return 0;
> +err:
> +	return ret;
> +}
> +
> +static void coresight_disable_sink(struct coresight_device *csdev)
> +{
> +	if (csdev->refcnt.sink_refcnt == 1) {
> +		if (csdev->ops->sink_ops->disable) {
> +			csdev->ops->sink_ops->disable(csdev);
> +			csdev->enable = false;
> +		}
> +	}
> +	csdev->refcnt.sink_refcnt--;
> +}
> +
> +static int coresight_enable_link(struct coresight_device *csdev)
> +{
> +	int ret;
> +	int link_subtype;
> +	int refport, inport, outport;
> +
> +	inport = coresight_find_link_inport(csdev);
> +	outport = coresight_find_link_outport(csdev);
> +
> +	link_subtype = csdev->subtype.link_subtype;
> +	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
> +		refport = inport;
> +	else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
> +		refport = outport;
> +	else
> +		refport = 0;
> +
> +	if (csdev->refcnt.link_refcnts[refport] == 0) {
> +		if (csdev->ops->link_ops->enable) {
> +			ret = csdev->ops->link_ops->enable(csdev, inport,
> +							   outport);
> +			if (ret)
> +				goto err;
> +			csdev->enable = true;
> +		}
> +	}
> +	csdev->refcnt.link_refcnts[refport]++;
> +
> +	return 0;
> +err:
> +	return ret;
> +}
> +
> +static void coresight_disable_link(struct coresight_device *csdev)
> +{
> +	int link_subtype;
> +	int refport, inport, outport;
> +
> +	inport = coresight_find_link_inport(csdev);
> +	outport = coresight_find_link_outport(csdev);
> +
> +	link_subtype = csdev->subtype.link_subtype;
> +	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
> +		refport = inport;
> +	else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
> +		refport = outport;
> +	else
> +		refport = 0;

I already read these 7 lines once...

> +
> +	if (csdev->refcnt.link_refcnts[refport] == 1) {
> +		if (csdev->ops->link_ops->disable) {
> +			csdev->ops->link_ops->disable(csdev, inport, outport);
> +			csdev->enable = false;
> +		}
> +	}
> +	csdev->refcnt.link_refcnts[refport]--;
> +}
> +
> +static int coresight_enable_source(struct coresight_device *csdev)
> +{
> +	int ret;
> +
> +	if (csdev->refcnt.source_refcnt == 0) {
> +		if (csdev->ops->source_ops->enable) {
> +			ret = csdev->ops->source_ops->enable(csdev);
> +			if (ret)
> +				goto err;
> +			csdev->enable = true;
> +		}
> +	}
> +	csdev->refcnt.source_refcnt++;
> +
> +	return 0;
> +err:
> +	return ret;
> +}
> +
> +static void coresight_disable_source(struct coresight_device *csdev)
> +{
> +	if (csdev->refcnt.source_refcnt == 1) {
> +		if (csdev->ops->source_ops->disable) {
> +			csdev->ops->source_ops->disable(csdev);
> +			csdev->enable = false;
> +		}
> +	}
> +	csdev->refcnt.source_refcnt--;
> +}
> +
> +static struct list_head *coresight_build_path(struct coresight_device *csdev,
> +					      struct list_head *path)
> +{
> +	int i;
> +	struct list_head *p;
> +	struct coresight_connection *conn;
> +
> +	if (csdev->id == curr_sink) {
> +		list_add_tail(&csdev->path_link, path);
> +		return path;
> +	}
> +
> +	for (i = 0; i < csdev->nr_conns; i++) {
> +		conn = &csdev->conns[i];
> +		p = coresight_build_path(conn->child_dev, path);
> +		if (p) {
> +			list_add_tail(&csdev->path_link, p);
> +			return p;
> +		}
> +	}
> +	return NULL;
> +}
> +
> +static void coresight_release_path(struct list_head *path)
> +{
> +	struct coresight_device *cd, *temp;
> +
> +	list_for_each_entry_safe(cd, temp, path, path_link)
> +		list_del(&cd->path_link);
> +}
> +
> +static int coresight_enable_path(struct list_head *path, bool incl_source)
> +{
> +	int ret = 0;
> +	struct coresight_device *cd;
> +
> +	list_for_each_entry(cd, path, path_link) {
> +		if (cd == list_first_entry(path, struct coresight_device,
> +					   path_link)) {
> +			ret = coresight_enable_sink(cd);
> +		} else if (list_is_last(&cd->path_link, path)) {
> +			if (incl_source)
> +				ret = coresight_enable_source(cd);
> +		} else {
> +			ret = coresight_enable_link(cd);
> +		}
> +		if (ret)
> +			goto err;
> +	}
> +	return 0;
> +err:
> +	list_for_each_entry_continue_reverse(cd, path, path_link) {
> +		if (cd == list_first_entry(path, struct coresight_device,
> +					   path_link)) {
> +			coresight_disable_sink(cd);
> +		} else if (list_is_last(&cd->path_link, path)) {
> +			if (incl_source)
> +				coresight_disable_source(cd);
> +		} else {
> +			coresight_disable_link(cd);
> +		}
> +	}
> +	return ret;
> +}
> +
> +static void coresight_disable_path(struct list_head *path, bool incl_source)
> +{
> +	struct coresight_device *cd;
> +
> +	list_for_each_entry(cd, path, path_link) {
> +		if (cd == list_first_entry(path, struct coresight_device,
> +					   path_link)) {
> +			coresight_disable_sink(cd);
> +		} else if (list_is_last(&cd->path_link, path)) {
> +			if (incl_source)
> +				coresight_disable_source(cd);
> +		} else {
> +			coresight_disable_link(cd);
> +		}
> +	}
> +}
> +
> +static int coresight_switch_sink(struct coresight_device *csdev)
> +{
> +	int ret = 0;
> +	LIST_HEAD(path);
> +	struct coresight_device *cd;
> +
> +	if (IS_ERR_OR_NULL(csdev))
> +		return -EINVAL;

If we really believe the caller is likely to do something this stupid we
should probably WARN_ON() for their own good.


> +
> +	down(&coresight_mutex);
> +	if (csdev->id == curr_sink)
> +		goto out;
> +
> +	list_for_each_entry(cd, &coresight_devs, dev_link) {
> +		if (cd->type == CORESIGHT_DEV_TYPE_SOURCE && cd->enable) {
> +			coresight_build_path(cd, &path);
> +			coresight_disable_path(&path, false);
> +			coresight_release_path(&path);
> +		}
> +	}
> +	curr_sink = csdev->id;
> +	list_for_each_entry(cd, &coresight_devs, dev_link) {
> +		if (cd->type == CORESIGHT_DEV_TYPE_SOURCE && cd->enable) {
> +			coresight_build_path(cd, &path);
> +			ret = coresight_enable_path(&path, false);
> +			coresight_release_path(&path);
> +			if (ret)
> +				goto err;
> +		}
> +	}
> +out:
> +	up(&coresight_mutex);
> +	return 0;
> +err:
> +	list_for_each_entry(cd, &coresight_devs, dev_link) {
> +		if (cd->type == CORESIGHT_DEV_TYPE_SOURCE && cd->enable)
> +			coresight_disable_source(cd);
> +	}
> +	pr_err("coresight: sink switch failed, sources disabled; try again\n");

coresight_mutex is still locked at this point (so trying again won't
help ;-).


> +	return ret;
> +}
> +
> +int coresight_enable(struct coresight_device *csdev)
> +{
> +	int ret = 0;
> +	LIST_HEAD(path);
> +
> +	if (IS_ERR_OR_NULL(csdev))
> +		return -EINVAL;

WARN_ON() or remove.


> +
> +	down(&coresight_mutex);
> +	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
> +		ret = -EINVAL;
> +		pr_err("coresight: wrong device type in %s\n", __func__);
> +		goto out;
> +	}
> +	if (csdev->enable)
> +		goto out;
> +
> +	coresight_build_path(csdev, &path);
> +	ret = coresight_enable_path(&path, true);
> +	coresight_release_path(&path);
> +	if (ret)
> +		pr_err("coresight: enable failed\n");
> +out:
> +	up(&coresight_mutex);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(coresight_enable);
> +
> +void coresight_disable(struct coresight_device *csdev)
> +{
> +	LIST_HEAD(path);
> +
> +	if (IS_ERR_OR_NULL(csdev))
> +		return;
> +
> +	down(&coresight_mutex);
> +	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
> +		pr_err("coresight: wrong device type in %s\n", __func__);
> +		goto out;
> +	}
> +	if (!csdev->enable)
> +		goto out;
> +
> +	coresight_build_path(csdev, &path);
> +	coresight_disable_path(&path, true);
> +	coresight_release_path(&path);
> +out:
> +	up(&coresight_mutex);
> +}
> +EXPORT_SYMBOL_GPL(coresight_disable);
> +
> +void coresight_abort(void)
> +{
> +	struct coresight_device *cd;
> +
> +	if (down_trylock(&coresight_mutex)) {
> +		pr_err("coresight: abort could not be processed\n");
> +		return;
> +	}
> +	if (curr_sink == NO_SINK)
> +		goto out;
> +
> +	list_for_each_entry(cd, &coresight_devs, dev_link) {
> +		if (cd->id == curr_sink) {
> +			if (cd->enable && cd->ops->sink_ops->abort) {
> +				cd->ops->sink_ops->abort(cd);
> +				cd->enable = false;
> +			}
> +		}
> +	}
> +out:
> +	up(&coresight_mutex);
> +}
> +EXPORT_SYMBOL_GPL(coresight_abort);
> +
> +static ssize_t debugfs_curr_sink_get(void *data, u64 *val)
> +{
> +	struct coresight_device *csdev = data;
> +
> +	*val = (csdev->id == curr_sink) ? 1 : 0;
> +	return 0;
> +}
> +
> +static ssize_t debugfs_curr_sink_set(void *data, u64 val)
> +{
> +	struct coresight_device *csdev = data;
> +
> +	if (val)
> +		return coresight_switch_sink(csdev);
> +	else
> +		return -EINVAL;
> +}
> +CORESIGHT_DEBUGFS_ENTRY(debugfs_curr_sink, "curr_sink",
> +			S_IRUGO | S_IWUSR, debugfs_curr_sink_get,
> +			debugfs_curr_sink_set, "%llu\n");
> +
> +static ssize_t debugfs_enable_get(void *data, u64 *val)
> +{
> +	struct coresight_device *csdev = data;
> +
> +	*val = csdev->enable;
> +	return 0;
> +}
> +
> +static ssize_t debugfs_enable_set(void *data, u64 val)
> +{
> +	struct coresight_device *csdev = data;
> +
> +	if (val)
> +		return coresight_enable(csdev);
> +	else
> +		coresight_disable(csdev);
> +
> +	return 0;
> +}
> +CORESIGHT_DEBUGFS_ENTRY(debugfs_enable, "enable",
> +			S_IRUGO | S_IWUSR, debugfs_enable_get,
> +			debugfs_enable_set, "%llu\n");
> +
> +
> +static const struct coresight_ops_entry *coresight_grps_sink[] = {
> +	&debugfs_curr_sink_entry,
> +	NULL,
> +};
> +
> +static const struct coresight_ops_entry *coresight_grps_source[] = {
> +	&debugfs_enable_entry,
> +	NULL,
> +};
> +
> +struct coresight_group_entries {
> +	const char *name;
> +	const struct coresight_ops_entry **entries;
> +};
> +
> +struct coresight_group_entries coresight_debugfs_entries[] = {
> +	{
> +		.name = "none",
> +	},
> +	{
> +		.name = "sink",
> +		.entries = coresight_grps_sink,
> +	},
> +	{
> +		.name = "link",
> +	},
> +	{
> +		.name = "linksink",
> +	},
> +	{
> +		.name = "source",
> +		.entries = coresight_grps_source,
> +	},
> +};
> +
> +static void coresight_device_release(struct device *dev)
> +{
> +	struct coresight_device *csdev = to_coresight_device(dev);
> +	kfree(csdev);
> +}
> +
> +static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
> +{
> +	struct coresight_connection *conn, *temp;
> +
> +	list_for_each_entry_safe(conn, temp, &coresight_orph_conns, link) {
> +		if (conn->child_id == csdev->id) {
> +			conn->child_dev = csdev;
> +			list_del(&conn->link);
> +		}
> +	}
> +}
> +
> +static void coresight_fixup_device_conns(struct coresight_device *csdev)
> +{
> +	int i;
> +	struct coresight_device *cd;
> +	bool found;
> +
> +	for (i = 0; i < csdev->nr_conns; i++) {
> +		found = false;
> +		list_for_each_entry(cd, &coresight_devs, dev_link) {
> +			if (csdev->conns[i].child_id == cd->id) {
> +				csdev->conns[i].child_dev = cd;
> +				found = true;
> +				break;
> +			}
> +		}
> +		if (!found)
> +			list_add_tail(&csdev->conns[i].link,
> +				      &coresight_orph_conns);
> +	}
> +}
> +
> +static int debugfs_coresight_init(void)
> +{
> +	if (!cs_debugfs_parent) {
> +		cs_debugfs_parent = debugfs_create_dir("coresight", 0);
> +		if (IS_ERR(cs_debugfs_parent))
> +			return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct dentry *coresight_debugfs_desc_init(
> +				struct coresight_device *csdev,
> +				const struct coresight_ops_entry **debugfs_ops)
> +{
> +	int i = 0;
> +	struct dentry *parent;
> +	struct device *dev = &csdev->dev;
> +	const struct coresight_ops_entry *ops_entry, **ops_entries;
> +
> +	parent = debugfs_create_dir(dev_name(dev), cs_debugfs_parent);
> +	if (IS_ERR(parent))
> +		return NULL;
> +
> +	/* device-specific ops */
> +	while (debugfs_ops && debugfs_ops[i]) {
> +		ops_entry = debugfs_ops[i];
> +		if (!debugfs_create_file(ops_entry->name, ops_entry->mode,
> +					 parent, dev_get_drvdata(dev->parent),
> +					 ops_entry->ops)) {
> +			debugfs_remove_recursive(parent);
> +			return NULL;
> +		}
> +		i++;
> +	}
> +
> +	/* group-specific ops */
> +	i = 0;
> +	ops_entries = coresight_debugfs_entries[csdev->type].entries;
> +
> +	while (ops_entries && ops_entries[i]) {
> +		if (!debugfs_create_file(ops_entries[i]->name,
> +					 ops_entries[i]->mode,
> +					 parent, csdev, ops_entries[i]->ops)) {
> +			debugfs_remove_recursive(parent);
> +			return NULL;
> +		}
> +		i++;
> +	}
> +
> +	return parent;
> +}
> +
> +struct coresight_device *coresight_register(struct coresight_desc *desc)
> +{
> +	int i;
> +	int ret;
> +	int link_subtype;
> +	int nr_refcnts;
> +	int *refcnts = NULL;
> +	struct coresight_device *csdev;
> +	struct coresight_connection *conns;
> +
> +	if (IS_ERR_OR_NULL(desc))
> +		return ERR_PTR(-EINVAL);
> +
> +	csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
> +	if (!csdev) {
> +		ret = -ENOMEM;
> +		goto err_kzalloc_csdev;
> +	}
> +
> +	csdev->id = desc->pdata->id;
> +
> +	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->nr_inports;
> +		else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
> +			nr_refcnts = desc->pdata->nr_outports;
> +		else
> +			nr_refcnts = 1;
> +
> +		refcnts = kzalloc(sizeof(*refcnts) * nr_refcnts, GFP_KERNEL);
> +		if (!refcnts) {
> +			ret = -ENOMEM;
> +			goto err_kzalloc_refcnts;
> +		}
> +		csdev->refcnt.link_refcnts = refcnts;
> +	}
> +
> +	csdev->nr_conns = desc->pdata->nr_outports;
> +	conns = kzalloc(sizeof(*conns) * csdev->nr_conns, GFP_KERNEL);
> +	if (!conns) {
> +		ret = -ENOMEM;
> +		goto err_kzalloc_conns;
> +	}
> +
> +	for (i = 0; i < csdev->nr_conns; i++) {
> +		conns[i].outport = desc->pdata->outports[i];
> +		conns[i].child_id = desc->pdata->child_ids[i];
> +		conns[i].child_port = desc->pdata->child_ports[i];
> +	}
> +	csdev->conns = conns;
> +
> +	csdev->type = desc->type;
> +	csdev->subtype = desc->subtype;
> +	csdev->ops = desc->ops;
> +	csdev->owner = desc->owner;
> +
> +	csdev->dev.parent = desc->dev;
> +	csdev->dev.release = coresight_device_release;
> +	dev_set_name(&csdev->dev, "%s", desc->pdata->name);
> +
> +	down(&coresight_mutex);
> +	if (desc->pdata->default_sink) {
> +		if (curr_sink == NO_SINK) {
> +			curr_sink = csdev->id;
> +		} else {
> +			ret = -EINVAL;
> +			goto err_default_sink;
> +		}
> +	}
> +
> +	coresight_fixup_device_conns(csdev);
> +
> +	debugfs_coresight_init();

Return value ignored here.


> +	csdev->de = coresight_debugfs_desc_init(csdev, desc->debugfs_ops);
> +
> +	coresight_fixup_orphan_conns(csdev);
> +
> +	list_add_tail(&csdev->dev_link, &coresight_devs);
> +	up(&coresight_mutex);
> +
> +	return csdev;
> ...


> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> new file mode 100644
> index 0000000..a19420e
> --- /dev/null
> +++ b/include/linux/coresight.h
> @@ -0,0 +1,190 @@
> +/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _LINUX_CORESIGHT_H
> +#define _LINUX_CORESIGHT_H
> +
> +#include <linux/device.h>
> +
> +/* Peripheral id registers (0xFD0-0xFEC) */
> +#define CORESIGHT_PERIPHIDR4	(0xFD0)
> +#define CORESIGHT_PERIPHIDR5	(0xFD4)
> +#define CORESIGHT_PERIPHIDR6	(0xFD8)
> +#define CORESIGHT_PERIPHIDR7	(0xFDC)
> +#define CORESIGHT_PERIPHIDR0	(0xFE0)
> +#define CORESIGHT_PERIPHIDR1	(0xFE4)
> +#define CORESIGHT_PERIPHIDR2	(0xFE8)
> +#define CORESIGHT_PERIPHIDR3	(0xFEC)
> +/* Component id registers (0xFF0-0xFFC) */
> +#define CORESIGHT_COMPIDR0	(0xFF0)
> +#define CORESIGHT_COMPIDR1	(0xFF4)
> +#define CORESIGHT_COMPIDR2	(0xFF8)
> +#define CORESIGHT_COMPIDR3	(0xFFC)
> +
> +#define ETM_ARCH_V3_3		(0x23)
> +#define ETM_ARCH_V3_5		(0x25)
> +#define PFT_ARCH_V1_1		(0x31)
> +
> +#define CORESIGHT_UNLOCK	(0xC5ACCE55)
> +
> +enum coresight_clk_rate {
> +	CORESIGHT_CLK_RATE_OFF,
> +	CORESIGHT_CLK_RATE_TRACE,
> +	CORESIGHT_CLK_RATE_HSTRACE,
> +};
> +
> +enum coresight_dev_type {
> +	CORESIGHT_DEV_TYPE_NONE,
> +	CORESIGHT_DEV_TYPE_SINK,
> +	CORESIGHT_DEV_TYPE_LINK,
> +	CORESIGHT_DEV_TYPE_LINKSINK,
> +	CORESIGHT_DEV_TYPE_SOURCE,
> +};
> +
> +enum coresight_dev_subtype_sink {
> +	CORESIGHT_DEV_SUBTYPE_SINK_NONE,
> +	CORESIGHT_DEV_SUBTYPE_SINK_PORT,
> +	CORESIGHT_DEV_SUBTYPE_SINK_BUFFER,
> +};
> +
> +enum coresight_dev_subtype_link {
> +	CORESIGHT_DEV_SUBTYPE_LINK_NONE,
> +	CORESIGHT_DEV_SUBTYPE_LINK_MERG,
> +	CORESIGHT_DEV_SUBTYPE_LINK_SPLIT,
> +	CORESIGHT_DEV_SUBTYPE_LINK_FIFO,
> +};
> +
> +enum coresight_dev_subtype_source {
> +	CORESIGHT_DEV_SUBTYPE_SOURCE_NONE,
> +	CORESIGHT_DEV_SUBTYPE_SOURCE_PROC,
> +	CORESIGHT_DEV_SUBTYPE_SOURCE_BUS,
> +	CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE,
> +};
> +
> +struct coresight_ops_entry {
> +	const char *name;
> +	umode_t mode;
> +	const struct file_operations *ops;
> +};
> +
> +struct coresight_dev_subtype {
> +	enum coresight_dev_subtype_sink sink_subtype;
> +	enum coresight_dev_subtype_link link_subtype;
> +	enum coresight_dev_subtype_source source_subtype;
> +};
> +
> +struct coresight_platform_data {
> +	int id;
> +	int cpu;
> +	const char *name;
> +	int nr_inports;
> +	const int *outports;
> +	const int *child_ids;
> +	const int *child_ports;
> +	int nr_outports;
> +	bool default_sink;
> +	struct clk *clk;
> +};
> +
> +struct coresight_desc {
> +	enum coresight_dev_type type;
> +	struct coresight_dev_subtype subtype;
> +	const struct coresight_ops *ops;
> +	struct coresight_platform_data *pdata;
> +	struct device *dev;
> +	const struct coresight_ops_entry **debugfs_ops;
> +	struct module *owner;
> +};
> +
> +struct coresight_connection {
> +	int outport;
> +	int child_id;
> +	int child_port;
> +	struct coresight_device *child_dev;
> +	struct list_head link;
> +};
> +
> +struct coresight_refcnt {
> +	int sink_refcnt;
> +	int *link_refcnts;
> +	int source_refcnt;
> +};
> +
> +struct coresight_device {
> +	int id;
> +	struct coresight_connection *conns;
> +	int nr_conns;
> +	enum coresight_dev_type type;
> +	struct coresight_dev_subtype subtype;
> +	const struct coresight_ops *ops;
> +	struct dentry *de;
> +	struct device dev;
> +	struct coresight_refcnt refcnt;
> +	struct list_head dev_link;
> +	struct list_head path_link;
> +	struct module *owner;
> +	bool enable;
> +};
> +
> +#define to_coresight_device(d) container_of(d, struct coresight_device, dev)
> +
> +#define CORESIGHT_DEBUGFS_ENTRY(__name, __entry_name,			\
> +				 __mode, __get, __set, __fmt)		\
> +DEFINE_SIMPLE_ATTRIBUTE(__name ## _ops, __get, __set, __fmt)		\
> +static const struct coresight_ops_entry __name ## _entry = {		\
> +	.name = __entry_name,						\
> +	.mode = __mode,							\
> +	.ops  = &__name ## _ops						\
> +}
> +
> +struct coresight_ops_sink {
> +	int (*enable)(struct coresight_device *csdev);
> +	void (*disable)(struct coresight_device *csdev);
> +	void (*abort)(struct coresight_device *csdev);
> +};
> +
> +struct coresight_ops_link {
> +	int (*enable)(struct coresight_device *csdev, int iport, int oport);
> +	void (*disable)(struct coresight_device *csdev, int iport, int oport);
> +};
> +
> +struct coresight_ops_source {
> +	int (*enable)(struct coresight_device *csdev);
> +	void (*disable)(struct coresight_device *csdev);
> +};
> +
> +struct coresight_ops {
> +	const struct coresight_ops_sink *sink_ops;
> +	const struct coresight_ops_link *link_ops;
> +	const struct coresight_ops_source *source_ops;
> +};
> +
> +#ifdef CONFIG_CORESIGHT
> +extern struct coresight_device *
> +coresight_register(struct coresight_desc *desc);
> +extern void coresight_unregister(struct coresight_device *csdev);
> +extern int coresight_enable(struct coresight_device *csdev);
> +extern void coresight_disable(struct coresight_device *csdev);
> +extern void coresight_abort(void);
> +extern struct clk *coresight_get_clk(void);
> +#else
> +static inline struct coresight_device *
> +coresight_register(struct coresight_desc *desc) { return NULL; }
> +static inline void coresight_unregister(struct coresight_device *csdev) {}
> +static inline int
> +coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
> +static inline void coresight_disable(struct coresight_device *csdev) {}
> +static inline void coresight_abort(void) {}
> +extern struct clk *coresight_get_clk(void) {};
   ^^^^^^                                     ^^

Not static and no return value.

> +#endif
> +
> +#endif




More information about the linux-arm-kernel mailing list