History

drm: revamp locking around fb creation/destruction

Well, at least step 1. The goal here is that framebuffer objects can survive outside of the mode_config lock, with just a reference held as protection. The first step to get there is to introduce a special fb_lock which protects fb lookup, creation and destruction, to make them appear atomic. This new fb_lock can nest within the mode_config lock. But the idea is (once the reference counting part is completed) that we only quickly take that fb_lock to lookup a framebuffer and grab a reference, without any other locks involved. vmwgfx is the only driver which does framebuffer lookups itself, also wrap those calls to drm_mode_object_find with the new lock. Also protect the fb_list walking in i915 and omapdrm with the new lock. As a slight complication there's also the list of user-created fbs attached to the file private. The problem now is that at fclose() time we need to walk that list, eventually do a modeset call to remove the fb from active usage (and are required to be able to take the mode_config lock), but in the end we need to grab the new fb_lock to remove the fb from the list. The easiest solution is to add another mutex to protect this per-file list. Currently that new fbs_lock nests within the modeset locks and so appears redudant. But later patches will switch around this sequence so that taking the modeset locks in the fb destruction path is optional in the fastpath. Ultimately the goal is that addfb and rmfb do not require the mode_config lock, since otherwise they have the potential to introduce stalls in the pageflip sequence of a compositor (if the compositor e.g. switches to a fullscreen client or if it enables a plane). But that requires a few more steps and hoops to jump through. Note that framebuffer creation/destruction is now double-protected - once by the fb_lock and in parts by the idr_lock. The later would be unnecessariy if framebuffers would have their own idr allocator. But that's material for another patch (series). v2: Properly initialize the fb->filp_head list in _init, otherwise the newly added WARN to check whether the fb isn't on a fpriv list any more will fail for driver-private objects. v3: Fixup two error-case unlock bugs spotted by Richard Wilbur.

Daniel Vetter committed 13 years ago

Commit 4b096ac1 parent dac35667 files · +113 −37Browse files

Showing the changes to include/drm (2 of 7 files). Show all

Unified · Split

2 files
  1. include/drm/drmP.h +8 −0
  2. include/drm/drm_crtc.h +14 −0
include/drm/drmP.h+8−0
@@ -446,7 +446,15 @@ struct drm_file { · 445 unmodified lines
446446 int is_master; /* this file private is a master for a minor */
447447 struct drm_master *master; /* master this node is currently associated with
448448 N.B. not always minor->master */
449+
450+ /**
451+ * fbs - List of framebuffers associated with this file.
452+ *
453+ * Protected by fbs_lock. Note that the fbs list holds a reference on
454+ * the fb object to prevent it from untimely disappearing.
455+ */
449456 struct list_head fbs;
457+ struct mutex fbs_lock;
450458
451459 wait_queue_head_t event_wait;
452460 struct list_head event_list;
include/drm/drm_crtc.h+14−0
@@ -254,6 +254,10 @@ struct drm_framebuffer { · 253 unmodified lines
254254 * userspace perspective.
255255 */
256256 struct kref refcount;
257+ /*
258+ * Place on the dev->mode_config.fb_list, access protected by
259+ * dev->mode_config.fb_lock.
260+ */
257261 struct list_head head;
258262 struct drm_mode_object base;
259263 const struct drm_framebuffer_funcs *funcs;
@@ -780,8 +784,18 @@ struct drm_mode_config { · 520 unmodified lines
780784 struct mutex idr_mutex; /* for IDR management */
781785 struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
782786 /* this is limited to one for now */
787+
788+
789+ /**
790+ * fb_lock - mutex to protect fb state
791+ *
792+ * Besides the global fb list his also protects the fbs list in the
793+ * file_priv
794+ */
795+ struct mutex fb_lock;
783796 int num_fb;
784797 struct list_head fb_list;
798+
785799 int num_connector;
786800 struct list_head connector_list;
787801 int num_encoder;