]>
Commit | Line | Data |
---|---|---|
14818f4b GKH |
1 | From 4a47a0e09c504e3ce0ccdb405411aefc5b09deb8 Mon Sep 17 00:00:00 2001 |
2 | From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org> | |
3 | Date: Fri, 2 Sep 2011 19:24:03 +0200 | |
4 | Subject: fb: sh-mobile: Fix deadlock risk between lock_fb_info() and console_lock() | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= <bonbons@linux-vserver.org> | |
10 | ||
11 | commit 4a47a0e09c504e3ce0ccdb405411aefc5b09deb8 upstream. | |
12 | ||
13 | Following on Herton's patch "fb: avoid possible deadlock caused by | |
14 | fb_set_suspend" which moves lock_fb_info() out of fb_set_suspend() | |
15 | to its callers, correct sh-mobile's locking around call to | |
16 | fb_set_suspend() and the same sort of deaklocks with console_lock() | |
17 | due to order of taking the lock. | |
18 | ||
19 | console_lock() must be taken while fb_info is already locked and fb_info | |
20 | must be locked while calling fb_set_suspend(). | |
21 | ||
22 | Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org> | |
23 | Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> | |
24 | Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
26 | ||
27 | --- | |
28 | drivers/video/sh_mobile_hdmi.c | 47 ++++++++++++++++++++++------------------- | |
29 | 1 file changed, 26 insertions(+), 21 deletions(-) | |
30 | ||
31 | --- a/drivers/video/sh_mobile_hdmi.c | |
32 | +++ b/drivers/video/sh_mobile_hdmi.c | |
33 | @@ -1111,6 +1111,7 @@ static long sh_hdmi_clk_configure(struct | |
34 | static void sh_hdmi_edid_work_fn(struct work_struct *work) | |
35 | { | |
36 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); | |
37 | + struct fb_info *info; | |
38 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | |
39 | struct sh_mobile_lcdc_chan *ch; | |
40 | int ret; | |
41 | @@ -1123,8 +1124,9 @@ static void sh_hdmi_edid_work_fn(struct | |
42 | ||
43 | mutex_lock(&hdmi->mutex); | |
44 | ||
45 | + info = hdmi->info; | |
46 | + | |
47 | if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { | |
48 | - struct fb_info *info = hdmi->info; | |
49 | unsigned long parent_rate = 0, hdmi_rate; | |
50 | ||
51 | ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); | |
52 | @@ -1148,42 +1150,45 @@ static void sh_hdmi_edid_work_fn(struct | |
53 | ||
54 | ch = info->par; | |
55 | ||
56 | - console_lock(); | |
57 | + if (lock_fb_info(info)) { | |
58 | + console_lock(); | |
59 | ||
60 | - /* HDMI plug in */ | |
61 | - if (!sh_hdmi_must_reconfigure(hdmi) && | |
62 | - info->state == FBINFO_STATE_RUNNING) { | |
63 | - /* | |
64 | - * First activation with the default monitor - just turn | |
65 | - * on, if we run a resume here, the logo disappears | |
66 | - */ | |
67 | - if (lock_fb_info(info)) { | |
68 | + /* HDMI plug in */ | |
69 | + if (!sh_hdmi_must_reconfigure(hdmi) && | |
70 | + info->state == FBINFO_STATE_RUNNING) { | |
71 | + /* | |
72 | + * First activation with the default monitor - just turn | |
73 | + * on, if we run a resume here, the logo disappears | |
74 | + */ | |
75 | info->var.width = hdmi->var.width; | |
76 | info->var.height = hdmi->var.height; | |
77 | sh_hdmi_display_on(hdmi, info); | |
78 | - unlock_fb_info(info); | |
79 | + } else { | |
80 | + /* New monitor or have to wake up */ | |
81 | + fb_set_suspend(info, 0); | |
82 | } | |
83 | - } else { | |
84 | - /* New monitor or have to wake up */ | |
85 | - fb_set_suspend(info, 0); | |
86 | - } | |
87 | ||
88 | - console_unlock(); | |
89 | + console_unlock(); | |
90 | + unlock_fb_info(info); | |
91 | + } | |
92 | } else { | |
93 | ret = 0; | |
94 | - if (!hdmi->info) | |
95 | + if (!info) | |
96 | goto out; | |
97 | ||
98 | hdmi->monspec.modedb_len = 0; | |
99 | fb_destroy_modedb(hdmi->monspec.modedb); | |
100 | hdmi->monspec.modedb = NULL; | |
101 | ||
102 | - console_lock(); | |
103 | + if (lock_fb_info(info)) { | |
104 | + console_lock(); | |
105 | ||
106 | - /* HDMI disconnect */ | |
107 | - fb_set_suspend(hdmi->info, 1); | |
108 | + /* HDMI disconnect */ | |
109 | + fb_set_suspend(info, 1); | |
110 | ||
111 | - console_unlock(); | |
112 | + console_unlock(); | |
113 | + unlock_fb_info(info); | |
114 | + } | |
115 | } | |
116 | ||
117 | out: |