rk30: vpu_service: fix dead lock in power on process and irq function
author陈恒明 <chm@rock-chips.com>
Thu, 12 Apr 2012 10:16:16 +0000 (18:16 +0800)
committer陈恒明 <chm@rock-chips.com>
Thu, 12 Apr 2012 10:16:16 +0000 (18:16 +0800)
arch/arm/plat-rk/vpu_service.c

index d59e8819b05cb21f9a0f6f57e596eb7a6e2dae1a..4b0c85ad47206cfe77dafbadb6e3ad1c5d4b8710 100644 (file)
@@ -131,6 +131,7 @@ typedef struct vpu_device {
 
 typedef struct vpu_service_info {
        spinlock_t              lock;
+       spinlock_t              lock_power;
        struct timer_list       timer;                  /* timer for power off */
        struct list_head        waiting;                /* link to link_reg in struct vpu_reg */
        struct list_head        running;                /* link to link_reg in struct vpu_reg */
@@ -264,8 +265,11 @@ static void vpu_service_power_off(void)
 {
        int total_running;
 
-       if (!service.enabled)
+       spin_lock_bh(&service.lock_power);
+       if (!service.enabled) {
+               spin_unlock_bh(&service.lock_power);
                return;
+       }
 
        service.enabled = false;
        total_running = atomic_read(&service.total_running);
@@ -289,6 +293,7 @@ static void vpu_service_power_off(void)
        clk_disable(aclk_vepu);
        clk_disable(clk_vpu);
        printk("done\n");
+       spin_unlock_bh(&service.lock_power);
 }
 
 static void vpu_service_power_off_work_func(unsigned long data)
@@ -310,7 +315,7 @@ static void vpu_service_power_on(void)
 {
        clk_enable(clk_vpu); /* notify vpu on without lock. */
 
-       spin_lock_bh(&service.lock);
+       spin_lock_bh(&service.lock_power);
        if (!service.enabled) {
                service.enabled = true;
                printk("vpu: power on\n");
@@ -331,9 +336,9 @@ static void vpu_service_power_on(void)
                service.timer.expires = jiffies + POWER_OFF_DELAY;
                service.timer.function = vpu_service_power_off_work_func;
                add_timer(&service.timer);
-               spin_unlock_bh(&service.lock);
+               spin_unlock_bh(&service.lock_power);
        } else {
-               spin_unlock_bh(&service.lock);
+               spin_unlock_bh(&service.lock_power);
                vpu_service_power_maintain();
        }
 
@@ -1137,6 +1142,7 @@ static int __init vpu_service_init(void)
        INIT_LIST_HEAD(&service.done);
        INIT_LIST_HEAD(&service.session);
        spin_lock_init(&service.lock);
+       spin_lock_init(&service.lock_power);
        service.reg_codec       = NULL;
        service.reg_pproc       = NULL;
        atomic_set(&service.total_running, 0);