[ar71xx] add initial profiles
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1271-always-call-resume-dependencies.patch.patch
1 From 36879992de8774cbf8686740bbda383cc6fbdcbb Mon Sep 17 00:00:00 2001
2 From: \\\\\\\"Mike (mwester)\\\\\\ <mwester@dls.net>
3 Date: Mon, 11 Aug 2008 20:16:09 +0100
4 Subject: [PATCH] always-call-resume-dependencies.patch
5
6 Attached is a patch that has greatly reduced the frequency of failures
7 to resume (due to an oops from the glamo resume handler), and the
8 dreaded "white screen after resume". I can't say that it fixes all of
9 these, although I have yet to see the white-screen since applying this
10 patch and suspending/resuming several hundred times (with the 30-second
11 suspend on the 2008.8 image and the endless stream of GSM error messages
12 generated by something in that image, it has proved to be very useful to
13 do an automated stress test!)
14
15 This patch will apply to stable, and should make stable slightly more,
16 well, "stable".
17
18 [Feel free to remove the debug messages if someone feels strongly about
19 that; I left them in because I think they might be useful in triaging
20 further crashes; I'm not at all convinced that this patch will fix all
21 the cases of resume failures.]
22
23 [[And, yes, this is ugly, really ugly.]]
24
25 [[[Oh yeah - there's still one extreme case that will result in an oops:
26 if a dependent driver is built as a module, and it is unloaded, and it
27 happened that the preceding suspend/resume was aborted, and that abort
28 happened between the dependent driver and the driver upon which it is
29 dependent, then a list entry will be left behind referencing the
30 unloaded module. There's just no good way to fix that given the way the
31 resume dependency plumbing is connected up right now, so just avoid
32 using modules for any of the drivers involved in the resume dependency
33 stuff.]]]
34
35 Regards,
36 Mike (mwester)
37 commit 905d2fc9c45f622418ce9ef4e67c23453aab7571
38 Author: Mike Westerhof <mwester@dls.net>
39 Date: Mon Aug 11 11:11:25 2008 -0500
40
41 always-call-resume-dependencies.patch
42
43 Ensure that a dependent resume handler is always executed,
44 even if the resume handler for driver upon which it is
45 dependent never suspends (and therefore never resumes either).
46 Also make sure that we do not end up with duplicate
47 dependencies registered, something that can happen if the
48 suspend is aborted due to driver failure or an early resume
49 (such as occurs when the GSM interrupts during suspend).
50
51 Signed-off-by: Mike Westerhof <mwester@dls.net>
52 ---
53 drivers/i2c/chips/pcf50633.c | 6 +++++
54 drivers/mfd/glamo/glamo-core.c | 5 ++++
55 drivers/mfd/glamo/glamo-core.h | 1 +
56 drivers/serial/s3c2410.c | 7 ++++++
57 include/linux/resume-dependency.h | 38 ++++++++++++++++++++++++++++++++++++-
58 5 files changed, 56 insertions(+), 1 deletions(-)
59
60 diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
61 index 98c254c..b90ea8c 100644
62 --- a/drivers/i2c/chips/pcf50633.c
63 +++ b/drivers/i2c/chips/pcf50633.c
64 @@ -183,6 +183,7 @@ struct pcf50633_data {
65 } standby_regs;
66
67 struct resume_dependency resume_dependency;
68 + int is_suspended;
69
70 #endif
71 };
72 @@ -2366,6 +2367,8 @@ void pcf50633_register_resume_dependency(struct pcf50633_data *pcf,
73 struct resume_dependency *dep)
74 {
75 register_resume_dependency(&pcf->resume_dependency, dep);
76 + if (pcf->is_suspended)
77 + activate_all_resume_dependencies(&pcf->resume_dependency);
78 }
79 EXPORT_SYMBOL_GPL(pcf50633_register_resume_dependency);
80
81 @@ -2462,6 +2465,8 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state)
82
83 mutex_unlock(&pcf->lock);
84
85 + pcf->is_suspended = 1;
86 + activate_all_resume_dependencies(&pcf->resume_dependency);
87 return 0;
88 }
89
90 @@ -2590,6 +2595,7 @@ static int pcf50633_resume(struct device *dev)
91 get_device(&pcf->client.dev);
92 pcf50633_work(&pcf->work);
93
94 + pcf->is_suspended = 0;
95 callback_all_resume_dependencies(&pcf->resume_dependency);
96
97 return 0;
98 diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
99 index c094a8c..e310382 100644
100 --- a/drivers/mfd/glamo/glamo-core.c
101 +++ b/drivers/mfd/glamo/glamo-core.c
102 @@ -1248,6 +1248,8 @@ void glamo_register_resume_dependency(struct resume_dependency *
103 {
104 register_resume_dependency(&glamo_handle->resume_dependency,
105 resume_dependency);
106 + if (glamo_handle->is_suspended)
107 + activate_all_resume_dependencies(&glamo_handle->resume_dependency);
108 }
109 EXPORT_SYMBOL_GPL(glamo_register_resume_dependency);
110
111 @@ -1255,12 +1257,15 @@ EXPORT_SYMBOL_GPL(glamo_register_resume_dependency);
112 static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
113 {
114 glamo_power(glamo_handle, GLAMO_POWER_SUSPEND);
115 + glamo_handle->is_suspended = 1;
116 + activate_all_resume_dependencies(&glamo_handle->resume_dependency);
117 return 0;
118 }
119
120 static int glamo_resume(struct platform_device *pdev)
121 {
122 glamo_power(glamo_handle, GLAMO_POWER_ON);
123 + glamo_handle->is_suspended = 0;
124 callback_all_resume_dependencies(&glamo_handle->resume_dependency);
125
126 return 0;
127 diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/glamo-core.h
128 index d3f4309..ac5eacf 100644
129 --- a/drivers/mfd/glamo/glamo-core.h
130 +++ b/drivers/mfd/glamo/glamo-core.h
131 @@ -32,6 +32,7 @@ struct glamo_core {
132 struct resume_dependency resume_dependency;
133 u32 engine_enabled_bitfield;
134 u32 engine_enabled_bitfield_suspend;
135 + int is_suspended;
136 };
137
138 struct glamo_script {
139 diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
140 index 2a388cf..3b1c07b 100644
141 --- a/drivers/serial/s3c2410.c
142 +++ b/drivers/serial/s3c2410.c
143 @@ -116,6 +116,7 @@ struct s3c24xx_uart_port {
144 struct uart_port port;
145
146 struct resume_dependency resume_dependency;
147 + int is_suspended;
148 };
149
150
151 @@ -1188,10 +1189,13 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
152 static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
153 {
154 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
155 + struct s3c24xx_uart_port *ourport = to_ourport(port);
156
157 if (port)
158 uart_suspend_port(&s3c24xx_uart_drv, port);
159
160 + activate_all_resume_dependencies(&ourport->resume_dependency);
161 + ourport->is_suspended = 1;
162 return 0;
163 }
164
165 @@ -1202,6 +1206,8 @@ void s3c24xx_serial_register_resume_dependency(struct resume_dependency *
166
167 register_resume_dependency(&ourport->resume_dependency,
168 resume_dependency);
169 + if (ourport->is_suspended)
170 + activate_all_resume_dependencies(&ourport->resume_dependency);
171 }
172 EXPORT_SYMBOL(s3c24xx_serial_register_resume_dependency);
173
174 @@ -1218,6 +1224,7 @@ static int s3c24xx_serial_resume(struct platform_device *dev)
175 uart_resume_port(&s3c24xx_uart_drv, port);
176 }
177
178 + ourport->is_suspended = 0;
179 callback_all_resume_dependencies(&ourport->resume_dependency);
180
181 return 0;
182 diff --git a/include/linux/resume-dependency.h b/include/linux/resume-dependency.h
183 index e0c0f33..959cadd 100644
184 --- a/include/linux/resume-dependency.h
185 +++ b/include/linux/resume-dependency.h
186 @@ -38,6 +38,7 @@ struct resume_dependency {
187 */
188
189 #define init_resume_dependency_list(_head) \
190 + printk(KERN_ERR "##### init_resume_dependency_list(head=%p)\n", (_head)); \
191 INIT_LIST_HEAD(&(_head)->list);
192
193
194 @@ -48,7 +49,18 @@ struct resume_dependency {
195 */
196
197 #define register_resume_dependency(_head, _dep) { \
198 - (_dep)->called_flag = 0; \
199 + struct list_head *_pos, *_q; \
200 + struct resume_dependency *_d; \
201 +\
202 + printk(KERN_ERR "##### register_resume_dependency(head=%p, dep=%p)\n", (_head), (_dep)); \
203 + (_dep)->called_flag = 1; \
204 + list_for_each_safe(_pos, _q, &((_head)->list)) { \
205 + _d = list_entry(_pos, struct resume_dependency, list); \
206 + if (_d == (_dep)) { \
207 + list_del(_pos); \
208 + printk(KERN_ERR "##### duplicate dependency removed first\n"); \
209 + } \
210 + } \
211 list_add(&(_dep)->list, &(_head)->list); \
212 }
213
214 @@ -61,14 +73,38 @@ struct resume_dependency {
215 struct list_head *_pos, *_q; \
216 struct resume_dependency *_dep; \
217 \
218 + printk(KERN_ERR "##### callback_all_resume_dependencies(head=%p)\n", (_head)); \
219 list_for_each_safe(_pos, _q, &((_head)->list)) { \
220 _dep = list_entry(_pos, struct resume_dependency, list); \
221 + printk(KERN_ERR "##### callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \
222 _dep->called_flag = 1; \
223 + printk(KERN_ERR "##### callback=%p(context=%p))\n", (_dep->callback),(_dep->context)); \
224 (_dep->callback)(_dep->context); \
225 list_del(_pos); \
226 } \
227 }
228
229 +/* When a dependency is added, it is not actually active; the dependent resume
230 + * handler will function as normal. The dependency is activated by the suspend
231 + * handler for the driver that will be doing the callbacks. This ensures that
232 + * if the suspend is aborted for any reason (error, driver busy, etc), that all
233 + * suspended drivers will resume, even if the driver upon which they are dependent
234 + * did not suspend, and hence will not resume, and thus would be unable to perform
235 + * the callbacks.
236 + */
237 +
238 +#define activate_all_resume_dependencies(_head) { \
239 + struct list_head *_pos, *_q; \
240 + struct resume_dependency *_dep; \
241 +\
242 + printk(KERN_ERR "##### activate_all_resume_dependencies(head=%p)\n", (_head)); \
243 + list_for_each_safe(_pos, _q, &((_head)->list)) { \
244 + _dep = list_entry(_pos, struct resume_dependency, list); \
245 + printk(KERN_ERR "##### activating callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \
246 + _dep->called_flag = 0; \
247 + } \
248 +}
249 +
250 /* if your resume action is dependent on multiple drivers being resumed already,
251 * register the same callback with each driver you are dependent on, and check
252 * .called_flag for all of the struct resume_dependency. When they are all 1
253 --
254 1.5.6.5
255
This page took 0.055199 seconds and 5 git commands to generate.