linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: mathieu.poirier@linaro.org (Mathieu Poirier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 14/17] coresight: etr: Add support for save restore buffers
Date: Fri, 3 Nov 2017 16:22:00 -0600	[thread overview]
Message-ID: <20171103222200.GA13173@xps15> (raw)
In-Reply-To: <20171019171553.24056-15-suzuki.poulose@arm.com>

On Thu, Oct 19, 2017 at 06:15:50PM +0100, Suzuki K Poulose wrote:
> Add support for creating buffers which can be used in save-restore
> mode (e.g, for use by perf). If the TMC-ETR supports save-restore
> feature, we could support the mode in all buffer backends. However,

Instead of using the term backend simply write continuous buffer or SG mode.  It
is a lot less cryptic that way.

> if it doesn't, we should fall back to using in built SG mechanism,
> where we can rotate the SG table by making some adjustments in the
> page table.
> 
> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
>  drivers/hwtracing/coresight/coresight-tmc-etr.c | 132 +++++++++++++++++++++++-
>  drivers/hwtracing/coresight/coresight-tmc.h     |  15 +++
>  2 files changed, 143 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 849684f85443..f8e654e1f5b2 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -590,7 +590,7 @@ tmc_etr_sg_table_index_to_daddr(struct tmc_sg_table *sg_table, u32 index)
>   * 3) Update the hwaddr to point to the table pointer for the buffer
>   *    which starts at "base".
>   */
> -static int __maybe_unused
> +static int
>  tmc_etr_sg_table_rotate(struct etr_sg_table *etr_table, u64 base_offset)
>  {
>  	u32 last_entry, first_entry;
> @@ -700,6 +700,9 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata,
>  		return -ENOMEM;
>  	etr_buf->vaddr = vaddr;
>  	etr_buf->hwaddr = paddr;
> +	etr_buf->rrp = paddr;
> +	etr_buf->rwp = paddr;
> +	etr_buf->status = 0;
>  	etr_buf->mode = ETR_MODE_FLAT;
>  	etr_buf->private = drvdata;
>  	return 0;
> @@ -754,13 +757,19 @@ static int tmc_etr_alloc_sg_buf(struct tmc_drvdata *drvdata,
>  				void **pages)
>  {
>  	struct etr_sg_table *etr_table;
> +	struct tmc_sg_table *sg_table;
>  
>  	etr_table = tmc_init_etr_sg_table(drvdata->dev, node,
>  					  etr_buf->size, pages);
>  	if (IS_ERR(etr_table))
>  		return -ENOMEM;
> +	sg_table = etr_table->sg_table;

As far as I can tell this doesn't do anything.

>  	etr_buf->vaddr = tmc_sg_table_data_vaddr(etr_table->sg_table);
>  	etr_buf->hwaddr = etr_table->hwaddr;
> +	/* TMC ETR SG automatically sets the RRP/RWP when enabled */

If TMC ETR SG automatically sets the RRP/RWP, why explicitly setting it?

> +	etr_buf->rrp = etr_table->hwaddr;
> +	etr_buf->rwp = etr_table->hwaddr;
> +	etr_buf->status = 0;
>  	etr_buf->mode = ETR_MODE_ETR_SG;
>  	etr_buf->private = etr_table;
>  	return 0;
> @@ -816,11 +825,49 @@ static void tmc_etr_sync_sg_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
>  	tmc_sg_table_sync_data_range(table, r_offset, etr_buf->len);
>  }
>  
> +static int tmc_etr_restore_sg_buf(struct etr_buf *etr_buf,
> +				   u64 r_offset, u64 w_offset,
> +				   u32 status, bool has_save_restore)

Indentation

> +{
> +	int rc;
> +	struct etr_sg_table *etr_table = etr_buf->private;
> +	struct device *dev = etr_table->sg_table->dev;
> +
> +	/*
> +	 * It is highly unlikely that we have an ETR with in-built SG and
> +	 * Save-Restore capability and we are not sure if the PTRs will
> +	 * be updated.
> +	 */
> +	if (has_save_restore) {
> +		dev_warn_once(dev,
> +		"Unexpected feature combination of SG and save-restore\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Since we cannot program RRP/RWP different from DBAL, the offsets
> +	 * should match.
> +	 */
> +	if (r_offset != w_offset) {
> +		dev_dbg(dev, "Mismatched RRP/RWP offsets\n");
> +		return -EINVAL;
> +	}
> +
> +	rc = tmc_etr_sg_table_rotate(etr_table, w_offset);
> +	if (!rc) {
> +		etr_buf->hwaddr = etr_table->hwaddr;
> +		etr_buf->rrp = etr_table->hwaddr;
> +		etr_buf->rwp = etr_table->hwaddr;
> +	}
> +	return rc;
> +}
> +
>  static const struct etr_buf_operations etr_sg_buf_ops = {
>  	.alloc = tmc_etr_alloc_sg_buf,
>  	.free = tmc_etr_free_sg_buf,
>  	.sync = tmc_etr_sync_sg_buf,
>  	.get_data = tmc_etr_get_data_sg_buf,
> +	.restore = tmc_etr_restore_sg_buf,
>  };
>  
>  static const struct etr_buf_operations *etr_buf_ops[] = {
> @@ -861,10 +908,42 @@ static struct etr_buf *tmc_alloc_etr_buf(struct tmc_drvdata *drvdata,
>  {
>  	int rc = -ENOMEM;
>  	bool has_etr_sg, has_iommu;
> +	bool has_flat, has_save_restore;
>  	struct etr_buf *etr_buf;
>  
>  	has_etr_sg = tmc_etr_has_cap(drvdata, TMC_ETR_SG);
>  	has_iommu = iommu_get_domain_for_dev(drvdata->dev);
> +	has_save_restore = tmc_etr_has_cap(drvdata, TMC_ETR_SAVE_RESTORE);
> +
> +	/*
> +	 * We can normally use flat DMA buffer provided that the buffer
> +	 * is not used in save restore fashion without hardware support.
> +	 */
> +	has_flat = !(flags & ETR_BUF_F_RESTORE_PTRS) || has_save_restore;
> +
> +	/*
> +	 * To support save-restore on a given ETR we have the following
> +	 * conditions:
> +	 *  1) If the buffer requires save-restore of a pointers as well
> +	 *     as the Status bit, we require ETR support for it and we coul
> +	 *     support all the backends.
> +	 *  2) If the buffer requires only save-restore of pointers, then
> +	 *     we could exploit a circular ETR SG list. None of the other
> +	 *     backends can support it without the ETR feature.
> +	 *
> +	 * If the buffer will be used in a save-restore mode without
> +	 * the ETR support for SAVE_RESTORE, we can only support TMC
> +	 * ETR in-built SG tables which can be rotated to make it work.
> +	 */
> +	if ((flags & ETR_BUF_F_RESTORE_STATUS) && !has_save_restore)
> +		return ERR_PTR(-EINVAL);
> +
> +	if (!has_flat && !has_etr_sg) {
> +		dev_dbg(drvdata->dev,
> +			"No available backends for ETR buffer with flags %x\n",
> +			flags);
> +		return ERR_PTR(-EINVAL);
> +	}
>  
>  	etr_buf = kzalloc(sizeof(*etr_buf), GFP_KERNEL);
>  	if (!etr_buf)
> @@ -883,7 +962,7 @@ static struct etr_buf *tmc_alloc_etr_buf(struct tmc_drvdata *drvdata,
>  	 * Fallback to available mechanisms.
>  	 *
>  	 */
> -	if (!pages &&
> +	if (!pages && has_flat &&
>  	    (!has_etr_sg || has_iommu || size < SZ_1M))
>  		rc = tmc_etr_mode_alloc_buf(ETR_MODE_FLAT, drvdata,
>  					    etr_buf, node, pages);
> @@ -961,6 +1040,51 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata)
>  		tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset);
>  }
>  
> +/*
> + * tmc_etr_restore_generic: Common helper to restore the buffer
> + * status for FLAT buffers, which use linear TMC ETR address range.
> + * This is only possible with in-built ETR capability to save-restore
> + * the pointers. The DBA will still point to the original start of the
> + * buffer.
> + */
> +static int tmc_etr_buf_generic_restore(struct etr_buf *etr_buf,
> +					u64 r_offset, u64 w_offset,
> +					u32 status, bool has_save_restore)

Indentation

> +{
> +	u64 size = etr_buf->size;
> +
> +	if (!has_save_restore)
> +		return -EINVAL;
> +	etr_buf->rrp = etr_buf->hwaddr + (r_offset % size);
> +	etr_buf->rwp = etr_buf->hwaddr + (w_offset % size);
> +	etr_buf->status = status;
> +	return 0;
> +}
> +
> +static int __maybe_unused
> +tmc_restore_etr_buf(struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
> +		    u64 r_offset, u64 w_offset, u32 status)
> +{
> +	bool has_save_restore = tmc_etr_has_cap(drvdata, TMC_ETR_SAVE_RESTORE);
> +
> +	if (WARN_ON_ONCE(!has_save_restore && etr_buf->mode != ETR_MODE_ETR_SG))
> +		return -EINVAL;
> +	/*
> +	 * If we use a circular SG list without ETR support, we can't
> +	 * support restoring "Full" bit.
> +	 */
> +	if (WARN_ON_ONCE(!has_save_restore && status))
> +		return -EINVAL;
> +	if (status & ~TMC_STS_FULL)
> +		return -EINVAL;
> +	if (etr_buf->ops->restore)
> +		return etr_buf->ops->restore(etr_buf, r_offset, w_offset,
> +					      status, has_save_restore);
> +	else
> +		return tmc_etr_buf_generic_restore(etr_buf, r_offset, w_offset,
> +					       status, has_save_restore);
> +}
> +
>  static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
>  			      struct etr_buf *etr_buf)
>  {
> @@ -1004,8 +1128,8 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
>  	 * STS to "not full").
>  	 */
>  	if (tmc_etr_has_cap(drvdata, TMC_ETR_SAVE_RESTORE)) {
> -		tmc_write_rrp(drvdata, etr_buf->hwaddr);
> -		tmc_write_rwp(drvdata, etr_buf->hwaddr);
> +		tmc_write_rrp(drvdata, etr_buf->rrp);
> +		tmc_write_rwp(drvdata, etr_buf->rwp);
>  		sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL;
>  		writel_relaxed(sts, drvdata->base + TMC_STS);
>  	}
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
> index 14a3dec50b0f..2c5b905b6494 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.h
> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
> @@ -142,12 +142,22 @@ enum etr_mode {
>  	ETR_MODE_ETR_SG,	/* Uses in-built TMC ETR SG mechanism */
>  };
>  
> +/* ETR buffer should support save-restore */
> +#define ETR_BUF_F_RESTORE_PTRS		0x1
> +#define ETR_BUF_F_RESTORE_STATUS	0x2
> +
> +#define ETR_BUF_F_RESTORE_MINIMAL	ETR_BUF_F_RESTORE_PTRS
> +#define ETR_BUF_F_RESTORE_FULL		(ETR_BUF_F_RESTORE_PTRS |\
> +					 ETR_BUF_F_RESTORE_STATUS)
>  struct etr_buf_operations;
>  
>  /**
>   * struct etr_buf - Details of the buffer used by ETR
>   * @mode	: Mode of the ETR buffer, contiguous, Scatter Gather etc.
>   * @full	: Trace data overflow
> + * @status	: Value for STATUS if the ETR supports save-restore.
> + * @rrp		: Value for RRP{LO:HI} if the ETR supports save-restore
> + * @rwp		: Value for RWP{LO:HI} if the ETR supports save-restore
>   * @size	: Size of the buffer.
>   * @hwaddr	: Address to be programmed in the TMC:DBA{LO,HI}
>   * @vaddr	: Virtual address of the buffer used for trace.
> @@ -159,6 +169,9 @@ struct etr_buf_operations;
>  struct etr_buf {
>  	enum etr_mode			mode;
>  	bool				full;
> +	u32				status;
> +	dma_addr_t			rrp;
> +	dma_addr_t			rwp;
>  	ssize_t				size;
>  	dma_addr_t			hwaddr;
>  	void				*vaddr;
> @@ -212,6 +225,8 @@ struct etr_buf_operations {
>  	int (*alloc)(struct tmc_drvdata *drvdata, struct etr_buf *etr_buf,
>  			int node, void **pages);
>  	void (*sync)(struct etr_buf *etr_buf, u64 rrp, u64 rwp);
> +	int (*restore)(struct etr_buf *etr_buf, u64 r_offset,
> +		       u64 w_offset, u32 status, bool has_save_restore);
>  	ssize_t (*get_data)(struct etr_buf *etr_buf, u64 offset, size_t len,
>  				char **bufpp);
>  	void (*free)(struct etr_buf *etr_buf);
> -- 
> 2.13.6
> 

  reply	other threads:[~2017-11-03 22:22 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-19 17:15 [PATCH 00/17] coresight: perf: TMC ETR backend support Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 01/17] coresight etr: Disallow perf mode temporarily Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 02/17] coresight tmc: Hide trace buffer handling for file read Suzuki K Poulose
2017-10-20 12:34   ` Julien Thierry
2017-11-01  9:55     ` Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 03/17] coresight: Add helper for inserting synchronization packets Suzuki K Poulose
2017-10-30 21:44   ` Mathieu Poirier
2017-11-01 10:01     ` Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 04/17] coresight: Add generic TMC sg table framework Suzuki K Poulose
2017-10-31 22:13   ` Mathieu Poirier
2017-11-01 10:09     ` Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 05/17] coresight: Add support for TMC ETR SG unit Suzuki K Poulose
2017-10-20 16:25   ` Julien Thierry
2017-11-01 10:11     ` Suzuki K Poulose
2017-11-01 20:41   ` Mathieu Poirier
2017-10-19 17:15 ` [PATCH 06/17] coresight: tmc: Make ETR SG table circular Suzuki K Poulose
2017-10-20 17:11   ` Julien Thierry
2017-11-01 10:12     ` Suzuki K Poulose
2017-11-01 23:47   ` Mathieu Poirier
2017-11-02 12:00     ` Suzuki K Poulose
2017-11-02 14:40       ` Mathieu Poirier
2017-11-02 15:13         ` Russell King - ARM Linux
2017-11-06 19:07   ` Mathieu Poirier
2017-11-07 10:36     ` Suzuki K Poulose
2017-11-09 16:19       ` Mathieu Poirier
2017-10-19 17:15 ` [PATCH 07/17] coresight: tmc etr: Add transparent buffer management Suzuki K Poulose
2017-11-02 17:48   ` Mathieu Poirier
2017-11-03 10:02     ` Suzuki K Poulose
2017-11-03 20:13       ` Mathieu Poirier
2017-10-19 17:15 ` [PATCH 08/17] coresight: tmc: Add configuration support for trace buffer size Suzuki K Poulose
2017-11-02 19:26   ` Mathieu Poirier
2017-10-19 17:15 ` [PATCH 09/17] coresight: Convert driver messages to dev_dbg Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 10/17] coresight: etr: Track if the device is coherent Suzuki K Poulose
2017-11-02 19:40   ` Mathieu Poirier
2017-11-03 10:03     ` Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 11/17] coresight etr: Handle driver mode specific ETR buffers Suzuki K Poulose
2017-11-02 20:26   ` Mathieu Poirier
2017-11-03 10:08     ` Suzuki K Poulose
2017-11-03 20:30       ` Mathieu Poirier
2017-10-19 17:15 ` [PATCH 12/17] coresight etr: Relax collection of trace from sysfs mode Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 13/17] coresight etr: Do not clean ETR trace buffer Suzuki K Poulose
2017-11-02 20:36   ` Mathieu Poirier
2017-11-03 10:10     ` Suzuki K Poulose
2017-11-03 20:17       ` Mathieu Poirier
2017-11-07 10:37         ` Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 14/17] coresight: etr: Add support for save restore buffers Suzuki K Poulose
2017-11-03 22:22   ` Mathieu Poirier [this message]
2017-10-19 17:15 ` [PATCH 15/17] coresight: etr_buf: Add helper for padding an area of trace data Suzuki K Poulose
2017-10-19 17:15 ` [PATCH 16/17] coresight: perf: Remove reset_buffer call back for sinks Suzuki K Poulose
2017-11-06 21:10   ` Mathieu Poirier
2017-10-19 17:15 ` [PATCH 17/17] coresight perf: Add ETR backend support for etm-perf Suzuki K Poulose
2017-11-07  0:24   ` Mathieu Poirier
2017-11-07 10:52     ` Suzuki K Poulose
2017-11-07 15:17       ` Mike Leach
2017-11-07 15:46         ` Mathieu Poirier
2017-10-20 11:00 ` [PATCH 00/17] coresight: perf: TMC ETR backend support Suzuki K Poulose

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171103222200.GA13173@xps15 \
    --to=mathieu.poirier@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).