diff options
| author | Inki Dae <inki.dae@samsung.com> | 2013-10-01 01:51:37 -0400 |
|---|---|---|
| committer | Inki Dae <inki.dae@samsung.com> | 2013-12-02 08:49:20 -0500 |
| commit | 0cbc330e12835fcbac44e33d5632d805b16635f2 (patch) | |
| tree | 58f2478f34d26b0e1af07f8583c6158dc2d1f1f5 /drivers | |
| parent | b8654b3753f8b79fc57dbd6a8a633d88274836a6 (diff) | |
drm/exynos: release unhandled page flip events at postclose.
This patch resolves a dead lock issue that could be incurred when
exynos_drm_crtc_dpms function was called.
The exynos_drm_crtc_dpms function waits for the completion of pended
page flip events. However, preclose callback - this releases all unhandled
page flip events - is called prior to the exynos_drm_crtc_dpms function call
when drm is closed. So at this time, this will make the exynos_drm_crtc_dpms
to wait infiniately for the completion of the page flip events.
This patch releases the unhandled page flip events at postclose instead
of preclose so that exynos_drm_crtc_dpms function can be waked up.
Changelog v2:
- fix a memory leak when drm is closed.
. it has a memory leak when a requeste page flip is handled after
drm_events_release() is called and before drm_fb_release()
is called. At this time, a drm_pending_event will not be freed.
So also this chage releases the drm_pending_event at postclose().
And it calls drm_vblank_put() for pair if there is any unhandled page
flip event.
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index b676006a95a0..22b8f5eced80 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
| @@ -173,28 +173,37 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) | |||
| 173 | static void exynos_drm_preclose(struct drm_device *dev, | 173 | static void exynos_drm_preclose(struct drm_device *dev, |
| 174 | struct drm_file *file) | 174 | struct drm_file *file) |
| 175 | { | 175 | { |
| 176 | exynos_drm_subdrv_close(dev, file); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) | ||
| 180 | { | ||
| 176 | struct exynos_drm_private *private = dev->dev_private; | 181 | struct exynos_drm_private *private = dev->dev_private; |
| 177 | struct drm_pending_vblank_event *e, *t; | 182 | struct drm_pending_vblank_event *v, *vt; |
| 183 | struct drm_pending_event *e, *et; | ||
| 178 | unsigned long flags; | 184 | unsigned long flags; |
| 179 | 185 | ||
| 180 | /* release events of current file */ | 186 | if (!file->driver_priv) |
| 187 | return; | ||
| 188 | |||
| 189 | /* Release all events not unhandled by page flip handler. */ | ||
| 181 | spin_lock_irqsave(&dev->event_lock, flags); | 190 | spin_lock_irqsave(&dev->event_lock, flags); |
| 182 | list_for_each_entry_safe(e, t, &private->pageflip_event_list, | 191 | list_for_each_entry_safe(v, vt, &private->pageflip_event_list, |
| 183 | base.link) { | 192 | base.link) { |
| 184 | if (e->base.file_priv == file) { | 193 | if (v->base.file_priv == file) { |
| 185 | list_del(&e->base.link); | 194 | list_del(&v->base.link); |
| 186 | e->base.destroy(&e->base); | 195 | drm_vblank_put(dev, v->pipe); |
| 196 | v->base.destroy(&v->base); | ||
| 187 | } | 197 | } |
| 188 | } | 198 | } |
| 189 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 190 | 199 | ||
| 191 | exynos_drm_subdrv_close(dev, file); | 200 | /* Release all events handled by page flip handler but not freed. */ |
| 192 | } | 201 | list_for_each_entry_safe(e, et, &file->event_list, link) { |
| 202 | list_del(&e->link); | ||
| 203 | e->destroy(e); | ||
| 204 | } | ||
| 205 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 193 | 206 | ||
| 194 | static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) | ||
| 195 | { | ||
| 196 | if (!file->driver_priv) | ||
| 197 | return; | ||
| 198 | 207 | ||
| 199 | kfree(file->driver_priv); | 208 | kfree(file->driver_priv); |
| 200 | file->driver_priv = NULL; | 209 | file->driver_priv = NULL; |
