Skip to content

Commit

Permalink
[PATCH] spi: use linked lists rather than an array
Browse files Browse the repository at this point in the history
This makes the SPI core and its users access transfers in the SPI message
structure as linked list not as an array, as discussed on LKML.

From: David Brownell <dbrownell@users.sourceforge.net>

  Updates including doc, bugfixes to the list code, add
  spi_message_add_tail().  Plus, initialize things _before_ grabbing the
  locks in some cases (in case it grows more expensive).  This also merges
  some bitbang updates of mine that didn't yet make it into the mm tree.

Signed-off-by: Vitaly Wool <vwool@ru.mvista.com>
Signed-off-by: Dmitry Pervushin <dpervushin@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Vitaly Wool authored and Greg Kroah-Hartman committed Jan 14, 2006
1 parent 2f9f762 commit 8275c64
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 113 deletions.
12 changes: 8 additions & 4 deletions drivers/input/touchscreen/ads7846.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL);
int status;
int sample;
int i;

if (!req)
return -ENOMEM;

INIT_LIST_HEAD(&req->msg.transfers);

/* activate reference, so it has time to settle; */
req->xfer[0].tx_buf = &ref_on;
req->xfer[0].len = 1;
Expand Down Expand Up @@ -192,8 +195,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
/* group all the transfers together, so we can't interfere with
* reading touchscreen state; disable penirq while sampling
*/
req->msg.transfers = req->xfer;
req->msg.n_transfer = 6;
for (i = 0; i < 6; i++)
spi_message_add_tail(&req->xfer[i], &req->msg);

disable_irq(spi->irq);
status = spi_sync(spi, &req->msg);
Expand Down Expand Up @@ -398,6 +401,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
struct ads7846 *ts;
struct ads7846_platform_data *pdata = spi->dev.platform_data;
struct spi_transfer *x;
int i;

if (!spi->irq) {
dev_dbg(&spi->dev, "no IRQ?\n");
Expand Down Expand Up @@ -500,8 +504,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)

CS_CHANGE(x[-1]);

ts->msg.transfers = ts->xfer;
ts->msg.n_transfer = x - ts->xfer;
for (i = 0; i < x - ts->xfer; i++)
spi_message_add_tail(&ts->xfer[i], &ts->msg);
ts->msg.complete = ads7846_rx;
ts->msg.context = ts;

Expand Down
50 changes: 25 additions & 25 deletions drivers/mtd/devices/m25p80.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,21 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
if (from + len > flash->mtd.size)
return -EINVAL;

spi_message_init(&m);
memset(t, 0, (sizeof t));

t[0].tx_buf = flash->command;
t[0].len = sizeof(flash->command);
spi_message_add_tail(&t[0], &m);

t[1].rx_buf = buf;
t[1].len = len;
spi_message_add_tail(&t[1], &m);

/* Byte count starts at zero. */
if (retlen)
*retlen = 0;

down(&flash->lock);

/* Wait till previous write/erase is done. */
Expand All @@ -254,8 +269,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
return 1;
}

memset(t, 0, (sizeof t));

/* NOTE: OPCODE_FAST_READ (if available) is faster... */

/* Set up the write data buffer. */
Expand All @@ -264,19 +277,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
flash->command[2] = from >> 8;
flash->command[3] = from;

/* Byte count starts at zero. */
if (retlen)
*retlen = 0;

t[0].tx_buf = flash->command;
t[0].len = sizeof(flash->command);

t[1].rx_buf = buf;
t[1].len = len;

m.transfers = t;
m.n_transfer = 2;

spi_sync(flash->spi, &m);

*retlen = m.actual_length - sizeof(flash->command);
Expand Down Expand Up @@ -313,6 +313,16 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
if (to + len > flash->mtd.size)
return -EINVAL;

spi_message_init(&m);
memset(t, 0, (sizeof t));

t[0].tx_buf = flash->command;
t[0].len = sizeof(flash->command);
spi_message_add_tail(&t[0], &m);

t[1].tx_buf = buf;
spi_message_add_tail(&t[1], &m);

down(&flash->lock);

/* Wait until finished previous write command. */
Expand All @@ -321,26 +331,17 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,

write_enable(flash);

memset(t, 0, (sizeof t));

/* Set up the opcode in the write buffer. */
flash->command[0] = OPCODE_PP;
flash->command[1] = to >> 16;
flash->command[2] = to >> 8;
flash->command[3] = to;

t[0].tx_buf = flash->command;
t[0].len = sizeof(flash->command);

m.transfers = t;
m.n_transfer = 2;

/* what page do we start with? */
page_offset = to % FLASH_PAGESIZE;

/* do all the bytes fit onto one page? */
if (page_offset + len <= FLASH_PAGESIZE) {
t[1].tx_buf = buf;
t[1].len = len;

spi_sync(flash->spi, &m);
Expand All @@ -352,7 +353,6 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
/* the size of data remaining on the first page */
page_size = FLASH_PAGESIZE - page_offset;

t[1].tx_buf = buf;
t[1].len = page_size;
spi_sync(flash->spi, &m);

Expand Down
28 changes: 17 additions & 11 deletions drivers/mtd/devices/mtd_dataflash.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct dataflash *priv = (struct dataflash *)mtd->priv;
struct spi_device *spi = priv->spi;
struct spi_transfer x[1] = { { .tx_dma = 0, }, };
struct spi_transfer x = { .tx_dma = 0, };
struct spi_message msg;
unsigned blocksize = priv->page_size << 3;
u8 *command;
Expand All @@ -162,10 +162,11 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
|| (instr->addr % priv->page_size) != 0)
return -EINVAL;

x[0].tx_buf = command = priv->command;
x[0].len = 4;
msg.transfers = x;
msg.n_transfer = 1;
spi_message_init(&msg);

x.tx_buf = command = priv->command;
x.len = 4;
spi_message_add_tail(&x, &msg);

down(&priv->lock);
while (instr->len > 0) {
Expand Down Expand Up @@ -256,12 +257,15 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
command[0], command[1], command[2], command[3]);

spi_message_init(&msg);

x[0].tx_buf = command;
x[0].len = 8;
spi_message_add_tail(&x[0], &msg);

x[1].rx_buf = buf;
x[1].len = len;
msg.transfers = x;
msg.n_transfer = 2;
spi_message_add_tail(&x[1], &msg);

down(&priv->lock);

Expand Down Expand Up @@ -320,9 +324,11 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
if ((to + len) > mtd->size)
return -EINVAL;

spi_message_init(&msg);

x[0].tx_buf = command = priv->command;
x[0].len = 4;
msg.transfers = x;
spi_message_add_tail(&x[0], &msg);

pageaddr = ((unsigned)to / priv->page_size);
offset = ((unsigned)to % priv->page_size);
Expand Down Expand Up @@ -364,7 +370,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
command[0], command[1], command[2], command[3]);

msg.n_transfer = 1;
status = spi_sync(spi, &msg);
if (status < 0)
DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
Expand All @@ -385,14 +390,16 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,

x[1].tx_buf = writebuf;
x[1].len = writelen;
msg.n_transfer = 2;
spi_message_add_tail(x + 1, &msg);
status = spi_sync(spi, &msg);
spi_transfer_del(x + 1);
if (status < 0)
DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
spi->dev.bus_id, addr, writelen, status);

(void) dataflash_waitready(priv->spi);


#ifdef CONFIG_DATAFLASH_WRITE_VERIFY

/* (3) Compare to Buffer1 */
Expand All @@ -405,7 +412,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
command[0], command[1], command[2], command[3]);

msg.n_transfer = 1;
status = spi_sync(spi, &msg);
if (status < 0)
DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
Expand Down
18 changes: 11 additions & 7 deletions drivers/spi/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,17 @@ int spi_write_then_read(struct spi_device *spi,
if ((n_tx + n_rx) > SPI_BUFSIZ)
return -EINVAL;

spi_message_init(&message);
memset(x, 0, sizeof x);
if (n_tx) {
x[0].len = n_tx;
spi_message_add_tail(&x[0], &message);
}
if (n_rx) {
x[1].len = n_rx;
spi_message_add_tail(&x[1], &message);
}

/* ... unless someone else is using the pre-allocated buffer */
if (down_trylock(&lock)) {
local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
Expand All @@ -565,18 +576,11 @@ int spi_write_then_read(struct spi_device *spi,
} else
local_buf = buf;

memset(x, 0, sizeof x);

memcpy(local_buf, txbuf, n_tx);
x[0].tx_buf = local_buf;
x[0].len = n_tx;

x[1].rx_buf = local_buf + n_tx;
x[1].len = n_rx;

/* 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);
Expand Down
Loading

0 comments on commit 8275c64

Please sign in to comment.