diff options
-rw-r--r-- | arch/mips/alchemy/common/dbdma.c | 111 |
1 files changed, 56 insertions, 55 deletions
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c index 493e5708f664..99ae84ce5af3 100644 --- a/arch/mips/alchemy/common/dbdma.c +++ b/arch/mips/alchemy/common/dbdma.c | |||
@@ -237,7 +237,7 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
237 | void (*callback)(int, void *), void *callparam) | 237 | void (*callback)(int, void *), void *callparam) |
238 | { | 238 | { |
239 | unsigned long flags; | 239 | unsigned long flags; |
240 | u32 used, chan, rv; | 240 | u32 used, chan; |
241 | u32 dcp; | 241 | u32 dcp; |
242 | int i; | 242 | int i; |
243 | dbdev_tab_t *stp, *dtp; | 243 | dbdev_tab_t *stp, *dtp; |
@@ -260,7 +260,6 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
260 | return 0; | 260 | return 0; |
261 | 261 | ||
262 | used = 0; | 262 | used = 0; |
263 | rv = 0; | ||
264 | 263 | ||
265 | /* Check to see if we can get both channels. */ | 264 | /* Check to see if we can get both channels. */ |
266 | spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); | 265 | spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); |
@@ -281,63 +280,65 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
281 | used++; | 280 | used++; |
282 | spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); | 281 | spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); |
283 | 282 | ||
284 | if (!used) { | 283 | if (used) |
285 | /* Let's see if we can allocate a channel for it. */ | 284 | return 0; |
286 | ctp = NULL; | ||
287 | chan = 0; | ||
288 | spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); | ||
289 | for (i = 0; i < NUM_DBDMA_CHANS; i++) | ||
290 | if (chan_tab_ptr[i] == NULL) { | ||
291 | /* | ||
292 | * If kmalloc fails, it is caught below same | ||
293 | * as a channel not available. | ||
294 | */ | ||
295 | ctp = kmalloc(sizeof(chan_tab_t), GFP_ATOMIC); | ||
296 | chan_tab_ptr[i] = ctp; | ||
297 | break; | ||
298 | } | ||
299 | spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); | ||
300 | |||
301 | if (ctp != NULL) { | ||
302 | memset(ctp, 0, sizeof(chan_tab_t)); | ||
303 | ctp->chan_index = chan = i; | ||
304 | dcp = DDMA_CHANNEL_BASE; | ||
305 | dcp += (0x0100 * chan); | ||
306 | ctp->chan_ptr = (au1x_dma_chan_t *)dcp; | ||
307 | cp = (au1x_dma_chan_t *)dcp; | ||
308 | ctp->chan_src = stp; | ||
309 | ctp->chan_dest = dtp; | ||
310 | ctp->chan_callback = callback; | ||
311 | ctp->chan_callparam = callparam; | ||
312 | |||
313 | /* Initialize channel configuration. */ | ||
314 | i = 0; | ||
315 | if (stp->dev_intlevel) | ||
316 | i |= DDMA_CFG_SED; | ||
317 | if (stp->dev_intpolarity) | ||
318 | i |= DDMA_CFG_SP; | ||
319 | if (dtp->dev_intlevel) | ||
320 | i |= DDMA_CFG_DED; | ||
321 | if (dtp->dev_intpolarity) | ||
322 | i |= DDMA_CFG_DP; | ||
323 | if ((stp->dev_flags & DEV_FLAGS_SYNC) || | ||
324 | (dtp->dev_flags & DEV_FLAGS_SYNC)) | ||
325 | i |= DDMA_CFG_SYNC; | ||
326 | cp->ddma_cfg = i; | ||
327 | au_sync(); | ||
328 | 285 | ||
329 | /* Return a non-zero value that can be used to | 286 | /* Let's see if we can allocate a channel for it. */ |
330 | * find the channel information in subsequent | 287 | ctp = NULL; |
331 | * operations. | 288 | chan = 0; |
289 | spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags); | ||
290 | for (i = 0; i < NUM_DBDMA_CHANS; i++) | ||
291 | if (chan_tab_ptr[i] == NULL) { | ||
292 | /* | ||
293 | * If kmalloc fails, it is caught below same | ||
294 | * as a channel not available. | ||
332 | */ | 295 | */ |
333 | rv = (u32)(&chan_tab_ptr[chan]); | 296 | ctp = kmalloc(sizeof(chan_tab_t), GFP_ATOMIC); |
334 | } else { | 297 | chan_tab_ptr[i] = ctp; |
335 | /* Release devices */ | 298 | break; |
336 | stp->dev_flags &= ~DEV_FLAGS_INUSE; | ||
337 | dtp->dev_flags &= ~DEV_FLAGS_INUSE; | ||
338 | } | 299 | } |
300 | spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags); | ||
301 | |||
302 | if (ctp != NULL) { | ||
303 | memset(ctp, 0, sizeof(chan_tab_t)); | ||
304 | ctp->chan_index = chan = i; | ||
305 | dcp = DDMA_CHANNEL_BASE; | ||
306 | dcp += (0x0100 * chan); | ||
307 | ctp->chan_ptr = (au1x_dma_chan_t *)dcp; | ||
308 | cp = (au1x_dma_chan_t *)dcp; | ||
309 | ctp->chan_src = stp; | ||
310 | ctp->chan_dest = dtp; | ||
311 | ctp->chan_callback = callback; | ||
312 | ctp->chan_callparam = callparam; | ||
313 | |||
314 | /* Initialize channel configuration. */ | ||
315 | i = 0; | ||
316 | if (stp->dev_intlevel) | ||
317 | i |= DDMA_CFG_SED; | ||
318 | if (stp->dev_intpolarity) | ||
319 | i |= DDMA_CFG_SP; | ||
320 | if (dtp->dev_intlevel) | ||
321 | i |= DDMA_CFG_DED; | ||
322 | if (dtp->dev_intpolarity) | ||
323 | i |= DDMA_CFG_DP; | ||
324 | if ((stp->dev_flags & DEV_FLAGS_SYNC) || | ||
325 | (dtp->dev_flags & DEV_FLAGS_SYNC)) | ||
326 | i |= DDMA_CFG_SYNC; | ||
327 | cp->ddma_cfg = i; | ||
328 | au_sync(); | ||
329 | |||
330 | /* | ||
331 | * Return a non-zero value that can be used to find the channel | ||
332 | * information in subsequent operations. | ||
333 | */ | ||
334 | return (u32)(&chan_tab_ptr[chan]); | ||
339 | } | 335 | } |
340 | return rv; | 336 | |
337 | /* Release devices */ | ||
338 | stp->dev_flags &= ~DEV_FLAGS_INUSE; | ||
339 | dtp->dev_flags &= ~DEV_FLAGS_INUSE; | ||
340 | |||
341 | return 0; | ||
341 | } | 342 | } |
342 | EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); | 343 | EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); |
343 | 344 | ||