Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On Thu, Nov 05, 2015 at 05:59:36PM +0530, Vignesh R wrote: > On 11/04/2015 08:09 PM, Mark Brown wrote: > > It's a bit worrying that this doesn't sync with the message queue except > > via the mutex: this means that we might be out of order with respect to > > any asynchronous transfers that are happening on the device. I'm not > > sure that this is a practical problem, though there is some risk of > > unfair scheduling that would have to be under extreme load and it might > > make sense to prioritise reads anyway. > Since mmap interface is used only by mtd flash drivers and since almost > all mtd flash devices use synchronous transfers (spi_sync()), IMO, there > wont be out of order problem wrt mtd flashes. > But mmap read might delay transfers queued for non mtd flash devices. It > is difficult to wait for all transfers already queued to be pumped out > by __spi_pump_messages() and then do the mmap transfer. Do you have any > thoughts on how to sync with message queue? Like I say I think it probably doesn't matter. The main issue would be with other devices sharing the bus with a flash chip. signature.asc Description: PGP signature
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On 11/04/2015 08:09 PM, Mark Brown wrote: > On Tue, Nov 03, 2015 at 03:36:10PM +0530, Vignesh R wrote: > >> +} >> +mutex_lock(>mmap_lock_mutex); >> +ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, >> +read_opcode, addr_width, >> +dummy_bytes); >> +mutex_unlock(>mmap_lock_mutex); >> +if (master->auto_runtime_pm) >> +pm_runtime_put(master->dev.parent); > > It's a bit worrying that this doesn't sync with the message queue except > via the mutex: this means that we might be out of order with respect to > any asynchronous transfers that are happening on the device. I'm not > sure that this is a practical problem, though there is some risk of > unfair scheduling that would have to be under extreme load and it might > make sense to prioritise reads anyway. > Since mmap interface is used only by mtd flash drivers and since almost all mtd flash devices use synchronous transfers (spi_sync()), IMO, there wont be out of order problem wrt mtd flashes. But mmap read might delay transfers queued for non mtd flash devices. It is difficult to wait for all transfers already queued to be pumped out by __spi_pump_messages() and then do the mmap transfer. Do you have any thoughts on how to sync with message queue? -- Regards Vignesh -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On 11/04/2015 08:09 PM, Mark Brown wrote: > On Tue, Nov 03, 2015 at 03:36:10PM +0530, Vignesh R wrote: > >> +} >> +mutex_lock(>mmap_lock_mutex); >> +ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, >> +read_opcode, addr_width, >> +dummy_bytes); >> +mutex_unlock(>mmap_lock_mutex); >> +if (master->auto_runtime_pm) >> +pm_runtime_put(master->dev.parent); > > It's a bit worrying that this doesn't sync with the message queue except > via the mutex: this means that we might be out of order with respect to > any asynchronous transfers that are happening on the device. I'm not > sure that this is a practical problem, though there is some risk of > unfair scheduling that would have to be under extreme load and it might > make sense to prioritise reads anyway. > Since mmap interface is used only by mtd flash drivers and since almost all mtd flash devices use synchronous transfers (spi_sync()), IMO, there wont be out of order problem wrt mtd flashes. But mmap read might delay transfers queued for non mtd flash devices. It is difficult to wait for all transfers already queued to be pumped out by __spi_pump_messages() and then do the mmap transfer. Do you have any thoughts on how to sync with message queue? -- Regards Vignesh -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On Thu, Nov 05, 2015 at 05:59:36PM +0530, Vignesh R wrote: > On 11/04/2015 08:09 PM, Mark Brown wrote: > > It's a bit worrying that this doesn't sync with the message queue except > > via the mutex: this means that we might be out of order with respect to > > any asynchronous transfers that are happening on the device. I'm not > > sure that this is a practical problem, though there is some risk of > > unfair scheduling that would have to be under extreme load and it might > > make sense to prioritise reads anyway. > Since mmap interface is used only by mtd flash drivers and since almost > all mtd flash devices use synchronous transfers (spi_sync()), IMO, there > wont be out of order problem wrt mtd flashes. > But mmap read might delay transfers queued for non mtd flash devices. It > is difficult to wait for all transfers already queued to be pumped out > by __spi_pump_messages() and then do the mmap transfer. Do you have any > thoughts on how to sync with message queue? Like I say I think it probably doesn't matter. The main issue would be with other devices sharing the bus with a flash chip. signature.asc Description: PGP signature
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On Tue, Nov 03, 2015 at 03:36:10PM +0530, Vignesh R wrote: > + } > + mutex_lock(>mmap_lock_mutex); > + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, > + read_opcode, addr_width, > + dummy_bytes); > + mutex_unlock(>mmap_lock_mutex); > + if (master->auto_runtime_pm) > + pm_runtime_put(master->dev.parent); It's a bit worrying that this doesn't sync with the message queue except via the mutex: this means that we might be out of order with respect to any asynchronous transfers that are happening on the device. I'm not sure that this is a practical problem, though there is some risk of unfair scheduling that would have to be under extreme load and it might make sense to prioritise reads anyway. signature.asc Description: PGP signature
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On Tue, Nov 03, 2015 at 03:36:10PM +0530, Vignesh R wrote: > + } > + mutex_lock(>mmap_lock_mutex); > + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, > + read_opcode, addr_width, > + dummy_bytes); > + mutex_unlock(>mmap_lock_mutex); > + if (master->auto_runtime_pm) > + pm_runtime_put(master->dev.parent); It's a bit worrying that this doesn't sync with the message queue except via the mutex: this means that we might be out of order with respect to any asynchronous transfers that are happening on the device. I'm not sure that this is a practical problem, though there is some risk of unfair scheduling that would have to be under extreme load and it might make sense to prioritise reads anyway. signature.asc Description: PGP signature
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
Hi, On 11/03/2015 04:49 PM, Michal Suchanek wrote: > On 3 November 2015 at 11:06, Vignesh R wrote: >> In addition to providing direct access to SPI bus, some spi controller >> hardwares (like ti-qspi) provide special memory mapped port >> to accesses SPI flash devices in order to increase read performance. >> This means the controller can automatically send the SPI signals >> required to read data from the SPI flash device. >> For this, spi controller needs to know flash specific information like >> read command to use, dummy bytes and address width. Once these settings >> are populated in hardware registers, any read accesses to flash's memory >> map region(SoC specific) through memcpy (or mem-to mem DMA copy) will be >> handled by controller hardware. The hardware will automatically generate >> SPI signals required to read data from flash and present it to CPU/DMA. >> >> Introduce spi_mtd_mmap_read() interface to support memory mapped read >> over SPI flash devices. SPI master drivers can implement this callback to >> support memory mapped read interfaces. m25p80 flash driver and other >> flash drivers can call this to request memory mapped read. The interface >> should only be used MTD flashes and cannot be used with other SPI devices. >> >> Signed-off-by: Vignesh R >> --- >> drivers/spi/spi.c | 35 +++ >> include/linux/spi/spi.h | 23 +++ >> 2 files changed, 58 insertions(+) >> >> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c >> index a5f53de813d3..5a5c7a7d47f2 100644 >> --- a/drivers/spi/spi.c >> +++ b/drivers/spi/spi.c >> @@ -1059,6 +1059,7 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> } >> } >> >> + mutex_lock(>mmap_lock_mutex); >> trace_spi_message_start(master->cur_msg); >> >> if (master->prepare_message) { >> @@ -1068,6 +1069,7 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> "failed to prepare message: %d\n", ret); >> master->cur_msg->status = ret; >> spi_finalize_current_message(master); >> + mutex_unlock(>mmap_lock_mutex); >> return; >> } >> master->cur_msg_prepared = true; >> @@ -1077,6 +1079,7 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> if (ret) { >> master->cur_msg->status = ret; >> spi_finalize_current_message(master); >> + mutex_unlock(>mmap_lock_mutex); >> return; >> } >> >> @@ -1084,8 +1087,10 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> if (ret) { >> dev_err(>dev, >> "failed to transfer one message from queue\n"); >> + mutex_unlock(>mmap_lock_mutex); >> return; >> } >> + mutex_unlock(>mmap_lock_mutex); >> } >> >> /** >> @@ -1732,6 +1737,7 @@ int spi_register_master(struct spi_master *master) >> spin_lock_init(>queue_lock); >> spin_lock_init(>bus_lock_spinlock); >> mutex_init(>bus_lock_mutex); >> + mutex_init(>mmap_lock_mutex); >> master->bus_lock_flag = 0; >> init_completion(>xfer_completion); >> if (!master->max_dma_len) >> @@ -2237,6 +2243,35 @@ int spi_async_locked(struct spi_device *spi, struct >> spi_message *message) >> EXPORT_SYMBOL_GPL(spi_async_locked); >> >> >> +int spi_mtd_mmap_read(struct spi_device *spi, loff_t from, size_t len, >> + size_t *retlen, u_char *buf, u8 read_opcode, >> + u8 addr_width, u8 dummy_bytes) >> + >> +{ >> + struct spi_master *master = spi->master; >> + int ret; >> + >> + if (master->auto_runtime_pm) { >> + ret = pm_runtime_get_sync(master->dev.parent); >> + if (ret < 0) { >> + dev_err(>dev, "Failed to power device: %d\n", >> + ret); >> + goto err; >> + } >> + } >> + mutex_lock(>mmap_lock_mutex); >> + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, >> + read_opcode, addr_width, >> + dummy_bytes); >> + mutex_unlock(>mmap_lock_mutex); >> + if (master->auto_runtime_pm) >> + pm_runtime_put(master->dev.parent); >> + >> +err: >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(spi_mtd_mmap_read); >> + >> >> /*-*/ >> >> /* Utility methods for SPI master protocol drivers, layered on >> diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h >> index 6b00f18f5e6b..0a6d8ad57357 100644 >> --- a/include/linux/spi/spi.h >> +++
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On 3 November 2015 at 11:06, Vignesh R wrote: > In addition to providing direct access to SPI bus, some spi controller > hardwares (like ti-qspi) provide special memory mapped port > to accesses SPI flash devices in order to increase read performance. > This means the controller can automatically send the SPI signals > required to read data from the SPI flash device. > For this, spi controller needs to know flash specific information like > read command to use, dummy bytes and address width. Once these settings > are populated in hardware registers, any read accesses to flash's memory > map region(SoC specific) through memcpy (or mem-to mem DMA copy) will be > handled by controller hardware. The hardware will automatically generate > SPI signals required to read data from flash and present it to CPU/DMA. > > Introduce spi_mtd_mmap_read() interface to support memory mapped read > over SPI flash devices. SPI master drivers can implement this callback to > support memory mapped read interfaces. m25p80 flash driver and other > flash drivers can call this to request memory mapped read. The interface > should only be used MTD flashes and cannot be used with other SPI devices. > > Signed-off-by: Vignesh R > --- > drivers/spi/spi.c | 35 +++ > include/linux/spi/spi.h | 23 +++ > 2 files changed, 58 insertions(+) > > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c > index a5f53de813d3..5a5c7a7d47f2 100644 > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -1059,6 +1059,7 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > } > } > > + mutex_lock(>mmap_lock_mutex); > trace_spi_message_start(master->cur_msg); > > if (master->prepare_message) { > @@ -1068,6 +1069,7 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > "failed to prepare message: %d\n", ret); > master->cur_msg->status = ret; > spi_finalize_current_message(master); > + mutex_unlock(>mmap_lock_mutex); > return; > } > master->cur_msg_prepared = true; > @@ -1077,6 +1079,7 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > if (ret) { > master->cur_msg->status = ret; > spi_finalize_current_message(master); > + mutex_unlock(>mmap_lock_mutex); > return; > } > > @@ -1084,8 +1087,10 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > if (ret) { > dev_err(>dev, > "failed to transfer one message from queue\n"); > + mutex_unlock(>mmap_lock_mutex); > return; > } > + mutex_unlock(>mmap_lock_mutex); > } > > /** > @@ -1732,6 +1737,7 @@ int spi_register_master(struct spi_master *master) > spin_lock_init(>queue_lock); > spin_lock_init(>bus_lock_spinlock); > mutex_init(>bus_lock_mutex); > + mutex_init(>mmap_lock_mutex); > master->bus_lock_flag = 0; > init_completion(>xfer_completion); > if (!master->max_dma_len) > @@ -2237,6 +2243,35 @@ int spi_async_locked(struct spi_device *spi, struct > spi_message *message) > EXPORT_SYMBOL_GPL(spi_async_locked); > > > +int spi_mtd_mmap_read(struct spi_device *spi, loff_t from, size_t len, > + size_t *retlen, u_char *buf, u8 read_opcode, > + u8 addr_width, u8 dummy_bytes) > + > +{ > + struct spi_master *master = spi->master; > + int ret; > + > + if (master->auto_runtime_pm) { > + ret = pm_runtime_get_sync(master->dev.parent); > + if (ret < 0) { > + dev_err(>dev, "Failed to power device: %d\n", > + ret); > + goto err; > + } > + } > + mutex_lock(>mmap_lock_mutex); > + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, > + read_opcode, addr_width, > + dummy_bytes); > + mutex_unlock(>mmap_lock_mutex); > + if (master->auto_runtime_pm) > + pm_runtime_put(master->dev.parent); > + > +err: > + return ret; > +} > +EXPORT_SYMBOL_GPL(spi_mtd_mmap_read); > + > /*-*/ > > /* Utility methods for SPI master protocol drivers, layered on > diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h > index 6b00f18f5e6b..0a6d8ad57357 100644 > --- a/include/linux/spi/spi.h > +++ b/include/linux/spi/spi.h > @@ -297,6 +297,7 @@ static inline void spi_unregister_driver(struct > spi_driver *sdrv) > * @flags: other constraints relevant to this driver > *
[PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
In addition to providing direct access to SPI bus, some spi controller hardwares (like ti-qspi) provide special memory mapped port to accesses SPI flash devices in order to increase read performance. This means the controller can automatically send the SPI signals required to read data from the SPI flash device. For this, spi controller needs to know flash specific information like read command to use, dummy bytes and address width. Once these settings are populated in hardware registers, any read accesses to flash's memory map region(SoC specific) through memcpy (or mem-to mem DMA copy) will be handled by controller hardware. The hardware will automatically generate SPI signals required to read data from flash and present it to CPU/DMA. Introduce spi_mtd_mmap_read() interface to support memory mapped read over SPI flash devices. SPI master drivers can implement this callback to support memory mapped read interfaces. m25p80 flash driver and other flash drivers can call this to request memory mapped read. The interface should only be used MTD flashes and cannot be used with other SPI devices. Signed-off-by: Vignesh R --- drivers/spi/spi.c | 35 +++ include/linux/spi/spi.h | 23 +++ 2 files changed, 58 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a5f53de813d3..5a5c7a7d47f2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1059,6 +1059,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) } } + mutex_lock(>mmap_lock_mutex); trace_spi_message_start(master->cur_msg); if (master->prepare_message) { @@ -1068,6 +1069,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) "failed to prepare message: %d\n", ret); master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(>mmap_lock_mutex); return; } master->cur_msg_prepared = true; @@ -1077,6 +1079,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(>mmap_lock_mutex); return; } @@ -1084,8 +1087,10 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { dev_err(>dev, "failed to transfer one message from queue\n"); + mutex_unlock(>mmap_lock_mutex); return; } + mutex_unlock(>mmap_lock_mutex); } /** @@ -1732,6 +1737,7 @@ int spi_register_master(struct spi_master *master) spin_lock_init(>queue_lock); spin_lock_init(>bus_lock_spinlock); mutex_init(>bus_lock_mutex); + mutex_init(>mmap_lock_mutex); master->bus_lock_flag = 0; init_completion(>xfer_completion); if (!master->max_dma_len) @@ -2237,6 +2243,35 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) EXPORT_SYMBOL_GPL(spi_async_locked); +int spi_mtd_mmap_read(struct spi_device *spi, loff_t from, size_t len, + size_t *retlen, u_char *buf, u8 read_opcode, + u8 addr_width, u8 dummy_bytes) + +{ + struct spi_master *master = spi->master; + int ret; + + if (master->auto_runtime_pm) { + ret = pm_runtime_get_sync(master->dev.parent); + if (ret < 0) { + dev_err(>dev, "Failed to power device: %d\n", + ret); + goto err; + } + } + mutex_lock(>mmap_lock_mutex); + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, + read_opcode, addr_width, + dummy_bytes); + mutex_unlock(>mmap_lock_mutex); + if (master->auto_runtime_pm) + pm_runtime_put(master->dev.parent); + +err: + return ret; +} +EXPORT_SYMBOL_GPL(spi_mtd_mmap_read); + /*-*/ /* Utility methods for SPI master protocol drivers, layered on diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6b00f18f5e6b..0a6d8ad57357 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -297,6 +297,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @flags: other constraints relevant to this driver * @bus_lock_spinlock: spinlock for SPI bus locking * @bus_lock_mutex: mutex for SPI bus locking + * @mmap_lock_mutex: mutex for locking SPI bus when mmap transfer is on. * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use * @setup: updates the device
[PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
In addition to providing direct access to SPI bus, some spi controller hardwares (like ti-qspi) provide special memory mapped port to accesses SPI flash devices in order to increase read performance. This means the controller can automatically send the SPI signals required to read data from the SPI flash device. For this, spi controller needs to know flash specific information like read command to use, dummy bytes and address width. Once these settings are populated in hardware registers, any read accesses to flash's memory map region(SoC specific) through memcpy (or mem-to mem DMA copy) will be handled by controller hardware. The hardware will automatically generate SPI signals required to read data from flash and present it to CPU/DMA. Introduce spi_mtd_mmap_read() interface to support memory mapped read over SPI flash devices. SPI master drivers can implement this callback to support memory mapped read interfaces. m25p80 flash driver and other flash drivers can call this to request memory mapped read. The interface should only be used MTD flashes and cannot be used with other SPI devices. Signed-off-by: Vignesh R--- drivers/spi/spi.c | 35 +++ include/linux/spi/spi.h | 23 +++ 2 files changed, 58 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a5f53de813d3..5a5c7a7d47f2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1059,6 +1059,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) } } + mutex_lock(>mmap_lock_mutex); trace_spi_message_start(master->cur_msg); if (master->prepare_message) { @@ -1068,6 +1069,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) "failed to prepare message: %d\n", ret); master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(>mmap_lock_mutex); return; } master->cur_msg_prepared = true; @@ -1077,6 +1079,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(>mmap_lock_mutex); return; } @@ -1084,8 +1087,10 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { dev_err(>dev, "failed to transfer one message from queue\n"); + mutex_unlock(>mmap_lock_mutex); return; } + mutex_unlock(>mmap_lock_mutex); } /** @@ -1732,6 +1737,7 @@ int spi_register_master(struct spi_master *master) spin_lock_init(>queue_lock); spin_lock_init(>bus_lock_spinlock); mutex_init(>bus_lock_mutex); + mutex_init(>mmap_lock_mutex); master->bus_lock_flag = 0; init_completion(>xfer_completion); if (!master->max_dma_len) @@ -2237,6 +2243,35 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) EXPORT_SYMBOL_GPL(spi_async_locked); +int spi_mtd_mmap_read(struct spi_device *spi, loff_t from, size_t len, + size_t *retlen, u_char *buf, u8 read_opcode, + u8 addr_width, u8 dummy_bytes) + +{ + struct spi_master *master = spi->master; + int ret; + + if (master->auto_runtime_pm) { + ret = pm_runtime_get_sync(master->dev.parent); + if (ret < 0) { + dev_err(>dev, "Failed to power device: %d\n", + ret); + goto err; + } + } + mutex_lock(>mmap_lock_mutex); + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, + read_opcode, addr_width, + dummy_bytes); + mutex_unlock(>mmap_lock_mutex); + if (master->auto_runtime_pm) + pm_runtime_put(master->dev.parent); + +err: + return ret; +} +EXPORT_SYMBOL_GPL(spi_mtd_mmap_read); + /*-*/ /* Utility methods for SPI master protocol drivers, layered on diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6b00f18f5e6b..0a6d8ad57357 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -297,6 +297,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @flags: other constraints relevant to this driver * @bus_lock_spinlock: spinlock for SPI bus locking * @bus_lock_mutex: mutex for SPI bus locking + * @mmap_lock_mutex: mutex for locking SPI bus when mmap transfer is on. * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use * @setup:
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
On 3 November 2015 at 11:06, Vignesh Rwrote: > In addition to providing direct access to SPI bus, some spi controller > hardwares (like ti-qspi) provide special memory mapped port > to accesses SPI flash devices in order to increase read performance. > This means the controller can automatically send the SPI signals > required to read data from the SPI flash device. > For this, spi controller needs to know flash specific information like > read command to use, dummy bytes and address width. Once these settings > are populated in hardware registers, any read accesses to flash's memory > map region(SoC specific) through memcpy (or mem-to mem DMA copy) will be > handled by controller hardware. The hardware will automatically generate > SPI signals required to read data from flash and present it to CPU/DMA. > > Introduce spi_mtd_mmap_read() interface to support memory mapped read > over SPI flash devices. SPI master drivers can implement this callback to > support memory mapped read interfaces. m25p80 flash driver and other > flash drivers can call this to request memory mapped read. The interface > should only be used MTD flashes and cannot be used with other SPI devices. > > Signed-off-by: Vignesh R > --- > drivers/spi/spi.c | 35 +++ > include/linux/spi/spi.h | 23 +++ > 2 files changed, 58 insertions(+) > > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c > index a5f53de813d3..5a5c7a7d47f2 100644 > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -1059,6 +1059,7 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > } > } > > + mutex_lock(>mmap_lock_mutex); > trace_spi_message_start(master->cur_msg); > > if (master->prepare_message) { > @@ -1068,6 +1069,7 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > "failed to prepare message: %d\n", ret); > master->cur_msg->status = ret; > spi_finalize_current_message(master); > + mutex_unlock(>mmap_lock_mutex); > return; > } > master->cur_msg_prepared = true; > @@ -1077,6 +1079,7 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > if (ret) { > master->cur_msg->status = ret; > spi_finalize_current_message(master); > + mutex_unlock(>mmap_lock_mutex); > return; > } > > @@ -1084,8 +1087,10 @@ static void __spi_pump_messages(struct spi_master > *master, bool in_kthread) > if (ret) { > dev_err(>dev, > "failed to transfer one message from queue\n"); > + mutex_unlock(>mmap_lock_mutex); > return; > } > + mutex_unlock(>mmap_lock_mutex); > } > > /** > @@ -1732,6 +1737,7 @@ int spi_register_master(struct spi_master *master) > spin_lock_init(>queue_lock); > spin_lock_init(>bus_lock_spinlock); > mutex_init(>bus_lock_mutex); > + mutex_init(>mmap_lock_mutex); > master->bus_lock_flag = 0; > init_completion(>xfer_completion); > if (!master->max_dma_len) > @@ -2237,6 +2243,35 @@ int spi_async_locked(struct spi_device *spi, struct > spi_message *message) > EXPORT_SYMBOL_GPL(spi_async_locked); > > > +int spi_mtd_mmap_read(struct spi_device *spi, loff_t from, size_t len, > + size_t *retlen, u_char *buf, u8 read_opcode, > + u8 addr_width, u8 dummy_bytes) > + > +{ > + struct spi_master *master = spi->master; > + int ret; > + > + if (master->auto_runtime_pm) { > + ret = pm_runtime_get_sync(master->dev.parent); > + if (ret < 0) { > + dev_err(>dev, "Failed to power device: %d\n", > + ret); > + goto err; > + } > + } > + mutex_lock(>mmap_lock_mutex); > + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, > + read_opcode, addr_width, > + dummy_bytes); > + mutex_unlock(>mmap_lock_mutex); > + if (master->auto_runtime_pm) > + pm_runtime_put(master->dev.parent); > + > +err: > + return ret; > +} > +EXPORT_SYMBOL_GPL(spi_mtd_mmap_read); > + > /*-*/ > > /* Utility methods for SPI master protocol drivers, layered on > diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h > index 6b00f18f5e6b..0a6d8ad57357 100644 > --- a/include/linux/spi/spi.h > +++ b/include/linux/spi/spi.h > @@ -297,6 +297,7 @@ static inline void spi_unregister_driver(struct > spi_driver *sdrv) > * @flags: other constraints
Re: [PATCH v2 1/5] spi: introduce mmap read support for spi flash devices
Hi, On 11/03/2015 04:49 PM, Michal Suchanek wrote: > On 3 November 2015 at 11:06, Vignesh Rwrote: >> In addition to providing direct access to SPI bus, some spi controller >> hardwares (like ti-qspi) provide special memory mapped port >> to accesses SPI flash devices in order to increase read performance. >> This means the controller can automatically send the SPI signals >> required to read data from the SPI flash device. >> For this, spi controller needs to know flash specific information like >> read command to use, dummy bytes and address width. Once these settings >> are populated in hardware registers, any read accesses to flash's memory >> map region(SoC specific) through memcpy (or mem-to mem DMA copy) will be >> handled by controller hardware. The hardware will automatically generate >> SPI signals required to read data from flash and present it to CPU/DMA. >> >> Introduce spi_mtd_mmap_read() interface to support memory mapped read >> over SPI flash devices. SPI master drivers can implement this callback to >> support memory mapped read interfaces. m25p80 flash driver and other >> flash drivers can call this to request memory mapped read. The interface >> should only be used MTD flashes and cannot be used with other SPI devices. >> >> Signed-off-by: Vignesh R >> --- >> drivers/spi/spi.c | 35 +++ >> include/linux/spi/spi.h | 23 +++ >> 2 files changed, 58 insertions(+) >> >> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c >> index a5f53de813d3..5a5c7a7d47f2 100644 >> --- a/drivers/spi/spi.c >> +++ b/drivers/spi/spi.c >> @@ -1059,6 +1059,7 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> } >> } >> >> + mutex_lock(>mmap_lock_mutex); >> trace_spi_message_start(master->cur_msg); >> >> if (master->prepare_message) { >> @@ -1068,6 +1069,7 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> "failed to prepare message: %d\n", ret); >> master->cur_msg->status = ret; >> spi_finalize_current_message(master); >> + mutex_unlock(>mmap_lock_mutex); >> return; >> } >> master->cur_msg_prepared = true; >> @@ -1077,6 +1079,7 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> if (ret) { >> master->cur_msg->status = ret; >> spi_finalize_current_message(master); >> + mutex_unlock(>mmap_lock_mutex); >> return; >> } >> >> @@ -1084,8 +1087,10 @@ static void __spi_pump_messages(struct spi_master >> *master, bool in_kthread) >> if (ret) { >> dev_err(>dev, >> "failed to transfer one message from queue\n"); >> + mutex_unlock(>mmap_lock_mutex); >> return; >> } >> + mutex_unlock(>mmap_lock_mutex); >> } >> >> /** >> @@ -1732,6 +1737,7 @@ int spi_register_master(struct spi_master *master) >> spin_lock_init(>queue_lock); >> spin_lock_init(>bus_lock_spinlock); >> mutex_init(>bus_lock_mutex); >> + mutex_init(>mmap_lock_mutex); >> master->bus_lock_flag = 0; >> init_completion(>xfer_completion); >> if (!master->max_dma_len) >> @@ -2237,6 +2243,35 @@ int spi_async_locked(struct spi_device *spi, struct >> spi_message *message) >> EXPORT_SYMBOL_GPL(spi_async_locked); >> >> >> +int spi_mtd_mmap_read(struct spi_device *spi, loff_t from, size_t len, >> + size_t *retlen, u_char *buf, u8 read_opcode, >> + u8 addr_width, u8 dummy_bytes) >> + >> +{ >> + struct spi_master *master = spi->master; >> + int ret; >> + >> + if (master->auto_runtime_pm) { >> + ret = pm_runtime_get_sync(master->dev.parent); >> + if (ret < 0) { >> + dev_err(>dev, "Failed to power device: %d\n", >> + ret); >> + goto err; >> + } >> + } >> + mutex_lock(>mmap_lock_mutex); >> + ret = master->spi_mtd_mmap_read(spi, from, len, retlen, buf, >> + read_opcode, addr_width, >> + dummy_bytes); >> + mutex_unlock(>mmap_lock_mutex); >> + if (master->auto_runtime_pm) >> + pm_runtime_put(master->dev.parent); >> + >> +err: >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(spi_mtd_mmap_read); >> + >> >> /*-*/ >> >> /* Utility methods for SPI master protocol drivers, layered on >> diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h >> index 6b00f18f5e6b..0a6d8ad57357 100644 >> ---