summaryrefslogtreecommitdiffstats
path: root/drivers/tty/sysrq.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-07-07 10:17:56 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-07-07 10:17:56 +0200
commitf1615bbe9be4def59c3b3eaddb60722efeed16c2 (patch)
treeca3020e65447576fc1826e819651e6ba072030b5 /drivers/tty/sysrq.c
parentcfb3c0ab0903abb6ea5215b37eebd9c2a1f057eb (diff)
parentcd3de83f147601356395b57a8673e9c5ff1e59d1 (diff)
Merge tag 'v3.16-rc4' into drm-intel-next-queued
Due to Dave's vacation drm-next hasn't opened yet for 3.17 so I couldn't move my drm-intel-next queue forward yet like I usually do. Just pull in the latest upstream -rc to unblock patch merging - I don't want to needlessly rebase my current patch pile really and void all the testing we've done already. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/tty/sysrq.c')
-rw-r--r--drivers/tty/sysrq.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index ce396ecdf41..454b65898e2 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -46,6 +46,7 @@
#include <linux/jiffies.h>
#include <linux/syscalls.h>
#include <linux/of.h>
+#include <linux/rcupdate.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
@@ -88,7 +89,7 @@ static void sysrq_handle_loglevel(int key)
int i;
i = key - '0';
- console_loglevel = 7;
+ console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
printk("Loglevel set to %d\n", i);
console_loglevel = i;
}
@@ -343,7 +344,7 @@ static void send_sig_all(int sig)
static void sysrq_handle_term(int key)
{
send_sig_all(SIGTERM);
- console_loglevel = 8;
+ console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
}
static struct sysrq_key_op sysrq_term_op = {
.handler = sysrq_handle_term,
@@ -387,7 +388,7 @@ static struct sysrq_key_op sysrq_thaw_op = {
static void sysrq_handle_kill(int key)
{
send_sig_all(SIGKILL);
- console_loglevel = 8;
+ console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
}
static struct sysrq_key_op sysrq_kill_op = {
.handler = sysrq_handle_kill,
@@ -510,9 +511,9 @@ void __handle_sysrq(int key, bool check_mask)
struct sysrq_key_op *op_p;
int orig_log_level;
int i;
- unsigned long flags;
- spin_lock_irqsave(&sysrq_key_table_lock, flags);
+ rcu_sysrq_start();
+ rcu_read_lock();
/*
* Raise the apparent loglevel to maximum so that the sysrq header
* is shown to provide the user with positive feedback. We do not
@@ -520,7 +521,7 @@ void __handle_sysrq(int key, bool check_mask)
* routing in the consumers of /proc/kmsg.
*/
orig_log_level = console_loglevel;
- console_loglevel = 7;
+ console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
printk(KERN_INFO "SysRq : ");
op_p = __sysrq_get_key_op(key);
@@ -554,7 +555,8 @@ void __handle_sysrq(int key, bool check_mask)
printk("\n");
console_loglevel = orig_log_level;
}
- spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
+ rcu_read_unlock();
+ rcu_sysrq_end();
}
void handle_sysrq(int key)
@@ -1043,16 +1045,23 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
struct sysrq_key_op *remove_op_p)
{
int retval;
- unsigned long flags;
- spin_lock_irqsave(&sysrq_key_table_lock, flags);
+ spin_lock(&sysrq_key_table_lock);
if (__sysrq_get_key_op(key) == remove_op_p) {
__sysrq_put_key_op(key, insert_op_p);
retval = 0;
} else {
retval = -1;
}
- spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
+ spin_unlock(&sysrq_key_table_lock);
+
+ /*
+ * A concurrent __handle_sysrq either got the old op or the new op.
+ * Wait for it to go away before returning, so the code for an old
+ * op is not freed (eg. on module unload) while it is in use.
+ */
+ synchronize_rcu();
+
return retval;
}