aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2008-02-06 04:38:13 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:10 -0500
commit8bacb219018a52e6f02a3cff6a7badf102ddfc44 (patch)
tree7e89a0346ce1694c32cf035c2badb2ff77db6a00 /drivers
parent154443c72f47169ebcb3a7befbff0e934c49bff3 (diff)
atmel_spi: fix dmachain oops with DEBUG enabled
In atmel_spi_next_xfer, xfer can be NULL because the next transfer may already have been submitted to the PDC (using DMA chaining). This can cause an oops, since the debug message assumed it was never null. The fix changes how those debug messages are issued, ensuring that one is issued each time a transfer is started instead of once per call. Also, properly indent the "can this transfer be chained" test so it's not hidden as if it were non-conditional code. Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/atmel_spi.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 545519a063b8..293b7cab3e57 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -198,6 +198,11 @@ static void atmel_spi_next_xfer(struct spi_master *master,
198 len >>= 1; 198 len >>= 1;
199 spi_writel(as, RCR, len); 199 spi_writel(as, RCR, len);
200 spi_writel(as, TCR, len); 200 spi_writel(as, TCR, len);
201
202 dev_dbg(&msg->spi->dev,
203 " start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
204 xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
205 xfer->rx_buf, xfer->rx_dma);
201 } else { 206 } else {
202 xfer = as->next_transfer; 207 xfer = as->next_transfer;
203 remaining = as->next_remaining_bytes; 208 remaining = as->next_remaining_bytes;
@@ -208,8 +213,8 @@ static void atmel_spi_next_xfer(struct spi_master *master,
208 213
209 if (remaining > 0) 214 if (remaining > 0)
210 len = remaining; 215 len = remaining;
211 else if (!atmel_spi_xfer_is_last(msg, xfer) && 216 else if (!atmel_spi_xfer_is_last(msg, xfer)
212 atmel_spi_xfer_can_be_chained(xfer)) { 217 && atmel_spi_xfer_can_be_chained(xfer)) {
213 xfer = list_entry(xfer->transfer_list.next, 218 xfer = list_entry(xfer->transfer_list.next,
214 struct spi_transfer, transfer_list); 219 struct spi_transfer, transfer_list);
215 len = xfer->len; 220 len = xfer->len;
@@ -230,6 +235,11 @@ static void atmel_spi_next_xfer(struct spi_master *master,
230 len >>= 1; 235 len >>= 1;
231 spi_writel(as, RNCR, len); 236 spi_writel(as, RNCR, len);
232 spi_writel(as, TNCR, len); 237 spi_writel(as, TNCR, len);
238
239 dev_dbg(&msg->spi->dev,
240 " next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
241 xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
242 xfer->rx_buf, xfer->rx_dma);
233 } else { 243 } else {
234 spi_writel(as, RNCR, 0); 244 spi_writel(as, RNCR, 0);
235 spi_writel(as, TNCR, 0); 245 spi_writel(as, TNCR, 0);
@@ -246,12 +256,6 @@ static void atmel_spi_next_xfer(struct spi_master *master,
246 * It should be doable, though. Just not now... 256 * It should be doable, though. Just not now...
247 */ 257 */
248 spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); 258 spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
249
250 dev_dbg(&msg->spi->dev,
251 " start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n",
252 xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
253 xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR));
254
255 spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); 259 spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
256} 260}
257 261