gfx: drv: Avoid freeing the sync counter before completing it
authorPauli Nieminen <pauli.nieminen@linux.intel.com>
Thu, 22 Mar 2012 17:34:15 +0000 (19:34 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:30:46 +0000 (12:30 +0300)
If memory reference is freed before read complete count is increment
sync completion access already free memory.

[  428.488124] BUG: unable to handle kernel paging request at 6b6b6b77
[  428.494583] IP: [<c1384af5>] PVRSRVCheckPendingSyncs+0x45/0xc6
[  428.500581] *pdpt = 000000002d34c001 *pde = 0000000000000000
[  428.506418] Oops: 0000 [#1] PREEMPT SMP
[  428.510541] Modules linked in: wl12xx_compat_sdio(C) btwilink
wl12xx_compat(C) mac80211_compat(C) cfg80211_compat(C) compat(C) fm_drv
st_drv fuse atomisp snd_soc_mfld_machine snd_soc_sn95031
snd_soc_sst_platform lm3554 mt9m114 mt9e013 videobuf_vmalloc
videobuf_core atmel_mxt_ts pn544_nxp
[  428.536909]
[  428.538432] Pid: 5, comm: kworker/u:0 Tainted: G        WC 3.0.22-mid15 #1
[  428.545753] EIP: 0060:[<c1384af5>] EFLAGS: 00010002 CPU: 0
[  428.551279] EIP is at PVRSRVCheckPendingSyncs+0x45/0xc6
[  428.556628] EAX: eb2eda10 EBX: e8e1698c ECX: 00000001 EDX: 00000003
[  428.562933] ESI: ed6172dc EDI: 6b6b6b6b EBP: ee04ff28 ESP: ee04ff0c
[  428.569328]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[  428.574767] Process kworker/u:0 (pid: 5, ti=ee04e000 task=ee0428c0 task.ti=ee04e000)
[  428.582631] Stack:
[  428.584668]  00000000 00000246 ee04ff14 ee04ff14 c1e6b880 ed696e00 ed22bb05 ee04ff34
[  428.592662]  c138efb8 ed6cd55c ee04ff3c c1383f1a ee04ff78 c104b6cb 0000009a c1383f0f
[  428.600683]  00000000 ed22bb00 c1847800 ee028120 c1e6a5f4 00000000 00000000 c16c36d7
[  428.608794] Call Trace:
[  428.611282]  [<c138efb8>] PVRSRVMISR+0x80/0x85
[  428.615853]  [<c1383f1a>] MISRWrapper+0xb/0xd
[  428.620250]  [<c104b6cb>] process_one_work+0x1ef/0x357
[  428.625523]  [<c1383f0f>] ? OSMemHandleToCpuPAddr+0x29/0x29
[  428.631145]  [<c104d782>] worker_thread+0xfd/0x20f
[  428.636069]  [<c104d685>] ? manage_workers+0x2ba/0x2ba
[  428.641253]  [<c1050311>] kthread+0x63/0x68
[  428.645480]  [<c10502ae>] ? __init_kthread_worker+0x42/0x42
[  428.651185]  [<c14ee602>] kernel_thread_helper+0x6/0xd

Issue: ANDROID-2144
Issue: ANDROID-2168
Signed-off-by: Pauli Nieminen <pauli.nieminen@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
drivers/staging/mrst/drv/mdfld_overlay.c
drivers/staging/mrst/drv/psb_page_flip.c

index cb346a1..ddc0b99 100644 (file)
@@ -1665,8 +1665,10 @@ static bool ovl_flip_vblank(struct drm_flip *pending_flip)
 
 static void free_flip(struct mfld_overlay_flip *oflip)
 {
-       if (atomic_dec_and_test(&oflip->refcnt))
+       if (atomic_dec_and_test(&oflip->refcnt)) {
+               psb_fb_unref(oflip->old_mem_info, oflip->tgid);
                kfree(oflip);
+       }
 }
 
 static void ovl_sync_callback(struct pvr_pending_sync *sync,
@@ -1714,10 +1716,6 @@ static void ovl_flip_complete(struct drm_flip *pending_flip)
 
 static void ovl_flip_finish(struct drm_flip *pending_flip)
 {
-       struct mfld_overlay_flip *oflip =
-               container_of(pending_flip, struct mfld_overlay_flip, base);
-
-       psb_fb_unref(oflip->old_mem_info, oflip->tgid);
 }
 
 static void ovl_flip_cleanup(struct drm_flip *pending_flip)
index e4c339f..dc0d129 100644 (file)
@@ -205,8 +205,10 @@ unlock:
 
 static void free_flip(struct pending_flip *crtc_flip)
 {
-       if (atomic_dec_and_test(&crtc_flip->refcnt))
+       if (atomic_dec_and_test(&crtc_flip->refcnt)) {
+               psb_fb_unref(crtc_flip->old_mem_info, crtc_flip->tgid);
                kfree(crtc_flip);
+       }
 }
 
 static void crtc_flip_cleanup(struct drm_flip *flip)
@@ -224,10 +226,6 @@ static void crtc_flip_cleanup(struct drm_flip *flip)
 
 static void crtc_flip_finish(struct drm_flip *flip)
 {
-       struct pending_flip *crtc_flip =
-               container_of(flip, struct pending_flip, base);
-
-       psb_fb_unref(crtc_flip->old_mem_info, crtc_flip->tgid);
 }
 
 static void psb_flip_driver_flush(struct drm_flip_driver *driver)