]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ENGR00289859 PXP: fix that multi users may access PXP hardware simultaneously
authorFancy Fang <B47543@freescale.com>
Wed, 27 Nov 2013 08:41:38 +0000 (16:41 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Wed, 20 Aug 2014 08:06:46 +0000 (10:06 +0200)
After the patch 6320ada11093ef0a4ded9065d6ae284a9129f7d6, there still exists
some cases that more than one user would set PXP hardware registers before the
previous task done. Now use another mutex lock to make sure that registers
settings can only happen when PXP hardware is idle.

Signed-off-by: Fancy Fang <B47543@freescale.com>
drivers/dma/pxp/pxp_dma_v2.c

index a013c886c0803bea06bf154d109d5f083fa20e1c..a7c73f90c0e7a8521b466ad3fe9ef0d9d73eeeb5 100644 (file)
@@ -46,6 +46,7 @@
 static LIST_HEAD(head);
 static int timeout_in_ms = 600;
 static unsigned int block_size;
+struct mutex hard_lock;
 
 struct pxp_dma {
        struct dma_device dma;
@@ -68,7 +69,6 @@ struct pxps {
        struct device *dev;
        struct pxp_dma pxp_dma;
        struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
-       wait_queue_head_t done;
        struct work_struct work;
 
        /* describes most recent processing configuration */
@@ -86,9 +86,6 @@ struct pxps {
 #define PXP_DEF_BUFS   2
 #define PXP_MIN_PIX    8
 
-#define PXP_WAITCON    ((__raw_readl(pxp->base + HW_PXP_STAT) & \
-                               BM_PXP_STAT_IRQ) != BM_PXP_STAT_IRQ)
-
 static uint32_t pxp_s0_formats[] = {
        PXP_PIX_FMT_RGB32,
        PXP_PIX_FMT_RGB565,
@@ -1315,7 +1312,7 @@ static irqreturn_t pxp_irq(int irq, void *dev_id)
        list_splice_init(&desc->tx_list, &pxp_chan->free_list);
        list_move(&desc->list, &pxp_chan->free_list);
 
-       wake_up_interruptible(&pxp->done);
+       mutex_unlock(&hard_lock);
        pxp->pxp_ongoing = 0;
        mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
 
@@ -1431,7 +1428,6 @@ static void pxp_issue_pending(struct dma_chan *chan)
        struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
        struct pxps *pxp = to_pxp(pxp_dma);
        unsigned long flags0, flags;
-       int ret;
 
        spin_lock_irqsave(&pxp->lock, flags0);
        spin_lock_irqsave(&pxp_chan->lock, flags);
@@ -1449,10 +1445,7 @@ static void pxp_issue_pending(struct dma_chan *chan)
        spin_unlock_irqrestore(&pxp->lock, flags0);
 
        pxp_clk_enable(pxp);
-again:
-       ret = wait_event_interruptible_exclusive(pxp->done, PXP_WAITCON);
-       if (ret < 0)
-               goto again;
+       mutex_lock(&hard_lock);
 
        spin_lock_irqsave(&pxp->lock, flags);
        pxp->pxp_ongoing = 1;
@@ -1789,6 +1782,7 @@ static int pxp_probe(struct platform_device *pdev)
 
        spin_lock_init(&pxp->lock);
        mutex_init(&pxp->clk_mutex);
+       mutex_init(&hard_lock);
 
        pxp->base = devm_request_and_ioremap(&pdev->dev, res);
        if (pxp->base == NULL) {
@@ -1828,7 +1822,6 @@ static int pxp_probe(struct platform_device *pdev)
        dump_pxp_reg(pxp);
 
        INIT_WORK(&pxp->work, clkoff_callback);
-       init_waitqueue_head(&pxp->done);
        init_timer(&pxp->clk_timer);
        pxp->clk_timer.function = pxp_clkoff_timer;
        pxp->clk_timer.data = (unsigned long)pxp;