kernel-drm: resolve linked list operation contend issue
authorFei Jiang <fei.jiang@intel.com>
Sun, 3 Jun 2012 14:00:22 +0000 (22:00 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 6 Jun 2012 00:15:45 +0000 (17:15 -0700)
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 <fei.jiang@intel.com>
Reviewed-on: http://android.intel.com:8080/51050
Reviewed-by: Zeng, Li <li.zeng@intel.com>
Reviewed-by: Ding, Haitao <haitao.ding@intel.com>
Tested-by: Ding, Haitao <haitao.ding@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/staging/mrst/drv/psb_reset.c
drivers/staging/mrst/imgv/psb_msvdx.c

index ab5a870..681c836 100644 (file)
@@ -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);
index 382d606..fcbde3f 100644 (file)
@@ -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;
 }