changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1214-introduce-resume-exception-capture.patch.patch
1 From 8e18a9db5f895f654b06000d7bd10528e6b795f3 Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Wed, 2 Jul 2008 22:44:11 +0100
4 Subject: [PATCH] introduce-resume-exception-capture.patch
5
6 This patch introduces a new resume debugging concept: if we
7 get an OOPS inbetween starting suspend and finishing resume, it
8 uses a new "emergency spew" device similar to BUT NOT REQUIRING
9 CONFIG_DEBUG_LL to dump the syslog buffer and then the OOPS
10 on the debug device defined by the existing CONFIG_DEBUG_S3C_UART
11 index.  But neither CONFIG_DEBUG_LL nor the S3C low level configs
12 are needed to use this feature.
13
14 Another difference between this feature and CONFIG_DEBUG_LL is that
15 it does not affect resume timing, ordering or UART traffic UNLESS
16 there is an OOPS during resume.
17
18 The patch adds three global exports, one to say if we are inside
19 suspend / resume, and two callbacks for printk() to use to init
20 and dump the emergency data.  The callbacks are set in s3c serial
21 device init, but the whole structure is arch independent.
22
23 Signed-off-by: Andy Green <andy@openmoko.com>
24 ---
25  drivers/serial/s3c2410.c |   69 ++++++++++++++++++++++++++++++++++++++++++++++
26  include/linux/kernel.h   |    2 +
27  include/linux/suspend.h  |    6 ++++
28  kernel/power/main.c      |   10 ++++++-
29  kernel/printk.c          |   41 +++++++++++++++++++++++++++
30  5 files changed, 127 insertions(+), 1 deletions(-)
31
32 diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
33 index 73c6284..fef3c8f 100644
34 --- a/drivers/serial/s3c2410.c
35 +++ b/drivers/serial/s3c2410.c
36 @@ -81,6 +81,7 @@
37  
38  #include <asm/plat-s3c/regs-serial.h>
39  #include <asm/arch/regs-gpio.h>
40 +#include <asm/arch/regs-clock.h>
41  
42  /* structures */
43  
44 @@ -992,6 +993,69 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
45  #endif
46  };
47  
48 +static void s3c24xx_serial_force_debug_port_up(void)
49 +{
50 +       struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[
51 +                                                        CONFIG_DEBUG_S3C_UART];
52 +       struct s3c24xx_uart_clksrc *clksrc = NULL;
53 +       struct clk *clk = NULL;
54 +       unsigned long tmp;
55 +
56 +       s3c24xx_serial_getclk(&ourport->port, &clksrc, &clk, 115200);
57 +
58 +       tmp = __raw_readl(S3C2410_CLKCON);
59 +
60 +       /* re-start uart clocks */
61 +       tmp |= S3C2410_CLKCON_UART0;
62 +       tmp |= S3C2410_CLKCON_UART1;
63 +       tmp |= S3C2410_CLKCON_UART2;
64 +
65 +       __raw_writel(tmp, S3C2410_CLKCON);
66 +       udelay(10);
67 +
68 +       s3c24xx_serial_setsource(&ourport->port, clksrc);
69 +
70 +       if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
71 +               clk_disable(ourport->baudclk);
72 +               ourport->baudclk  = NULL;
73 +       }
74 +
75 +       clk_enable(clk);
76 +
77 +       ourport->clksrc = clksrc;
78 +       ourport->baudclk = clk;
79 +}
80 +
81 +static void s3c2410_printascii(const char *sz)
82 +{
83 +       struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[
84 +                                                        CONFIG_DEBUG_S3C_UART];
85 +       struct uart_port *port = &ourport->port;
86 +
87 +       /* 8 N 1 */
88 +       wr_regl(port, S3C2410_ULCON, (rd_regl(port, S3C2410_ULCON)) | 3);
89 +       /* polling mode */
90 +       wr_regl(port, S3C2410_UCON, (rd_regl(port, S3C2410_UCON) & ~0xc0f) | 5);
91 +       /* disable FIFO */
92 +       wr_regl(port, S3C2410_UFCON, (rd_regl(port, S3C2410_UFCON) & ~0x01));
93 +       /* fix baud rate */
94 +       wr_regl(port, S3C2410_UBRDIV, 26);
95 +
96 +       while (*sz) {
97 +               int timeout = 10000000;
98 +
99 +               /* spin on it being busy */
100 +               while ((!(rd_regl(port, S3C2410_UTRSTAT) & 2)) && timeout--)
101 +                       ;
102 +
103 +               /* transmit register */
104 +               wr_regl(port, S3C2410_UTXH, *sz);
105 +
106 +               sz++;
107 +       }
108 +}
109 +
110 +
111  /* s3c24xx_serial_resetport
112   *
113   * wrapper to call the specific reset for this port (reset the fifos
114 @@ -1167,6 +1231,11 @@ static int s3c24xx_serial_resume(struct platform_device *dev)
115  static int s3c24xx_serial_init(struct platform_driver *drv,
116                                struct s3c24xx_uart_info *info)
117  {
118 +       /* set up the emergency debug UART functions */
119 +
120 +       printk_emergency_debug_spew_init = s3c24xx_serial_force_debug_port_up;
121 +       printk_emergency_debug_spew_send_string = s3c2410_printascii;
122 +
123         dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
124         return platform_driver_register(drv);
125  }
126 diff --git a/include/linux/kernel.h b/include/linux/kernel.h
127 index 94bc996..8e565b4 100644
128 --- a/include/linux/kernel.h
129 +++ b/include/linux/kernel.h
130 @@ -182,6 +182,8 @@ asmlinkage int printk(const char * fmt, ...)
131  extern int log_buf_get_len(void);
132  extern int log_buf_read(int idx);
133  extern int log_buf_copy(char *dest, int idx, int len);
134 +extern void (*printk_emergency_debug_spew_init)(void);
135 +extern void (*printk_emergency_debug_spew_send_string)(const char *);
136  #else
137  static inline int vprintk(const char *s, va_list args)
138         __attribute__ ((format (printf, 1, 0)));
139 diff --git a/include/linux/suspend.h b/include/linux/suspend.h
140 index 4360e08..7186eef 100644
141 --- a/include/linux/suspend.h
142 +++ b/include/linux/suspend.h
143 @@ -122,6 +122,12 @@ struct pbe {
144         struct pbe *next;
145  };
146  
147 +/**
148 + * global indication we are somewhere between start of suspend and end of
149 + * resume, nonzero is true
150 + */
151 +extern int global_inside_suspend;
152 +
153  /* mm/page_alloc.c */
154  extern void drain_local_pages(void);
155  extern void mark_free_pages(struct zone *zone);
156 diff --git a/kernel/power/main.c b/kernel/power/main.c
157 index f71c950..d87bf0d 100644
158 --- a/kernel/power/main.c
159 +++ b/kernel/power/main.c
160 @@ -31,6 +31,10 @@ DEFINE_MUTEX(pm_mutex);
161  unsigned int pm_flags;
162  EXPORT_SYMBOL(pm_flags);
163  
164 +int global_inside_suspend;
165 +EXPORT_SYMBOL(global_inside_suspend);
166 +
167 +
168  #ifdef CONFIG_SUSPEND
169  
170  /* This is just an arbitrary number */
171 @@ -156,10 +160,12 @@ int suspend_devices_and_enter(suspend_state_t state)
172         if (!suspend_ops)
173                 return -ENOSYS;
174  
175 +       global_inside_suspend = 1;
176 +
177         if (suspend_ops->set_target) {
178                 error = suspend_ops->set_target(state);
179                 if (error)
180 -                       return error;
181 +                       goto bail;
182         }
183         suspend_console();
184         error = device_suspend(PMSG_SUSPEND);
185 @@ -183,6 +189,8 @@ int suspend_devices_and_enter(suspend_state_t state)
186         device_resume();
187   Resume_console:
188         resume_console();
189 +bail:
190 +       global_inside_suspend = 0;
191         return error;
192  }
193  
194 diff --git a/kernel/printk.c b/kernel/printk.c
195 index 89011bf..c8691bc 100644
196 --- a/kernel/printk.c
197 +++ b/kernel/printk.c
198 @@ -33,8 +33,11 @@
199  #include <linux/bootmem.h>
200  #include <linux/syscalls.h>
201  #include <linux/jiffies.h>
202 +#include <linux/suspend.h>
203  
204  #include <asm/uaccess.h>
205 +#include <asm/plat-s3c24xx/neo1973.h>
206 +#include <asm/arch/gta02.h>
207  
208  #define __LOG_BUF_LEN  (1 << CONFIG_LOG_BUF_SHIFT)
209  
210 @@ -61,6 +64,12 @@ int console_printk[4] = {
211  int oops_in_progress;
212  EXPORT_SYMBOL(oops_in_progress);
213  
214 +void (*printk_emergency_debug_spew_init)(void) = NULL;
215 +EXPORT_SYMBOL(printk_emergency_debug_spew_init);
216 +
217 +void (*printk_emergency_debug_spew_send_string)(const char *) = NULL;
218 +EXPORT_SYMBOL(printk_emergency_debug_spew_send_string);
219 +
220  /*
221   * console_sem protects the console_drivers list, and also
222   * provides serialisation for access to the entire console
223 @@ -653,6 +662,38 @@ asmlinkage int vprintk(const char *fmt, va_list args)
224         /* Emit the output into the temporary buffer */
225         printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
226  
227 +       /* if you're debugging resume, the normal methods can change resume
228 +        * ordering behaviours because their debugging output is synchronous
229 +        * (ie, CONFIG_DEBUG_LL).  If your problem is an OOPS, this code
230 +        * will not affect the speed and duration and ordering of resume
231 +        * actions, but will give you a chance to read the full undumped
232 +        * syslog AND the OOPS data when it happens
233 +        *
234 +        * if you support it, your debug device init can override the exported
235 +        * emergency_debug_spew_init and emergency_debug_spew_send_string to
236 +        * usually force polling or bitbanging on your debug console device
237 +        */
238 +       if (oops_in_progress && global_inside_suspend &&
239 +           printk_emergency_debug_spew_init &&
240 +           printk_emergency_debug_spew_send_string) {
241 +               unsigned long cur_index;
242 +               char ch[2];
243 +
244 +               if (global_inside_suspend == 1) {
245 +                       (printk_emergency_debug_spew_init)();
246 +
247 +                       ch[1] = '\0';
248 +                       cur_index = con_start;
249 +                       while (cur_index != log_end) {
250 +                               ch[0] = LOG_BUF(cur_index);
251 +                               (printk_emergency_debug_spew_send_string)(ch);
252 +                               cur_index++;
253 +                       }
254 +                       global_inside_suspend++; /* only once */
255 +               }
256 +               (printk_emergency_debug_spew_send_string)(printk_buf);
257 +       }
258 +
259         /*
260          * Copy the output into log_buf.  If the caller didn't provide
261          * appropriate log level tags, we insert them here
262 -- 
263 1.5.6.5
264