aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNed Forrester <nforrester@whoi.edu>2008-09-13 05:33:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-09-13 17:41:52 -0400
commit7e96445533ac3f4f7964646a202ff3620602fab4 (patch)
tree8c8dfd18cb0447cabd834e2b68d209c2e870be24 /drivers
parent8423597d676615f3dd2d9ab36f59f147086b90b8 (diff)
pxa2xx_spi: dma bugfixes
Fixes two DMA bugs in the pxa2xx_spi driver. The first bug is in all versions of this driver; the second was introduced in the 2.6.20 kernel, and prevents using the driver with chips like m25p16 flash (which can issue large DMA reads). 1. Zero length transfers are permitted for use to insert timing, but pxa2xx_spi.c will fail if this is requested in DMA mode. Fixed by using programmed I/O (PIO) mode for such transfers. 2. Transfers larger than 8191 are not permitted in DMA mode. A test for length rejects all large transfers regardless of DMA or PIO mode. Worked around by rejecting only large transfers with DMA mapped buffers, and forcing all other transfers larger than 8191 to use PIO mode. A rate limited warning is issued for DMA transfers forced to PIO mode. This patch should apply to all kernels back to and including 2.6.20; it was test patched against 2.6.20. An additional patch would be required for older kernels, but those versions are very buggy anyway. Signed-off-by: Ned Forrester <nforrester@whoi.edu> Cc: Vernon Sauder <vernoninhand@gmail.com> Cc: Eric Miao <eric.y.miao@gmail.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: <stable@kernel.org> [2.6.25.x, 2.6.26.x] 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/pxa2xx_spi.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index a7b9070e1b46..0e53354c1cfe 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -47,9 +47,10 @@ MODULE_ALIAS("platform:pxa2xx-spi");
47 47
48#define MAX_BUSES 3 48#define MAX_BUSES 3
49 49
50#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) 50#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
51#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) 51#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
52#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) 52#define IS_DMA_ALIGNED(x) (((x) & 0x07) == 0)
53#define MAX_DMA_LEN 8191
53 54
54/* 55/*
55 * for testing SSCR1 changes that require SSP restart, basically 56 * for testing SSCR1 changes that require SSP restart, basically
@@ -887,14 +888,27 @@ static void pump_transfers(unsigned long data)
887 drv_data->cs_control(PXA2XX_CS_DEASSERT); 888 drv_data->cs_control(PXA2XX_CS_DEASSERT);
888 } 889 }
889 890
890 /* Check transfer length */ 891 /* Check for transfers that need multiple DMA segments */
891 if (transfer->len > 8191) 892 if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
892 { 893
893 dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer " 894 /* reject already-mapped transfers; PIO won't always work */
894 "length greater than 8191\n"); 895 if (message->is_dma_mapped
895 message->status = -EINVAL; 896 || transfer->rx_dma || transfer->tx_dma) {
896 giveback(drv_data); 897 dev_err(&drv_data->pdev->dev,
897 return; 898 "pump_transfers: mapped transfer length "
899 "of %lu is greater than %d\n",
900 transfer->len, MAX_DMA_LEN);
901 message->status = -EINVAL;
902 giveback(drv_data);
903 return;
904 }
905
906 /* warn ... we force this to PIO mode */
907 if (printk_ratelimit())
908 dev_warn(&message->spi->dev, "pump_transfers: "
909 "DMA disabled for transfer length %ld "
910 "greater than %d\n",
911 (long)drv_data->len, MAX_DMA_LEN);
898 } 912 }
899 913
900 /* Setup the transfer state based on the type of transfer */ 914 /* Setup the transfer state based on the type of transfer */
@@ -962,7 +976,7 @@ static void pump_transfers(unsigned long data)
962 &dma_thresh)) 976 &dma_thresh))
963 if (printk_ratelimit()) 977 if (printk_ratelimit())
964 dev_warn(&message->spi->dev, 978 dev_warn(&message->spi->dev,
965 "pump_transfer: " 979 "pump_transfers: "
966 "DMA burst size reduced to " 980 "DMA burst size reduced to "
967 "match bits_per_word\n"); 981 "match bits_per_word\n");
968 } 982 }
@@ -976,8 +990,23 @@ static void pump_transfers(unsigned long data)
976 990
977 message->state = RUNNING_STATE; 991 message->state = RUNNING_STATE;
978 992
979 /* Try to map dma buffer and do a dma transfer if successful */ 993 /* Try to map dma buffer and do a dma transfer if successful, but
980 if ((drv_data->dma_mapped = map_dma_buffers(drv_data))) { 994 * only if the length is non-zero and less than MAX_DMA_LEN.
995 *
996 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
997 * of PIO instead. Care is needed above because the transfer may
998 * have have been passed with buffers that are already dma mapped.
999 * A zero-length transfer in PIO mode will not try to write/read
1000 * to/from the buffers
1001 *
1002 * REVISIT large transfers are exactly where we most want to be
1003 * using DMA. If this happens much, split those transfers into
1004 * multiple DMA segments rather than forcing PIO.
1005 */
1006 drv_data->dma_mapped = 0;
1007 if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
1008 drv_data->dma_mapped = map_dma_buffers(drv_data);
1009 if (drv_data->dma_mapped) {
981 1010
982 /* Ensure we have the correct interrupt handler */ 1011 /* Ensure we have the correct interrupt handler */
983 drv_data->transfer_handler = dma_transfer; 1012 drv_data->transfer_handler = dma_transfer;