aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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 /drivers
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
Diffstat (limited to 'drivers')
-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
7 files changed, 301 insertions, 2 deletions
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;