diff options
Diffstat (limited to 'drivers/dma/altera-msgdma.c')
| -rw-r--r-- | drivers/dma/altera-msgdma.c | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c index 0fe0676f8e1d..a203fdd84950 100644 --- a/drivers/dma/altera-msgdma.c +++ b/drivers/dma/altera-msgdma.c @@ -153,7 +153,7 @@ struct msgdma_extended_desc { /** * struct msgdma_sw_desc - implements a sw descriptor * @async_tx: support for the async_tx api - * @hw_desc: assosiated HW descriptor + * @hw_desc: associated HW descriptor * @node: node to move from the free list to the tx list * @tx_list: transmit list node */ @@ -233,7 +233,7 @@ static void msgdma_free_descriptor(struct msgdma_device *mdev, struct msgdma_sw_desc *child, *next; mdev->desc_free_cnt++; - list_add_tail(&desc->node, &mdev->free_list); + list_move_tail(&desc->node, &mdev->free_list); list_for_each_entry_safe(child, next, &desc->tx_list, node) { mdev->desc_free_cnt++; list_move_tail(&child->node, &mdev->free_list); @@ -511,7 +511,7 @@ static void msgdma_copy_one(struct msgdma_device *mdev, * of the DMA controller. The descriptor will get flushed to the * FIFO, once the last word (control word) is written. Since we * are not 100% sure that memcpy() writes all word in the "correct" - * oder (address from low to high) on all architectures, we make + * order (address from low to high) on all architectures, we make * sure this control word is written last by single coding it and * adding some write-barriers here. */ @@ -583,24 +583,25 @@ static void msgdma_issue_pending(struct dma_chan *chan) static void msgdma_chan_desc_cleanup(struct msgdma_device *mdev) { struct msgdma_sw_desc *desc, *next; + unsigned long irqflags; - list_for_each_entry_safe(desc, next, &mdev->done_list, node) { - dma_async_tx_callback callback; - void *callback_param; + spin_lock_irqsave(&mdev->lock, irqflags); - list_del(&desc->node); + list_for_each_entry_safe(desc, next, &mdev->done_list, node) { + struct dmaengine_desc_callback cb; - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; - if (callback) { - spin_unlock(&mdev->lock); - callback(callback_param); - spin_lock(&mdev->lock); + dmaengine_desc_get_callback(&desc->async_tx, &cb); + if (dmaengine_desc_callback_valid(&cb)) { + spin_unlock_irqrestore(&mdev->lock, irqflags); + dmaengine_desc_callback_invoke(&cb, NULL); + spin_lock_irqsave(&mdev->lock, irqflags); } /* Run any dependencies, then free the descriptor */ msgdma_free_descriptor(mdev, desc); } + + spin_unlock_irqrestore(&mdev->lock, irqflags); } /** @@ -691,10 +692,14 @@ static void msgdma_tasklet(struct tasklet_struct *t) spin_lock_irqsave(&mdev->lock, flags); - /* Read number of responses that are available */ - count = ioread32(mdev->csr + MSGDMA_CSR_RESP_FILL_LEVEL); - dev_dbg(mdev->dev, "%s (%d): response count=%d\n", - __func__, __LINE__, count); + if (mdev->resp) { + /* Read number of responses that are available */ + count = ioread32(mdev->csr + MSGDMA_CSR_RESP_FILL_LEVEL); + dev_dbg(mdev->dev, "%s (%d): response count=%d\n", + __func__, __LINE__, count); + } else { + count = 1; + } while (count--) { /* @@ -703,14 +708,19 @@ static void msgdma_tasklet(struct tasklet_struct *t) * have any real values, like transferred bytes or error * bits. So we need to just drop these values. */ - size = ioread32(mdev->resp + MSGDMA_RESP_BYTES_TRANSFERRED); - status = ioread32(mdev->resp + MSGDMA_RESP_STATUS); + if (mdev->resp) { + size = ioread32(mdev->resp + + MSGDMA_RESP_BYTES_TRANSFERRED); + status = ioread32(mdev->resp + + MSGDMA_RESP_STATUS); + } msgdma_complete_descriptor(mdev); - msgdma_chan_desc_cleanup(mdev); } spin_unlock_irqrestore(&mdev->lock, flags); + + msgdma_chan_desc_cleanup(mdev); } /** @@ -743,7 +753,7 @@ static irqreturn_t msgdma_irq_handler(int irq, void *data) } /** - * msgdma_chan_remove - Channel remove function + * msgdma_dev_remove() - Device remove function * @mdev: Pointer to the Altera mSGDMA device structure */ static void msgdma_dev_remove(struct msgdma_device *mdev) @@ -757,14 +767,21 @@ static void msgdma_dev_remove(struct msgdma_device *mdev) } static int request_and_map(struct platform_device *pdev, const char *name, - struct resource **res, void __iomem **ptr) + struct resource **res, void __iomem **ptr, + bool optional) { struct resource *region; struct device *device = &pdev->dev; *res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); if (*res == NULL) { - dev_err(device, "resource %s not defined\n", name); + if (optional) { + *ptr = NULL; + dev_info(device, "optional resource %s not defined\n", + name); + return 0; + } + dev_err(device, "mandatory resource %s not defined\n", name); return -ENODEV; } @@ -805,17 +822,17 @@ static int msgdma_probe(struct platform_device *pdev) mdev->dev = &pdev->dev; /* Map CSR space */ - ret = request_and_map(pdev, "csr", &dma_res, &mdev->csr); + ret = request_and_map(pdev, "csr", &dma_res, &mdev->csr, false); if (ret) return ret; /* Map (extended) descriptor space */ - ret = request_and_map(pdev, "desc", &dma_res, &mdev->desc); + ret = request_and_map(pdev, "desc", &dma_res, &mdev->desc, false); if (ret) return ret; /* Map response space */ - ret = request_and_map(pdev, "resp", &dma_res, &mdev->resp); + ret = request_and_map(pdev, "resp", &dma_res, &mdev->resp, true); if (ret) return ret; @@ -878,9 +895,7 @@ static int msgdma_probe(struct platform_device *pdev) ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (ret) { dev_warn(&pdev->dev, "unable to set coherent mask to 64"); - ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (ret) - goto fail; + goto fail; } msgdma_reset(mdev); @@ -907,12 +922,12 @@ fail: } /** - * msgdma_dma_remove - Driver remove function + * msgdma_remove() - Driver remove function * @pdev: Pointer to the platform_device structure * * Return: Always '0' */ -static int msgdma_remove(struct platform_device *pdev) +static void msgdma_remove(struct platform_device *pdev) { struct msgdma_device *mdev = platform_get_drvdata(pdev); @@ -922,8 +937,6 @@ static int msgdma_remove(struct platform_device *pdev) msgdma_dev_remove(mdev); dev_notice(&pdev->dev, "Altera mSGDMA driver removed\n"); - - return 0; } #ifdef CONFIG_OF |
