From: Fancy Fang Date: Wed, 27 Nov 2013 08:41:38 +0000 (+0800) Subject: ENGR00289859 PXP: fix that multi users may access PXP hardware simultaneously X-Git-Tag: KARO-TX6-2014-07-10~123 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=f392940f4a19a3f724752c27a2403dd4445a73a9;p=karo-tx-linux.git ENGR00289859 PXP: fix that multi users may access PXP hardware simultaneously 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 --- diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c index a013c886c080..a7c73f90c0e7 100644 --- a/drivers/dma/pxp/pxp_dma_v2.c +++ b/drivers/dma/pxp/pxp_dma_v2.c @@ -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;