Merge branch 'fixes' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dmaengine fixes from Vinod Koul: "Here is the slave dmanegine fixes. We have the fix for deadlock issue on imx-dma by Michael and Josh's edma config fix along with author change" * 'fixes' of git://git.infradead.org/users/vkoul/slave-dma: dmaengine: imx-dma: fix callback path in tasklet dmaengine: imx-dma: fix lockdep issue between irqhandler and tasklet dmaengine: imx-dma: fix slow path issue in prep_dma_cyclic dma/Kconfig: Make TI_EDMA select TI_PRIV_EDMA edma: Update author email address
This commit is contained in:
Коммит
831ae3c1df
|
@ -198,6 +198,7 @@ config TI_EDMA
|
||||||
depends on ARCH_DAVINCI || ARCH_OMAP
|
depends on ARCH_DAVINCI || ARCH_OMAP
|
||||||
select DMA_ENGINE
|
select DMA_ENGINE
|
||||||
select DMA_VIRTUAL_CHANNELS
|
select DMA_VIRTUAL_CHANNELS
|
||||||
|
select TI_PRIV_EDMA
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Enable support for the TI EDMA controller. This DMA
|
Enable support for the TI EDMA controller. This DMA
|
||||||
|
|
|
@ -749,6 +749,6 @@ static void __exit edma_exit(void)
|
||||||
}
|
}
|
||||||
module_exit(edma_exit);
|
module_exit(edma_exit);
|
||||||
|
|
||||||
MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
|
MODULE_AUTHOR("Matt Porter <matt.porter@linaro.org>");
|
||||||
MODULE_DESCRIPTION("TI EDMA DMA engine driver");
|
MODULE_DESCRIPTION("TI EDMA DMA engine driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -437,17 +437,18 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac)
|
||||||
struct imxdma_engine *imxdma = imxdmac->imxdma;
|
struct imxdma_engine *imxdma = imxdmac->imxdma;
|
||||||
int chno = imxdmac->channel;
|
int chno = imxdmac->channel;
|
||||||
struct imxdma_desc *desc;
|
struct imxdma_desc *desc;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock(&imxdma->lock);
|
spin_lock_irqsave(&imxdma->lock, flags);
|
||||||
if (list_empty(&imxdmac->ld_active)) {
|
if (list_empty(&imxdmac->ld_active)) {
|
||||||
spin_unlock(&imxdma->lock);
|
spin_unlock_irqrestore(&imxdma->lock, flags);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = list_first_entry(&imxdmac->ld_active,
|
desc = list_first_entry(&imxdmac->ld_active,
|
||||||
struct imxdma_desc,
|
struct imxdma_desc,
|
||||||
node);
|
node);
|
||||||
spin_unlock(&imxdma->lock);
|
spin_unlock_irqrestore(&imxdma->lock, flags);
|
||||||
|
|
||||||
if (desc->sg) {
|
if (desc->sg) {
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
@ -519,7 +520,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
|
||||||
{
|
{
|
||||||
struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan);
|
struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan);
|
||||||
struct imxdma_engine *imxdma = imxdmac->imxdma;
|
struct imxdma_engine *imxdma = imxdmac->imxdma;
|
||||||
unsigned long flags;
|
|
||||||
int slot = -1;
|
int slot = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -527,7 +527,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case IMXDMA_DESC_INTERLEAVED:
|
case IMXDMA_DESC_INTERLEAVED:
|
||||||
/* Try to get a free 2D slot */
|
/* Try to get a free 2D slot */
|
||||||
spin_lock_irqsave(&imxdma->lock, flags);
|
|
||||||
for (i = 0; i < IMX_DMA_2D_SLOTS; i++) {
|
for (i = 0; i < IMX_DMA_2D_SLOTS; i++) {
|
||||||
if ((imxdma->slots_2d[i].count > 0) &&
|
if ((imxdma->slots_2d[i].count > 0) &&
|
||||||
((imxdma->slots_2d[i].xsr != d->x) ||
|
((imxdma->slots_2d[i].xsr != d->x) ||
|
||||||
|
@ -537,10 +536,8 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
|
||||||
slot = i;
|
slot = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (slot < 0) {
|
if (slot < 0)
|
||||||
spin_unlock_irqrestore(&imxdma->lock, flags);
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
|
||||||
|
|
||||||
imxdma->slots_2d[slot].xsr = d->x;
|
imxdma->slots_2d[slot].xsr = d->x;
|
||||||
imxdma->slots_2d[slot].ysr = d->y;
|
imxdma->slots_2d[slot].ysr = d->y;
|
||||||
|
@ -549,7 +546,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
|
||||||
|
|
||||||
imxdmac->slot_2d = slot;
|
imxdmac->slot_2d = slot;
|
||||||
imxdmac->enabled_2d = true;
|
imxdmac->enabled_2d = true;
|
||||||
spin_unlock_irqrestore(&imxdma->lock, flags);
|
|
||||||
|
|
||||||
if (slot == IMX_DMA_2D_SLOT_A) {
|
if (slot == IMX_DMA_2D_SLOT_A) {
|
||||||
d->config_mem &= ~CCR_MSEL_B;
|
d->config_mem &= ~CCR_MSEL_B;
|
||||||
|
@ -625,18 +621,17 @@ static void imxdma_tasklet(unsigned long data)
|
||||||
struct imxdma_channel *imxdmac = (void *)data;
|
struct imxdma_channel *imxdmac = (void *)data;
|
||||||
struct imxdma_engine *imxdma = imxdmac->imxdma;
|
struct imxdma_engine *imxdma = imxdmac->imxdma;
|
||||||
struct imxdma_desc *desc;
|
struct imxdma_desc *desc;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock(&imxdma->lock);
|
spin_lock_irqsave(&imxdma->lock, flags);
|
||||||
|
|
||||||
if (list_empty(&imxdmac->ld_active)) {
|
if (list_empty(&imxdmac->ld_active)) {
|
||||||
/* Someone might have called terminate all */
|
/* Someone might have called terminate all */
|
||||||
goto out;
|
spin_unlock_irqrestore(&imxdma->lock, flags);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node);
|
desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node);
|
||||||
|
|
||||||
if (desc->desc.callback)
|
|
||||||
desc->desc.callback(desc->desc.callback_param);
|
|
||||||
|
|
||||||
/* If we are dealing with a cyclic descriptor, keep it on ld_active
|
/* If we are dealing with a cyclic descriptor, keep it on ld_active
|
||||||
* and dont mark the descriptor as complete.
|
* and dont mark the descriptor as complete.
|
||||||
* Only in non-cyclic cases it would be marked as complete
|
* Only in non-cyclic cases it would be marked as complete
|
||||||
|
@ -663,7 +658,11 @@ static void imxdma_tasklet(unsigned long data)
|
||||||
__func__, imxdmac->channel);
|
__func__, imxdmac->channel);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
spin_unlock(&imxdma->lock);
|
spin_unlock_irqrestore(&imxdma->lock, flags);
|
||||||
|
|
||||||
|
if (desc->desc.callback)
|
||||||
|
desc->desc.callback(desc->desc.callback_param);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
|
static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
|
||||||
|
@ -883,7 +882,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
|
||||||
kfree(imxdmac->sg_list);
|
kfree(imxdmac->sg_list);
|
||||||
|
|
||||||
imxdmac->sg_list = kcalloc(periods + 1,
|
imxdmac->sg_list = kcalloc(periods + 1,
|
||||||
sizeof(struct scatterlist), GFP_KERNEL);
|
sizeof(struct scatterlist), GFP_ATOMIC);
|
||||||
if (!imxdmac->sg_list)
|
if (!imxdmac->sg_list)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче