int dma_release_channel (unsigned int chn) { unsigned int mask = (0x3 << (chn * 2)); unsigned long flags; if (chn >= DMA_MAX_CHANNELS || !dma_channels[chn].name) { return -EINVAL; } lpc313x_dma_lock(); local_irq_save(flags); /* Otherwise an unexpected interrupt can occur when the channel is reallocated for another purpose */ DMACH_IRQ_STATUS = mask; dma_irq_mask |= mask; DMACH_IRQ_MASK = dma_irq_mask; /* reset counter */ DMACH_TCNT(chn) = 0; local_irq_restore(flags); dma_channels[chn].name = NULL; dma_channels[chn].callback_handler = NULL; dma_channels[chn].data = NULL; lpc313x_dma_unlock(); dma_decrement_usage(); return 0; }
int dma_release_sg_channel (unsigned int chn) { unsigned long flags; if (chn >= DMA_MAX_CHANNELS || !dma_channels[chn].name) { return -EINVAL; } lpc313x_dma_lock(); if (softirqmask[chn] != 0) { local_irq_save(flags); softirqen = 0; softirqmask[chn] = 0; dma_irq_mask |= DMA_IRQS_SOFT; DMACH_IRQ_MASK = dma_irq_mask; local_irq_restore(flags); } dma_channels[chn].name = NULL; dma_channels[chn].callback_handler = NULL; dma_channels[chn].data = NULL; chn--; dma_channels[chn].name = NULL; dma_channels[chn].callback_handler = NULL; dma_channels[chn].data = NULL; sg_higher_channel[chn] = 0; lpc313x_dma_unlock(); dma_decrement_usage(); return 0; }
void pnx4008_free_channel(int ch) { if (!dma_channels[ch].name) { printk(KERN_CRIT "%s: trying to free channel %d which is already freed\n", __FUNCTION__, ch); return; } pnx4008_dma_lock(); pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll); dma_channels[ch].ll = NULL; dma_decrement_usage(); dma_channels[ch].name = NULL; pnx4008_dma_unlock(); }