Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70eee89e authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "coresight: add support to enable multiple coresight paths"

parents 45826d76 3471644e
Loading
Loading
Loading
Loading
+56 −45
Original line number Diff line number Diff line
@@ -36,18 +36,16 @@ struct coresight_node {
};

/*
 * When operating Coresight drivers from the sysFS interface, only a single
 * path can exist from a tracer (associated to a CPU) to a sink.
 * struct coresight_path - path from source to sink
 * @path:	Address of path list.
 * @link:	hook to the list.
 */
static DEFINE_PER_CPU(struct list_head *, tracer_path);
struct coresight_path {
	struct list_head *path;
	struct list_head link;
};

/*
 * As of this writing only a single STM can be found in CS topologies.  Since
 * there is no way to know if we'll ever see more and what kind of
 * configuration they will enact, for the time being only define a single path
 * for STM.
 */
static struct list_head *stm_path;
static LIST_HEAD(cs_active_paths);

/*
 * When losing synchronisation a new barrier packet needs to be inserted at the
@@ -247,7 +245,7 @@ static void coresight_disable_sink(struct coresight_device *csdev)
	ret = sink_ops(csdev)->disable(csdev);
	if (ret)
		return;
	csdev->enable = false;
	csdev->activated = false;
}

static int coresight_enable_link(struct coresight_device *csdev,
@@ -484,6 +482,20 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
	goto out;
}

static struct coresight_device *coresight_get_source(struct list_head *path)
{
	struct coresight_device *csdev;

	if (!path)
		return NULL;

	csdev = list_first_entry(path, struct coresight_node, link)->csdev;
	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
		return NULL;

	return csdev;
}

struct coresight_device *coresight_get_sink(struct list_head *path)
{
	struct coresight_device *csdev;
@@ -756,9 +768,23 @@ static int coresight_validate_source(struct coresight_device *csdev,
	return 0;
}

static int coresight_store_path(struct list_head *path)
{
	struct coresight_path *node;

	node = kzalloc(sizeof(struct coresight_path), GFP_KERNEL);
	if (!node)
		return -ENOMEM;

	node->path = path;
	list_add(&node->link, &cs_active_paths);

	return 0;
}

int coresight_enable(struct coresight_device *csdev)
{
	int cpu, ret = 0;
	int ret = 0;
	struct coresight_device *sink;
	struct list_head *path;
	enum coresight_dev_subtype_source subtype;
@@ -807,25 +833,9 @@ int coresight_enable(struct coresight_device *csdev)
	if (ret)
		goto err_source;

	switch (subtype) {
	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
		/*
		 * When working from sysFS it is important to keep track
		 * of the paths that were created so that they can be
		 * undone in 'coresight_disable()'.  Since there can only
		 * be a single session per tracer (when working from sysFS)
		 * a per-cpu variable will do just fine.
		 */
		cpu = source_ops(csdev)->cpu_id(csdev);
		per_cpu(tracer_path, cpu) = path;
		break;
	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
		stm_path = path;
		break;
	default:
		/* We can't be here */
		break;
	}
	ret = coresight_store_path(path);
	if (ret)
		goto err_source;

out:
	mutex_unlock(&coresight_mutex);
@@ -842,8 +852,11 @@ EXPORT_SYMBOL_GPL(coresight_enable);

void coresight_disable(struct coresight_device *csdev)
{
	int cpu, ret;
	int  ret;
	struct list_head *path = NULL;
	struct coresight_path *cspath = NULL;
	struct coresight_path *cspath_next = NULL;
	struct coresight_device *src_csdev = NULL;

	mutex_lock(&coresight_mutex);

@@ -854,20 +867,18 @@ void coresight_disable(struct coresight_device *csdev)
	if (!csdev->enable || !coresight_disable_source(csdev))
		goto out;

	switch (csdev->subtype.source_subtype) {
	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
		cpu = source_ops(csdev)->cpu_id(csdev);
		path = per_cpu(tracer_path, cpu);
		per_cpu(tracer_path, cpu) = NULL;
		break;
	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
		path = stm_path;
		stm_path = NULL;
		break;
	default:
		/* We can't be here */
		break;
	list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) {
		src_csdev = coresight_get_source(cspath->path);
		if (!src_csdev)
			continue;
		if (src_csdev == csdev) {
			path = cspath->path;
			list_del(&cspath->link);
			kfree(cspath);
		}
	}
	if (path == NULL)
		goto out;

	coresight_disable_path(path);
	coresight_release_path(path);