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

Commit 3994a5c1 authored by Arve Hjønnevåg's avatar Arve Hjønnevåg Committed by Ruchi Kandoi
Browse files

ARM: etm: Add some missing locks and error checks



It is not safe to call etm_lock or etb_lock without holding the
mutex since another thread may also have unlocked the registers.

Also add some missing checks for valid etb_regs in the etm sysfs
entries.

Change-Id: I939f76a6ea7546a8fc0d4ddafa2fd2b6f38103bb
Signed-off-by: default avatarArve Hjønnevåg <arve@android.com>
parent ae815d26
Loading
Loading
Loading
Loading
+39 −18
Original line number Diff line number Diff line
@@ -264,8 +264,13 @@ static void etm_dump(void)

static void sysrq_etm_dump(int key)
{
	if (!mutex_trylock(&tracer.mutex)) {
		printk(KERN_INFO "Tracing hardware busy\n");
		return;
	}
	dev_dbg(tracer.dev, "Dumping ETB buffer\n");
	etm_dump();
	mutex_unlock(&tracer.mutex);
}

static struct sysrq_key_op sysrq_etm_op = {
@@ -374,6 +379,7 @@ static int etb_probe(struct amba_device *dev, const struct amba_id *id)
	if (ret)
		goto out;

	mutex_lock(&t->mutex);
	t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
	if (!t->etb_regs) {
		ret = -ENOMEM;
@@ -382,6 +388,16 @@ static int etb_probe(struct amba_device *dev, const struct amba_id *id)

	amba_set_drvdata(dev, t);

	etb_unlock(t);
	t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
	dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);

	/* make sure trace capture is disabled */
	etb_writel(t, 0, ETBR_CTRL);
	etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
	etb_lock(t);
	mutex_unlock(&t->mutex);

	etb_miscdev.parent = &dev->dev;

	ret = misc_register(&etb_miscdev);
@@ -395,24 +411,18 @@ static int etb_probe(struct amba_device *dev, const struct amba_id *id)
	else
		clk_enable(t->emu_clk);

	etb_unlock(t);
	t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
	dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);

	/* make sure trace capture is disabled */
	etb_writel(t, 0, ETBR_CTRL);
	etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
	etb_lock(t);

	dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");

out:
	return ret;

out_unmap:
	mutex_lock(&t->mutex);
	iounmap(t->etb_regs);
	t->etb_regs = NULL;

out_release:
	mutex_unlock(&t->mutex);
	amba_release_regions(dev);

	return ret;
@@ -472,6 +482,9 @@ static ssize_t trace_running_store(struct kobject *kobj,
		return -EINVAL;

	mutex_lock(&tracer.mutex);
	if (!tracer.etb_regs)
		ret = -ENODEV;
	else
		ret = value ? trace_start(&tracer) : trace_stop(&tracer);
	mutex_unlock(&tracer.mutex);

@@ -488,6 +501,8 @@ static ssize_t trace_info_show(struct kobject *kobj,
	u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
	int datalen;

	mutex_lock(&tracer.mutex);
	if (tracer.etb_regs) {
		etb_unlock(&tracer);
		datalen = etb_getdatalen(&tracer);
		etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
@@ -495,11 +510,16 @@ static ssize_t trace_info_show(struct kobject *kobj,
		etb_st = etb_readl(&tracer, ETBR_STATUS);
		etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
		etb_lock(&tracer);
	} else {
		etb_wa = etb_ra = etb_st = etb_fc = ~0;
		datalen = -1;
	}

	etm_unlock(&tracer);
	etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
	etm_st = etm_readl(&tracer, ETMR_STATUS);
	etm_lock(&tracer);
	mutex_unlock(&tracer.mutex);

	return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
			"ETBR_WRITEADDR:\t%08x\n"
@@ -649,7 +669,6 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id)

	amba_set_drvdata(dev, t);

	mutex_init(&t->mutex);
	t->dev = &dev->dev;
	t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
	t->etm_portsz = 1;
@@ -740,6 +759,8 @@ static int __init etm_init(void)
{
	int retval;

	mutex_init(&tracer.mutex);

	retval = amba_driver_register(&etb_driver);
	if (retval) {
		printk(KERN_ERR "Failed to register etb\n");