diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-08-25 09:45:14 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2015-12-15 08:41:24 -0500 |
commit | c3c296b069dd84264cbaf7a0c4c13783e7508d50 (patch) | |
tree | a6e66ebae1cf330d046aa2bc57a9aa6e380cf88d | |
parent | 1c639baeafa5fe40e6b6e6ee99e9ddd29986fba1 (diff) |
fbdev: Debug knob to register without holding console_lock
When the usual fbcon legacy options are enabled we have
->register_framebuffer
->fb notifier chain calls into fbcon
->fbcon sets up console on new fbi
->fbi->set_par
->drm_fb_helper_set_par exercises full kms api
And because of locking inversion hilarity all of register_framebuffer
is done with the console lock held. Which means that the first time on
driver load we exercise _all_ the kms code (all probe paths and
modeset paths for everything connected) is under the console lock.
That means if anything goes belly-up in that big pile of code nothing
ever reaches logfiles (and the machine is dead).
Usual tactic to debug that is to temporarily remove those console_lock
calls to be able to capture backtraces. I'm fed up writing this patch
and recompiling kernels. Hence this patch here to add an unsafe,
kernel-taining option to do this at runtime.
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: linux-fbdev@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r-- | drivers/video/fbdev/core/fbmem.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 0705d8883ede..4e73b6f6b1c0 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c | |||
@@ -1608,6 +1608,11 @@ static int do_remove_conflicting_framebuffers(struct apertures_struct *a, | |||
1608 | return 0; | 1608 | return 0; |
1609 | } | 1609 | } |
1610 | 1610 | ||
1611 | static bool lockless_register_fb; | ||
1612 | module_param_named_unsafe(lockless_register_fb, lockless_register_fb, bool, 0400); | ||
1613 | MODULE_PARM_DESC(lockless_register_fb, | ||
1614 | "Lockless framebuffer registration for debugging [default=off]"); | ||
1615 | |||
1611 | static int do_register_framebuffer(struct fb_info *fb_info) | 1616 | static int do_register_framebuffer(struct fb_info *fb_info) |
1612 | { | 1617 | { |
1613 | int i, ret; | 1618 | int i, ret; |
@@ -1675,15 +1680,18 @@ static int do_register_framebuffer(struct fb_info *fb_info) | |||
1675 | registered_fb[i] = fb_info; | 1680 | registered_fb[i] = fb_info; |
1676 | 1681 | ||
1677 | event.info = fb_info; | 1682 | event.info = fb_info; |
1678 | console_lock(); | 1683 | if (!lockless_register_fb) |
1684 | console_lock(); | ||
1679 | if (!lock_fb_info(fb_info)) { | 1685 | if (!lock_fb_info(fb_info)) { |
1680 | console_unlock(); | 1686 | if (!lockless_register_fb) |
1687 | console_unlock(); | ||
1681 | return -ENODEV; | 1688 | return -ENODEV; |
1682 | } | 1689 | } |
1683 | 1690 | ||
1684 | fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); | 1691 | fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); |
1685 | unlock_fb_info(fb_info); | 1692 | unlock_fb_info(fb_info); |
1686 | console_unlock(); | 1693 | if (!lockless_register_fb) |
1694 | console_unlock(); | ||
1687 | return 0; | 1695 | return 0; |
1688 | } | 1696 | } |
1689 | 1697 | ||