aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-10-09 18:18:12 -0400
committerMike Frysinger <vapier@gentoo.org>2009-12-15 00:14:18 -0500
commitd2e015d65fc692475b8513259d6afacd2cded8e8 (patch)
treee296f8daa8a7ba957d0ae080c71212f77172d382 /arch/blackfin/kernel
parentadfc046740b4161cbb1f0a3ea0d4200e21113489 (diff)
Blackfin: convert DMA mutex to an atomic and drop redundant code
The DMA channel status field was encoding redundant info wrt the DMA MMR config register, and it was doing an incomplete job of checking all DMA channels (some drivers write directly to the config register). So drop the tristate field in favor of a binary atomic field. This simplifies the code in general, removes the implicit need for sleeping, and forces the suspend code to handle all channels properly. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c31
1 files changed, 10 insertions, 21 deletions
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 3946aff4f414..639dcee5611c 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -37,9 +37,8 @@ static int __init blackfin_dma_init(void)
37 printk(KERN_INFO "Blackfin DMA Controller\n"); 37 printk(KERN_INFO "Blackfin DMA Controller\n");
38 38
39 for (i = 0; i < MAX_DMA_CHANNELS; i++) { 39 for (i = 0; i < MAX_DMA_CHANNELS; i++) {
40 dma_ch[i].chan_status = DMA_CHANNEL_FREE; 40 atomic_set(&dma_ch[i].chan_status, 0);
41 dma_ch[i].regs = dma_io_base_addr[i]; 41 dma_ch[i].regs = dma_io_base_addr[i];
42 mutex_init(&(dma_ch[i].dmalock));
43 } 42 }
44 /* Mark MEMDMA Channel 0 as requested since we're using it internally */ 43 /* Mark MEMDMA Channel 0 as requested since we're using it internally */
45 request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy"); 44 request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy");
@@ -60,7 +59,7 @@ static int proc_dma_show(struct seq_file *m, void *v)
60 int i; 59 int i;
61 60
62 for (i = 0; i < MAX_DMA_CHANNELS; ++i) 61 for (i = 0; i < MAX_DMA_CHANNELS; ++i)
63 if (dma_ch[i].chan_status != DMA_CHANNEL_FREE) 62 if (dma_channel_active(i))
64 seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id); 63 seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id);
65 64
66 return 0; 65 return 0;
@@ -107,20 +106,11 @@ int request_dma(unsigned int channel, const char *device_id)
107 } 106 }
108#endif 107#endif
109 108
110 mutex_lock(&(dma_ch[channel].dmalock)); 109 if (atomic_cmpxchg(&dma_ch[channel].chan_status, 0, 1)) {
111
112 if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED)
113 || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) {
114 mutex_unlock(&(dma_ch[channel].dmalock));
115 pr_debug("DMA CHANNEL IN USE \n"); 110 pr_debug("DMA CHANNEL IN USE \n");
116 return -EBUSY; 111 return -EBUSY;
117 } else {
118 dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
119 pr_debug("DMA CHANNEL IS ALLOCATED \n");
120 } 112 }
121 113
122 mutex_unlock(&(dma_ch[channel].dmalock));
123
124#ifdef CONFIG_BF54x 114#ifdef CONFIG_BF54x
125 if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) { 115 if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
126 unsigned int per_map; 116 unsigned int per_map;
@@ -149,7 +139,7 @@ EXPORT_SYMBOL(request_dma);
149int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data) 139int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
150{ 140{
151 BUG_ON(channel >= MAX_DMA_CHANNELS || 141 BUG_ON(channel >= MAX_DMA_CHANNELS ||
152 dma_ch[channel].chan_status == DMA_CHANNEL_FREE); 142 !atomic_read(&dma_ch[channel].chan_status));
153 143
154 if (callback != NULL) { 144 if (callback != NULL) {
155 int ret; 145 int ret;
@@ -184,7 +174,7 @@ void free_dma(unsigned int channel)
184{ 174{
185 pr_debug("freedma() : BEGIN \n"); 175 pr_debug("freedma() : BEGIN \n");
186 BUG_ON(channel >= MAX_DMA_CHANNELS || 176 BUG_ON(channel >= MAX_DMA_CHANNELS ||
187 dma_ch[channel].chan_status == DMA_CHANNEL_FREE); 177 !atomic_read(&dma_ch[channel].chan_status));
188 178
189 /* Halt the DMA */ 179 /* Halt the DMA */
190 disable_dma(channel); 180 disable_dma(channel);
@@ -194,9 +184,7 @@ void free_dma(unsigned int channel)
194 free_irq(dma_ch[channel].irq, dma_ch[channel].data); 184 free_irq(dma_ch[channel].irq, dma_ch[channel].data);
195 185
196 /* Clear the DMA Variable in the Channel */ 186 /* Clear the DMA Variable in the Channel */
197 mutex_lock(&(dma_ch[channel].dmalock)); 187 atomic_set(&dma_ch[channel].chan_status, 0);
198 dma_ch[channel].chan_status = DMA_CHANNEL_FREE;
199 mutex_unlock(&(dma_ch[channel].dmalock));
200 188
201 pr_debug("freedma() : END \n"); 189 pr_debug("freedma() : END \n");
202} 190}
@@ -210,13 +198,14 @@ int blackfin_dma_suspend(void)
210{ 198{
211 int i; 199 int i;
212 200
213 for (i = 0; i < MAX_DMA_SUSPEND_CHANNELS; ++i) { 201 for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
214 if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) { 202 if (dma_ch[i].regs->cfg & DMAEN) {
215 printk(KERN_ERR "DMA Channel %d failed to suspend\n", i); 203 printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
216 return -EBUSY; 204 return -EBUSY;
217 } 205 }
218 206
219 dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map; 207 if (i < MAX_DMA_SUSPEND_CHANNELS)
208 dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
220 } 209 }
221 210
222 return 0; 211 return 0;