[PATCH] drm: fix drm_framebuffer cleanup.

Inki Dae inki.dae at samsung.com
Fri Nov 9 01:21:48 PST 2012


2012/11/9 Prathyush K <prathyush at chromium.org>

>
> On Fri, Nov 9, 2012 at 1:09 PM, Inki Dae <inki.dae at samsung.com> wrote:
>
>> This patch fixes access issue to invalid memory region.
>>
>> crtc had only one drm_framebuffer object so when framebuffer
>> cleanup was requested after page flip, it'd try to disable
>> hardware overlay to current crtc.
>> But if current crtc points to another drm_framebuffer,
>> This may induce invalid memory access.
>>
>> Assume that some application are doing page flip with two
>> drm_framebuffer objects. At this time, if second drm_framebuffer
>> is set to current crtc and the cleanup to first drm_framebuffer
>> is requested once drm release is requested, then first
>> drm_framebuffer would be cleaned up without disabling
>> hardware overlay because current crtc points to second
>> drm_framebuffer. After that, gem buffer to first drm_framebuffer
>> would be released and this makes dma access invalid memory region.
>>
>
>
> I am confused regarding this. If crtc points to second frame buffer, then
> the dma is accessing the memory region
> of the second framebuffer. Why can't we free the first framebuffer and its
> gem buffer?
>
> With this patch, there is no way to free a framebuffer (which has been set
> to a crtc), without disabling
> the crtc.
>
> Consider this example:
> I have three framebuffers (0, 1, 2) and I set them to a crtc A one by one.
> So with your patch,
> fb[0]->crtc = A
> fb[1]->crtc = A
> fb[2]->crtc = A
>
> After this, I am using only framebuffer 0 and 1 i.e. 0 and 1 are being
> page flipped.
> Now, I want to remove framebuffer 2.
> fb[2]->crtc = A .. so while removing the framebuffer, we will end up
> disabling the crtc
> which is not correct.
>
> I think, there should be an additional interface to unset a fb to a crtc.
> That way, we can
> reset the crtc inside a framebuffer so that it can be freed if not in use.
> i.e. fb[2]->crtc = NULL;
>
>
>
Right, thank you for comments. There is my missing point. how about adding
fb->crtc = NULL like below then?

int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file
*file_priv) {
        ....
        fb->crtc = NULL;
        fb->funcs->destroy(fb);
out:
        ...
}

With this, when user requested rmfb to remove fb[2], fb[2]'s crtc becomes
NULL so the fb would be freed without disabling crtc.

Thanks,
Inki Dae



>
>
>
>
>> This patch adds drm_framebuffer to drm_crtc structure as member
>> and makes drm_framebuffer_cleanup function check if fb->crtc is
>> same as desired fb. And also when setcrtc and pageflip are
>> requested, it makes each drm_framebuffer point to current crtc.
>>
>> Signed-off-by: Inki Dae <inki.dae at samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
>> ---
>>  drivers/gpu/drm/drm_crtc.c |    7 ++++---
>>  include/drm/drm_crtc.h     |    1 +
>>  2 files changed, 5 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
>> index ef1b221..5c04bd4 100644
>> --- a/drivers/gpu/drm/drm_crtc.c
>> +++ b/drivers/gpu/drm/drm_crtc.c
>> @@ -386,7 +386,7 @@ void drm_framebuffer_remove(struct drm_framebuffer
>> *fb)
>>
>>         /* remove from any CRTC */
>>         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>> -               if (crtc->fb == fb) {
>> +               if (fb->crtc == crtc) {
>>                         /* should turn off the crtc */
>>                         memset(&set, 0, sizeof(struct drm_mode_set));
>>                         set.crtc = crtc;
>> @@ -2027,6 +2027,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void
>> *data,
>>         set.mode = mode;
>>         set.connectors = connector_set;
>>         set.num_connectors = crtc_req->count_connectors;
>> +       fb->crtc = crtc;
>>         set.fb = fb;
>>         ret = crtc->funcs->set_config(&set);
>>
>> @@ -3635,8 +3636,8 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
>>                         spin_unlock_irqrestore(&dev->event_lock, flags);
>>                         kfree(e);
>>                 }
>> -       }
>> -
>> +       } else
>> +               fb->crtc = crtc;
>>  out:
>>         mutex_unlock(&dev->mode_config.mutex);
>>         return ret;
>> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
>> index 3fa18b7..92889be 100644
>> --- a/include/drm/drm_crtc.h
>> +++ b/include/drm/drm_crtc.h
>> @@ -256,6 +256,7 @@ struct drm_framebuffer {
>>         struct kref refcount;
>>         struct list_head head;
>>         struct drm_mode_object base;
>> +       struct drm_crtc *crtc;
>>         const struct drm_framebuffer_funcs *funcs;
>>         unsigned int pitches[4];
>>         unsigned int offsets[4];
>> --
>> 1.7.4.1
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20121109/a7a753a7/attachment.html>


More information about the dri-devel mailing list