From: Russell King - ARM Linux <linux@arm.linux.org.uk>
To: Daniel Vetter <daniel@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org
Subject: DRM framebuffer refcounting bug... still present
Date: Sat, 11 Oct 2014 10:26:20 +0100 [thread overview]
Message-ID: <20141011092620.GQ5182@n2100.arm.linux.org.uk> (raw)
Daniel,
A while back you had a go at fixing the framebuffer reference counting.
Unfortunately, I'm still seeing leaks, particularly with the framebuffer
used with a mode set which is subsequently flipped. It is only this
framebuffer which is leaked, flips of an already flipped framebuffer do
not.
Looking at what happens to this framebuffer, I see these refcount changes:
ADDFB
- 0->1 - kref_init
- 1->2 - drm_framebuffer_reference() creation
SETCRTC
- 2->3 - drm_framebuffer_lookup() in drm_mode_setcrtc()
- 3->4 - drm_framebuffer_reference() in armada_drm_crtc_mode_set()
- 4->5 - drm_framebuffer_reference() in drm_mode_set_config_internal()
- 5->4 - drm_framebuffer_unreference() in drm_mode_setcrtc()
* current scanout framebuffer has refcount of 4
PAGE_FLIP
- 4->5 - drm_framebuffer_reference() in armada_drm_crtc_page_flip()
- 5->4 - drm_framebuffer_unreference(old_fb) in drm_mode_page_flip_ioctl()
- 4->3 - drm_framebuffer_unreference() in armada_drm_unref_work()
RMFB
- 3->2 - __drm_framebuffer_unreference()
- 2->1 - drm_framebuffer_unreference() - *LEAK*
For the framebuffer being flipped in:
ADDFB
- 0->1 - kref_init
- 1->2 - drm_framebuffer_reference() creation
PAGE_FLIP (incoming)
- 2->3 - drm_framebuffer_lookup() in drm_mode_page_flip_ioctl()
* current scanout framebuffer has refcount of 3 - different from setcrtc.
PAGE_FLIP (outgoing)
- 3->4 - drm_framebuffer_reference() in armada_drm_crtc_page_flip()
- 4->3 - drm_framebuffer_unreference(old_fb) in drm_mode_page_flip_ioctl()
- 3->2 - drm_framebuffer_unreference() in armada_drm_unref_work()
RMFB
- 2->1 - __drm_framebuffer_unreference()
- 1->0 - drm_framebuffer_unreference() - *free*
Of course, this isn't going to be nice given appropriate timing of a
subsequent SETCRTC removing the FB and dropping its refcounts.
If I get rid of the referencing of the old framebuffer in PAGE_FLIP,
then:
ADDFB
- 0->1 - kref_init
- 1->2 - drm_framebuffer_reference() creation
SETCRTC
- 2->3 - drm_framebuffer_lookup() in drm_mode_setcrtc()
- 3->4 - drm_framebuffer_reference() in armada_drm_crtc_mode_set()
- 4->5 - drm_framebuffer_reference() in drm_mode_set_config_internal()
- 5->4 - drm_framebuffer_unreference() in drm_mode_setcrtc()
* current scanout framebuffer has refcount of 4
PAGE_FLIP
- 4->3 - drm_framebuffer_unreference(old_fb) in drm_mode_page_flip_ioctl()
- 3->2 - drm_framebuffer_unreference() in armada_drm_unref_work()
RMFB
- 2->1 - __drm_framebuffer_unreference()
- 1->0 - drm_framebuffer_unreference() - *free*
So that looks good, but let's look at what happens to the framebuffer
being flipped in:
ADDFB
- 0->1 - kref_init
- 1->2 - drm_framebuffer_reference() creation
PAGE_FLIP (incoming)
- 2->3 - drm_framebuffer_lookup() in drm_mode_page_flip_ioctl()
* current scanout framebuffer has refcount of 3 - different from setcrtc.
PAGE_FLIP (outgoing)
- 3->2 - drm_framebuffer_unreference(old_fb) in drm_mode_page_flip_ioctl()
- 2->1 - drm_framebuffer_unreference() in armada_drm_unref_work()
RMFB
- 1->0 - __drm_framebuffer_unreference() - *OOPS*
- 0->-1 - drm_framebuffer_unreference() - *broken*
So that doesn't work - and it still isn't good because the framebuffer
which was flipped in has a different refcount to the one going out.
If I instead try taking a reference on the new framebuffer and dropping
the previous ref in PAGE_FLIP:
ADDFB
- 0->1 - kref_init
- 1->2 - drm_framebuffer_reference() creation
SETCRTC
- 2->3 - drm_framebuffer_lookup() in drm_mode_setcrtc()
- 3->4 - drm_framebuffer_reference() in armada_drm_crtc_mode_set()
- 4->5 - drm_framebuffer_reference() in drm_mode_set_config_internal()
- 5->4 - drm_framebuffer_unreference() in drm_mode_setcrtc()
* current scanout framebuffer has refcount of 4
PAGE_FLIP
- 4->3 - drm_framebuffer_unreference() in armada_drm_crtc_page_flip()
- 3->2 - drm_framebuffer_unreference(old_fb) in drm_mode_page_flip_ioctl()
- 2->1 - drm_framebuffer_unreference() in armada_drm_unref_work()
RMFB
- 1->0 - __drm_framebuffer_unreference() - *OOPS*
- 0->-1 - drm_framebuffer_unreference() - (never happens)
I can see no way to solve this in driver code, other than tracking where
the framebuffer came from, and conditionally adjusting the refcount to
keep things sane. The real problem here is the different behaviour in
the DRM core code between the refcounts resulting on the active scanout
framebuffer.
Any other thoughts how to solve this without having such refcount hacks
in drivers?
Thanks.
--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
next reply other threads:[~2014-10-11 9:26 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-11 9:26 Russell King - ARM Linux [this message]
2014-10-11 14:08 ` DRM framebuffer refcounting bug... still present Russell King - ARM Linux
2014-10-11 19:12 ` Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20141011092620.GQ5182@n2100.arm.linux.org.uk \
--to=linux@arm.linux.org.uk \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox