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

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

Merge "coresight: fix tmc flush timeout issue"

parents 60d52d43 ce82c6f2
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -573,9 +573,12 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
	}

	/* Disable the TMC if need be */
	if (drvdata->mode == CS_MODE_SYSFS)
	if (drvdata->mode == CS_MODE_SYSFS) {
		spin_unlock_irqrestore(&drvdata->spinlock, flags);
		coresight_disable_all_source_link();
		spin_lock_irqsave(&drvdata->spinlock, flags);
		tmc_etb_disable_hw(drvdata);

	}
	drvdata->reading = true;
out:
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -605,6 +608,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
		}
	}

	drvdata->reading = false;
	/* Re-enable the TMC if need be */
	if (drvdata->mode == CS_MODE_SYSFS) {
		/*
@@ -617,6 +621,9 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
		 */
		memset(drvdata->buf, 0, drvdata->size);
		tmc_etb_enable_hw(drvdata);
		spin_unlock_irqrestore(&drvdata->spinlock, flags);
		coresight_enable_all_source_link();
		spin_lock_irqsave(&drvdata->spinlock, flags);
	} else {
		/*
		 * The ETB/ETF is not tracing and the buffer was just read.
@@ -626,7 +633,6 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
		drvdata->buf = NULL;
	}

	drvdata->reading = false;
	spin_unlock_irqrestore(&drvdata->spinlock, flags);

	/*
+11 −4
Original line number Diff line number Diff line
@@ -1617,9 +1617,13 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
	}

	/* Disable the TMC if need be */
	if (drvdata->mode == CS_MODE_SYSFS)
		tmc_etr_disable_hw(drvdata, true);
	if (drvdata->mode == CS_MODE_SYSFS) {
		spin_unlock_irqrestore(&drvdata->spinlock, flags);
		coresight_disable_all_source_link();
		spin_lock_irqsave(&drvdata->spinlock, flags);

		tmc_etr_disable_hw(drvdata, true);
	}
	drvdata->reading = true;
out:
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -1639,6 +1643,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
	mutex_lock(&drvdata->mem_lock);
	spin_lock_irqsave(&drvdata->spinlock, flags);

	drvdata->reading = false;
	/* RE-enable the TMC if need be */
	if (drvdata->mode == CS_MODE_SYSFS) {
		/*
@@ -1647,6 +1652,10 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
		 * be NULL.
		 */
		tmc_etr_enable_hw(drvdata);

		spin_unlock_irqrestore(&drvdata->spinlock, flags);
		coresight_enable_all_source_link();
		spin_lock_irqsave(&drvdata->spinlock, flags);
	} else {
		/*
		 * The ETR is not tracing and the buffer was just read.
@@ -1656,14 +1665,12 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
		drvdata->etr_buf = NULL;
	}

	drvdata->reading = false;
	spin_unlock_irqrestore(&drvdata->spinlock, flags);

	/* Free allocated memory out side of the spinlock */
	if (etr_buf)
		tmc_free_etr_buf(etr_buf);


	mutex_unlock(&drvdata->mem_lock);
	return 0;
}
+141 −2
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ static LIST_HEAD(cs_disabled_link);

static LIST_HEAD(cs_active_paths);

static struct coresight_device *activated_sink;

/*
 * When losing synchronisation a new barrier packet needs to be inserted at the
 * beginning of the data collected in a buffer.  That way the decoder knows that
@@ -850,6 +852,129 @@ int coresight_store_path(struct coresight_device *csdev, struct list_head *path)
	return 0;
}

static void coresight_enable_source_link(struct list_head *path)
{
	u32 type;
	int ret;
	struct coresight_node *nd;
	struct coresight_device *csdev, *parent, *child;

	list_for_each_entry_reverse(nd, path, link) {
		csdev = nd->csdev;
		type = csdev->type;

		if (type == CORESIGHT_DEV_TYPE_LINKSINK)
			type = (csdev == coresight_get_sink(path)) ?
						CORESIGHT_DEV_TYPE_SINK :
						CORESIGHT_DEV_TYPE_LINK;

		switch (type) {
		case CORESIGHT_DEV_TYPE_SINK:
			break;
		case CORESIGHT_DEV_TYPE_SOURCE:
			if (source_ops(csdev)->enable) {
				ret = coresight_enable_reg_clk(csdev);
				if (ret)
					goto err;

				ret = source_ops(csdev)->enable(csdev,
					NULL, CS_MODE_SYSFS);
				if (ret) {
					coresight_disable_reg_clk(csdev);
					goto err;
				}
			}
			csdev->enable = true;
			break;
		case CORESIGHT_DEV_TYPE_LINK:
			parent = list_prev_entry(nd, link)->csdev;
			child = list_next_entry(nd, link)->csdev;
			ret = coresight_enable_link(csdev, parent, child, path);
			if (ret)
				goto err;
			break;
		default:
			break;
		}
	}

	return;
err:
	coresight_disable_previous_devs(path, nd);
	coresight_release_path(csdev, path);
}

static void coresight_disable_source_link(struct list_head *path)
{
	u32 type;
	struct coresight_node *nd;
	struct coresight_device *csdev, *parent, *child;

	list_for_each_entry(nd, path, link) {
		csdev = nd->csdev;
		type = csdev->type;

		if (type == CORESIGHT_DEV_TYPE_LINKSINK)
			type = (csdev == coresight_get_sink(path)) ?
						CORESIGHT_DEV_TYPE_SINK :
						CORESIGHT_DEV_TYPE_LINK;

		switch (type) {
		case CORESIGHT_DEV_TYPE_SINK:
			break;
		case CORESIGHT_DEV_TYPE_SOURCE:
			if (source_ops(csdev)->disable) {
				source_ops(csdev)->disable(csdev, NULL);
				coresight_disable_reg_clk(csdev);
			}
			csdev->enable = false;
			break;
		case CORESIGHT_DEV_TYPE_LINK:
			parent = list_prev_entry(nd, link)->csdev;
			child = list_next_entry(nd, link)->csdev;
			coresight_disable_link(csdev, parent, child, path);
			break;
		default:
			break;
		}
	}
}
void coresight_disable_all_source_link(void)
{
	struct coresight_path *cspath = NULL;
	struct coresight_path *cspath_next = NULL;

	mutex_lock(&coresight_mutex);

	list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) {
		coresight_disable_source_link(cspath->path);
	}

	activated_sink = coresight_get_enabled_sink(false);
	if (activated_sink)
		activated_sink->activated = false;

	mutex_unlock(&coresight_mutex);
}

void coresight_enable_all_source_link(void)
{
	struct coresight_path *cspath = NULL;
	struct coresight_path *cspath_next = NULL;

	mutex_lock(&coresight_mutex);

	list_for_each_entry_safe(cspath, cspath_next, &cs_active_paths, link) {
		coresight_enable_source_link(cspath->path);
	}

	if (activated_sink && activated_sink->enable)
		activated_sink->activated = true;

	activated_sink = NULL;
	mutex_unlock(&coresight_mutex);
}

int coresight_enable(struct coresight_device *csdev)
{
	int ret = 0;
@@ -959,18 +1084,32 @@ static ssize_t enable_sink_store(struct device *dev,
	int ret;
	unsigned long val;
	struct coresight_device *csdev = to_coresight_device(dev);
	struct coresight_device *sink = NULL;

	ret = kstrtoul(buf, 10, &val);
	if (ret)
		return ret;
	mutex_lock(&coresight_mutex);

	if (val)
	if (val) {
		sink = activated_sink ? activated_sink :
			coresight_get_enabled_sink(false);
		if (sink && strcmp(dev_name(&sink->dev),
				dev_name(&csdev->dev)))
			goto err;
		csdev->activated = true;
	else
	} else {
		if (csdev->enable)
			goto err;
		csdev->activated = false;
	}
	mutex_unlock(&coresight_mutex);

	return size;

err:
	mutex_unlock(&coresight_mutex);
	return -EINVAL;
}
static DEVICE_ATTR_RW(enable_sink);

+4 −0
Original line number Diff line number Diff line
@@ -306,6 +306,8 @@ static inline bool coresight_link_late_disable(void)
	else
		return false;
}
extern void coresight_disable_all_source_link(void);
extern void coresight_enable_all_source_link(void);
#else
static inline struct coresight_device *
coresight_register(struct coresight_desc *desc) { return NULL; }
@@ -319,6 +321,8 @@ static inline void coresight_abort(void) {}
static inline void coresight_disable_reg_clk(struct coresight_device *csdev) {}
static inline int coresight_enable_reg_clk(struct coresight_device *csdev)
{ return -EINVAL; }
static void coresight_disable_all_source_link(void) {};
static void coresight_enable_all_source_link(void) {};
#endif

#if defined(CONFIG_OF) && defined(CONFIG_CORESIGHT)