Greetings,
the patch attached changes the way transfers are chained in the SPI
core. Namely, they are turned into linked lists instead of array. The
reason behind is that we'd like to be able to use lightweight memory
allocation mechanism to use it in interrupt context. An example of such
kind of mechanism can be found in spi-alloc.c file in our core. The
lightweightness is achieved by the knowledge that all the blocks to be
allocated are of the same size. We'd like to use this allocation
technique for both message structure and transfer structure The problem
with the current code is that transfers are represnted as an array so it
can be of any size effectively.
Vitaly
diff -uNr a/drivers/spi/spi.c b/drivers/spi/spi.c
--- a/drivers/spi/spi.c 2005-12-17 22:13:13.947792000 +0300
+++ b/drivers/spi/spi.c 2005-12-17 22:29:07.283863088 +0300
@@ -535,7 +535,9 @@
static DECLARE_MUTEX(lock);
int status;
- struct spi_message message;
+ struct spi_message message = {
+ .transfers = LIST_HEAD_INIT(message.transfers);
+ };
struct spi_transfer x[2];
/* Use preallocated DMA-safe buffer. We can't avoid copying here,
@@ -551,13 +553,13 @@
memcpy(buf, txbuf, n_tx);
x[0].tx_buf = buf;
x[0].len = n_tx;
+ list_add_tail(&x[0].link, &message.transfers);
x[1].rx_buf = buf + n_tx;
x[1].len = n_rx;
+ list_add_tail(&x[1].link, &message.transfers);
/* 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);
diff -uNr a/include/linux/spi/spi.h b/include/linux/spi/spi.h
--- a/include/linux/spi/spi.h 2005-12-17 22:13:13.957790000 +0300
+++ b/include/linux/spi/spi.h 2005-12-17 23:39:32.304562312 +0300
@@ -286,6 +286,8 @@
unsigned cs_change:1;
u16 delay_usecs;
+
+ struct list_head link;
};
/**
@@ -304,8 +306,7 @@
* @state: for use by whichever driver currently owns the message
*/
struct spi_message {
- struct spi_transfer *transfers;
- unsigned n_transfer;
+ struct list_head transfers;
struct spi_device *spi;
@@ -406,16 +407,16 @@
spi_write(struct spi_device *spi, const u8 *buf, size_t len)
{
struct spi_transfer t = {
- .tx_buf = buf,
- .rx_buf = NULL,
- .len = len,
- .cs_change = 0,
- };
+ .tx_buf = buf,
+ .rx_buf = NULL,
+ .len = len,
+ .cs_change = 0,
+ };
struct spi_message m = {
- .transfers = &t,
- .n_transfer = 1,
- };
+ .transfers = LIST_HEAD_INIT(m.transfers);
+ };
+ list_add_tail(&t.link, &m.transfers);
return spi_sync(spi, &m);
}
@@ -432,16 +433,16 @@
spi_read(struct spi_device *spi, u8 *buf, size_t len)
{
struct spi_transfer t = {
- .tx_buf = NULL,
- .rx_buf = buf,
- .len = len,
- .cs_change = 0,
- };
+ .tx_buf = NULL,
+ .rx_buf = buf,
+ .len = len,
+ .cs_change = 0,
+ };
struct spi_message m = {
- .transfers = &t,
- .n_transfer = 1,
- };
+ .transfers = LIST_HEAD_INIT(m.transfers);
+ };
+ list_add_tail(&t.link, &m.transfers);
return spi_sync(spi, &m);
}
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]