* [RFC 1/4] spi: reenable sync SPI transfers
[not found] ` <1410705908-20847-1-git-send-email-jepler-ixP+gI44yfQ4d9/VWYMlNA@public.gmane.org>
@ 2014-09-14 14:45 ` Jeff Epler
[not found] ` <1410705908-20847-2-git-send-email-jepler-ixP+gI44yfQ4d9/VWYMlNA@public.gmane.org>
2014-09-14 14:45 ` [RFC 2/4] spidev: Avoid runtime memory allocations Jeff Epler
` (2 subsequent siblings)
3 siblings, 1 reply; 6+ messages in thread
From: Jeff Epler @ 2014-09-14 14:45 UTC (permalink / raw)
To: linux-u79uwXL29TY76Z2rM5mHXA, linux-spi-u79uwXL29TY76Z2rM5mHXA
one source of excess latency in hm2_spi / hal_spidev is latency due
to async transfers. Make the __spi_sync primitive actually synchronous,
rather than building on an asynchronous primitive.
---
drivers/spi/spi.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 19ee901..55404b5 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -664,10 +664,18 @@ void spi_finalize_current_message(struct spi_master *master)
struct spi_message *mesg;
unsigned long flags;
+ if(!master->cur_msg)
+ return;
+
spin_lock_irqsave(&master->queue_lock, flags);
mesg = master->cur_msg;
master->cur_msg = NULL;
+ if(!mesg) {
+ spin_unlock_irqrestore(&master->queue_lock, flags);
+ return;
+ }
+
queue_kthread_work(&master->kworker, &master->pump_messages);
spin_unlock_irqrestore(&master->queue_lock, flags);
@@ -1490,24 +1498,26 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
int bus_locked)
{
DECLARE_COMPLETION_ONSTACK(done);
- int status;
+ int status = 0;
struct spi_master *master = spi->master;
message->complete = spi_complete;
message->context = &done;
+ message->spi = spi;
if (!bus_locked)
mutex_lock(&master->bus_lock_mutex);
- status = spi_async_locked(spi, message);
+ if(master->prepare_transfer_hardware)
+ status = master->prepare_transfer_hardware(master);
+ if(status >= 0)
+ status = master->transfer_one_message(master, message);
+ if(status >= 0 && master->unprepare_transfer_hardware)
+ status = master->unprepare_transfer_hardware(master);
if (!bus_locked)
mutex_unlock(&master->bus_lock_mutex);
- if (status == 0) {
- wait_for_completion(&done);
- status = message->status;
- }
message->context = NULL;
return status;
}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC 2/4] spidev: Avoid runtime memory allocations
[not found] ` <1410705908-20847-1-git-send-email-jepler-ixP+gI44yfQ4d9/VWYMlNA@public.gmane.org>
2014-09-14 14:45 ` [RFC 1/4] spi: reenable sync SPI transfers Jeff Epler
@ 2014-09-14 14:45 ` Jeff Epler
2014-09-14 14:45 ` [RFC 3/4] spidev: actually use synchronous transfers Jeff Epler
2014-09-14 14:45 ` [RFC 4/4] spidev-s3c64xx: allocate dma channel at startup Jeff Epler
3 siblings, 0 replies; 6+ messages in thread
From: Jeff Epler @ 2014-09-14 14:45 UTC (permalink / raw)
To: linux-u79uwXL29TY76Z2rM5mHXA, linux-spi-u79uwXL29TY76Z2rM5mHXA
allocating bounce and k_xfers at every iteration was a source of
excess delays.
---
drivers/spi/spidev.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e0655d..dda7632 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -85,6 +85,8 @@ struct spidev_data {
struct mutex buf_lock;
unsigned users;
u8 *buffer;
+ struct spi_ioc_transfer *bounce;
+ struct spi_transfer *k_xfers;
};
static LIST_HEAD(device_list);
@@ -227,9 +229,9 @@ static int spidev_message(struct spidev_data *spidev,
int status = -EFAULT;
spi_message_init(&msg);
- k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
- if (k_xfers == NULL)
- return -ENOMEM;
+ if (n_xfers * sizeof(*k_tmp) > bufsiz)
+ return -ENOMEM;
+ k_xfers = spidev->k_xfers;
/* Construct spi_message, copying any tx data to bounce buffer.
* We walk the array of user-provided transfers, using each one
@@ -302,7 +304,6 @@ static int spidev_message(struct spidev_data *spidev,
status = total;
done:
- kfree(k_xfers);
return status;
}
@@ -451,8 +452,12 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (n_ioc == 0)
break;
+ if(tmp > bufsiz) {
+ retval = -EINVAL;
+ break;
+ }
/* copy into scratch area */
- ioc = kmalloc(tmp, GFP_KERNEL);
+ ioc = spidev->bounce;
if (!ioc) {
retval = -ENOMEM;
break;
@@ -465,7 +470,6 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
/* translate to spi_message, execute */
retval = spidev_message(spidev, ioc, n_ioc);
- kfree(ioc);
break;
}
@@ -504,6 +508,19 @@ static int spidev_open(struct inode *inode, struct file *filp)
dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
status = -ENOMEM;
}
+ spidev->bounce = kmalloc(bufsiz, GFP_KERNEL);
+ if (!spidev->bounce) {
+ dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
+ kfree(spidev->buffer);
+ status = -ENOMEM;
+ }
+ spidev->k_xfers = kmalloc(bufsiz, GFP_KERNEL);
+ if (!spidev->k_xfers) {
+ dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
+ kfree(spidev->buffer);
+ kfree(spidev->bounce);
+ status = -ENOMEM;
+ }
}
if (status == 0) {
spidev->users++;
@@ -534,6 +551,12 @@ static int spidev_release(struct inode *inode, struct file *filp)
kfree(spidev->buffer);
spidev->buffer = NULL;
+ kfree(spidev->bounce);
+ spidev->bounce = NULL;
+
+ kfree(spidev->k_xfers);
+ spidev->k_xfers = NULL;
+
/* ... after we unbound from the underlying device? */
spin_lock_irq(&spidev->spi_lock);
dofree = (spidev->spi == NULL);
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC 3/4] spidev: actually use synchronous transfers
[not found] ` <1410705908-20847-1-git-send-email-jepler-ixP+gI44yfQ4d9/VWYMlNA@public.gmane.org>
2014-09-14 14:45 ` [RFC 1/4] spi: reenable sync SPI transfers Jeff Epler
2014-09-14 14:45 ` [RFC 2/4] spidev: Avoid runtime memory allocations Jeff Epler
@ 2014-09-14 14:45 ` Jeff Epler
2014-09-14 14:45 ` [RFC 4/4] spidev-s3c64xx: allocate dma channel at startup Jeff Epler
3 siblings, 0 replies; 6+ messages in thread
From: Jeff Epler @ 2014-09-14 14:45 UTC (permalink / raw)
To: linux-u79uwXL29TY76Z2rM5mHXA, linux-spi-u79uwXL29TY76Z2rM5mHXA
this reduces a source of latency
---
drivers/spi/spidev.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index dda7632..6e37c59 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -120,15 +120,9 @@ spidev_sync(struct spidev_data *spidev, struct spi_message *message)
if (spidev->spi == NULL)
status = -ESHUTDOWN;
else
- status = spi_async(spidev->spi, message);
+ status = spi_sync(spidev->spi, message);
spin_unlock_irq(&spidev->spi_lock);
- if (status == 0) {
- wait_for_completion(&done);
- status = message->status;
- if (status == 0)
- status = message->actual_length;
- }
return status;
}
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC 4/4] spidev-s3c64xx: allocate dma channel at startup
[not found] ` <1410705908-20847-1-git-send-email-jepler-ixP+gI44yfQ4d9/VWYMlNA@public.gmane.org>
` (2 preceding siblings ...)
2014-09-14 14:45 ` [RFC 3/4] spidev: actually use synchronous transfers Jeff Epler
@ 2014-09-14 14:45 ` Jeff Epler
3 siblings, 0 replies; 6+ messages in thread
From: Jeff Epler @ 2014-09-14 14:45 UTC (permalink / raw)
To: linux-u79uwXL29TY76Z2rM5mHXA, linux-spi-u79uwXL29TY76Z2rM5mHXA
it appears that acquire_dma introduces intolerable delays; the system
is fine with the dma channnels allocated all the time.
---
drivers/spi/spi-s3c64xx.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 92de1b5..e6a46c9 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -797,10 +797,6 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
{
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
- /* Acquire DMA channels */
- while (!acquire_dma(sdd))
- msleep(10);
-
pm_runtime_get_sync(&sdd->pdev->dev);
return 0;
@@ -810,10 +806,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
{
struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
- /* Free DMA channels */
- sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
- sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
-
pm_runtime_put(&sdd->pdev->dev);
return 0;
@@ -1344,6 +1336,9 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
goto err7;
}
+ // cannot fail(?)
+ acquire_dma(sdd);
+
writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN |
S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN,
sdd->regs + S3C64XX_SPI_INT_EN);
@@ -1396,6 +1391,10 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
spi_unregister_master(master);
+ /* Free DMA channels */
+ sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
+ sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
+
writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
free_irq(platform_get_irq(pdev, 0), sdd);
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 6+ messages in thread