aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFancy Fang <B47543@freescale.com>2013-11-21 06:44:45 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:47:23 -0400
commit94f609967b18344dd664e69e9ee28d517b428429 (patch)
treee74e02d53f49df0fca2cb4f1eaf71cfb7271262e
parentf2da7fb11242e1951ecb52c4549f5ef14d21483b (diff)
ENGR00289237 PXP: fix a multiple instances hang issue
In pxp_issue_pending(), the wait for pxp done processes will be woken up together in PXP ISR. So there will be some situations that one process will set PXP hardware registers after another process's setting but before the first PXP task done. So the PXP hardware may be corrupted and hang maybe happen. Signed-off-by: Fancy Fang <B47543@freescale.com>
-rw-r--r--drivers/dma/pxp/pxp_device.c8
-rw-r--r--drivers/dma/pxp/pxp_dma_v2.c18
2 files changed, 11 insertions, 15 deletions
diff --git a/drivers/dma/pxp/pxp_device.c b/drivers/dma/pxp/pxp_device.c
index 140dce0a99f6..d05b06df0c90 100644
--- a/drivers/dma/pxp/pxp_device.c
+++ b/drivers/dma/pxp/pxp_device.c
@@ -433,12 +433,10 @@ static long pxp_device_ioctl(struct file *filp,
433 if (chan_id < 0 || chan_id >= NR_PXP_VIRT_CHANNEL) 433 if (chan_id < 0 || chan_id >= NR_PXP_VIRT_CHANNEL)
434 return -ENODEV; 434 return -ENODEV;
435 435
436 if (!wait_event_interruptible_timeout 436 ret = wait_event_interruptible
437 (irq_info[chan_id].waitq, 437 (irq_info[chan_id].waitq,
438 (irq_info[chan_id].irq_pending != 0), 2 * HZ)) { 438 (irq_info[chan_id].irq_pending != 0));
439 pr_warning("pxp blocking: timeout.\n"); 439 if (ret < 0) {
440 return -ETIME;
441 } else if (signal_pending(current)) {
442 printk(KERN_WARNING 440 printk(KERN_WARNING
443 "pxp interrupt received.\n"); 441 "pxp interrupt received.\n");
444 return -ERESTARTSYS; 442 return -ERESTARTSYS;
diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c
index 0df4200d2481..55c35b35a875 100644
--- a/drivers/dma/pxp/pxp_dma_v2.c
+++ b/drivers/dma/pxp/pxp_dma_v2.c
@@ -477,10 +477,11 @@ static void pxp_set_oln(int layer_no, struct pxps *pxp)
477 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; 477 struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
478 struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no]; 478 struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
479 dma_addr_t phys_addr = olparams_data->paddr; 479 dma_addr_t phys_addr = olparams_data->paddr;
480 __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
481 u32 pitch = olparams_data->stride ? olparams_data->stride : 480 u32 pitch = olparams_data->stride ? olparams_data->stride :
482 olparams_data->width; 481 olparams_data->width;
483 482
483 __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
484
484 /* Fixme */ 485 /* Fixme */
485 if (olparams_data->width == 0 && olparams_data->height == 0) { 486 if (olparams_data->width == 0 && olparams_data->height == 0) {
486 __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC); 487 __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC);
@@ -1114,9 +1115,6 @@ static void pxpdma_dostart_work(struct pxps *pxp)
1114 struct pxp_channel *pxp_chan = NULL; 1115 struct pxp_channel *pxp_chan = NULL;
1115 unsigned long flags, flags1; 1116 unsigned long flags, flags1;
1116 1117
1117 while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
1118 ;
1119
1120 spin_lock_irqsave(&pxp->lock, flags); 1118 spin_lock_irqsave(&pxp->lock, flags);
1121 if (list_empty(&head)) { 1119 if (list_empty(&head)) {
1122 pxp->pxp_ongoing = 0; 1120 pxp->pxp_ongoing = 0;
@@ -1323,7 +1321,7 @@ static irqreturn_t pxp_irq(int irq, void *dev_id)
1323 list_splice_init(&desc->tx_list, &pxp_chan->free_list); 1321 list_splice_init(&desc->tx_list, &pxp_chan->free_list);
1324 list_move(&desc->list, &pxp_chan->free_list); 1322 list_move(&desc->list, &pxp_chan->free_list);
1325 1323
1326 wake_up(&pxp->done); 1324 wake_up_interruptible(&pxp->done);
1327 pxp->pxp_ongoing = 0; 1325 pxp->pxp_ongoing = 0;
1328 mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms)); 1326 mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
1329 1327
@@ -1439,6 +1437,7 @@ static void pxp_issue_pending(struct dma_chan *chan)
1439 struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); 1437 struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
1440 struct pxps *pxp = to_pxp(pxp_dma); 1438 struct pxps *pxp = to_pxp(pxp_dma);
1441 unsigned long flags0, flags; 1439 unsigned long flags0, flags;
1440 int ret;
1442 1441
1443 spin_lock_irqsave(&pxp->lock, flags0); 1442 spin_lock_irqsave(&pxp->lock, flags0);
1444 spin_lock_irqsave(&pxp_chan->lock, flags); 1443 spin_lock_irqsave(&pxp_chan->lock, flags);
@@ -1456,11 +1455,10 @@ static void pxp_issue_pending(struct dma_chan *chan)
1456 spin_unlock_irqrestore(&pxp->lock, flags0); 1455 spin_unlock_irqrestore(&pxp->lock, flags0);
1457 1456
1458 pxp_clk_enable(pxp); 1457 pxp_clk_enable(pxp);
1459 if (!wait_event_interruptible_timeout(pxp->done, PXP_WAITCON, 2 * HZ) || 1458again:
1460 signal_pending(current)) { 1459 ret = wait_event_interruptible_exclusive(pxp->done, PXP_WAITCON);
1461 pxp_clk_disable(pxp); 1460 if (ret < 0)
1462 return; 1461 goto again;
1463 }
1464 1462
1465 spin_lock_irqsave(&pxp->lock, flags); 1463 spin_lock_irqsave(&pxp->lock, flags);
1466 pxp->pxp_ongoing = 1; 1464 pxp->pxp_ongoing = 1;