From e11e4e904e06b604b45d3f3e4e971b5a6384f76b Mon Sep 17 00:00:00 2001 From: Fei Jiang Date: Sun, 3 Jun 2012 22:00:22 +0800 Subject: [PATCH] kernel-drm: resolve linked list operation contend issue BZ: 38174 Linked list operation need be protected with spin_lock, otherwise it will cause random contend issue. Change-Id: I61102fe9f9e5c984d48046530aa893eb5992a42c Signed-off-by: Fei Jiang Reviewed-on: http://android.intel.com:8080/51050 Reviewed-by: Zeng, Li Reviewed-by: Ding, Haitao Tested-by: Ding, Haitao Reviewed-by: buildbot Tested-by: buildbot --- drivers/staging/mrst/drv/psb_reset.c | 15 ++++++++------- drivers/staging/mrst/imgv/psb_msvdx.c | 14 +++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/staging/mrst/drv/psb_reset.c b/drivers/staging/mrst/drv/psb_reset.c index ab5a870..681c836 100644 --- a/drivers/staging/mrst/drv/psb_reset.c +++ b/drivers/staging/mrst/drv/psb_reset.c @@ -68,22 +68,25 @@ void psb_msvdx_flush_cmd_queue(struct drm_device *dev) struct psb_msvdx_cmd_queue *msvdx_cmd; struct list_head *list, *next; struct msvdx_private *msvdx_priv = dev_priv->msvdx_private; - + unsigned long irq_flags; + spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags); /*Flush the msvdx cmd queue and signal all fences in the queue */ list_for_each_safe(list, next, &msvdx_priv->msvdx_queue) { msvdx_cmd = list_entry(list, struct psb_msvdx_cmd_queue, head); + list_del(list); PSB_DEBUG_GENERAL("MSVDXQUE: flushing sequence:0x%08x\n", msvdx_cmd->sequence); msvdx_priv->msvdx_current_sequence = msvdx_cmd->sequence; + spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags); psb_fence_error(dev, PSB_ENGINE_VIDEO, - msvdx_priv->msvdx_current_sequence, + msvdx_cmd->sequence, _PSB_FENCE_TYPE_EXE, DRM_CMD_HANG); - list_del(list); kfree(msvdx_cmd->cmd); - kfree(msvdx_cmd - ); + kfree(msvdx_cmd); + spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags); } + spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags); } static void psb_msvdx_reset_wq(struct work_struct *work) @@ -114,9 +117,7 @@ static void psb_msvdx_reset_wq(struct work_struct *work) dev_priv->timer_available = 1; spin_unlock_irqrestore(&dev_priv->watchdog_lock, irq_flags); - spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags); psb_msvdx_flush_cmd_queue(scheduler->dev); - spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags); psb_schedule_watchdog(dev_priv); mutex_unlock(&msvdx_priv->msvdx_mutex); diff --git a/drivers/staging/mrst/imgv/psb_msvdx.c b/drivers/staging/mrst/imgv/psb_msvdx.c index 382d606..fcbde3f 100644 --- a/drivers/staging/mrst/imgv/psb_msvdx.c +++ b/drivers/staging/mrst/imgv/psb_msvdx.c @@ -42,26 +42,28 @@ static int psb_msvdx_dequeue_send(struct drm_device *dev) struct psb_msvdx_cmd_queue *msvdx_cmd = NULL; int ret = 0; struct msvdx_private *msvdx_priv = dev_priv->msvdx_private; + unsigned long irq_flags; - spin_lock(&msvdx_priv->msvdx_lock); + spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags); if (list_empty(&msvdx_priv->msvdx_queue)) { PSB_DEBUG_GENERAL("MSVDXQUE: msvdx list empty.\n"); msvdx_priv->msvdx_busy = 0; - spin_unlock(&msvdx_priv->msvdx_lock); + spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags); return -EINVAL; } - spin_unlock(&msvdx_priv->msvdx_lock); - msvdx_cmd = list_first_entry(&msvdx_priv->msvdx_queue, struct psb_msvdx_cmd_queue, head); + list_del(&msvdx_cmd->head); + spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags); + PSB_DEBUG_GENERAL("MSVDXQUE: Queue has id %08x\n", msvdx_cmd->sequence); ret = psb_msvdx_send(dev, msvdx_cmd->cmd, msvdx_cmd->cmd_size); if (ret) { DRM_ERROR("MSVDXQUE: psb_msvdx_send failed\n"); ret = -EINVAL; } - list_del(&msvdx_cmd->head); + kfree(msvdx_cmd->cmd); kfree(msvdx_cmd); @@ -1660,9 +1662,7 @@ int psb_msvdx_check_reset_fw(struct drm_device *dev) msvdx_priv->msvdx_needs_reset &= ~MSVDX_RESET_NEEDS_REUPLOAD_FW; ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND); } - spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags); - return 0; } -- 2.7.4