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

Commit 42466950 authored by Satyajit Desai's avatar Satyajit Desai Committed by Gerrit - the friendly Code Review server
Browse files

coresight: tmc: add support to configure etr memory size



Add support to expose a node for user to configure memory buffer size
for an ETR device.

Change-Id: I18e8688c45d87b26a1aaac25a91b2deaaf61272e
Signed-off-by: default avatarSatyajit Desai <sadesai@codeaurora.org>
parent 4865500b
Loading
Loading
Loading
Loading
+56 −5
Original line number Diff line number Diff line
/*
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
 * Copyright(C) 2016 Linaro Limited. All rights reserved.
 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
 *
@@ -96,6 +96,41 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
	CS_LOCK(drvdata->base);
}

static int tmc_etr_alloc_mem(struct tmc_drvdata *drvdata)
{
	int ret;

	if (!drvdata->vaddr) {
		drvdata->vaddr = dma_zalloc_coherent(drvdata->dev,
						     drvdata->size,
						     &drvdata->paddr,
						     GFP_KERNEL);
		if (!drvdata->vaddr) {
			ret = -ENOMEM;
			goto err;
		}
	}
	/*
	 * Need to reinitialize buf for each tmc enable session since it is
	 * getting modified during tmc etr dump.
	 */
	drvdata->buf = drvdata->vaddr;
	return 0;
err:
	dev_err(drvdata->dev, "etr ddr memory allocation failed\n");
	return ret;
}

static void tmc_etr_free_mem(struct tmc_drvdata *drvdata)
{
	if (drvdata->vaddr) {
		dma_free_coherent(drvdata->dev, drvdata->size,
				  drvdata->vaddr, drvdata->paddr);
		drvdata->vaddr = 0;
		drvdata->paddr = 0;
	}
}

static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
{
	int ret = 0;
@@ -123,10 +158,26 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
		 * held.  As such allocate memory here and free it if a buffer
		 * has already been allocated (from a previous session).
		 */
		vaddr = dma_alloc_coherent(drvdata->dev, drvdata->size,
					   &paddr, GFP_KERNEL);
		if (!vaddr)
			return -ENOMEM;
		mutex_lock(&drvdata->mem_lock);

		/*
		 * ETR DDR memory is not allocated until user enables
		 * tmc at least once. If user specifies different ETR
		 * DDR size than the default size or switches between
		 * contiguous or scatter-gather memory type after
		 * enabling tmc; the new selection will be honored from
		 * next tmc enable session.
		 */
		if (drvdata->size != drvdata->mem_size)
			tmc_etr_free_mem(drvdata);

		ret = tmc_etr_alloc_mem(drvdata);
		if (ret) {
			pm_runtime_put(drvdata->dev);
			mutex_unlock(&drvdata->mem_lock);
			return ret;
		}
		mutex_unlock(&drvdata->mem_lock);

		/* Let's try again */
		spin_lock_irqsave(&drvdata->spinlock, flags);
+60 −11
Original line number Diff line number Diff line
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved.
 *
 * Description: CoreSight Trace Memory Controller driver
 *
@@ -273,13 +273,52 @@ static ssize_t trigger_cntr_store(struct device *dev,
}
static DEVICE_ATTR_RW(trigger_cntr);

static struct attribute *coresight_tmc_attrs[] = {
static ssize_t mem_size_show(struct device *dev,
			     struct device_attribute *attr,
			     char *buf)
{
	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
	unsigned long val = drvdata->mem_size;

	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}

static ssize_t mem_size_store(struct device *dev,
			      struct device_attribute *attr,
			      const char *buf, size_t size)
{
	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
	unsigned long val;

	mutex_lock(&drvdata->mem_lock);
	if (kstrtoul(buf, 16, &val)) {
		mutex_unlock(&drvdata->mem_lock);
		return -EINVAL;
	}

	drvdata->mem_size = val;
	mutex_unlock(&drvdata->mem_lock);
	return size;
}
static DEVICE_ATTR_RW(mem_size);

static struct attribute *coresight_tmc_etf_attrs[] = {
	&dev_attr_trigger_cntr.attr,
	NULL,
};

static const struct attribute_group coresight_tmc_group = {
	.attrs = coresight_tmc_attrs,
static struct attribute *coresight_tmc_etr_attrs[] = {
	&dev_attr_mem_size.attr,
	&dev_attr_trigger_cntr.attr,
	NULL,
};

static const struct attribute_group coresight_tmc_etf_group = {
	.attrs = coresight_tmc_etf_attrs,
};

static const struct attribute_group coresight_tmc_etr_group = {
	.attrs = coresight_tmc_etr_attrs,
};

static const struct attribute_group coresight_tmc_mgmt_group = {
@@ -287,8 +326,14 @@ static const struct attribute_group coresight_tmc_mgmt_group = {
	.name = "mgmt",
};

const struct attribute_group *coresight_tmc_groups[] = {
	&coresight_tmc_group,
const struct attribute_group *coresight_tmc_etf_groups[] = {
	&coresight_tmc_etf_group,
	&coresight_tmc_mgmt_group,
	NULL,
};

const struct attribute_group *coresight_tmc_etr_groups[] = {
	&coresight_tmc_etr_group,
	&coresight_tmc_mgmt_group,
	NULL,
};
@@ -332,6 +377,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
	drvdata->base = base;

	spin_lock_init(&drvdata->spinlock);
	mutex_init(&drvdata->mem_lock);

	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
	drvdata->config_type = BMVAL(devid, 6, 7);
@@ -344,6 +390,8 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
						   &drvdata->size);
		if (ret)
			drvdata->size = SZ_1M;

		drvdata->mem_size = drvdata->size;
	} else {
		drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
	}
@@ -352,20 +400,21 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)

	desc.pdata = pdata;
	desc.dev = dev;
	desc.groups = coresight_tmc_groups;

	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
		desc.type = CORESIGHT_DEV_TYPE_SINK;
		desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
		desc.ops = &tmc_etb_cs_ops;
		desc.groups = coresight_tmc_etf_groups;
		desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
		desc.type = CORESIGHT_DEV_TYPE_SINK;
		desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
		desc.ops = &tmc_etr_cs_ops;
		desc.groups = coresight_tmc_etr_groups;
		desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
	} else {
		desc.type = CORESIGHT_DEV_TYPE_LINKSINK;
		desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
		desc.ops = &tmc_etf_cs_ops;
		desc.groups = coresight_tmc_etf_groups;
		desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
	}

	drvdata->csdev = coresight_register(&desc);
+2 −0
Original line number Diff line number Diff line
@@ -122,6 +122,8 @@ struct tmc_drvdata {
	local_t			mode;
	enum tmc_config_type	config_type;
	enum tmc_mem_intf_width	memwidth;
	struct mutex		mem_lock;
	u32			mem_size;
	u32			trigger_cntr;
};