Messages in this thread Patch in this message | | | From | David Brownell <> | Subject | [patch 2.6.15-rc5-mm2] SPI, priority inversion tweak | Date | Tue, 13 Dec 2005 10:28:49 -0800 |
| |
This is an updated version of the patch from Mark Underwood, handling the no-memory case better and using SLAB_KERNEL not SLAB_ATOMIC.
Please apply it on top of the current SPI code in the MM tree.
- Dave Update the SPI framework to remove a potential priority inversion case by reverting to kmalloc if the pre-allocated DMA-safe buffer isn't available.
From: Mark Underwood <basicmark@yahoo.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
--- g26.orig/drivers/spi/spi.c 2005-12-11 11:06:38.000000000 -0800 +++ g26/drivers/spi/spi.c 2005-12-13 09:56:22.000000000 -0800 @@ -541,22 +541,30 @@ int spi_write_then_read(struct spi_devic int status; struct spi_message message; struct spi_transfer x[2]; + u8 *local_buf; /* 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. + * out of the hot path ... */ if ((n_tx + n_rx) > SPI_BUFSIZ) return -EINVAL; - down(&lock); + /* ... unless someone else is using the pre-allocated buffer */ + if (down_trylock(&lock)) { + local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); + if (!local_buf) + return -ENOMEM; + } else + local_buf = buf; + memset(x, 0, sizeof x); - memcpy(buf, txbuf, n_tx); - x[0].tx_buf = buf; + memcpy(local_buf, txbuf, n_tx); + x[0].tx_buf = local_buf; x[0].len = n_tx; - x[1].rx_buf = buf + n_tx; + x[1].rx_buf = local_buf + n_tx; x[1].len = n_rx; /* do the i/o */ @@ -568,7 +576,11 @@ int spi_write_then_read(struct spi_devic status = message.status; } - up(&lock); + if (x[0].tx_buf == buf) + up(&lock); + else + kfree(local_buf); + return status; } EXPORT_SYMBOL_GPL(spi_write_then_read); | |