| .. | .. |
|---|
| 19 | 19 | #include <linux/sched/rt.h> |
|---|
| 20 | 20 | #include <linux/sched/debug.h> |
|---|
| 21 | 21 | #include <linux/sched/task.h> |
|---|
| 22 | +#include <linux/ctype.h> |
|---|
| 22 | 23 | #include <linux/interrupt.h> |
|---|
| 23 | 24 | #include <linux/mm.h> |
|---|
| 24 | 25 | #include <linux/fs.h> |
|---|
| .. | .. |
|---|
| 63 | 64 | return sysrq_enabled || sysrq_always_enabled; |
|---|
| 64 | 65 | } |
|---|
| 65 | 66 | |
|---|
| 67 | +/** |
|---|
| 68 | + * sysrq_mask - Getter for sysrq_enabled mask. |
|---|
| 69 | + * |
|---|
| 70 | + * Return: 1 if sysrq is always enabled, enabled sysrq_key_op mask otherwise. |
|---|
| 71 | + */ |
|---|
| 72 | +int sysrq_mask(void) |
|---|
| 73 | +{ |
|---|
| 74 | + if (sysrq_always_enabled) |
|---|
| 75 | + return 1; |
|---|
| 76 | + return sysrq_enabled; |
|---|
| 77 | +} |
|---|
| 78 | +EXPORT_SYMBOL_GPL(sysrq_mask); |
|---|
| 79 | + |
|---|
| 66 | 80 | /* |
|---|
| 67 | 81 | * A value of 1 means 'all', other nonzero values are an op mask: |
|---|
| 68 | 82 | */ |
|---|
| .. | .. |
|---|
| 93 | 107 | pr_info("Loglevel set to %d\n", i); |
|---|
| 94 | 108 | console_loglevel = i; |
|---|
| 95 | 109 | } |
|---|
| 96 | | -static struct sysrq_key_op sysrq_loglevel_op = { |
|---|
| 110 | +static const struct sysrq_key_op sysrq_loglevel_op = { |
|---|
| 97 | 111 | .handler = sysrq_handle_loglevel, |
|---|
| 98 | 112 | .help_msg = "loglevel(0-9)", |
|---|
| 99 | 113 | .action_msg = "Changing Loglevel", |
|---|
| .. | .. |
|---|
| 106 | 120 | struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; |
|---|
| 107 | 121 | schedule_work(SAK_work); |
|---|
| 108 | 122 | } |
|---|
| 109 | | -static struct sysrq_key_op sysrq_SAK_op = { |
|---|
| 123 | +static const struct sysrq_key_op sysrq_SAK_op = { |
|---|
| 110 | 124 | .handler = sysrq_handle_SAK, |
|---|
| 111 | 125 | .help_msg = "sak(k)", |
|---|
| 112 | 126 | .action_msg = "SAK", |
|---|
| 113 | 127 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, |
|---|
| 114 | 128 | }; |
|---|
| 115 | 129 | #else |
|---|
| 116 | | -#define sysrq_SAK_op (*(struct sysrq_key_op *)NULL) |
|---|
| 130 | +#define sysrq_SAK_op (*(const struct sysrq_key_op *)NULL) |
|---|
| 117 | 131 | #endif |
|---|
| 118 | 132 | |
|---|
| 119 | 133 | #ifdef CONFIG_VT |
|---|
| .. | .. |
|---|
| 122 | 136 | vt_reset_unicode(fg_console); |
|---|
| 123 | 137 | } |
|---|
| 124 | 138 | |
|---|
| 125 | | -static struct sysrq_key_op sysrq_unraw_op = { |
|---|
| 139 | +static const struct sysrq_key_op sysrq_unraw_op = { |
|---|
| 126 | 140 | .handler = sysrq_handle_unraw, |
|---|
| 127 | 141 | .help_msg = "unraw(r)", |
|---|
| 128 | 142 | .action_msg = "Keyboard mode set to system default", |
|---|
| 129 | 143 | .enable_mask = SYSRQ_ENABLE_KEYBOARD, |
|---|
| 130 | 144 | }; |
|---|
| 131 | 145 | #else |
|---|
| 132 | | -#define sysrq_unraw_op (*(struct sysrq_key_op *)NULL) |
|---|
| 146 | +#define sysrq_unraw_op (*(const struct sysrq_key_op *)NULL) |
|---|
| 133 | 147 | #endif /* CONFIG_VT */ |
|---|
| 134 | 148 | |
|---|
| 135 | 149 | static void sysrq_handle_crash(int key) |
|---|
| .. | .. |
|---|
| 139 | 153 | |
|---|
| 140 | 154 | panic("sysrq triggered crash\n"); |
|---|
| 141 | 155 | } |
|---|
| 142 | | -static struct sysrq_key_op sysrq_crash_op = { |
|---|
| 156 | +static const struct sysrq_key_op sysrq_crash_op = { |
|---|
| 143 | 157 | .handler = sysrq_handle_crash, |
|---|
| 144 | 158 | .help_msg = "crash(c)", |
|---|
| 145 | 159 | .action_msg = "Trigger a crash", |
|---|
| .. | .. |
|---|
| 152 | 166 | local_irq_enable(); |
|---|
| 153 | 167 | emergency_restart(); |
|---|
| 154 | 168 | } |
|---|
| 155 | | -static struct sysrq_key_op sysrq_reboot_op = { |
|---|
| 169 | +static const struct sysrq_key_op sysrq_reboot_op = { |
|---|
| 156 | 170 | .handler = sysrq_handle_reboot, |
|---|
| 157 | 171 | .help_msg = "reboot(b)", |
|---|
| 158 | 172 | .action_msg = "Resetting", |
|---|
| 159 | 173 | .enable_mask = SYSRQ_ENABLE_BOOT, |
|---|
| 160 | 174 | }; |
|---|
| 161 | 175 | |
|---|
| 176 | +const struct sysrq_key_op *__sysrq_reboot_op = &sysrq_reboot_op; |
|---|
| 177 | + |
|---|
| 162 | 178 | static void sysrq_handle_sync(int key) |
|---|
| 163 | 179 | { |
|---|
| 164 | 180 | emergency_sync(); |
|---|
| 165 | 181 | } |
|---|
| 166 | | -static struct sysrq_key_op sysrq_sync_op = { |
|---|
| 182 | +static const struct sysrq_key_op sysrq_sync_op = { |
|---|
| 167 | 183 | .handler = sysrq_handle_sync, |
|---|
| 168 | 184 | .help_msg = "sync(s)", |
|---|
| 169 | 185 | .action_msg = "Emergency Sync", |
|---|
| .. | .. |
|---|
| 175 | 191 | sysrq_timer_list_show(); |
|---|
| 176 | 192 | } |
|---|
| 177 | 193 | |
|---|
| 178 | | -static struct sysrq_key_op sysrq_show_timers_op = { |
|---|
| 194 | +static const struct sysrq_key_op sysrq_show_timers_op = { |
|---|
| 179 | 195 | .handler = sysrq_handle_show_timers, |
|---|
| 180 | 196 | .help_msg = "show-all-timers(q)", |
|---|
| 181 | 197 | .action_msg = "Show clockevent devices & pending hrtimers (no others)", |
|---|
| .. | .. |
|---|
| 185 | 201 | { |
|---|
| 186 | 202 | emergency_remount(); |
|---|
| 187 | 203 | } |
|---|
| 188 | | -static struct sysrq_key_op sysrq_mountro_op = { |
|---|
| 204 | +static const struct sysrq_key_op sysrq_mountro_op = { |
|---|
| 189 | 205 | .handler = sysrq_handle_mountro, |
|---|
| 190 | 206 | .help_msg = "unmount(u)", |
|---|
| 191 | 207 | .action_msg = "Emergency Remount R/O", |
|---|
| .. | .. |
|---|
| 198 | 214 | debug_show_all_locks(); |
|---|
| 199 | 215 | } |
|---|
| 200 | 216 | |
|---|
| 201 | | -static struct sysrq_key_op sysrq_showlocks_op = { |
|---|
| 217 | +static const struct sysrq_key_op sysrq_showlocks_op = { |
|---|
| 202 | 218 | .handler = sysrq_handle_showlocks, |
|---|
| 203 | 219 | .help_msg = "show-all-locks(d)", |
|---|
| 204 | 220 | .action_msg = "Show Locks Held", |
|---|
| 205 | 221 | }; |
|---|
| 206 | 222 | #else |
|---|
| 207 | | -#define sysrq_showlocks_op (*(struct sysrq_key_op *)NULL) |
|---|
| 223 | +#define sysrq_showlocks_op (*(const struct sysrq_key_op *)NULL) |
|---|
| 208 | 224 | #endif |
|---|
| 209 | 225 | |
|---|
| 210 | 226 | #ifdef CONFIG_SMP |
|---|
| .. | .. |
|---|
| 215 | 231 | unsigned long flags; |
|---|
| 216 | 232 | |
|---|
| 217 | 233 | /* Idle CPUs have no interesting backtrace. */ |
|---|
| 218 | | - if (idle_cpu(smp_processor_id())) |
|---|
| 234 | + if (idle_cpu(smp_processor_id())) { |
|---|
| 235 | + pr_info("CPU%d: backtrace skipped as idling\n", smp_processor_id()); |
|---|
| 219 | 236 | return; |
|---|
| 237 | + } |
|---|
| 220 | 238 | |
|---|
| 221 | 239 | raw_spin_lock_irqsave(&show_lock, flags); |
|---|
| 222 | 240 | pr_info("CPU%d:\n", smp_processor_id()); |
|---|
| 223 | | - show_stack(NULL, NULL); |
|---|
| 241 | + show_stack(NULL, NULL, KERN_INFO); |
|---|
| 224 | 242 | raw_spin_unlock_irqrestore(&show_lock, flags); |
|---|
| 225 | 243 | } |
|---|
| 226 | 244 | |
|---|
| .. | .. |
|---|
| 243 | 261 | |
|---|
| 244 | 262 | if (in_irq()) |
|---|
| 245 | 263 | regs = get_irq_regs(); |
|---|
| 246 | | - if (regs) { |
|---|
| 247 | | - pr_info("CPU%d:\n", smp_processor_id()); |
|---|
| 264 | + |
|---|
| 265 | + pr_info("CPU%d:\n", smp_processor_id()); |
|---|
| 266 | + if (regs) |
|---|
| 248 | 267 | show_regs(regs); |
|---|
| 249 | | - } |
|---|
| 268 | + else |
|---|
| 269 | + show_stack(NULL, NULL, KERN_INFO); |
|---|
| 270 | + |
|---|
| 250 | 271 | schedule_work(&sysrq_showallcpus); |
|---|
| 251 | 272 | } |
|---|
| 252 | 273 | } |
|---|
| 253 | 274 | |
|---|
| 254 | | -static struct sysrq_key_op sysrq_showallcpus_op = { |
|---|
| 275 | +static const struct sysrq_key_op sysrq_showallcpus_op = { |
|---|
| 255 | 276 | .handler = sysrq_handle_showallcpus, |
|---|
| 256 | 277 | .help_msg = "show-backtrace-all-active-cpus(l)", |
|---|
| 257 | 278 | .action_msg = "Show backtrace of all active CPUs", |
|---|
| .. | .. |
|---|
| 269 | 290 | show_regs(regs); |
|---|
| 270 | 291 | perf_event_print_debug(); |
|---|
| 271 | 292 | } |
|---|
| 272 | | -static struct sysrq_key_op sysrq_showregs_op = { |
|---|
| 293 | +static const struct sysrq_key_op sysrq_showregs_op = { |
|---|
| 273 | 294 | .handler = sysrq_handle_showregs, |
|---|
| 274 | 295 | .help_msg = "show-registers(p)", |
|---|
| 275 | 296 | .action_msg = "Show Regs", |
|---|
| .. | .. |
|---|
| 281 | 302 | show_state(); |
|---|
| 282 | 303 | show_workqueue_state(); |
|---|
| 283 | 304 | } |
|---|
| 284 | | -static struct sysrq_key_op sysrq_showstate_op = { |
|---|
| 305 | +static const struct sysrq_key_op sysrq_showstate_op = { |
|---|
| 285 | 306 | .handler = sysrq_handle_showstate, |
|---|
| 286 | 307 | .help_msg = "show-task-states(t)", |
|---|
| 287 | 308 | .action_msg = "Show State", |
|---|
| .. | .. |
|---|
| 292 | 313 | { |
|---|
| 293 | 314 | show_state_filter(TASK_UNINTERRUPTIBLE); |
|---|
| 294 | 315 | } |
|---|
| 295 | | -static struct sysrq_key_op sysrq_showstate_blocked_op = { |
|---|
| 316 | +static const struct sysrq_key_op sysrq_showstate_blocked_op = { |
|---|
| 296 | 317 | .handler = sysrq_handle_showstate_blocked, |
|---|
| 297 | 318 | .help_msg = "show-blocked-tasks(w)", |
|---|
| 298 | 319 | .action_msg = "Show Blocked State", |
|---|
| .. | .. |
|---|
| 306 | 327 | { |
|---|
| 307 | 328 | ftrace_dump(DUMP_ALL); |
|---|
| 308 | 329 | } |
|---|
| 309 | | -static struct sysrq_key_op sysrq_ftrace_dump_op = { |
|---|
| 330 | +static const struct sysrq_key_op sysrq_ftrace_dump_op = { |
|---|
| 310 | 331 | .handler = sysrq_ftrace_dump, |
|---|
| 311 | 332 | .help_msg = "dump-ftrace-buffer(z)", |
|---|
| 312 | 333 | .action_msg = "Dump ftrace buffer", |
|---|
| 313 | 334 | .enable_mask = SYSRQ_ENABLE_DUMP, |
|---|
| 314 | 335 | }; |
|---|
| 315 | 336 | #else |
|---|
| 316 | | -#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL) |
|---|
| 337 | +#define sysrq_ftrace_dump_op (*(const struct sysrq_key_op *)NULL) |
|---|
| 317 | 338 | #endif |
|---|
| 318 | 339 | |
|---|
| 319 | 340 | static void sysrq_handle_showmem(int key) |
|---|
| 320 | 341 | { |
|---|
| 321 | 342 | show_mem(0, NULL); |
|---|
| 322 | 343 | } |
|---|
| 323 | | -static struct sysrq_key_op sysrq_showmem_op = { |
|---|
| 344 | +static const struct sysrq_key_op sysrq_showmem_op = { |
|---|
| 324 | 345 | .handler = sysrq_handle_showmem, |
|---|
| 325 | 346 | .help_msg = "show-memory-usage(m)", |
|---|
| 326 | 347 | .action_msg = "Show Memory", |
|---|
| .. | .. |
|---|
| 341 | 362 | if (is_global_init(p)) |
|---|
| 342 | 363 | continue; |
|---|
| 343 | 364 | |
|---|
| 344 | | - do_send_sig_info(sig, SEND_SIG_FORCED, p, PIDTYPE_MAX); |
|---|
| 365 | + do_send_sig_info(sig, SEND_SIG_PRIV, p, PIDTYPE_MAX); |
|---|
| 345 | 366 | } |
|---|
| 346 | 367 | read_unlock(&tasklist_lock); |
|---|
| 347 | 368 | } |
|---|
| .. | .. |
|---|
| 351 | 372 | send_sig_all(SIGTERM); |
|---|
| 352 | 373 | console_loglevel = CONSOLE_LOGLEVEL_DEBUG; |
|---|
| 353 | 374 | } |
|---|
| 354 | | -static struct sysrq_key_op sysrq_term_op = { |
|---|
| 375 | +static const struct sysrq_key_op sysrq_term_op = { |
|---|
| 355 | 376 | .handler = sysrq_handle_term, |
|---|
| 356 | 377 | .help_msg = "terminate-all-tasks(e)", |
|---|
| 357 | 378 | .action_msg = "Terminate All Tasks", |
|---|
| .. | .. |
|---|
| 381 | 402 | { |
|---|
| 382 | 403 | schedule_work(&moom_work); |
|---|
| 383 | 404 | } |
|---|
| 384 | | -static struct sysrq_key_op sysrq_moom_op = { |
|---|
| 405 | +static const struct sysrq_key_op sysrq_moom_op = { |
|---|
| 385 | 406 | .handler = sysrq_handle_moom, |
|---|
| 386 | 407 | .help_msg = "memory-full-oom-kill(f)", |
|---|
| 387 | 408 | .action_msg = "Manual OOM execution", |
|---|
| 388 | 409 | .enable_mask = SYSRQ_ENABLE_SIGNAL, |
|---|
| 389 | 410 | }; |
|---|
| 390 | 411 | |
|---|
| 391 | | -#ifdef CONFIG_BLOCK |
|---|
| 392 | 412 | static void sysrq_handle_thaw(int key) |
|---|
| 393 | 413 | { |
|---|
| 394 | 414 | emergency_thaw_all(); |
|---|
| 395 | 415 | } |
|---|
| 396 | | -static struct sysrq_key_op sysrq_thaw_op = { |
|---|
| 416 | +static const struct sysrq_key_op sysrq_thaw_op = { |
|---|
| 397 | 417 | .handler = sysrq_handle_thaw, |
|---|
| 398 | 418 | .help_msg = "thaw-filesystems(j)", |
|---|
| 399 | 419 | .action_msg = "Emergency Thaw of all frozen filesystems", |
|---|
| 400 | 420 | .enable_mask = SYSRQ_ENABLE_SIGNAL, |
|---|
| 401 | 421 | }; |
|---|
| 402 | | -#endif |
|---|
| 403 | 422 | |
|---|
| 404 | 423 | static void sysrq_handle_kill(int key) |
|---|
| 405 | 424 | { |
|---|
| 406 | 425 | send_sig_all(SIGKILL); |
|---|
| 407 | 426 | console_loglevel = CONSOLE_LOGLEVEL_DEBUG; |
|---|
| 408 | 427 | } |
|---|
| 409 | | -static struct sysrq_key_op sysrq_kill_op = { |
|---|
| 428 | +static const struct sysrq_key_op sysrq_kill_op = { |
|---|
| 410 | 429 | .handler = sysrq_handle_kill, |
|---|
| 411 | 430 | .help_msg = "kill-all-tasks(i)", |
|---|
| 412 | 431 | .action_msg = "Kill All Tasks", |
|---|
| .. | .. |
|---|
| 417 | 436 | { |
|---|
| 418 | 437 | normalize_rt_tasks(); |
|---|
| 419 | 438 | } |
|---|
| 420 | | -static struct sysrq_key_op sysrq_unrt_op = { |
|---|
| 439 | +static const struct sysrq_key_op sysrq_unrt_op = { |
|---|
| 421 | 440 | .handler = sysrq_handle_unrt, |
|---|
| 422 | 441 | .help_msg = "nice-all-RT-tasks(n)", |
|---|
| 423 | 442 | .action_msg = "Nice All RT Tasks", |
|---|
| .. | .. |
|---|
| 427 | 446 | /* Key Operations table and lock */ |
|---|
| 428 | 447 | static DEFINE_SPINLOCK(sysrq_key_table_lock); |
|---|
| 429 | 448 | |
|---|
| 430 | | -static struct sysrq_key_op *sysrq_key_table[36] = { |
|---|
| 449 | +static const struct sysrq_key_op *sysrq_key_table[62] = { |
|---|
| 431 | 450 | &sysrq_loglevel_op, /* 0 */ |
|---|
| 432 | 451 | &sysrq_loglevel_op, /* 1 */ |
|---|
| 433 | 452 | &sysrq_loglevel_op, /* 2 */ |
|---|
| .. | .. |
|---|
| 484 | 503 | /* y: May be registered on sparc64 for global register dump */ |
|---|
| 485 | 504 | NULL, /* y */ |
|---|
| 486 | 505 | &sysrq_ftrace_dump_op, /* z */ |
|---|
| 506 | + NULL, /* A */ |
|---|
| 507 | + NULL, /* B */ |
|---|
| 508 | + NULL, /* C */ |
|---|
| 509 | + NULL, /* D */ |
|---|
| 510 | + NULL, /* E */ |
|---|
| 511 | + NULL, /* F */ |
|---|
| 512 | + NULL, /* G */ |
|---|
| 513 | + NULL, /* H */ |
|---|
| 514 | + NULL, /* I */ |
|---|
| 515 | + NULL, /* J */ |
|---|
| 516 | + NULL, /* K */ |
|---|
| 517 | + NULL, /* L */ |
|---|
| 518 | + NULL, /* M */ |
|---|
| 519 | + NULL, /* N */ |
|---|
| 520 | + NULL, /* O */ |
|---|
| 521 | + NULL, /* P */ |
|---|
| 522 | + NULL, /* Q */ |
|---|
| 523 | + NULL, /* R */ |
|---|
| 524 | + NULL, /* S */ |
|---|
| 525 | + NULL, /* T */ |
|---|
| 526 | + NULL, /* U */ |
|---|
| 527 | + NULL, /* V */ |
|---|
| 528 | + NULL, /* W */ |
|---|
| 529 | + NULL, /* X */ |
|---|
| 530 | + NULL, /* Y */ |
|---|
| 531 | + NULL, /* Z */ |
|---|
| 487 | 532 | }; |
|---|
| 488 | 533 | |
|---|
| 489 | 534 | /* key2index calculation, -1 on invalid index */ |
|---|
| .. | .. |
|---|
| 495 | 540 | retval = key - '0'; |
|---|
| 496 | 541 | else if ((key >= 'a') && (key <= 'z')) |
|---|
| 497 | 542 | retval = key + 10 - 'a'; |
|---|
| 543 | + else if ((key >= 'A') && (key <= 'Z')) |
|---|
| 544 | + retval = key + 36 - 'A'; |
|---|
| 498 | 545 | else |
|---|
| 499 | 546 | retval = -1; |
|---|
| 500 | 547 | return retval; |
|---|
| .. | .. |
|---|
| 503 | 550 | /* |
|---|
| 504 | 551 | * get and put functions for the table, exposed to modules. |
|---|
| 505 | 552 | */ |
|---|
| 506 | | -struct sysrq_key_op *__sysrq_get_key_op(int key) |
|---|
| 553 | +static const struct sysrq_key_op *__sysrq_get_key_op(int key) |
|---|
| 507 | 554 | { |
|---|
| 508 | | - struct sysrq_key_op *op_p = NULL; |
|---|
| 555 | + const struct sysrq_key_op *op_p = NULL; |
|---|
| 509 | 556 | int i; |
|---|
| 510 | 557 | |
|---|
| 511 | 558 | i = sysrq_key_table_key2index(key); |
|---|
| .. | .. |
|---|
| 515 | 562 | return op_p; |
|---|
| 516 | 563 | } |
|---|
| 517 | 564 | |
|---|
| 518 | | -static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p) |
|---|
| 565 | +static void __sysrq_put_key_op(int key, const struct sysrq_key_op *op_p) |
|---|
| 519 | 566 | { |
|---|
| 520 | 567 | int i = sysrq_key_table_key2index(key); |
|---|
| 521 | 568 | |
|---|
| .. | .. |
|---|
| 525 | 572 | |
|---|
| 526 | 573 | void __handle_sysrq(int key, bool check_mask) |
|---|
| 527 | 574 | { |
|---|
| 528 | | - struct sysrq_key_op *op_p; |
|---|
| 575 | + const struct sysrq_key_op *op_p; |
|---|
| 529 | 576 | int orig_log_level; |
|---|
| 577 | + int orig_suppress_printk; |
|---|
| 530 | 578 | int i; |
|---|
| 579 | + |
|---|
| 580 | + orig_suppress_printk = suppress_printk; |
|---|
| 581 | + suppress_printk = 0; |
|---|
| 531 | 582 | |
|---|
| 532 | 583 | rcu_sysrq_start(); |
|---|
| 533 | 584 | rcu_read_lock(); |
|---|
| .. | .. |
|---|
| 574 | 625 | } |
|---|
| 575 | 626 | rcu_read_unlock(); |
|---|
| 576 | 627 | rcu_sysrq_end(); |
|---|
| 628 | + |
|---|
| 629 | + suppress_printk = orig_suppress_printk; |
|---|
| 577 | 630 | } |
|---|
| 578 | 631 | |
|---|
| 579 | 632 | void handle_sysrq(int key) |
|---|
| .. | .. |
|---|
| 602 | 655 | unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; |
|---|
| 603 | 656 | unsigned int alt; |
|---|
| 604 | 657 | unsigned int alt_use; |
|---|
| 658 | + unsigned int shift; |
|---|
| 659 | + unsigned int shift_use; |
|---|
| 605 | 660 | bool active; |
|---|
| 606 | 661 | bool need_reinject; |
|---|
| 607 | 662 | bool reinjecting; |
|---|
| .. | .. |
|---|
| 653 | 708 | |
|---|
| 654 | 709 | state->reset_requested = true; |
|---|
| 655 | 710 | |
|---|
| 656 | | - ksys_sync(); |
|---|
| 657 | | - kernel_restart(NULL); |
|---|
| 711 | + orderly_reboot(); |
|---|
| 658 | 712 | } |
|---|
| 659 | 713 | |
|---|
| 660 | 714 | static void sysrq_handle_reset_request(struct sysrq_state *state) |
|---|
| .. | .. |
|---|
| 729 | 783 | |
|---|
| 730 | 784 | /* Get reset timeout if any. */ |
|---|
| 731 | 785 | of_property_read_u32(np, "timeout-ms", &sysrq_reset_downtime_ms); |
|---|
| 786 | + |
|---|
| 787 | + of_node_put(np); |
|---|
| 732 | 788 | } |
|---|
| 733 | 789 | #else |
|---|
| 734 | 790 | static void sysrq_of_get_keyreset_config(void) |
|---|
| .. | .. |
|---|
| 785 | 841 | } |
|---|
| 786 | 842 | break; |
|---|
| 787 | 843 | |
|---|
| 844 | + case KEY_LEFTSHIFT: |
|---|
| 845 | + case KEY_RIGHTSHIFT: |
|---|
| 846 | + if (!value) |
|---|
| 847 | + sysrq->shift = KEY_RESERVED; |
|---|
| 848 | + else if (value != 2) |
|---|
| 849 | + sysrq->shift = code; |
|---|
| 850 | + break; |
|---|
| 851 | + |
|---|
| 788 | 852 | case KEY_SYSRQ: |
|---|
| 789 | 853 | if (value == 1 && sysrq->alt != KEY_RESERVED) { |
|---|
| 790 | 854 | sysrq->active = true; |
|---|
| 791 | 855 | sysrq->alt_use = sysrq->alt; |
|---|
| 856 | + /* either RESERVED (for released) or actual code */ |
|---|
| 857 | + sysrq->shift_use = sysrq->shift; |
|---|
| 792 | 858 | /* |
|---|
| 793 | 859 | * If nothing else will be pressed we'll need |
|---|
| 794 | 860 | * to re-inject Alt-SysRq keysroke. |
|---|
| .. | .. |
|---|
| 811 | 877 | |
|---|
| 812 | 878 | default: |
|---|
| 813 | 879 | if (sysrq->active && value && value != 2) { |
|---|
| 880 | + unsigned char c = sysrq_xlate[code]; |
|---|
| 881 | + |
|---|
| 814 | 882 | sysrq->need_reinject = false; |
|---|
| 815 | | - __handle_sysrq(sysrq_xlate[code], true); |
|---|
| 883 | + if (sysrq->shift_use != KEY_RESERVED) |
|---|
| 884 | + c = toupper(c); |
|---|
| 885 | + __handle_sysrq(c, true); |
|---|
| 816 | 886 | } |
|---|
| 817 | 887 | break; |
|---|
| 818 | 888 | } |
|---|
| .. | .. |
|---|
| 960 | 1030 | .id_table = sysrq_ids, |
|---|
| 961 | 1031 | }; |
|---|
| 962 | 1032 | |
|---|
| 963 | | -static bool sysrq_handler_registered; |
|---|
| 964 | | - |
|---|
| 965 | 1033 | static inline void sysrq_register_handler(void) |
|---|
| 966 | 1034 | { |
|---|
| 967 | 1035 | int error; |
|---|
| .. | .. |
|---|
| 971 | 1039 | error = input_register_handler(&sysrq_handler); |
|---|
| 972 | 1040 | if (error) |
|---|
| 973 | 1041 | pr_err("Failed to register input handler, error %d", error); |
|---|
| 974 | | - else |
|---|
| 975 | | - sysrq_handler_registered = true; |
|---|
| 976 | 1042 | } |
|---|
| 977 | 1043 | |
|---|
| 978 | 1044 | static inline void sysrq_unregister_handler(void) |
|---|
| 979 | 1045 | { |
|---|
| 980 | | - if (sysrq_handler_registered) { |
|---|
| 981 | | - input_unregister_handler(&sysrq_handler); |
|---|
| 982 | | - sysrq_handler_registered = false; |
|---|
| 983 | | - } |
|---|
| 1046 | + input_unregister_handler(&sysrq_handler); |
|---|
| 984 | 1047 | } |
|---|
| 985 | 1048 | |
|---|
| 986 | 1049 | static int sysrq_reset_seq_param_set(const char *buffer, |
|---|
| .. | .. |
|---|
| 1046 | 1109 | |
|---|
| 1047 | 1110 | return 0; |
|---|
| 1048 | 1111 | } |
|---|
| 1112 | +EXPORT_SYMBOL_GPL(sysrq_toggle_support); |
|---|
| 1049 | 1113 | |
|---|
| 1050 | | -static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, |
|---|
| 1051 | | - struct sysrq_key_op *remove_op_p) |
|---|
| 1114 | +static int __sysrq_swap_key_ops(int key, const struct sysrq_key_op *insert_op_p, |
|---|
| 1115 | + const struct sysrq_key_op *remove_op_p) |
|---|
| 1052 | 1116 | { |
|---|
| 1053 | 1117 | int retval; |
|---|
| 1054 | 1118 | |
|---|
| .. | .. |
|---|
| 1071 | 1135 | return retval; |
|---|
| 1072 | 1136 | } |
|---|
| 1073 | 1137 | |
|---|
| 1074 | | -int register_sysrq_key(int key, struct sysrq_key_op *op_p) |
|---|
| 1138 | +int register_sysrq_key(int key, const struct sysrq_key_op *op_p) |
|---|
| 1075 | 1139 | { |
|---|
| 1076 | 1140 | return __sysrq_swap_key_ops(key, op_p, NULL); |
|---|
| 1077 | 1141 | } |
|---|
| 1078 | 1142 | EXPORT_SYMBOL(register_sysrq_key); |
|---|
| 1079 | 1143 | |
|---|
| 1080 | | -int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) |
|---|
| 1144 | +int unregister_sysrq_key(int key, const struct sysrq_key_op *op_p) |
|---|
| 1081 | 1145 | { |
|---|
| 1082 | 1146 | return __sysrq_swap_key_ops(key, NULL, op_p); |
|---|
| 1083 | 1147 | } |
|---|
| .. | .. |
|---|
| 1101 | 1165 | return count; |
|---|
| 1102 | 1166 | } |
|---|
| 1103 | 1167 | |
|---|
| 1104 | | -static const struct file_operations proc_sysrq_trigger_operations = { |
|---|
| 1105 | | - .write = write_sysrq_trigger, |
|---|
| 1106 | | - .llseek = noop_llseek, |
|---|
| 1168 | +static const struct proc_ops sysrq_trigger_proc_ops = { |
|---|
| 1169 | + .proc_write = write_sysrq_trigger, |
|---|
| 1170 | + .proc_lseek = noop_llseek, |
|---|
| 1107 | 1171 | }; |
|---|
| 1108 | 1172 | |
|---|
| 1109 | 1173 | static void sysrq_init_procfs(void) |
|---|
| 1110 | 1174 | { |
|---|
| 1111 | 1175 | if (!proc_create("sysrq-trigger", S_IWUSR, NULL, |
|---|
| 1112 | | - &proc_sysrq_trigger_operations)) |
|---|
| 1176 | + &sysrq_trigger_proc_ops)) |
|---|
| 1113 | 1177 | pr_err("Failed to register proc interface\n"); |
|---|
| 1114 | 1178 | } |
|---|
| 1115 | 1179 | |
|---|