X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=drivers%2Fdma%2Fdma-jz4780.c;h=6b8c4c458e8a39a0b9500804a3c0a4cb8f6e5839;hb=4c89cc73d1da42ae48b5c5dfbfd12304d0b86786;hp=7204fdeff6c5357d6d9ce516689e3b6468f1e7a0;hpb=72cea7ac5f14ee25cb96c7863a05223ba5a2c9a9;p=mirror_ubuntu-jammy-kernel.git diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index 7204fdeff6c5..6b8c4c458e8a 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -662,10 +662,11 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan, return status; } -static void jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, - struct jz4780_dma_chan *jzchan) +static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, + struct jz4780_dma_chan *jzchan) { uint32_t dcs; + bool ack = true; spin_lock(&jzchan->vchan.lock); @@ -688,12 +689,20 @@ static void jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, if ((dcs & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT)) == 0) { if (jzchan->desc->type == DMA_CYCLIC) { vchan_cyclic_callback(&jzchan->desc->vdesc); - } else { + + jz4780_dma_begin(jzchan); + } else if (dcs & JZ_DMA_DCS_TT) { vchan_cookie_complete(&jzchan->desc->vdesc); jzchan->desc = NULL; - } - jz4780_dma_begin(jzchan); + jz4780_dma_begin(jzchan); + } else { + /* False positive - continue the transfer */ + ack = false; + jz4780_dma_chn_writel(jzdma, jzchan->id, + JZ_DMA_REG_DCS, + JZ_DMA_DCS_CTE); + } } } else { dev_err(&jzchan->vchan.chan.dev->device, @@ -701,21 +710,23 @@ static void jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, } spin_unlock(&jzchan->vchan.lock); + + return ack; } static irqreturn_t jz4780_dma_irq_handler(int irq, void *data) { struct jz4780_dma_dev *jzdma = data; - uint32_t pending, dmac; + unsigned int nb_channels = jzdma->soc_data->nb_channels; + unsigned long pending; + uint32_t dmac; int i; pending = jz4780_dma_ctrl_readl(jzdma, JZ_DMA_REG_DIRQP); - for (i = 0; i < jzdma->soc_data->nb_channels; i++) { - if (!(pending & (1<chan[i]); + for_each_set_bit(i, &pending, nb_channels) { + if (jz4780_dma_chan_irq(jzdma, &jzdma->chan[i])) + pending &= ~BIT(i); } /* Clear halt and address error status of all channels. */ @@ -724,7 +735,7 @@ static irqreturn_t jz4780_dma_irq_handler(int irq, void *data) jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DMAC, dmac); /* Clear interrupt pending status. */ - jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DIRQP, 0); + jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DIRQP, pending); return IRQ_HANDLED; }