All of lore.kernel.org
 help / color / mirror / Atom feed
From: Miquel Raynal <miquel.raynal@bootlin.com>
To: Boris Brezillon <boris.brezillon@bootlin.com>
Cc: David Woodhouse <dwmw2@infradead.org>,
	Brian Norris <computersforpeace@gmail.com>,
	Marek Vasut <marek.vasut@gmail.com>,
	Richard Weinberger <richard@nod.at>,
	linux-mtd@lists.infradead.org, Mark Brown <broonie@kernel.org>,
	linux-spi@vger.kernel.org,
	Cyrille Pitchen <cyrille.pitchen@microchip.com>,
	Vignesh R <vigneshr@ti.com>,
	Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Subject: Re: [RFC PATCH 1/2] spi: spi-mem: Add a new API to support direct mapping
Date: Thu, 7 Jun 2018 17:01:53 +0200	[thread overview]
Message-ID: <20180607170153.757ca102@xps13> (raw)
In-Reply-To: <20180601143603.4047-2-boris.brezillon@bootlin.com>

Hi Boris,

On Fri,  1 Jun 2018 16:36:02 +0200, Boris Brezillon
<boris.brezillon@bootlin.com> wrote:

> Most modern QSPI controllers support can directly map a SPI memory (or

s/support// ?

> a portion of the SPI memory) in the CPU address space. Most of the time
> this brings significant performance improvements as it automates the
> whole process of sending SPI memory operations every time a new region
> is accessed.
> 
> This new API allow SPI memory driver to create direct mappings and then

s/allow/allows/
s/driver/drivers/ ?

> use them to access the memory instead of using spi_mem_exec_op().
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> ---
>  drivers/spi/spi-mem.c       | 267 ++++++++++++++++++++++++++++++++++++++++----
>  include/linux/spi/spi-mem.h |  72 ++++++++++++
>  2 files changed, 318 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
> index 990770dfa5cf..90ea0c5263a7 100644
> --- a/drivers/spi/spi-mem.c
> +++ b/drivers/spi/spi-mem.c
> @@ -175,6 +175,44 @@ bool spi_mem_supports_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  }
>  EXPORT_SYMBOL_GPL(spi_mem_supports_op);
>  
> +static int spi_mem_access_start(struct spi_mem *mem)
> +{
> +	struct spi_controller *ctlr = mem->spi->controller;
> +
> +	/*
> +	 * Flush the message queue before executing our SPI memory
> +	 * operation to prevent preemption of regular SPI transfers.
> +	 */
> +	spi_flush_queue(ctlr);
> +
> +	if (ctlr->auto_runtime_pm) {
> +		int ret;
> +
> +		ret = pm_runtime_get_sync(ctlr->dev.parent);
> +		if (ret < 0) {
> +			dev_err(&ctlr->dev, "Failed to power device: %d\n",
> +				ret);
> +			return ret;
> +		}
> +	}
> +
> +	mutex_lock(&ctlr->bus_lock_mutex);
> +	mutex_lock(&ctlr->io_mutex);
> +
> +	return 0;
> +}
> +
> +static void spi_mem_access_end(struct spi_mem *mem)
> +{
> +	struct spi_controller *ctlr = mem->spi->controller;
> +
> +	mutex_unlock(&ctlr->io_mutex);
> +	mutex_unlock(&ctlr->bus_lock_mutex);
> +
> +	if (ctlr->auto_runtime_pm)
> +		pm_runtime_put(ctlr->dev.parent);
> +}
> +
>  /**
>   * spi_mem_exec_op() - Execute a memory operation
>   * @mem: the SPI memory
> @@ -200,30 +238,13 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  		return -ENOTSUPP;
>  
>  	if (ctlr->mem_ops) {
> -		/*
> -		 * Flush the message queue before executing our SPI memory
> -		 * operation to prevent preemption of regular SPI transfers.
> -		 */
> -		spi_flush_queue(ctlr);
> -
> -		if (ctlr->auto_runtime_pm) {
> -			ret = pm_runtime_get_sync(ctlr->dev.parent);
> -			if (ret < 0) {
> -				dev_err(&ctlr->dev,
> -					"Failed to power device: %d\n",
> -					ret);
> -				return ret;
> -			}
> -		}
> +		ret = spi_mem_access_start(mem);
> +		if (ret)
> +			return ret;
>  
> -		mutex_lock(&ctlr->bus_lock_mutex);
> -		mutex_lock(&ctlr->io_mutex);
>  		ret = ctlr->mem_ops->exec_op(mem, op);
> -		mutex_unlock(&ctlr->io_mutex);
> -		mutex_unlock(&ctlr->bus_lock_mutex);
>  
> -		if (ctlr->auto_runtime_pm)
> -			pm_runtime_put(ctlr->dev.parent);
> +		spi_mem_access_end(mem);

As this is something you tell me on a weekly basis: would you mind to
separate the direct mapping support and the
spi_mem_access_start/end() helpers introduction in different
patches? :)

>  
>  		/*
>  		 * Some controllers only optimize specific paths (typically the
> @@ -336,6 +357,210 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
>  }
>  EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size);
>  

[...]

> +
> +/**
> + * struct spi_mem_dirmap_desc - Direct mapping descriptor
> + * @mem: the SPI memory device this direct mapping is attached to
> + * @info: information passed at direct mapping creation time
> + * @nodirmap: set to true if the SPI controller does not implement
> + *	      ->mem_ops->dirmap_create() or when this function returned an

s/returned/returns/

> + *	      error. If dirmap is true, all spi_mem_dirmap_{read,write}()
> + *	      calls will use spi_mem_exec_op() to access the memory. This is a
> + *	      degraded mode that allows higher spi_mem drivers to use the same
> + *	      code no matter if the controller supports direct mapping or not
> + * @priv: field pointing to controller specific data
> + *
> + * Common part of a direct mapping descriptor. This object is created by
> + * spi_mem_dirmap_create() and controller implementation of ->create_dirmap()
> + * can create/attach direct mapping resources to the descriptor in the ->priv
> + * field.
> + */
> +struct spi_mem_dirmap_desc {
> +	struct spi_mem *mem;
> +	struct spi_mem_dirmap_info info;
> +	bool nodirmap;
> +	void *priv;
> +};
> +
>  /**
>   * struct spi_mem - describes a SPI memory device
>   * @spi: the underlying SPI device
> @@ -167,10 +210,24 @@ static inline void *spi_mem_get_drvdata(struct spi_mem *mem)
>   *		    limitations)
>   * @supports_op: check if an operation is supported by the controller
>   * @exec_op: execute a SPI memory operation
> + * @dirmap_create: create a direct mapping descriptor that can later be used to
> + *		   access the memory device. This method is optional

Only *dirmap_create() is marked as optional while all are.

> + * @dirmap_destroy: destroy a memory descriptor previous created by
> + *		    ->dirmap_create()

s/previous/previously/

> + * @dirmap_read: read data from the memory device using the direct mapping
> + *		 created by ->dirmap_create().
> + * @dirmap_write: write data to the memory device using the direct mapping
> + *		  created by ->dirmap_create().

I think there is a better kernel-doc way to reference dirmap_create(),
maybe with '@' (I don't remember exactly).

>   *
>   * This interface should be implemented by SPI controllers providing an
>   * high-level interface to execute SPI memory operation, which is usually the
>   * case for QSPI controllers.
> + *
> + * Note on ->dirmap_{read,write}(): drivers should avoid accessing the direct
> + * mapping from the CPU because doing that can stall the CPU waiting for the
> + * SPI mem transaction to finish, and this will make real-time maintainers
> + * unhappy and might make your system less reactive. Instead, drivers should
> + * use DMA to access this direct mapping.
>   */
>  struct spi_controller_mem_ops {
>  	int (*adjust_op_size)(struct spi_mem *mem, struct spi_mem_op *op);
> @@ -178,6 +235,12 @@ struct spi_controller_mem_ops {
>  			    const struct spi_mem_op *op);
>  	int (*exec_op)(struct spi_mem *mem,
>  		       const struct spi_mem_op *op);
> +	int (*dirmap_create)(struct spi_mem_dirmap_desc *desc);
> +	void (*dirmap_destroy)(struct spi_mem_dirmap_desc *desc);
> +	ssize_t (*dirmap_read)(struct spi_mem_dirmap_desc *desc,
> +			       u64 offs, size_t len, void *buf);
> +	ssize_t (*dirmap_write)(struct spi_mem_dirmap_desc *desc,
> +				u64 offs, size_t len, const void *buf);
>  };
>  
>  /**
> @@ -236,6 +299,15 @@ bool spi_mem_supports_op(struct spi_mem *mem,
>  int spi_mem_exec_op(struct spi_mem *mem,
>  		    const struct spi_mem_op *op);
>  
> +struct spi_mem_dirmap_desc *
> +spi_mem_dirmap_create(struct spi_mem *mem,
> +		      const struct spi_mem_dirmap_info *info);
> +void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc);
> +ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
> +			    u64 offs, size_t len, void *buf);
> +ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
> +			     u64 offs, size_t len, const void *buf);
> +
>  int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv,
>  				       struct module *owner);
>  

The rest is clear for me.

Thanks,
Miquèl

WARNING: multiple messages have this Message-ID (diff)
From: Miquel Raynal <miquel.raynal@bootlin.com>
To: Boris Brezillon <boris.brezillon@bootlin.com>
Cc: Vignesh R <vigneshr@ti.com>, Richard Weinberger <richard@nod.at>,
	Cyrille Pitchen <cyrille.pitchen@microchip.com>,
	linux-spi@vger.kernel.org, Marek Vasut <marek.vasut@gmail.com>,
	Mark Brown <broonie@kernel.org>,
	linux-mtd@lists.infradead.org,
	Thomas Petazzoni <thomas.petazzoni@bootlin.com>,
	Brian Norris <computersforpeace@gmail.com>,
	David Woodhouse <dwmw2@infradead.org>
Subject: Re: [RFC PATCH 1/2] spi: spi-mem: Add a new API to support direct mapping
Date: Thu, 7 Jun 2018 17:01:53 +0200	[thread overview]
Message-ID: <20180607170153.757ca102@xps13> (raw)
In-Reply-To: <20180601143603.4047-2-boris.brezillon@bootlin.com>

Hi Boris,

On Fri,  1 Jun 2018 16:36:02 +0200, Boris Brezillon
<boris.brezillon@bootlin.com> wrote:

> Most modern QSPI controllers support can directly map a SPI memory (or

s/support// ?

> a portion of the SPI memory) in the CPU address space. Most of the time
> this brings significant performance improvements as it automates the
> whole process of sending SPI memory operations every time a new region
> is accessed.
> 
> This new API allow SPI memory driver to create direct mappings and then

s/allow/allows/
s/driver/drivers/ ?

> use them to access the memory instead of using spi_mem_exec_op().
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> ---
>  drivers/spi/spi-mem.c       | 267 ++++++++++++++++++++++++++++++++++++++++----
>  include/linux/spi/spi-mem.h |  72 ++++++++++++
>  2 files changed, 318 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
> index 990770dfa5cf..90ea0c5263a7 100644
> --- a/drivers/spi/spi-mem.c
> +++ b/drivers/spi/spi-mem.c
> @@ -175,6 +175,44 @@ bool spi_mem_supports_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  }
>  EXPORT_SYMBOL_GPL(spi_mem_supports_op);
>  
> +static int spi_mem_access_start(struct spi_mem *mem)
> +{
> +	struct spi_controller *ctlr = mem->spi->controller;
> +
> +	/*
> +	 * Flush the message queue before executing our SPI memory
> +	 * operation to prevent preemption of regular SPI transfers.
> +	 */
> +	spi_flush_queue(ctlr);
> +
> +	if (ctlr->auto_runtime_pm) {
> +		int ret;
> +
> +		ret = pm_runtime_get_sync(ctlr->dev.parent);
> +		if (ret < 0) {
> +			dev_err(&ctlr->dev, "Failed to power device: %d\n",
> +				ret);
> +			return ret;
> +		}
> +	}
> +
> +	mutex_lock(&ctlr->bus_lock_mutex);
> +	mutex_lock(&ctlr->io_mutex);
> +
> +	return 0;
> +}
> +
> +static void spi_mem_access_end(struct spi_mem *mem)
> +{
> +	struct spi_controller *ctlr = mem->spi->controller;
> +
> +	mutex_unlock(&ctlr->io_mutex);
> +	mutex_unlock(&ctlr->bus_lock_mutex);
> +
> +	if (ctlr->auto_runtime_pm)
> +		pm_runtime_put(ctlr->dev.parent);
> +}
> +
>  /**
>   * spi_mem_exec_op() - Execute a memory operation
>   * @mem: the SPI memory
> @@ -200,30 +238,13 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
>  		return -ENOTSUPP;
>  
>  	if (ctlr->mem_ops) {
> -		/*
> -		 * Flush the message queue before executing our SPI memory
> -		 * operation to prevent preemption of regular SPI transfers.
> -		 */
> -		spi_flush_queue(ctlr);
> -
> -		if (ctlr->auto_runtime_pm) {
> -			ret = pm_runtime_get_sync(ctlr->dev.parent);
> -			if (ret < 0) {
> -				dev_err(&ctlr->dev,
> -					"Failed to power device: %d\n",
> -					ret);
> -				return ret;
> -			}
> -		}
> +		ret = spi_mem_access_start(mem);
> +		if (ret)
> +			return ret;
>  
> -		mutex_lock(&ctlr->bus_lock_mutex);
> -		mutex_lock(&ctlr->io_mutex);
>  		ret = ctlr->mem_ops->exec_op(mem, op);
> -		mutex_unlock(&ctlr->io_mutex);
> -		mutex_unlock(&ctlr->bus_lock_mutex);
>  
> -		if (ctlr->auto_runtime_pm)
> -			pm_runtime_put(ctlr->dev.parent);
> +		spi_mem_access_end(mem);

As this is something you tell me on a weekly basis: would you mind to
separate the direct mapping support and the
spi_mem_access_start/end() helpers introduction in different
patches? :)

>  
>  		/*
>  		 * Some controllers only optimize specific paths (typically the
> @@ -336,6 +357,210 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
>  }
>  EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size);
>  

[...]

> +
> +/**
> + * struct spi_mem_dirmap_desc - Direct mapping descriptor
> + * @mem: the SPI memory device this direct mapping is attached to
> + * @info: information passed at direct mapping creation time
> + * @nodirmap: set to true if the SPI controller does not implement
> + *	      ->mem_ops->dirmap_create() or when this function returned an

s/returned/returns/

> + *	      error. If dirmap is true, all spi_mem_dirmap_{read,write}()
> + *	      calls will use spi_mem_exec_op() to access the memory. This is a
> + *	      degraded mode that allows higher spi_mem drivers to use the same
> + *	      code no matter if the controller supports direct mapping or not
> + * @priv: field pointing to controller specific data
> + *
> + * Common part of a direct mapping descriptor. This object is created by
> + * spi_mem_dirmap_create() and controller implementation of ->create_dirmap()
> + * can create/attach direct mapping resources to the descriptor in the ->priv
> + * field.
> + */
> +struct spi_mem_dirmap_desc {
> +	struct spi_mem *mem;
> +	struct spi_mem_dirmap_info info;
> +	bool nodirmap;
> +	void *priv;
> +};
> +
>  /**
>   * struct spi_mem - describes a SPI memory device
>   * @spi: the underlying SPI device
> @@ -167,10 +210,24 @@ static inline void *spi_mem_get_drvdata(struct spi_mem *mem)
>   *		    limitations)
>   * @supports_op: check if an operation is supported by the controller
>   * @exec_op: execute a SPI memory operation
> + * @dirmap_create: create a direct mapping descriptor that can later be used to
> + *		   access the memory device. This method is optional

Only *dirmap_create() is marked as optional while all are.

> + * @dirmap_destroy: destroy a memory descriptor previous created by
> + *		    ->dirmap_create()

s/previous/previously/

> + * @dirmap_read: read data from the memory device using the direct mapping
> + *		 created by ->dirmap_create().
> + * @dirmap_write: write data to the memory device using the direct mapping
> + *		  created by ->dirmap_create().

I think there is a better kernel-doc way to reference dirmap_create(),
maybe with '@' (I don't remember exactly).

>   *
>   * This interface should be implemented by SPI controllers providing an
>   * high-level interface to execute SPI memory operation, which is usually the
>   * case for QSPI controllers.
> + *
> + * Note on ->dirmap_{read,write}(): drivers should avoid accessing the direct
> + * mapping from the CPU because doing that can stall the CPU waiting for the
> + * SPI mem transaction to finish, and this will make real-time maintainers
> + * unhappy and might make your system less reactive. Instead, drivers should
> + * use DMA to access this direct mapping.
>   */
>  struct spi_controller_mem_ops {
>  	int (*adjust_op_size)(struct spi_mem *mem, struct spi_mem_op *op);
> @@ -178,6 +235,12 @@ struct spi_controller_mem_ops {
>  			    const struct spi_mem_op *op);
>  	int (*exec_op)(struct spi_mem *mem,
>  		       const struct spi_mem_op *op);
> +	int (*dirmap_create)(struct spi_mem_dirmap_desc *desc);
> +	void (*dirmap_destroy)(struct spi_mem_dirmap_desc *desc);
> +	ssize_t (*dirmap_read)(struct spi_mem_dirmap_desc *desc,
> +			       u64 offs, size_t len, void *buf);
> +	ssize_t (*dirmap_write)(struct spi_mem_dirmap_desc *desc,
> +				u64 offs, size_t len, const void *buf);
>  };
>  
>  /**
> @@ -236,6 +299,15 @@ bool spi_mem_supports_op(struct spi_mem *mem,
>  int spi_mem_exec_op(struct spi_mem *mem,
>  		    const struct spi_mem_op *op);
>  
> +struct spi_mem_dirmap_desc *
> +spi_mem_dirmap_create(struct spi_mem *mem,
> +		      const struct spi_mem_dirmap_info *info);
> +void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc);
> +ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
> +			    u64 offs, size_t len, void *buf);
> +ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
> +			     u64 offs, size_t len, const void *buf);
> +
>  int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv,
>  				       struct module *owner);
>  

The rest is clear for me.

Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

  reply	other threads:[~2018-06-07 15:02 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-01 14:36 [RFC PATCH 0/2] spi: spi-mem: Add a direct mapping API Boris Brezillon
2018-06-01 14:36 ` Boris Brezillon
2018-06-01 14:36 ` [RFC PATCH 1/2] spi: spi-mem: Add a new API to support direct mapping Boris Brezillon
2018-06-01 14:36   ` Boris Brezillon
2018-06-07 15:01   ` Miquel Raynal [this message]
2018-06-07 15:01     ` Miquel Raynal
2018-06-07 15:16     ` Boris Brezillon
2018-06-07 15:16       ` Boris Brezillon
2018-06-01 14:36 ` [RFC PATCH 2/2] mtd: m25p80: Use the SPI mem direct API to possibly improve performances Boris Brezillon
2018-06-01 14:36   ` Boris Brezillon
2018-06-07 15:08   ` Miquel Raynal
2018-06-07 15:08     ` Miquel Raynal
2018-06-07 15:18     ` Boris Brezillon
2018-06-07 15:18       ` Boris Brezillon
2018-06-07 15:23       ` Miquel Raynal
2018-06-07 15:23         ` Miquel Raynal

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=20180607170153.757ca102@xps13 \
    --to=miquel.raynal@bootlin.com \
    --cc=boris.brezillon@bootlin.com \
    --cc=broonie@kernel.org \
    --cc=computersforpeace@gmail.com \
    --cc=cyrille.pitchen@microchip.com \
    --cc=dwmw2@infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux-spi@vger.kernel.org \
    --cc=marek.vasut@gmail.com \
    --cc=richard@nod.at \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=vigneshr@ti.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.