X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsh%2Fdrivers%2Fdma%2Fdma-sh.c;h=f63721ed86c273fc20864fe107e0877e88d3b65c;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=cca26c4c9d1b9e42f7052559df07bb1fb5fb9f81;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index cca26c4c9..f63721ed8 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -11,36 +11,42 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ - -#include #include -#include #include #include #include -#include -#include #include #include #include "dma-sh.h" -static inline unsigned int get_dmte_irq(unsigned int chan) -{ - unsigned int irq = 0; + +#ifdef CONFIG_CPU_SH4 +static struct ipr_data dmae_ipr_map[] = { + { DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, +}; +#endif +static struct ipr_data dmte_ipr_map[] = { /* * Normally we could just do DMTE0_IRQ + chan outright, though in the * case of the 7751R, the DMTE IRQs for channels > 4 start right above * the SCIF */ - if (chan < 4) { - irq = DMTE0_IRQ + chan; - } else { -#ifdef DMTE4_IRQ - irq = DMTE4_IRQ + chan - 4; -#endif - } + { DMTE0_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE0_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE0_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE0_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 0, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 1, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 2, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, + { DMTE4_IRQ + 3, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, +}; +static inline unsigned int get_dmte_irq(unsigned int chan) +{ + unsigned int irq = 0; + if (chan < ARRAY_SIZE(dmte_ipr_map)) + irq = dmte_ipr_map[chan].irq; return irq; } @@ -65,9 +71,9 @@ static inline unsigned int calc_xmit_shift(struct dma_channel *chan) * Besides that it needs to waken any waiting process, which should handle * setting up the next transfer. */ -static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dma_tei(int irq, void *dev_id) { - struct dma_channel *chan = (struct dma_channel *)dev_id; + struct dma_channel *chan = dev_id; u32 chcr; chcr = ctrl_inl(CHCR[chan->chan]); @@ -85,13 +91,11 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) static int sh_dmac_request_dma(struct dma_channel *chan) { - char name[32]; - - snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", - chan->chan); + if (unlikely(!chan->flags & DMA_TEI_CAPABLE)) + return 0; return request_irq(get_dmte_irq(chan->chan), dma_tei, - SA_INTERRUPT, name, chan); + IRQF_DISABLED, chan->dev_id, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) @@ -228,7 +232,7 @@ static inline int dmaor_reset(void) } #if defined(CONFIG_CPU_SH4) -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dma_err(int irq, void *dummy) { dmaor_reset(); disable_irq(irq); @@ -258,24 +262,23 @@ static int __init sh_dmac_init(void) int i; #ifdef CONFIG_CPU_SH4 - make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - i = request_irq(DMAE_IRQ, dma_err, SA_INTERRUPT, "DMAC Address Error", 0); - if (i < 0) + make_ipr_irq(dmae_ipr_map, ARRAY_SIZE(dmae_ipr_map)); + i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0); + if (unlikely(i < 0)) return i; #endif - for (i = 0; i < info->nr_channels; i++) { - int irq = get_dmte_irq(i); - - make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - } + i = info->nr_channels; + if (i > ARRAY_SIZE(dmte_ipr_map)) + i = ARRAY_SIZE(dmte_ipr_map); + make_ipr_irq(dmte_ipr_map, i); /* * Initialize DMAOR, and clean up any error flags that may have * been set. */ i = dmaor_reset(); - if (i < 0) + if (unlikely(i != 0)) return i; return register_dmac(info);