CHROMIUM: mali-t6xx: Convert mali_dvfs_spinlock to IRQ-safe spinlock
authorMichael Spang <spang@chromium.org>
Fri, 26 Oct 2012 19:04:40 +0000 (15:04 -0400)
committerGerrit <chrome-bot@google.com>
Thu, 1 Nov 2012 01:01:55 +0000 (18:01 -0700)
This fixes the following potential deadlock reported by lockdep:

[    2.204853] =================================
[    2.209181] [ INFO: inconsistent lock state ]
[    2.213523] 3.4.0 #101 Not tainted
[    2.216906] ---------------------------------
[    2.221247] inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage.
[    2.227237] swapper/0/0 [HC1[1]:SC0[0]:HE0:SE1] takes:
[    2.232357]  (&((&mali_dvfs_spinlock))->rlock){?.+...}, at: [<402cef00>] kbase_platform_dvfs_event+0x28/0x54
[    2.242165] {HARDIRQ-ON-W} state was registered at:
[    2.247026]   [<4007a77c>] mark_lock+0x290/0x630
[    2.251626]   [<4007b17c>] __lock_acquire+0x660/0x180c
[    2.256747]   [<4007c8ac>] lock_acquire+0x104/0x128
[    2.261608]   [<40516464>] _raw_spin_lock+0x3c/0x4c
[    2.266469]   [<402cdf00>] kbase_platform_dvfs_init+0x64/0xb0
[    2.272198]   [<402ce17c>] kbase_platform_init+0x164/0x1cc
[    2.277666]   [<402ce200>] kbase_platform_exynos5_init+0x1c/0x124
[    2.283742]   [<402c7118>] kbasep_platform_device_init+0x48/0x54
[    2.289731]   [<402b9128>] kbase_device_init+0x44/0x400
[    2.294939]   [<402ca6ec>] kbase_platform_device_probe+0x1b4/0x6c8
[    2.301102]   [<402d56fc>] platform_drv_probe+0x24/0x28
[    2.306310]   [<402d42b4>] driver_probe_device+0xd8/0x214
[    2.311691]   [<402d4468>] __driver_attach+0x78/0x9c
[    2.316639]   [<402d28e4>] bus_for_each_dev+0x60/0x9c
[    2.321673]   [<402d3d88>] driver_attach+0x28/0x30
[    2.326448]   [<402d38f0>] bus_add_driver+0xc0/0x248
[    2.331395]   [<402d49d8>] driver_register+0xac/0x138
[    2.336429]   [<402d5a18>] platform_driver_register+0x54/0x68
[    2.342158]   [<40767a94>] kbase_driver_init+0xb4/0xd0
[    2.347279]   [<4000869c>] do_one_initcall+0xa0/0x174
[    2.352314]   [<4074db90>] kernel_init+0xf8/0x1b4
[    2.357001]   [<4000f240>] kernel_thread_exit+0x0/0x8
[    2.362036] irq event stamp: 41284
[    2.365421] hardirqs last  enabled at (41281): [<4000f304>] default_idle+0x34/0x40
[    2.372973] hardirqs last disabled at (41282): [<4000db74>] __irq_svc+0x34/0x60
[    2.380264] softirqs last  enabled at (41284): [<40032af8>] _local_bh_enable+0x1c/0x20
[    2.388163] softirqs last disabled at (41283): [<40033340>] irq_enter+0x50/0x7c
[    2.395454]
[    2.395455] other info that might help us debug this:
[    2.401964]  Possible unsafe locking scenario:
[    2.401967]
[    2.407866]        CPU0
[    2.410296]        ----
[    2.412727]   lock(&((&mali_dvfs_spinlock))->rlock);
[    2.417674]   <Interrupt>
[    2.420278]     lock(&((&mali_dvfs_spinlock))->rlock);
[    2.425399]
[    2.425401]  *** DEADLOCK ***
[    2.425403]
[    2.431302] no locks held by swapper/0/0.
[    2.435295]
[    2.435296] stack backtrace:
[    2.439642] [<40015580>] (unwind_backtrace+0x0/0xec) from [<4050e2ec>] (dump_stack+0x20/0x24)
[    2.448146] [<4050e2ec>] (dump_stack+0x20/0x24) from [<4050f5ac>] (print_usage_bug+0x250/0x2b8)
[    2.456826] [<4050f5ac>] (print_usage_bug+0x250/0x2b8) from [<4007a844>] (mark_lock+0x358/0x630)
[    2.465593] [<4007a844>] (mark_lock+0x358/0x630) from [<4007b0f8>] (__lock_acquire+0x5dc/0x180c)
[    2.474359] [<4007b0f8>] (__lock_acquire+0x5dc/0x180c) from [<4007c8ac>] (lock_acquire+0x104/0x128)
[    2.483387] [<4007c8ac>] (lock_acquire+0x104/0x128) from [<40516464>] (_raw_spin_lock+0x3c/0x4c)
[    2.492154] [<40516464>] (_raw_spin_lock+0x3c/0x4c) from [<402cef00>] (kbase_platform_dvfs_event+0x28/0x54)
[    2.501876] [<402cef00>] (kbase_platform_dvfs_event+0x28/0x54) from [<402c6498>] (dvfs_callback+0x28/0x74)
[    2.511511] [<402c6498>] (dvfs_callback+0x28/0x74) from [<400514ec>] (__run_hrtimer+0x144/0x220)
[    2.520276] [<400514ec>] (__run_hrtimer+0x144/0x220) from [<400522f4>] (hrtimer_interrupt+0x120/0x248)
[    2.529566] [<400522f4>] (hrtimer_interrupt+0x120/0x248) from [<400244d8>] (exynos4_mct_tick_isr+0x58/0x60)
[    2.539289] [<400244d8>] (exynos4_mct_tick_isr+0x58/0x60) from [<40091968>] (handle_irq_event_percpu+0x8c/0x248)
[    2.549442] [<40091968>] (handle_irq_event_percpu+0x8c/0x248) from [<40091b70>] (handle_irq_event+0x4c/0x6c)
[    2.559251] [<40091b70>] (handle_irq_event+0x4c/0x6c) from [<40094b50>] (handle_fasteoi_irq+0xe4/0x150)
[    2.568624] [<40094b50>] (handle_fasteoi_irq+0xe4/0x150) from [<40091110>] (generic_handle_irq+0x3c/0x50)
[    2.578173] [<40091110>] (generic_handle_irq+0x3c/0x50) from [<4000efc4>] (handle_IRQ+0x88/0xc8)
[    2.586939] [<4000efc4>] (handle_IRQ+0x88/0xc8) from [<40008564>] (gic_handle_irq+0x44/0x68)
[    2.595358] [<40008564>] (gic_handle_irq+0x44/0x68) from [<4000db84>] (__irq_svc+0x44/0x60)
[    2.603688] Exception stack(0x40797f18 to 0x40797f60)
[    2.608723] 7f00:                                                       00000001 00000004
[    2.616883] 7f20: 00000000 00000000 40796000 4080a1c8 4051a564 407be97c 4000406a 410fc0f4
[    2.625042] 7f40: 00000000 40797f6c 40797f30 40797f60 4007d1b0 4000f308 20000013 ffffffff
[    2.633204] [<4000db84>] (__irq_svc+0x44/0x60) from [<4000f308>] (default_idle+0x38/0x40)
[    2.641363] [<4000f308>] (default_idle+0x38/0x40) from [<4000f570>] (cpu_idle+0xb4/0x10c)
[    2.649523] [<4000f570>] (cpu_idle+0xb4/0x10c) from [<404fccac>] (rest_init+0xb4/0xdc)
[    2.657421] [<404fccac>] (rest_init+0xb4/0xdc) from [<4074d9e0>] (start_kernel+0x46c/0x524)
[    2.665753] [<4074d9e0>] (start_kernel+0x46c/0x524) from [<40008044>] (0x40008044)
[

BUG=chrome-os-partner:15688
TEST=boot with CONFIG_PROVE_LOCKING, check dmesg for warning

Change-Id: Ie2c9fa5b57de6d8f9769d5969142ad7b5ede6440
Signed-off-by: Michael Spang <spang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/36705
Reviewed-by: Mandeep Singh Baines <msb@chromium.org>
Reviewed-by: Sam Leffler <sleffler@chromium.org>
drivers/gpu/arm/t6xx/kbase/src/linux/config/tpip/mali_kbase_config_exynos5.c

index f2f4500..826c578 100644 (file)
@@ -1321,7 +1321,7 @@ struct mali_dvfs_status {
 
 static struct workqueue_struct *mali_dvfs_wq = 0;
 int mali_dvfs_control=0;
-osk_spinlock mali_dvfs_spinlock;
+osk_spinlock_irq mali_dvfs_spinlock;
 
 
 static struct mali_dvfs_status mali_dvfs_status_current;
@@ -1494,7 +1494,7 @@ static void mali_dvfs_event_proc(struct work_struct *w)
        const struct mali_dvfs_info *info;
        int avg_utilisation;
 
-       osk_spinlock_lock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_lock(&mali_dvfs_spinlock);
        dvfs_status = mali_dvfs_status_current;
 #ifdef MALI_DVFS_ASV_ENABLE
        if (dvfs_status.asv_need_update == DVFS_UPDATE_ASV_DEFAULT_TBL) {
@@ -1506,7 +1506,7 @@ static void mali_dvfs_event_proc(struct work_struct *w)
                dvfs_status.asv_need_update = DVFS_NOT_UPDATE_ASV_TBL;
        }
 #endif
-       osk_spinlock_unlock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
 
        info = &mali_dvfs_infotbl[dvfs_status.step];
 
@@ -1547,9 +1547,9 @@ static void mali_dvfs_event_proc(struct work_struct *w)
                kbase_platform_dvfs_set_level(dvfs_status.kbdev,
                dvfs_status.step);
 
-       osk_spinlock_lock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_lock(&mali_dvfs_spinlock);
        mali_dvfs_status_current = dvfs_status;
-       osk_spinlock_unlock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
 
 }
 
@@ -1576,10 +1576,10 @@ int kbase_platform_dvfs_init(kbase_device *kbdev)
        if (!mali_dvfs_wq)
                mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
 
-       osk_spinlock_init(&mali_dvfs_spinlock,OSK_LOCK_ORDER_PM_METRICS);
+       osk_spinlock_irq_init(&mali_dvfs_spinlock, OSK_LOCK_ORDER_PM_METRICS);
 
        /*add a error handling here*/
-       osk_spinlock_lock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_lock(&mali_dvfs_spinlock);
        mali_dvfs_status_current.kbdev = kbdev;
        mali_dvfs_status_current.step = MALI_DVFS_STEP-1;
        mali_dvfs_status_current.utilisation = 100;
@@ -1589,7 +1589,7 @@ int kbase_platform_dvfs_init(kbase_device *kbdev)
        mali_dvfs_status_current.asv_group = -1;
 #endif
        mali_dvfs_control = 1;
-       osk_spinlock_unlock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
 
        return MALI_TRUE;
 }
@@ -1609,9 +1609,9 @@ int kbase_platform_dvfs_event(struct kbase_device *kbdev)
 #ifdef CONFIG_T6XX_DVFS
         int utilisation = kbase_pm_get_dvfs_utilisation(kbdev);
 
-       osk_spinlock_lock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_lock(&mali_dvfs_spinlock);
        mali_dvfs_status_current.utilisation = utilisation;
-       osk_spinlock_unlock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
        queue_work_on(0, mali_dvfs_wq, &mali_dvfs_work);
 
        /*add error handle here*/
@@ -1898,14 +1898,14 @@ static int kbase_platform_dvfs_sprint_avs_table(char *buf)
 
 static int kbase_platform_asv_set(int enable)
 {
-       osk_spinlock_lock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_lock(&mali_dvfs_spinlock);
        if (enable) {
                mali_dvfs_status_current.asv_need_update = DVFS_UPDATE_ASV_TBL;
                mali_dvfs_status_current.asv_group = -1;
        } else{
                mali_dvfs_status_current.asv_need_update = DVFS_UPDATE_ASV_DEFAULT_TBL;
        }
-       osk_spinlock_unlock(&mali_dvfs_spinlock);
+       osk_spinlock_irq_unlock(&mali_dvfs_spinlock);
        return 0;
 }
 #endif /* MALI_DVFS_ASV_ENABLE */