Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=8dab63761219d7bc6a7d7d3b5f0fca76af5533a5
Commit:     8dab63761219d7bc6a7d7d3b5f0fca76af5533a5
Parent:     ba21611c9c0031ca8388cae5e43b38c29c8b595d
Author:     Jeremy Kerr <[EMAIL PROTECTED]>
AuthorDate: Fri Jan 11 14:28:04 2008 +0100
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Fri Jan 11 11:47:43 2008 -0800

    ps3fb: fix deadlock on kexec()
    
    Since the introduction of the acquire_console_sem calls in
    0333d83509c7d8496c8965b5ba9bc0c98e83c259, kexecing can cause the
    kernel to deadlock:
    
     ps3fb_shutdown()
      -> unregister_framebuffer()
      -> fb_notifier_call_chain(FB_EVENT_FB_UNBIND)
      -> fbcon_fb_unbind()
      -> unbind_con_driver()
      -> bind_con_driver()
        [ acquires console_sem ]
      -> fbcon_deinit()
      -> fbops->fb_release(newinfo, 0)
      -> ps3fb_release()
      -> ps3fb_sync()
        [ acquires console_sem ]
    
    This change avoids the deadlock by moving the acquire_console_sem()
    out of ps3fb_sync(), and puts it into the two other callsites, leaving
    ps3fb_release() to call ps3fb_sync() without the console semaphore.
    
    [Geert]
      - Corrected call sequence above
      - ps3fb_release() may be called with and without console_sem held. This 
is an
        inconsistency that should be fixed at the fb level, but for now, try to
        acquire console_sem in ps3fb_release().
    
        I think it's safer to let ps3fb_release() try to acquire console_sem and
        not refresh the screen if it fails, than to call ps3fb_sync() without
        holding console_sem, as ps3fb_par may be modified at the same time, 
causing
        crashes or lockups.
    
        Besides, ps3fb_release() only calls ps3fb_sync() to refresh the screen
        when display flipping is disabled, which is an uncommon case (except 
during
        shutdown/kexec).
    
    Signed-off-by: Jeremy Kerr <[EMAIL PROTECTED]>
    Signed-off-by: Geert Uytterhoeven <[EMAIL PROTECTED]>
    Cc: Benjamin Herrenschmidt <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 drivers/video/ps3fb.c |   12 ++++++++----
 1 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index ae07e02..044a423 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -443,8 +443,6 @@ static int ps3fb_sync(struct fb_info *info, u32 frame)
        u32 ddr_line_length, xdr_line_length;
        u64 ddr_base, xdr_base;
 
-       acquire_console_sem();
-
        if (frame > par->num_frames - 1) {
                dev_dbg(info->device, "%s: invalid frame number (%u)\n",
                        __func__, frame);
@@ -464,7 +462,6 @@ static int ps3fb_sync(struct fb_info *info, u32 frame)
                         xdr_line_length);
 
 out:
-       release_console_sem();
        return error;
 }
 
@@ -479,7 +476,10 @@ static int ps3fb_release(struct fb_info *info, int user)
        if (atomic_dec_and_test(&ps3fb.f_count)) {
                if (atomic_read(&ps3fb.ext_flip)) {
                        atomic_set(&ps3fb.ext_flip, 0);
-                       ps3fb_sync(info, 0);    /* single buffer */
+                       if (!try_acquire_console_sem()) {
+                               ps3fb_sync(info, 0);    /* single buffer */
+                               release_console_sem();
+                       }
                }
        }
        return 0;
@@ -865,7 +865,9 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int 
cmd,
                        break;
 
                dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val);
+               acquire_console_sem();
                retval = ps3fb_sync(info, val);
+               release_console_sem();
                break;
 
        default:
@@ -885,7 +887,9 @@ static int ps3fbd(void *arg)
                set_current_state(TASK_INTERRUPTIBLE);
                if (ps3fb.is_kicked) {
                        ps3fb.is_kicked = 0;
+                       acquire_console_sem();
                        ps3fb_sync(info, 0);    /* single buffer */
+                       release_console_sem();
                }
                schedule();
        }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to