diff options
author | Martin Sperl <kernel@martin.sperl.org> | 2015-12-14 15:20:18 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-02-09 19:25:43 +0000 |
commit | d780c3711d9df9bacd56b71cf23443b895a331ca (patch) | |
tree | 4c6cf9ae8b0cd70fd6128a9bc2cec1ba1676dc47 /include/linux | |
parent | 92e963f50fc74041b5e9e744c330dca48e04f08d (diff) | |
download | op-kernel-dev-d780c3711d9df9bacd56b71cf23443b895a331ca.zip op-kernel-dev-d780c3711d9df9bacd56b71cf23443b895a331ca.tar.gz |
spi: core: added spi_resource management
SPI resource management framework used while processing a spi_message
via the spi-core.
The basic idea is taken from devres, but as the allocation may happen
fairly frequently, some provisioning (in the form of an unused spi_device
pointer argument to spi_res_alloc) has been made so that at a later stage
we may implement reuse objects allocated earlier avoiding the repeated
allocation by keeping a cache of objects that we can reuse.
This framework can get used for:
* rewriting spi_messages
* to fullfill alignment requirements of the spi_master HW
* to fullfill transfer length requirements
(e.g: transfers need to be less than 64k)
* consolidate spi_messages with multiple transfers into a single transfer
when the total transfer length is below a threshold.
* reimplement spi_unmap_buf without explicitly needing to check if it has
been mapped
Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/spi/spi.h | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 53be3a4..38204b5 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -582,6 +582,37 @@ extern void spi_unregister_master(struct spi_master *master); extern struct spi_master *spi_busnum_to_master(u16 busnum); +/* + * SPI resource management while processing a SPI message + */ + +/** + * struct spi_res - spi resource management structure + * @entry: list entry + * @release: release code called prior to freeing this resource + * @data: extra data allocated for the specific use-case + * + * this is based on ideas from devres, but focused on life-cycle + * management during spi_message processing + */ +typedef void (*spi_res_release_t)(struct spi_master *master, + struct spi_message *msg, + void *res); +struct spi_res { + struct list_head entry; + spi_res_release_t release; + unsigned long long data[]; /* guarantee ull alignment */ +}; + +extern void *spi_res_alloc(struct spi_device *spi, + spi_res_release_t release, + size_t size, gfp_t gfp); +extern void spi_res_add(struct spi_message *message, void *res); +extern void spi_res_free(void *res); + +extern void spi_res_release(struct spi_master *master, + struct spi_message *message); + /*---------------------------------------------------------------------------*/ /* @@ -720,6 +751,7 @@ struct spi_transfer { * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message + * @resources: for resource management when the spi message is processed * * A @spi_message is used to execute an atomic sequence of data transfers, * each represented by a struct spi_transfer. The sequence is "atomic" @@ -766,11 +798,15 @@ struct spi_message { */ struct list_head queue; void *state; + + /* list of spi_res reources when the spi message is processed */ + struct list_head resources; }; static inline void spi_message_init_no_memset(struct spi_message *m) { INIT_LIST_HEAD(&m->transfers); + INIT_LIST_HEAD(&m->resources); } static inline void spi_message_init(struct spi_message *m) |