aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 19:00:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 19:00:44 -0400
commit9779714c8af09d57527f18d9aa2207dcc27a8687 (patch)
tree52182f2289d9b7a77fbe119f4cd5726ef6494e66
parent89a6c8cb9e6e11b6e3671dce7e037789b8f7cf62 (diff)
parent65b5ac1479840a3e87f086d68e5ef91f3002e8e2 (diff)
Merge branch 'kms-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'kms-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb: kgdb,docs: Update the kgdb docs to include kms drm_fb_helper: Preserve capability to use atomic kms i915: when kgdb is active display compression should be off drm/i915: use new fb debug hooks drm: add KGDB/KDB support fb: add hooks to handle KDB enter/exit kgdboc: Add call backs to allow kernel mode switching vt,console,kdb: automatically set kdb LINES variable vt,console,kdb: implement atomic console enter/leave functions
-rw-r--r--Documentation/DocBook/kgdb.tmpl108
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--drivers/char/vt.c78
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c76
-rw-r--r--drivers/gpu/drm/i915/intel_display.c102
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c2
-rw-r--r--drivers/serial/kgdboc.c18
-rw-r--r--drivers/video/console/fbcon.c26
-rw-r--r--drivers/video/console/fbcon.h1
-rw-r--r--include/drm/drm_crtc_helper.h2
-rw-r--r--include/drm/drm_fb_helper.h5
-rw-r--r--include/linux/console.h13
-rw-r--r--include/linux/fb.h13
-rw-r--r--include/linux/kdb.h4
-rw-r--r--kernel/debug/kdb/kdb_private.h2
15 files changed, 444 insertions, 15 deletions
diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl
index 55f12ac37acd..490d862c5f0d 100644
--- a/Documentation/DocBook/kgdb.tmpl
+++ b/Documentation/DocBook/kgdb.tmpl
@@ -199,10 +199,33 @@
199 may be configured as a kernel built-in or a kernel loadable module. 199 may be configured as a kernel built-in or a kernel loadable module.
200 You can only make use of <constant>kgdbwait</constant> and early 200 You can only make use of <constant>kgdbwait</constant> and early
201 debugging if you build kgdboc into the kernel as a built-in. 201 debugging if you build kgdboc into the kernel as a built-in.
202 <para>Optionally you can elect to activate kms (Kernel Mode
203 Setting) integration. When you use kms with kgdboc and you have a
204 video driver that has atomic mode setting hooks, it is possible to
205 enter the debugger on the graphics console. When the kernel
206 execution is resumed, the previous graphics mode will be restored.
207 This integration can serve as a useful tool to aid in diagnosing
208 crashes or doing analysis of memory with kdb while allowing the
209 full graphics console applications to run.
210 </para>
202 </para> 211 </para>
203 <sect2 id="kgdbocArgs"> 212 <sect2 id="kgdbocArgs">
204 <title>kgdboc arguments</title> 213 <title>kgdboc arguments</title>
205 <para>Usage: <constant>kgdboc=[kbd][[,]serial_device][,baud]</constant></para> 214 <para>Usage: <constant>kgdboc=[kms][[,]kbd][[,]serial_device][,baud]</constant></para>
215 <para>The order listed above must be observed if you use any of the
216 optional configurations together.
217 </para>
218 <para>Abbreviations:
219 <itemizedlist>
220 <listitem><para>kms = Kernel Mode Setting</para></listitem>
221 <listitem><para>kbd = Keyboard</para></listitem>
222 </itemizedlist>
223 </para>
224 <para>You can configure kgdboc to use the keyboard, and or a serial
225 device depending on if you are using kdb and or kgdb, in one of the
226 following scenarios. The order listed above must be observed if
227 you use any of the optional configurations together. Using kms +
228 only gdb is generally not a useful combination.</para>
206 <sect3 id="kgdbocArgs1"> 229 <sect3 id="kgdbocArgs1">
207 <title>Using loadable module or built-in</title> 230 <title>Using loadable module or built-in</title>
208 <para> 231 <para>
@@ -212,7 +235,7 @@
212 <listitem> 235 <listitem>
213 <para>As a kernel loadable module:</para> 236 <para>As a kernel loadable module:</para>
214 <para>Use the command: <constant>modprobe kgdboc kgdboc=&lt;tty-device&gt;,[baud]</constant></para> 237 <para>Use the command: <constant>modprobe kgdboc kgdboc=&lt;tty-device&gt;,[baud]</constant></para>
215 <para>Here are two examples of how you might formate the kgdboc 238 <para>Here are two examples of how you might format the kgdboc
216 string. The first is for an x86 target using the first serial port. 239 string. The first is for an x86 target using the first serial port.
217 The second example is for the ARM Versatile AB using the second 240 The second example is for the ARM Versatile AB using the second
218 serial port. 241 serial port.
@@ -240,6 +263,9 @@
240 </sect3> 263 </sect3>
241 <sect3 id="kgdbocArgs3"> 264 <sect3 id="kgdbocArgs3">
242 <title>More examples</title> 265 <title>More examples</title>
266 <para>You can configure kgdboc to use the keyboard, and or a serial
267 device depending on if you are using kdb and or kgdb, in one of the
268 following scenarios.</para>
243 <para>You can configure kgdboc to use the keyboard, and or a serial device 269 <para>You can configure kgdboc to use the keyboard, and or a serial device
244 depending on if you are using kdb and or kgdb, in one of the 270 depending on if you are using kdb and or kgdb, in one of the
245 following scenarios. 271 following scenarios.
@@ -255,6 +281,12 @@
255 <listitem><para>kdb with a keyboard</para> 281 <listitem><para>kdb with a keyboard</para>
256 <para><constant>kgdboc=kbd</constant></para> 282 <para><constant>kgdboc=kbd</constant></para>
257 </listitem> 283 </listitem>
284 <listitem><para>kdb with kernel mode setting</para>
285 <para><constant>kgdboc=kms,kbd</constant></para>
286 </listitem>
287 <listitem><para>kdb with kernel mode setting and kgdb over a serial port</para>
288 <para><constant>kgdboc=kms,kbd,ttyS0,115200</constant></para>
289 </listitem>
258 </orderedlist> 290 </orderedlist>
259 </para> 291 </para>
260 </sect3> 292 </sect3>
@@ -637,6 +669,8 @@ Task Addr Pid Parent [*] cpu State Thread Command
637 <listitem><para>The logic to perform safe memory reads and writes to memory while using the debugger</para></listitem> 669 <listitem><para>The logic to perform safe memory reads and writes to memory while using the debugger</para></listitem>
638 <listitem><para>A full implementation for software breakpoints unless overridden by the arch</para></listitem> 670 <listitem><para>A full implementation for software breakpoints unless overridden by the arch</para></listitem>
639 <listitem><para>The API to invoke either the kdb or kgdb frontend to the debug core.</para></listitem> 671 <listitem><para>The API to invoke either the kdb or kgdb frontend to the debug core.</para></listitem>
672 <listitem><para>The structures and callback API for atomic kernel mode setting.</para>
673 <para>NOTE: kgdboc is where the kms callbacks are invoked.</para></listitem>
640 </itemizedlist> 674 </itemizedlist>
641 </para> 675 </para>
642 </listitem> 676 </listitem>
@@ -747,6 +781,8 @@ Task Addr Pid Parent [*] cpu State Thread Command
747 </sect1> 781 </sect1>
748 <sect1 id="kgdbocDesign"> 782 <sect1 id="kgdbocDesign">
749 <title>kgdboc internals</title> 783 <title>kgdboc internals</title>
784 <sect2>
785 <title>kgdboc and uarts</title>
750 <para> 786 <para>
751 The kgdboc driver is actually a very thin driver that relies on the 787 The kgdboc driver is actually a very thin driver that relies on the
752 underlying low level to the hardware driver having "polling hooks" 788 underlying low level to the hardware driver having "polling hooks"
@@ -754,11 +790,8 @@ Task Addr Pid Parent [*] cpu State Thread Command
754 implementation of kgdboc it the serial_core was changed to expose a 790 implementation of kgdboc it the serial_core was changed to expose a
755 low level UART hook for doing polled mode reading and writing of a 791 low level UART hook for doing polled mode reading and writing of a
756 single character while in an atomic context. When kgdb makes an I/O 792 single character while in an atomic context. When kgdb makes an I/O
757 request to the debugger, kgdboc invokes a call back in the serial 793 request to the debugger, kgdboc invokes a callback in the serial
758 core which in turn uses the call back in the UART driver. It is 794 core which in turn uses the callback in the UART driver.</para>
759 certainly possible to extend kgdboc to work with non-UART based
760 consoles in the future.
761 </para>
762 <para> 795 <para>
763 When using kgdboc with a UART, the UART driver must implement two callbacks in the <constant>struct uart_ops</constant>. Example from drivers/8250.c:<programlisting> 796 When using kgdboc with a UART, the UART driver must implement two callbacks in the <constant>struct uart_ops</constant>. Example from drivers/8250.c:<programlisting>
764#ifdef CONFIG_CONSOLE_POLL 797#ifdef CONFIG_CONSOLE_POLL
@@ -772,9 +805,68 @@ Task Addr Pid Parent [*] cpu State Thread Command
772 that they can be called from an atomic context and have to restore 805 that they can be called from an atomic context and have to restore
773 the state of the UART chip on return such that the system can return 806 the state of the UART chip on return such that the system can return
774 to normal when the debugger detaches. You need to be very careful 807 to normal when the debugger detaches. You need to be very careful
775 with any kind of lock you consider, because failing here is most 808 with any kind of lock you consider, because failing here is most likely
776 going to mean pressing the reset button. 809 going to mean pressing the reset button.
777 </para> 810 </para>
811 </sect2>
812 <sect2 id="kgdbocKbd">
813 <title>kgdboc and keyboards</title>
814 <para>The kgdboc driver contains logic to configure communications
815 with an attached keyboard. The keyboard infrastructure is only
816 compiled into the kernel when CONFIG_KDB_KEYBOARD=y is set in the
817 kernel configuration.</para>
818 <para>The core polled keyboard driver driver for PS/2 type keyboards
819 is in drivers/char/kdb_keyboard.c. This driver is hooked into the
820 debug core when kgdboc populates the callback in the array
821 called <constant>kdb_poll_funcs[]</constant>. The
822 kdb_get_kbd_char() is the top-level function which polls hardware
823 for single character input.
824 </para>
825 </sect2>
826 <sect2 id="kgdbocKms">
827 <title>kgdboc and kms</title>
828 <para>The kgdboc driver contains logic to request the graphics
829 display to switch to a text context when you are using
830 "kgdboc=kms,kbd", provided that you have a video driver which has a
831 frame buffer console and atomic kernel mode setting support.</para>
832 <para>
833 Every time the kernel
834 debugger is entered it calls kgdboc_pre_exp_handler() which in turn
835 calls con_debug_enter() in the virtual console layer. On resuming kernel
836 execution, the kernel debugger calls kgdboc_post_exp_handler() which
837 in turn calls con_debug_leave().</para>
838 <para>Any video driver that wants to be compatible with the kernel
839 debugger and the atomic kms callbacks must implement the
840 mode_set_base_atomic, fb_debug_enter and fb_debug_leave operations.
841 For the fb_debug_enter and fb_debug_leave the option exists to use
842 the generic drm fb helper functions or implement something custom for
843 the hardware. The following example shows the initialization of the
844 .mode_set_base_atomic operation in
845 drivers/gpu/drm/i915/intel_display.c:
846 <informalexample>
847 <programlisting>
848static const struct drm_crtc_helper_funcs intel_helper_funcs = {
849[...]
850 .mode_set_base_atomic = intel_pipe_set_base_atomic,
851[...]
852};
853 </programlisting>
854 </informalexample>
855 </para>
856 <para>Here is an example of how the i915 driver initializes the fb_debug_enter and fb_debug_leave functions to use the generic drm helpers in
857 drivers/gpu/drm/i915/intel_fb.c:
858 <informalexample>
859 <programlisting>
860static struct fb_ops intelfb_ops = {
861[...]
862 .fb_debug_enter = drm_fb_helper_debug_enter,
863 .fb_debug_leave = drm_fb_helper_debug_leave,
864[...]
865};
866 </programlisting>
867 </informalexample>
868 </para>
869 </sect2>
778 </sect1> 870 </sect1>
779 </chapter> 871 </chapter>
780 <chapter id="credits"> 872 <chapter id="credits">
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ef8b11cec6e9..f72ba727441f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1145,9 +1145,12 @@ and is between 256 and 4096 characters. It is defined in the file
1145 kgdboc= [KGDB,HW] kgdb over consoles. 1145 kgdboc= [KGDB,HW] kgdb over consoles.
1146 Requires a tty driver that supports console polling, 1146 Requires a tty driver that supports console polling,
1147 or a supported polling keyboard driver (non-usb). 1147 or a supported polling keyboard driver (non-usb).
1148 Serial only format: <serial_device>[,baud] 1148 Serial only format: <serial_device>[,baud]
1149 keyboard only format: kbd 1149 keyboard only format: kbd
1150 keyboard and serial format: kbd,<serial_device>[,baud] 1150 keyboard and serial format: kbd,<serial_device>[,baud]
1151 Optional Kernel mode setting:
1152 kms, kbd format: kms,kbd
1153 kms, kbd and serial format: kms,kbd,<ser_dev>[,baud]
1151 1154
1152 kgdbwait [KGDB] Stop kernel execution and enter the 1155 kgdbwait [KGDB] Stop kernel execution and enter the
1153 kernel debugger at the earliest opportunity. 1156 kernel debugger at the earliest opportunity.
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 7cdb6ee569cd..4a9eb3044e52 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -104,6 +104,7 @@
104#include <linux/io.h> 104#include <linux/io.h>
105#include <asm/system.h> 105#include <asm/system.h>
106#include <linux/uaccess.h> 106#include <linux/uaccess.h>
107#include <linux/kdb.h>
107 108
108#define MAX_NR_CON_DRIVER 16 109#define MAX_NR_CON_DRIVER 16
109 110
@@ -187,10 +188,15 @@ static DECLARE_WORK(console_work, console_callback);
187 * fg_console is the current virtual console, 188 * fg_console is the current virtual console,
188 * last_console is the last used one, 189 * last_console is the last used one,
189 * want_console is the console we want to switch to, 190 * want_console is the console we want to switch to,
191 * saved_* variants are for save/restore around kernel debugger enter/leave
190 */ 192 */
191int fg_console; 193int fg_console;
192int last_console; 194int last_console;
193int want_console = -1; 195int want_console = -1;
196int saved_fg_console;
197int saved_last_console;
198int saved_want_console;
199int saved_vc_mode;
194 200
195/* 201/*
196 * For each existing display, we have a pointer to console currently visible 202 * For each existing display, we have a pointer to console currently visible
@@ -3414,6 +3420,78 @@ int con_is_bound(const struct consw *csw)
3414EXPORT_SYMBOL(con_is_bound); 3420EXPORT_SYMBOL(con_is_bound);
3415 3421
3416/** 3422/**
3423 * con_debug_enter - prepare the console for the kernel debugger
3424 * @sw: console driver
3425 *
3426 * Called when the console is taken over by the kernel debugger, this
3427 * function needs to save the current console state, then put the console
3428 * into a state suitable for the kernel debugger.
3429 *
3430 * RETURNS:
3431 * Zero on success, nonzero if a failure occurred when trying to prepare
3432 * the console for the debugger.
3433 */
3434int con_debug_enter(struct vc_data *vc)
3435{
3436 int ret = 0;
3437
3438 saved_fg_console = fg_console;
3439 saved_last_console = last_console;
3440 saved_want_console = want_console;
3441 saved_vc_mode = vc->vc_mode;
3442 vc->vc_mode = KD_TEXT;
3443 console_blanked = 0;
3444 if (vc->vc_sw->con_debug_enter)
3445 ret = vc->vc_sw->con_debug_enter(vc);
3446#ifdef CONFIG_KGDB_KDB
3447 /* Set the initial LINES variable if it is not already set */
3448 if (vc->vc_rows < 999) {
3449 int linecount;
3450 char lns[4];
3451 const char *setargs[3] = {
3452 "set",
3453 "LINES",
3454 lns,
3455 };
3456 if (kdbgetintenv(setargs[0], &linecount)) {
3457 snprintf(lns, 4, "%i", vc->vc_rows);
3458 kdb_set(2, setargs);
3459 }
3460 }
3461#endif /* CONFIG_KGDB_KDB */
3462 return ret;
3463}
3464EXPORT_SYMBOL_GPL(con_debug_enter);
3465
3466/**
3467 * con_debug_leave - restore console state
3468 * @sw: console driver
3469 *
3470 * Restore the console state to what it was before the kernel debugger
3471 * was invoked.
3472 *
3473 * RETURNS:
3474 * Zero on success, nonzero if a failure occurred when trying to restore
3475 * the console.
3476 */
3477int con_debug_leave(void)
3478{
3479 struct vc_data *vc;
3480 int ret = 0;
3481
3482 fg_console = saved_fg_console;
3483 last_console = saved_last_console;
3484 want_console = saved_want_console;
3485 vc_cons[fg_console].d->vc_mode = saved_vc_mode;
3486
3487 vc = vc_cons[fg_console].d;
3488 if (vc->vc_sw->con_debug_leave)
3489 ret = vc->vc_sw->con_debug_leave(vc);
3490 return ret;
3491}
3492EXPORT_SYMBOL_GPL(con_debug_leave);
3493
3494/**
3417 * register_con_driver - register console driver to console layer 3495 * register_con_driver - register console driver to console layer
3418 * @csw: console driver 3496 * @csw: console driver
3419 * @first: the first console to take over, minimum value is 0 3497 * @first: the first console to take over, minimum value is 0
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 719662034bbf..de82e201d682 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -241,6 +241,80 @@ static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
241 return 0; 241 return 0;
242} 242}
243 243
244int drm_fb_helper_debug_enter(struct fb_info *info)
245{
246 struct drm_fb_helper *helper = info->par;
247 struct drm_crtc_helper_funcs *funcs;
248 int i;
249
250 if (list_empty(&kernel_fb_helper_list))
251 return false;
252
253 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
254 for (i = 0; i < helper->crtc_count; i++) {
255 struct drm_mode_set *mode_set =
256 &helper->crtc_info[i].mode_set;
257
258 if (!mode_set->crtc->enabled)
259 continue;
260
261 funcs = mode_set->crtc->helper_private;
262 funcs->mode_set_base_atomic(mode_set->crtc,
263 mode_set->fb,
264 mode_set->x,
265 mode_set->y);
266
267 }
268 }
269
270 return 0;
271}
272EXPORT_SYMBOL(drm_fb_helper_debug_enter);
273
274/* Find the real fb for a given fb helper CRTC */
275static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
276{
277 struct drm_device *dev = crtc->dev;
278 struct drm_crtc *c;
279
280 list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
281 if (crtc->base.id == c->base.id)
282 return c->fb;
283 }
284
285 return NULL;
286}
287
288int drm_fb_helper_debug_leave(struct fb_info *info)
289{
290 struct drm_fb_helper *helper = info->par;
291 struct drm_crtc *crtc;
292 struct drm_crtc_helper_funcs *funcs;
293 struct drm_framebuffer *fb;
294 int i;
295
296 for (i = 0; i < helper->crtc_count; i++) {
297 struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
298 crtc = mode_set->crtc;
299 funcs = crtc->helper_private;
300 fb = drm_mode_config_fb(crtc);
301
302 if (!crtc->enabled)
303 continue;
304
305 if (!fb) {
306 DRM_ERROR("no fb to restore??\n");
307 continue;
308 }
309
310 funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
311 crtc->y);
312 }
313
314 return 0;
315}
316EXPORT_SYMBOL(drm_fb_helper_debug_leave);
317
244bool drm_fb_helper_force_kernel_mode(void) 318bool drm_fb_helper_force_kernel_mode(void)
245{ 319{
246 int i = 0; 320 int i = 0;
@@ -611,7 +685,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
611 struct drm_framebuffer *fb = fb_helper->fb; 685 struct drm_framebuffer *fb = fb_helper->fb;
612 int depth; 686 int depth;
613 687
614 if (var->pixclock != 0) 688 if (var->pixclock != 0 || in_dbg_master())
615 return -EINVAL; 689 return -EINVAL;
616 690
617 /* Need to resize the fb object !!! */ 691 /* Need to resize the fb object !!! */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5e21b3119824..714bf539918b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -975,7 +975,10 @@ void
975intel_wait_for_vblank(struct drm_device *dev) 975intel_wait_for_vblank(struct drm_device *dev)
976{ 976{
977 /* Wait for 20ms, i.e. one cycle at 50hz. */ 977 /* Wait for 20ms, i.e. one cycle at 50hz. */
978 msleep(20); 978 if (in_dbg_master())
979 mdelay(20); /* The kernel debugger cannot call msleep() */
980 else
981 msleep(20);
979} 982}
980 983
981/* Parameters have changed, update FBC info */ 984/* Parameters have changed, update FBC info */
@@ -1248,6 +1251,10 @@ static void intel_update_fbc(struct drm_crtc *crtc,
1248 goto out_disable; 1251 goto out_disable;
1249 } 1252 }
1250 1253
1254 /* If the kernel debugger is active, always disable compression */
1255 if (in_dbg_master())
1256 goto out_disable;
1257
1251 if (intel_fbc_enabled(dev)) { 1258 if (intel_fbc_enabled(dev)) {
1252 /* We can re-enable it in this case, but need to update pitch */ 1259 /* We can re-enable it in this case, but need to update pitch */
1253 if ((fb->pitch > dev_priv->cfb_pitch) || 1260 if ((fb->pitch > dev_priv->cfb_pitch) ||
@@ -1314,6 +1321,98 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
1314 return 0; 1321 return 0;
1315} 1322}
1316 1323
1324/* Assume fb object is pinned & idle & fenced and just update base pointers */
1325static int
1326intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
1327 int x, int y)
1328{
1329 struct drm_device *dev = crtc->dev;
1330 struct drm_i915_private *dev_priv = dev->dev_private;
1331 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1332 struct intel_framebuffer *intel_fb;
1333 struct drm_i915_gem_object *obj_priv;
1334 struct drm_gem_object *obj;
1335 int plane = intel_crtc->plane;
1336 unsigned long Start, Offset;
1337 int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR);
1338 int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
1339 int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
1340 int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
1341 int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
1342 u32 dspcntr;
1343
1344 switch (plane) {
1345 case 0:
1346 case 1:
1347 break;
1348 default:
1349 DRM_ERROR("Can't update plane %d in SAREA\n", plane);
1350 return -EINVAL;
1351 }
1352
1353 intel_fb = to_intel_framebuffer(fb);
1354 obj = intel_fb->obj;
1355 obj_priv = to_intel_bo(obj);
1356
1357 dspcntr = I915_READ(dspcntr_reg);
1358 /* Mask out pixel format bits in case we change it */
1359 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
1360 switch (fb->bits_per_pixel) {
1361 case 8:
1362 dspcntr |= DISPPLANE_8BPP;
1363 break;
1364 case 16:
1365 if (fb->depth == 15)
1366 dspcntr |= DISPPLANE_15_16BPP;
1367 else
1368 dspcntr |= DISPPLANE_16BPP;
1369 break;
1370 case 24:
1371 case 32:
1372 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
1373 break;
1374 default:
1375 DRM_ERROR("Unknown color depth\n");
1376 return -EINVAL;
1377 }
1378 if (IS_I965G(dev)) {
1379 if (obj_priv->tiling_mode != I915_TILING_NONE)
1380 dspcntr |= DISPPLANE_TILED;
1381 else
1382 dspcntr &= ~DISPPLANE_TILED;
1383 }
1384
1385 if (IS_IRONLAKE(dev))
1386 /* must disable */
1387 dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
1388
1389 I915_WRITE(dspcntr_reg, dspcntr);
1390
1391 Start = obj_priv->gtt_offset;
1392 Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
1393
1394 DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
1395 I915_WRITE(dspstride, fb->pitch);
1396 if (IS_I965G(dev)) {
1397 I915_WRITE(dspbase, Offset);
1398 I915_READ(dspbase);
1399 I915_WRITE(dspsurf, Start);
1400 I915_READ(dspsurf);
1401 I915_WRITE(dsptileoff, (y << 16) | x);
1402 } else {
1403 I915_WRITE(dspbase, Start + Offset);
1404 I915_READ(dspbase);
1405 }
1406
1407 if ((IS_I965G(dev) || plane == 0))
1408 intel_update_fbc(crtc, &crtc->mode);
1409
1410 intel_wait_for_vblank(dev);
1411 intel_increase_pllclock(crtc, true);
1412
1413 return 0;
1414}
1415
1317static int 1416static int
1318intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, 1417intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
1319 struct drm_framebuffer *old_fb) 1418 struct drm_framebuffer *old_fb)
@@ -4814,6 +4913,7 @@ static const struct drm_crtc_helper_funcs intel_helper_funcs = {
4814 .mode_fixup = intel_crtc_mode_fixup, 4913 .mode_fixup = intel_crtc_mode_fixup,
4815 .mode_set = intel_crtc_mode_set, 4914 .mode_set = intel_crtc_mode_set,
4816 .mode_set_base = intel_pipe_set_base, 4915 .mode_set_base = intel_pipe_set_base,
4916 .mode_set_base_atomic = intel_pipe_set_base_atomic,
4817 .prepare = intel_crtc_prepare, 4917 .prepare = intel_crtc_prepare,
4818 .commit = intel_crtc_commit, 4918 .commit = intel_crtc_commit,
4819 .load_lut = intel_crtc_load_lut, 4919 .load_lut = intel_crtc_load_lut,
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 3e18c9e7729b..54acd8b534df 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -61,6 +61,8 @@ static struct fb_ops intelfb_ops = {
61 .fb_pan_display = drm_fb_helper_pan_display, 61 .fb_pan_display = drm_fb_helper_pan_display,
62 .fb_blank = drm_fb_helper_blank, 62 .fb_blank = drm_fb_helper_blank,
63 .fb_setcmap = drm_fb_helper_setcmap, 63 .fb_setcmap = drm_fb_helper_setcmap,
64 .fb_debug_enter = drm_fb_helper_debug_enter,
65 .fb_debug_leave = drm_fb_helper_debug_leave,
64}; 66};
65 67
66static int intelfb_create(struct intel_fbdev *ifbdev, 68static int intelfb_create(struct intel_fbdev *ifbdev,
diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
index a9a94ae72349..39f9a1adaa75 100644
--- a/drivers/serial/kgdboc.c
+++ b/drivers/serial/kgdboc.c
@@ -17,6 +17,7 @@
17#include <linux/kdb.h> 17#include <linux/kdb.h>
18#include <linux/tty.h> 18#include <linux/tty.h>
19#include <linux/console.h> 19#include <linux/console.h>
20#include <linux/vt_kern.h>
20 21
21#define MAX_CONFIG_LEN 40 22#define MAX_CONFIG_LEN 40
22 23
@@ -31,6 +32,7 @@ static struct kparam_string kps = {
31 .maxlen = MAX_CONFIG_LEN, 32 .maxlen = MAX_CONFIG_LEN,
32}; 33};
33 34
35static int kgdboc_use_kms; /* 1 if we use kernel mode switching */
34static struct tty_driver *kgdb_tty_driver; 36static struct tty_driver *kgdb_tty_driver;
35static int kgdb_tty_line; 37static int kgdb_tty_line;
36 38
@@ -104,6 +106,12 @@ static int configure_kgdboc(void)
104 kgdboc_io_ops.is_console = 0; 106 kgdboc_io_ops.is_console = 0;
105 kgdb_tty_driver = NULL; 107 kgdb_tty_driver = NULL;
106 108
109 kgdboc_use_kms = 0;
110 if (strncmp(cptr, "kms,", 4) == 0) {
111 cptr += 4;
112 kgdboc_use_kms = 1;
113 }
114
107 if (kgdboc_register_kbd(&cptr)) 115 if (kgdboc_register_kbd(&cptr))
108 goto do_register; 116 goto do_register;
109 117
@@ -201,8 +209,14 @@ static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
201 return configure_kgdboc(); 209 return configure_kgdboc();
202} 210}
203 211
212static int dbg_restore_graphics;
213
204static void kgdboc_pre_exp_handler(void) 214static void kgdboc_pre_exp_handler(void)
205{ 215{
216 if (!dbg_restore_graphics && kgdboc_use_kms) {
217 dbg_restore_graphics = 1;
218 con_debug_enter(vc_cons[fg_console].d);
219 }
206 /* Increment the module count when the debugger is active */ 220 /* Increment the module count when the debugger is active */
207 if (!kgdb_connected) 221 if (!kgdb_connected)
208 try_module_get(THIS_MODULE); 222 try_module_get(THIS_MODULE);
@@ -213,6 +227,10 @@ static void kgdboc_post_exp_handler(void)
213 /* decrement the module count when the debugger detaches */ 227 /* decrement the module count when the debugger detaches */
214 if (!kgdb_connected) 228 if (!kgdb_connected)
215 module_put(THIS_MODULE); 229 module_put(THIS_MODULE);
230 if (kgdboc_use_kms && dbg_restore_graphics) {
231 dbg_restore_graphics = 0;
232 con_debug_leave();
233 }
216} 234}
217 235
218static struct kgdb_io kgdboc_io_ops = { 236static struct kgdb_io kgdboc_io_ops = {
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index b0a3fa00706d..3b3f5749af92 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2342,6 +2342,30 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
2342 return 0; 2342 return 0;
2343} 2343}
2344 2344
2345static int fbcon_debug_enter(struct vc_data *vc)
2346{
2347 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2348 struct fbcon_ops *ops = info->fbcon_par;
2349
2350 ops->save_graphics = ops->graphics;
2351 ops->graphics = 0;
2352 if (info->fbops->fb_debug_enter)
2353 info->fbops->fb_debug_enter(info);
2354 fbcon_set_palette(vc, color_table);
2355 return 0;
2356}
2357
2358static int fbcon_debug_leave(struct vc_data *vc)
2359{
2360 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2361 struct fbcon_ops *ops = info->fbcon_par;
2362
2363 ops->graphics = ops->save_graphics;
2364 if (info->fbops->fb_debug_leave)
2365 info->fbops->fb_debug_leave(info);
2366 return 0;
2367}
2368
2345static int fbcon_get_font(struct vc_data *vc, struct console_font *font) 2369static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
2346{ 2370{
2347 u8 *fontdata = vc->vc_font.data; 2371 u8 *fontdata = vc->vc_font.data;
@@ -3276,6 +3300,8 @@ static const struct consw fb_con = {
3276 .con_screen_pos = fbcon_screen_pos, 3300 .con_screen_pos = fbcon_screen_pos,
3277 .con_getxy = fbcon_getxy, 3301 .con_getxy = fbcon_getxy,
3278 .con_resize = fbcon_resize, 3302 .con_resize = fbcon_resize,
3303 .con_debug_enter = fbcon_debug_enter,
3304 .con_debug_leave = fbcon_debug_leave,
3279}; 3305};
3280 3306
3281static struct notifier_block fbcon_event_notifier = { 3307static struct notifier_block fbcon_event_notifier = {
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 89a346880ec0..6bd2e0c7f209 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -74,6 +74,7 @@ struct fbcon_ops {
74 int cursor_reset; 74 int cursor_reset;
75 int blank_state; 75 int blank_state;
76 int graphics; 76 int graphics;
77 int save_graphics; /* for debug enter/leave */
77 int flags; 78 int flags;
78 int rotate; 79 int rotate;
79 int cur_rotate; 80 int cur_rotate;
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 1121f7799c6f..10f7d03e58a9 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -60,6 +60,8 @@ struct drm_crtc_helper_funcs {
60 /* Move the crtc on the current fb to the given position *optional* */ 60 /* Move the crtc on the current fb to the given position *optional* */
61 int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, 61 int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
62 struct drm_framebuffer *old_fb); 62 struct drm_framebuffer *old_fb);
63 int (*mode_set_base_atomic)(struct drm_crtc *crtc,
64 struct drm_framebuffer *fb, int x, int y);
63 65
64 /* reload the current crtc LUT */ 66 /* reload the current crtc LUT */
65 void (*load_lut)(struct drm_crtc *crtc); 67 void (*load_lut)(struct drm_crtc *crtc);
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index f0a6afc47e76..f22e7fe4b6db 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -32,6 +32,8 @@
32 32
33struct drm_fb_helper; 33struct drm_fb_helper;
34 34
35#include <linux/kgdb.h>
36
35struct drm_fb_helper_crtc { 37struct drm_fb_helper_crtc {
36 uint32_t crtc_id; 38 uint32_t crtc_id;
37 struct drm_mode_set mode_set; 39 struct drm_mode_set mode_set;
@@ -78,6 +80,7 @@ struct drm_fb_helper_connector {
78 80
79struct drm_fb_helper { 81struct drm_fb_helper {
80 struct drm_framebuffer *fb; 82 struct drm_framebuffer *fb;
83 struct drm_framebuffer *saved_fb;
81 struct drm_device *dev; 84 struct drm_device *dev;
82 struct drm_display_mode *mode; 85 struct drm_display_mode *mode;
83 int crtc_count; 86 int crtc_count;
@@ -126,5 +129,7 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
126bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); 129bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
127bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); 130bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
128int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); 131int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
132int drm_fb_helper_debug_enter(struct fb_info *info);
133int drm_fb_helper_debug_leave(struct fb_info *info);
129 134
130#endif 135#endif
diff --git a/include/linux/console.h b/include/linux/console.h
index dcca5339ceb3..f76fc297322d 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -55,6 +55,16 @@ struct consw {
55 void (*con_invert_region)(struct vc_data *, u16 *, int); 55 void (*con_invert_region)(struct vc_data *, u16 *, int);
56 u16 *(*con_screen_pos)(struct vc_data *, int); 56 u16 *(*con_screen_pos)(struct vc_data *, int);
57 unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *); 57 unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
58 /*
59 * Prepare the console for the debugger. This includes, but is not
60 * limited to, unblanking the console, loading an appropriate
61 * palette, and allowing debugger generated output.
62 */
63 int (*con_debug_enter)(struct vc_data *);
64 /*
65 * Restore the console to its pre-debug state as closely as possible.
66 */
67 int (*con_debug_leave)(struct vc_data *);
58}; 68};
59 69
60extern const struct consw *conswitchp; 70extern const struct consw *conswitchp;
@@ -69,6 +79,9 @@ int register_con_driver(const struct consw *csw, int first, int last);
69int unregister_con_driver(const struct consw *csw); 79int unregister_con_driver(const struct consw *csw);
70int take_over_console(const struct consw *sw, int first, int last, int deflt); 80int take_over_console(const struct consw *sw, int first, int last, int deflt);
71void give_up_console(const struct consw *sw); 81void give_up_console(const struct consw *sw);
82int con_debug_enter(struct vc_data *vc);
83int con_debug_leave(void);
84
72/* scroll */ 85/* scroll */
73#define SM_UP (1) 86#define SM_UP (1)
74#define SM_DOWN (2) 87#define SM_DOWN (2)
diff --git a/include/linux/fb.h b/include/linux/fb.h
index e7445df44d6c..0c5659c41b01 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -3,6 +3,9 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/i2c.h> 5#include <linux/i2c.h>
6#ifdef __KERNEL__
7#include <linux/kgdb.h>
8#endif /* __KERNEL__ */
6 9
7/* Definitions of frame buffers */ 10/* Definitions of frame buffers */
8 11
@@ -607,6 +610,12 @@ struct fb_deferred_io {
607 * LOCKING NOTE: those functions must _ALL_ be called with the console 610 * LOCKING NOTE: those functions must _ALL_ be called with the console
608 * semaphore held, this is the only suitable locking mechanism we have 611 * semaphore held, this is the only suitable locking mechanism we have
609 * in 2.6. Some may be called at interrupt time at this point though. 612 * in 2.6. Some may be called at interrupt time at this point though.
613 *
614 * The exception to this is the debug related hooks. Putting the fb
615 * into a debug state (e.g. flipping to the kernel console) and restoring
616 * it must be done in a lock-free manner, so low level drivers should
617 * keep track of the initial console (if applicable) and may need to
618 * perform direct, unlocked hardware writes in these hooks.
610 */ 619 */
611 620
612struct fb_ops { 621struct fb_ops {
@@ -676,6 +685,10 @@ struct fb_ops {
676 685
677 /* teardown any resources to do with this framebuffer */ 686 /* teardown any resources to do with this framebuffer */
678 void (*fb_destroy)(struct fb_info *info); 687 void (*fb_destroy)(struct fb_info *info);
688
689 /* called at KDB enter and leave time to prepare the console */
690 int (*fb_debug_enter)(struct fb_info *info);
691 int (*fb_debug_leave)(struct fb_info *info);
679}; 692};
680 693
681#ifdef CONFIG_FB_TILEBLITTING 694#ifdef CONFIG_FB_TILEBLITTING
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
index ccb2b3ec0fe8..ea6e5244ed3f 100644
--- a/include/linux/kdb.h
+++ b/include/linux/kdb.h
@@ -114,4 +114,8 @@ enum {
114 KDB_INIT_EARLY, 114 KDB_INIT_EARLY,
115 KDB_INIT_FULL, 115 KDB_INIT_FULL,
116}; 116};
117
118extern int kdbgetintenv(const char *, int *);
119extern int kdb_set(int, const char **);
120
117#endif /* !_KDB_H */ 121#endif /* !_KDB_H */
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h
index 97d3ba69775d..c438f545a321 100644
--- a/kernel/debug/kdb/kdb_private.h
+++ b/kernel/debug/kdb/kdb_private.h
@@ -144,9 +144,7 @@ extern int kdb_getword(unsigned long *, unsigned long, size_t);
144extern int kdb_putword(unsigned long, unsigned long, size_t); 144extern int kdb_putword(unsigned long, unsigned long, size_t);
145 145
146extern int kdbgetularg(const char *, unsigned long *); 146extern int kdbgetularg(const char *, unsigned long *);
147extern int kdb_set(int, const char **);
148extern char *kdbgetenv(const char *); 147extern char *kdbgetenv(const char *);
149extern int kdbgetintenv(const char *, int *);
150extern int kdbgetaddrarg(int, const char **, int*, unsigned long *, 148extern int kdbgetaddrarg(int, const char **, int*, unsigned long *,
151 long *, char **); 149 long *, char **);
152extern int kdbgetsymval(const char *, kdb_symtab_t *); 150extern int kdbgetsymval(const char *, kdb_symtab_t *);