lkml.org 
[lkml]   [2005]   [Dec]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH/RFC] SPI: add DMAUNSAFE analog to David Brownell's core
Greetings,

this patch removes nasty buffer allocation in spi core for sync message transfers. (And thus solves the problem of possible priority inversion I've pointed out before).
The write_then_read function sets the flags singalling for buffers not being DMA-safe and it's absolutely up to the controller whatta do with that.
I. e. it will prolly allocate/copy if it performs DMA transfers or just don't do anything special if it's working in PIO. It can even use a single DMA-safe buffer as David's core did (although I wouldn't encourage anyone to do that! :))
This is of coure more flexible and also more optimal as it will *not* require _redundant_ memcpy's and semaphores protection in case of PIO transfers.
Please note that this is a key patch for us in some aspects, although it's rather small! :)

Signed-off-by: Vitaly Wool <vwool@ru.mvista.com>
Signed-off-by: Dmitry Pervushin <dpervushin@gmail.com>

drivers/spi/spi.c | 35 ++++++-----------------------------
include/linux/spi/spi.h | 7 +++++++
2 files changed, 13 insertions(+), 29 deletions(-)
Index: linux-2.6.orig/drivers/spi/spi.c
===================================================================
--- linux-2.6.orig.orig/drivers/spi/spi.c
+++ linux-2.6.orig/drivers/spi/spi.c
@@ -507,10 +507,6 @@ int spi_sync(struct spi_device *spi, str
}
EXPORT_SYMBOL_GPL(spi_sync);

-#define SPI_BUFSIZ (SMP_CACHE_BYTES)
-
-static u8 *buf;
-
/**
* spi_write_then_read - SPI synchronous write followed by read
* @spi: device with which data will be exchanged
@@ -532,39 +528,28 @@ int spi_write_then_read(struct spi_devic
const u8 *txbuf, unsigned n_tx,
u8 *rxbuf, unsigned n_rx)
{
- static DECLARE_MUTEX(lock);
-
int status;
struct spi_message message;
struct spi_transfer x[2];

- /* Use preallocated DMA-safe buffer. We can't avoid copying here,
- * (as a pure convenience thing), but we can keep heap costs
- * out of the hot path.
- */
- if ((n_tx + n_rx) > SPI_BUFSIZ)
- return -EINVAL;
-
- down(&lock);
memset(x, 0, sizeof x);
+ memset(&message, 0, sizeof message);

- memcpy(buf, txbuf, n_tx);
- x[0].tx_buf = buf;
+ x[0].tx_buf = tx_buf;
x[0].len = n_tx;
+ x[0].tx_dma_unsafe = 1;

- x[1].rx_buf = buf + n_tx;
+ x[1].rx_buf = rx_buf;
x[1].len = n_rx;
+ x[1].rx_dma_unsafe = 1;

/* do the i/o */
message.transfers = x;
message.n_transfer = ARRAY_SIZE(x);
status = spi_sync(spi, &message);
- if (status == 0) {
- memcpy(rxbuf, x[1].rx_buf, n_rx);
+ if (status == 0)
status = message.status;
- }

- up(&lock);
return status;
}
EXPORT_SYMBOL_GPL(spi_write_then_read);
@@ -575,12 +560,6 @@ static int __init spi_init(void)
{
int status;

- buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL);
- if (!buf) {
- status = -ENOMEM;
- goto err0;
- }
-
status = bus_register(&spi_bus_type);
if (status < 0)
goto err1;
@@ -593,9 +572,7 @@ static int __init spi_init(void)
err2:
bus_unregister(&spi_bus_type);
err1:
- kfree(buf);
buf = NULL;
-err0:
return status;
}

Index: linux-2.6.orig/include/linux/spi/spi.h
===================================================================
--- linux-2.6.orig.orig/include/linux/spi/spi.h
+++ linux-2.6.orig/include/linux/spi/spi.h
@@ -248,6 +248,10 @@ extern struct spi_master *spi_busnum_to_
* @rx_dma: DMA address of buffer, if spi_message.is_dma_mapped
* @len: size of rx and tx buffers (in bytes)
* @cs_change: affects chipselect after this transfer completes
+ * @tx_dma_unsafe: signals to controller driver that the buffer
+ * is not DMA-safe
+ * @rx_dma_unsafe: signals to controller driver that the buffer
+ * is not DMA-safe
* @delay_usecs: microseconds to delay after this transfer before
* (optionally) changing the chipselect status, then starting
* the next transfer or completing this spi_message.
@@ -288,6 +292,9 @@ struct spi_transfer {
dma_addr_t rx_dma;

unsigned cs_change:1;
+ unsigned rx_dma_unsafe:1;
+ unsigned tx_dma_unsafe:1;
+
u16 delay_usecs;
};

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-12-13 17:55    [from the cache]
©2003-2014 Jasper Spaans. Advertise on this site