2017-11-06 17:11:51 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Written for linux by Johan Myreen as a translation from
|
|
|
|
* the assembly version by Linus (with diacriticals added)
|
|
|
|
*
|
|
|
|
* Some additional features added by Christoph Niemann (ChN), March 1993
|
|
|
|
*
|
|
|
|
* Loadable keymaps by Risto Kankkunen, May 1993
|
|
|
|
*
|
|
|
|
* Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
|
|
|
|
* Added decr/incr_console, dynamic keymaps, Unicode support,
|
|
|
|
* dynamic function/string keys, led setting, Sept 1994
|
|
|
|
* `Sticky' modifier keys, 951006.
|
|
|
|
*
|
|
|
|
* 11-11-96: SAK should now work in the raw mode (Martin Mares)
|
2005-09-10 17:03:38 +00:00
|
|
|
*
|
2005-04-16 22:20:36 +00:00
|
|
|
* Modified to provide 'generic' keyboard support by Hamish Macdonald
|
|
|
|
* Merge with the m68k keyboard driver and split-off of the PC low-level
|
|
|
|
* parts by Geert Uytterhoeven, May 1997
|
|
|
|
*
|
|
|
|
* 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
|
|
|
|
* 30-07-98: Dead keys redone, aeb@cwi.nl.
|
|
|
|
* 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
|
|
|
|
*/
|
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
|
2007-07-16 06:40:40 +00:00
|
|
|
#include <linux/consolemap.h>
|
2020-10-29 11:32:08 +00:00
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/input.h>
|
|
|
|
#include <linux/jiffies.h>
|
|
|
|
#include <linux/kbd_diacr.h>
|
|
|
|
#include <linux/kbd_kern.h>
|
|
|
|
#include <linux/leds.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/mm.h>
|
2020-10-29 11:32:08 +00:00
|
|
|
#include <linux/module.h>
|
2020-07-30 10:55:46 +00:00
|
|
|
#include <linux/nospec.h>
|
2020-10-29 11:32:08 +00:00
|
|
|
#include <linux/notifier.h>
|
|
|
|
#include <linux/reboot.h>
|
|
|
|
#include <linux/sched/debug.h>
|
|
|
|
#include <linux/sched/signal.h>
|
|
|
|
#include <linux/slab.h>
|
2020-10-29 11:32:07 +00:00
|
|
|
#include <linux/spinlock.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/string.h>
|
2020-10-29 11:32:08 +00:00
|
|
|
#include <linux/tty_flip.h>
|
|
|
|
#include <linux/tty.h>
|
2012-02-27 23:18:56 +00:00
|
|
|
#include <linux/uaccess.h>
|
2020-10-29 11:32:08 +00:00
|
|
|
#include <linux/vt_kern.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-09-11 11:59:29 +00:00
|
|
|
#include <asm/irq_regs.h>
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Exported functions/variables
|
|
|
|
*/
|
|
|
|
|
2020-11-09 10:55:59 +00:00
|
|
|
#define KBD_DEFMODE (BIT(VC_REPEAT) | BIT(VC_META))
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-04-13 19:08:26 +00:00
|
|
|
#if defined(CONFIG_X86) || defined(CONFIG_PARISC)
|
|
|
|
#include <asm/kbdleds.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#else
|
2012-04-13 19:08:26 +00:00
|
|
|
static inline int kbd_defleds(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define KBD_DEFLOCK 0
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handler Tables.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define K_HANDLERS\
|
|
|
|
k_self, k_fn, k_spec, k_pad,\
|
|
|
|
k_dead, k_cons, k_cur, k_shift,\
|
|
|
|
k_meta, k_ascii, k_lock, k_lowercase,\
|
2006-04-02 05:10:28 +00:00
|
|
|
k_slock, k_dead2, k_brl, k_ignore
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-09-10 17:03:38 +00:00
|
|
|
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
char up_flag);
|
2005-04-16 22:20:36 +00:00
|
|
|
static k_handler_fn K_HANDLERS;
|
2010-03-22 05:31:26 +00:00
|
|
|
static k_handler_fn *k_handler[16] = { K_HANDLERS };
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
#define FN_HANDLERS\
|
2005-09-10 17:03:38 +00:00
|
|
|
fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\
|
|
|
|
fn_show_state, fn_send_intr, fn_lastcons, fn_caps_toggle,\
|
|
|
|
fn_num, fn_hold, fn_scroll_forw, fn_scroll_back,\
|
|
|
|
fn_boot_it, fn_caps_on, fn_compose, fn_SAK,\
|
|
|
|
fn_dec_console, fn_inc_console, fn_spawn_con, fn_bare_num
|
2005-04-16 22:20:36 +00:00
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
typedef void (fn_handler_fn)(struct vc_data *vc);
|
2005-04-16 22:20:36 +00:00
|
|
|
static fn_handler_fn FN_HANDLERS;
|
|
|
|
static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Variables exported for vt_ioctl.c
|
|
|
|
*/
|
|
|
|
|
2006-10-02 09:17:13 +00:00
|
|
|
struct vt_spawn_console vt_spawn_con = {
|
2007-05-08 07:30:09 +00:00
|
|
|
.lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),
|
2006-10-02 09:17:13 +00:00
|
|
|
.pid = NULL,
|
|
|
|
.sig = 0,
|
|
|
|
};
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal Data.
|
|
|
|
*/
|
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
static struct kbd_struct kbd_table[MAX_NR_CONSOLES];
|
|
|
|
static struct kbd_struct *kbd = kbd_table;
|
|
|
|
|
|
|
|
/* maximum values each key_handler can handle */
|
2020-10-29 11:32:10 +00:00
|
|
|
static const unsigned char max_vals[] = {
|
|
|
|
[ KT_LATIN ] = 255,
|
|
|
|
[ KT_FN ] = ARRAY_SIZE(func_table) - 1,
|
|
|
|
[ KT_SPEC ] = ARRAY_SIZE(fn_handler) - 1,
|
|
|
|
[ KT_PAD ] = NR_PAD - 1,
|
|
|
|
[ KT_DEAD ] = NR_DEAD - 1,
|
|
|
|
[ KT_CONS ] = 255,
|
|
|
|
[ KT_CUR ] = 3,
|
|
|
|
[ KT_SHIFT ] = NR_SHIFT - 1,
|
|
|
|
[ KT_META ] = 255,
|
|
|
|
[ KT_ASCII ] = NR_ASCII - 1,
|
|
|
|
[ KT_LOCK ] = NR_LOCK - 1,
|
|
|
|
[ KT_LETTER ] = 255,
|
|
|
|
[ KT_SLOCK ] = NR_LOCK - 1,
|
|
|
|
[ KT_DEAD2 ] = 255,
|
|
|
|
[ KT_BRL ] = NR_BRL - 1,
|
2012-02-28 14:49:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const int NR_TYPES = ARRAY_SIZE(max_vals);
|
|
|
|
|
2021-01-27 16:42:22 +00:00
|
|
|
static void kbd_bh(struct tasklet_struct *unused);
|
|
|
|
static DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh);
|
2021-01-05 12:02:29 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
static struct input_handler kbd_handler;
|
2009-11-30 07:40:58 +00:00
|
|
|
static DEFINE_SPINLOCK(kbd_event_lock);
|
2012-07-17 16:06:41 +00:00
|
|
|
static DEFINE_SPINLOCK(led_lock);
|
2019-03-10 21:24:15 +00:00
|
|
|
static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf' and friends */
|
2020-10-29 11:32:13 +00:00
|
|
|
static DECLARE_BITMAP(key_down, KEY_CNT); /* keyboard key bitmap */
|
2005-04-16 22:20:36 +00:00
|
|
|
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
|
2010-03-22 05:31:26 +00:00
|
|
|
static bool dead_key_next;
|
2020-05-25 23:27:40 +00:00
|
|
|
|
|
|
|
/* Handles a number being assembled on the number pad */
|
|
|
|
static bool npadch_active;
|
|
|
|
static unsigned int npadch_value;
|
|
|
|
|
2006-04-02 05:10:28 +00:00
|
|
|
static unsigned int diacr;
|
2020-10-29 11:32:14 +00:00
|
|
|
static bool rep; /* flag telling character repeat */
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
static int shift_state = 0;
|
|
|
|
|
2015-06-06 18:44:39 +00:00
|
|
|
static unsigned int ledstate = -1U; /* undefined */
|
2005-04-16 22:20:36 +00:00
|
|
|
static unsigned char ledioctl;
|
tty: Fix the keyboard led light display problem
Use the "ctrl+alt+Fn" key combination to switch the system from tty to
desktop or switch the system from desktop to tty. After the switch is
completed, it is found that the state of the keyboard lock is
inconsistent with the state of the keyboard Led light.The reasons are
as follows:
* The desktop environment (Xorg and other services) is bound to a tty
(assuming it is tty1), and the kb->kbdmode attribute value of tty1
will be set to VC_OFF. According to the current code logic, in the
desktop environment, the values of ledstate and kb->ledflagstate
of tty1 will not be modified anymore, so they are always 0.
* When switching between each tty, the final value of ledstate set by
the previous tty is compared with the kb->ledflagstate value of the
current tty to determine whether to set the state of the keyboard
light. The process of switching between desktop and tty is also the
process of switching between tty1 and other ttys. There are two
situations:
- (1) In the desktop environment, tty1 will not set the ledstate,
which will cause when switching from the desktop to other ttys,
if the desktop lights up the keyboard's led, after the switch is
completed, the keyboard's led light will always be on;
- (2) When switching from another tty to the desktop, this
mechanism will trigger tty1 to set the led state. If other tty
lights up the led of the keyboard before switching to the desktop,
the led will be forcibly turned off. This situation should
be avoided.
* The current patch is to solve these problems: When VT is switched,
the keyboard led needs to be set once.Ensure that after the
switch is completed, the state of the keyboard LED is consistent
with the state of the keyboard lock.
Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
Link: https://lore.kernel.org/r/20211215125125.10554-1-changlianzhi@uniontech.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2021-12-15 12:51:25 +00:00
|
|
|
static bool vt_switch;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
/*
|
|
|
|
* Notifier list for console keyboard events
|
|
|
|
*/
|
|
|
|
static ATOMIC_NOTIFIER_HEAD(keyboard_notifier_list);
|
|
|
|
|
|
|
|
int register_keyboard_notifier(struct notifier_block *nb)
|
|
|
|
{
|
|
|
|
return atomic_notifier_chain_register(&keyboard_notifier_list, nb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(register_keyboard_notifier);
|
|
|
|
|
|
|
|
int unregister_keyboard_notifier(struct notifier_block *nb)
|
|
|
|
{
|
|
|
|
return atomic_notifier_chain_unregister(&keyboard_notifier_list, nb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
2007-03-15 02:50:42 +00:00
|
|
|
* Translation of scancodes to keycodes. We set them on only the first
|
|
|
|
* keyboard in the list that accepts the scancode and keycode.
|
|
|
|
* Explanation for not choosing the first attached keyboard anymore:
|
|
|
|
* USB keyboards for example have two event devices: one for all "normal"
|
|
|
|
* keys and one for extra function keys (like "volume up", "make coffee",
|
|
|
|
* etc.). So this means that scancodes for the extra function keys won't
|
|
|
|
* be valid for the first event device, but will be for the second.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
struct getset_keycode_data {
|
2010-09-10 04:54:22 +00:00
|
|
|
struct input_keymap_entry ke;
|
2009-12-02 05:54:35 +00:00
|
|
|
int error;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int getkeycode_helper(struct input_handle *handle, void *data)
|
|
|
|
{
|
|
|
|
struct getset_keycode_data *d = data;
|
|
|
|
|
2010-09-10 04:54:22 +00:00
|
|
|
d->error = input_get_keycode(handle->dev, &d->ke);
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
return d->error == 0; /* stop as soon as we successfully get one */
|
|
|
|
}
|
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
static int getkeycode(unsigned int scancode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-09-10 04:54:22 +00:00
|
|
|
struct getset_keycode_data d = {
|
|
|
|
.ke = {
|
|
|
|
.flags = 0,
|
|
|
|
.len = sizeof(scancode),
|
|
|
|
.keycode = 0,
|
|
|
|
},
|
|
|
|
.error = -ENODEV,
|
|
|
|
};
|
|
|
|
|
|
|
|
memcpy(d.ke.scancode, &scancode, sizeof(scancode));
|
2007-03-15 02:50:42 +00:00
|
|
|
|
2009-12-02 05:54:35 +00:00
|
|
|
input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-09-10 04:54:22 +00:00
|
|
|
return d.error ?: d.ke.keycode;
|
2009-12-02 05:54:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int setkeycode_helper(struct input_handle *handle, void *data)
|
|
|
|
{
|
|
|
|
struct getset_keycode_data *d = data;
|
|
|
|
|
2010-09-10 04:54:22 +00:00
|
|
|
d->error = input_set_keycode(handle->dev, &d->ke);
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
return d->error == 0; /* stop as soon as we successfully set one */
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
static int setkeycode(unsigned int scancode, unsigned int keycode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-09-10 04:54:22 +00:00
|
|
|
struct getset_keycode_data d = {
|
|
|
|
.ke = {
|
|
|
|
.flags = 0,
|
|
|
|
.len = sizeof(scancode),
|
|
|
|
.keycode = keycode,
|
|
|
|
},
|
|
|
|
.error = -ENODEV,
|
|
|
|
};
|
|
|
|
|
|
|
|
memcpy(d.ke.scancode, &scancode, sizeof(scancode));
|
2007-03-15 02:50:42 +00:00
|
|
|
|
2009-12-02 05:54:35 +00:00
|
|
|
input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-12-02 05:54:35 +00:00
|
|
|
return d.error;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-12-16 00:26:53 +00:00
|
|
|
* Making beeps and bells. Note that we prefer beeps to bells, but when
|
|
|
|
* shutting the sound off we do both.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
static int kd_sound_helper(struct input_handle *handle, void *data)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-12-02 05:54:35 +00:00
|
|
|
unsigned int *hz = data;
|
|
|
|
struct input_dev *dev = handle->dev;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-12-02 05:54:35 +00:00
|
|
|
if (test_bit(EV_SND, dev->evbit)) {
|
2009-12-16 00:26:53 +00:00
|
|
|
if (test_bit(SND_TONE, dev->sndbit)) {
|
2009-12-02 05:54:35 +00:00
|
|
|
input_inject_event(handle, EV_SND, SND_TONE, *hz);
|
2009-12-16 00:26:53 +00:00
|
|
|
if (*hz)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (test_bit(SND_BELL, dev->sndbit))
|
2009-12-02 05:54:35 +00:00
|
|
|
input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-28 18:28:21 +00:00
|
|
|
static void kd_nosound(struct timer_list *unused)
|
2009-12-02 05:54:35 +00:00
|
|
|
{
|
|
|
|
static unsigned int zero;
|
|
|
|
|
|
|
|
input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2017-10-04 23:27:04 +00:00
|
|
|
static DEFINE_TIMER(kd_mksound_timer, kd_nosound);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
void kd_mksound(unsigned int hz, unsigned int ticks)
|
|
|
|
{
|
2009-12-02 05:54:35 +00:00
|
|
|
del_timer_sync(&kd_mksound_timer);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-12-02 05:54:35 +00:00
|
|
|
input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-12-02 05:54:35 +00:00
|
|
|
if (hz && ticks)
|
|
|
|
mod_timer(&kd_mksound_timer, jiffies + ticks);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2008-04-30 07:54:51 +00:00
|
|
|
EXPORT_SYMBOL(kd_mksound);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Setting the keyboard rate.
|
|
|
|
*/
|
|
|
|
|
2009-12-02 05:54:35 +00:00
|
|
|
static int kbd_rate_helper(struct input_handle *handle, void *data)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-12-02 05:54:35 +00:00
|
|
|
struct input_dev *dev = handle->dev;
|
2014-09-06 01:57:57 +00:00
|
|
|
struct kbd_repeat *rpt = data;
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
if (test_bit(EV_REP, dev->evbit)) {
|
|
|
|
|
2014-09-06 01:57:57 +00:00
|
|
|
if (rpt[0].delay > 0)
|
2009-12-02 05:54:35 +00:00
|
|
|
input_inject_event(handle,
|
2014-09-06 01:57:57 +00:00
|
|
|
EV_REP, REP_DELAY, rpt[0].delay);
|
|
|
|
if (rpt[0].period > 0)
|
2009-12-02 05:54:35 +00:00
|
|
|
input_inject_event(handle,
|
2014-09-06 01:57:57 +00:00
|
|
|
EV_REP, REP_PERIOD, rpt[0].period);
|
2009-12-02 05:54:35 +00:00
|
|
|
|
2014-09-06 01:57:57 +00:00
|
|
|
rpt[1].delay = dev->rep[REP_DELAY];
|
|
|
|
rpt[1].period = dev->rep[REP_PERIOD];
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-06 01:57:57 +00:00
|
|
|
int kbd_rate(struct kbd_repeat *rpt)
|
2009-12-02 05:54:35 +00:00
|
|
|
{
|
2014-09-06 01:57:57 +00:00
|
|
|
struct kbd_repeat data[2] = { *rpt };
|
2009-12-02 05:54:35 +00:00
|
|
|
|
|
|
|
input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
|
2014-09-06 01:57:57 +00:00
|
|
|
*rpt = data[1]; /* Copy currently used settings */
|
2009-12-02 05:54:35 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper Functions.
|
|
|
|
*/
|
|
|
|
static void put_queue(struct vc_data *vc, int ch)
|
|
|
|
{
|
2013-01-03 14:53:03 +00:00
|
|
|
tty_insert_flip_char(&vc->port, ch, 0);
|
2021-11-22 11:16:46 +00:00
|
|
|
tty_flip_buffer_push(&vc->port);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 11:32:22 +00:00
|
|
|
static void puts_queue(struct vc_data *vc, const char *cp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2020-10-29 11:32:22 +00:00
|
|
|
tty_insert_flip_string(&vc->port, cp, strlen(cp));
|
2021-11-22 11:16:46 +00:00
|
|
|
tty_flip_buffer_push(&vc->port);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void applkey(struct vc_data *vc, int key, char mode)
|
|
|
|
{
|
|
|
|
static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
|
|
|
|
|
|
|
|
buf[1] = (mode ? 'O' : '[');
|
|
|
|
buf[2] = key;
|
|
|
|
puts_queue(vc, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Many other routines do put_queue, but I think either
|
|
|
|
* they produce ASCII, or they produce some user-assigned
|
|
|
|
* string, and in both cases we might assume that it is
|
2007-07-16 06:40:40 +00:00
|
|
|
* in utf-8 already.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2007-07-16 06:40:40 +00:00
|
|
|
static void to_utf8(struct vc_data *vc, uint c)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (c < 0x80)
|
|
|
|
/* 0******* */
|
|
|
|
put_queue(vc, c);
|
2005-09-10 17:03:38 +00:00
|
|
|
else if (c < 0x800) {
|
2005-04-16 22:20:36 +00:00
|
|
|
/* 110***** 10****** */
|
2005-09-10 17:03:38 +00:00
|
|
|
put_queue(vc, 0xc0 | (c >> 6));
|
2005-04-16 22:20:36 +00:00
|
|
|
put_queue(vc, 0x80 | (c & 0x3f));
|
2010-03-22 05:31:26 +00:00
|
|
|
} else if (c < 0x10000) {
|
|
|
|
if (c >= 0xD800 && c < 0xE000)
|
2007-07-16 06:40:40 +00:00
|
|
|
return;
|
|
|
|
if (c == 0xFFFF)
|
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
/* 1110**** 10****** 10****** */
|
|
|
|
put_queue(vc, 0xe0 | (c >> 12));
|
|
|
|
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
|
|
|
|
put_queue(vc, 0x80 | (c & 0x3f));
|
2010-03-22 05:31:26 +00:00
|
|
|
} else if (c < 0x110000) {
|
2007-07-16 06:40:40 +00:00
|
|
|
/* 11110*** 10****** 10****** 10****** */
|
|
|
|
put_queue(vc, 0xf0 | (c >> 18));
|
|
|
|
put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
|
|
|
|
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
|
|
|
|
put_queue(vc, 0x80 | (c & 0x3f));
|
2005-09-10 17:03:38 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2021-01-05 12:02:28 +00:00
|
|
|
/* FIXME: review locking for vt.c callers */
|
|
|
|
static void set_leds(void)
|
|
|
|
{
|
|
|
|
tasklet_schedule(&keyboard_tasklet);
|
|
|
|
}
|
|
|
|
|
2005-09-10 17:03:38 +00:00
|
|
|
/*
|
2005-04-16 22:20:36 +00:00
|
|
|
* Called after returning from RAW mode or when changing consoles - recompute
|
|
|
|
* shift_down[] and shift_state from key_down[] maybe called when keymap is
|
2012-02-28 14:49:23 +00:00
|
|
|
* undefined, so that shiftkey release is seen. The caller must hold the
|
|
|
|
* kbd_event_lock.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2012-02-28 14:49:23 +00:00
|
|
|
|
|
|
|
static void do_compute_shiftstate(void)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2016-06-27 21:12:34 +00:00
|
|
|
unsigned int k, sym, val;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
shift_state = 0;
|
|
|
|
memset(shift_down, 0, sizeof(shift_down));
|
2005-09-10 17:03:38 +00:00
|
|
|
|
2016-06-27 21:12:34 +00:00
|
|
|
for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
|
|
|
|
sym = U(key_maps[0][k]);
|
|
|
|
if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
|
2005-04-16 22:20:36 +00:00
|
|
|
continue;
|
|
|
|
|
2016-06-27 21:12:34 +00:00
|
|
|
val = KVAL(sym);
|
|
|
|
if (val == KVAL(K_CAPSSHIFT))
|
|
|
|
val = KVAL(K_SHIFT);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2016-06-27 21:12:34 +00:00
|
|
|
shift_down[val]++;
|
|
|
|
shift_state |= BIT(val);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
/* We still have to export this method to vt.c */
|
2021-01-05 12:02:28 +00:00
|
|
|
void vt_set_leds_compute_shiftstate(void)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
2021-01-05 12:02:28 +00:00
|
|
|
|
tty: Fix the keyboard led light display problem
Use the "ctrl+alt+Fn" key combination to switch the system from tty to
desktop or switch the system from desktop to tty. After the switch is
completed, it is found that the state of the keyboard lock is
inconsistent with the state of the keyboard Led light.The reasons are
as follows:
* The desktop environment (Xorg and other services) is bound to a tty
(assuming it is tty1), and the kb->kbdmode attribute value of tty1
will be set to VC_OFF. According to the current code logic, in the
desktop environment, the values of ledstate and kb->ledflagstate
of tty1 will not be modified anymore, so they are always 0.
* When switching between each tty, the final value of ledstate set by
the previous tty is compared with the kb->ledflagstate value of the
current tty to determine whether to set the state of the keyboard
light. The process of switching between desktop and tty is also the
process of switching between tty1 and other ttys. There are two
situations:
- (1) In the desktop environment, tty1 will not set the ledstate,
which will cause when switching from the desktop to other ttys,
if the desktop lights up the keyboard's led, after the switch is
completed, the keyboard's led light will always be on;
- (2) When switching from another tty to the desktop, this
mechanism will trigger tty1 to set the led state. If other tty
lights up the led of the keyboard before switching to the desktop,
the led will be forcibly turned off. This situation should
be avoided.
* The current patch is to solve these problems: When VT is switched,
the keyboard led needs to be set once.Ensure that after the
switch is completed, the state of the keyboard LED is consistent
with the state of the keyboard lock.
Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
Link: https://lore.kernel.org/r/20211215125125.10554-1-changlianzhi@uniontech.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2021-12-15 12:51:25 +00:00
|
|
|
/*
|
|
|
|
* When VT is switched, the keyboard led needs to be set once.
|
|
|
|
* Ensure that after the switch is completed, the state of the
|
|
|
|
* keyboard LED is consistent with the state of the keyboard lock.
|
|
|
|
*/
|
|
|
|
vt_switch = true;
|
2021-01-05 12:02:28 +00:00
|
|
|
set_leds();
|
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
do_compute_shiftstate();
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* We have a combining character DIACR here, followed by the character CH.
|
|
|
|
* If the combination occurs in the table, return the corresponding value.
|
|
|
|
* Otherwise, if CH is a space or equals DIACR, return DIACR.
|
|
|
|
* Otherwise, conclude that DIACR was not combining after all,
|
|
|
|
* queue it and return CH.
|
|
|
|
*/
|
2006-04-02 05:10:28 +00:00
|
|
|
static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-04-02 05:10:28 +00:00
|
|
|
unsigned int d = diacr;
|
2005-04-16 22:20:36 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
diacr = 0;
|
|
|
|
|
2006-04-02 05:10:28 +00:00
|
|
|
if ((d & ~0xff) == BRL_UC_ROW) {
|
|
|
|
if ((ch & ~0xff) == BRL_UC_ROW)
|
|
|
|
return d | ch;
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < accent_table_size; i++)
|
|
|
|
if (accent_table[i].diacr == d && accent_table[i].base == ch)
|
|
|
|
return accent_table[i].result;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-04-02 05:10:28 +00:00
|
|
|
if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
|
2005-04-16 22:20:36 +00:00
|
|
|
return d;
|
|
|
|
|
2006-04-02 05:10:28 +00:00
|
|
|
if (kbd->kbdmode == VC_UNICODE)
|
2007-10-17 06:27:04 +00:00
|
|
|
to_utf8(vc, d);
|
|
|
|
else {
|
|
|
|
int c = conv_uni_to_8bit(d);
|
|
|
|
if (c != -1)
|
|
|
|
put_queue(vc, c);
|
|
|
|
}
|
2006-04-02 05:10:28 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Special function handlers
|
|
|
|
*/
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_enter(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (diacr) {
|
2006-04-02 05:10:28 +00:00
|
|
|
if (kbd->kbdmode == VC_UNICODE)
|
2007-10-17 06:27:04 +00:00
|
|
|
to_utf8(vc, diacr);
|
|
|
|
else {
|
|
|
|
int c = conv_uni_to_8bit(diacr);
|
|
|
|
if (c != -1)
|
|
|
|
put_queue(vc, c);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
diacr = 0;
|
|
|
|
}
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2020-11-09 10:56:00 +00:00
|
|
|
put_queue(vc, '\r');
|
2005-04-16 22:20:36 +00:00
|
|
|
if (vc_kbd_mode(kbd, VC_CRLF))
|
2020-11-09 10:56:00 +00:00
|
|
|
put_queue(vc, '\n');
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_caps_toggle(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (rep)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
chg_vc_kbd_led(kbd, VC_CAPSLOCK);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_caps_on(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (rep)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
set_vc_kbd_led(kbd, VC_CAPSLOCK);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_show_ptregs(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
struct pt_regs *regs = get_irq_regs();
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (regs)
|
|
|
|
show_regs(regs);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_hold(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-06-01 20:52:56 +00:00
|
|
|
struct tty_struct *tty = vc->port.tty;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (rep || !tty)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
|
|
|
|
* these routines are also activated by ^S/^Q.
|
|
|
|
* (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
|
|
|
|
*/
|
2021-05-05 09:19:05 +00:00
|
|
|
if (tty->flow.stopped)
|
2005-04-16 22:20:36 +00:00
|
|
|
start_tty(tty);
|
|
|
|
else
|
|
|
|
stop_tty(tty);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_num(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-03-22 05:31:26 +00:00
|
|
|
if (vc_kbd_mode(kbd, VC_APPLIC))
|
2005-04-16 22:20:36 +00:00
|
|
|
applkey(vc, 'P', 1);
|
|
|
|
else
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
fn_bare_num(vc);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bind this to Shift-NumLock if you work in application keypad mode
|
|
|
|
* but want to be able to change the NumLock flag.
|
|
|
|
* Bind this to NumLock if you prefer that the NumLock key always
|
|
|
|
* changes the NumLock flag.
|
|
|
|
*/
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_bare_num(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (!rep)
|
|
|
|
chg_vc_kbd_led(kbd, VC_NUMLOCK);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_lastcons(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
/* switch to the last used console, ChN */
|
|
|
|
set_console(last_console);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_dec_console(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int i, cur = fg_console;
|
|
|
|
|
|
|
|
/* Currently switching? Queue this next switch relative to that. */
|
|
|
|
if (want_console != -1)
|
|
|
|
cur = want_console;
|
|
|
|
|
2005-09-10 17:03:38 +00:00
|
|
|
for (i = cur - 1; i != cur; i--) {
|
2005-04-16 22:20:36 +00:00
|
|
|
if (i == -1)
|
2005-09-10 17:03:38 +00:00
|
|
|
i = MAX_NR_CONSOLES - 1;
|
2005-04-16 22:20:36 +00:00
|
|
|
if (vc_cons_allocated(i))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
set_console(i);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_inc_console(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int i, cur = fg_console;
|
|
|
|
|
|
|
|
/* Currently switching? Queue this next switch relative to that. */
|
|
|
|
if (want_console != -1)
|
|
|
|
cur = want_console;
|
|
|
|
|
|
|
|
for (i = cur+1; i != cur; i++) {
|
|
|
|
if (i == MAX_NR_CONSOLES)
|
|
|
|
i = 0;
|
|
|
|
if (vc_cons_allocated(i))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
set_console(i);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_send_intr(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2013-01-03 14:53:03 +00:00
|
|
|
tty_insert_flip_char(&vc->port, 0, TTY_BREAK);
|
2021-11-22 11:16:46 +00:00
|
|
|
tty_flip_buffer_push(&vc->port);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_scroll_forw(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
scrollfront(vc, 0);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_scroll_back(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2016-06-23 11:34:23 +00:00
|
|
|
scrollback(vc);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_show_mem(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2017-02-22 23:46:16 +00:00
|
|
|
show_mem(0, NULL);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_show_state(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
show_state();
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_boot_it(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
ctrl_alt_del();
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_compose(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-03-22 05:31:26 +00:00
|
|
|
dead_key_next = true;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_spawn_con(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-10-02 09:17:13 +00:00
|
|
|
spin_lock(&vt_spawn_con.lock);
|
|
|
|
if (vt_spawn_con.pid)
|
|
|
|
if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
|
|
|
|
put_pid(vt_spawn_con.pid);
|
|
|
|
vt_spawn_con.pid = NULL;
|
|
|
|
}
|
|
|
|
spin_unlock(&vt_spawn_con.lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_SAK(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2007-02-10 09:44:34 +00:00
|
|
|
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
|
|
|
|
schedule_work(SAK_work);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void fn_null(struct vc_data *vc)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-02-28 14:49:23 +00:00
|
|
|
do_compute_shiftstate();
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Special key handlers
|
|
|
|
*/
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_ignore(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (up_flag)
|
|
|
|
return;
|
|
|
|
if (value >= ARRAY_SIZE(fn_handler))
|
|
|
|
return;
|
2005-09-10 17:03:38 +00:00
|
|
|
if ((kbd->kbdmode == VC_RAW ||
|
2011-02-04 21:55:50 +00:00
|
|
|
kbd->kbdmode == VC_MEDIUMRAW ||
|
|
|
|
kbd->kbdmode == VC_OFF) &&
|
2005-04-16 22:20:36 +00:00
|
|
|
value != KVAL(K_SAK))
|
|
|
|
return; /* SAK is allowed even in raw mode */
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
fn_handler[value](vc);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-03-22 05:31:26 +00:00
|
|
|
pr_err("k_lowercase was called - impossible\n");
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (up_flag)
|
|
|
|
return; /* no action, if this is a key release */
|
|
|
|
|
|
|
|
if (diacr)
|
|
|
|
value = handle_diacr(vc, value);
|
|
|
|
|
|
|
|
if (dead_key_next) {
|
2010-03-22 05:31:26 +00:00
|
|
|
dead_key_next = false;
|
2005-04-16 22:20:36 +00:00
|
|
|
diacr = value;
|
|
|
|
return;
|
|
|
|
}
|
2006-04-02 05:10:28 +00:00
|
|
|
if (kbd->kbdmode == VC_UNICODE)
|
2007-10-17 06:27:04 +00:00
|
|
|
to_utf8(vc, value);
|
|
|
|
else {
|
|
|
|
int c = conv_uni_to_8bit(value);
|
|
|
|
if (c != -1)
|
|
|
|
put_queue(vc, c);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle dead key. Note that we now may have several
|
|
|
|
* dead keys modifying the same character. Very useful
|
|
|
|
* for Vietnamese.
|
|
|
|
*/
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (up_flag)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
diacr = (diacr ? handle_diacr(vc, value) : value);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
|
2006-04-02 05:10:28 +00:00
|
|
|
{
|
2008-06-12 22:21:51 +00:00
|
|
|
k_unicode(vc, conv_8bit_to_uni(value), up_flag);
|
2006-04-02 05:10:28 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
|
2006-04-02 05:10:28 +00:00
|
|
|
{
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
k_deadunicode(vc, value, up_flag);
|
2006-04-02 05:10:28 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Obsolete - for backwards compatibility only
|
|
|
|
*/
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2018-06-03 18:18:58 +00:00
|
|
|
static const unsigned char ret_diacr[NR_DEAD] = {
|
|
|
|
'`', /* dead_grave */
|
|
|
|
'\'', /* dead_acute */
|
|
|
|
'^', /* dead_circumflex */
|
|
|
|
'~', /* dead_tilda */
|
|
|
|
'"', /* dead_diaeresis */
|
|
|
|
',', /* dead_cedilla */
|
|
|
|
'_', /* dead_macron */
|
|
|
|
'U', /* dead_breve */
|
|
|
|
'.', /* dead_abovedot */
|
|
|
|
'*', /* dead_abovering */
|
|
|
|
'=', /* dead_doubleacute */
|
|
|
|
'c', /* dead_caron */
|
|
|
|
'k', /* dead_ogonek */
|
|
|
|
'i', /* dead_iota */
|
|
|
|
'#', /* dead_voiced_sound */
|
|
|
|
'o', /* dead_semivoiced_sound */
|
|
|
|
'!', /* dead_belowdot */
|
|
|
|
'?', /* dead_hook */
|
|
|
|
'+', /* dead_horn */
|
|
|
|
'-', /* dead_stroke */
|
|
|
|
')', /* dead_abovecomma */
|
|
|
|
'(', /* dead_abovereversedcomma */
|
|
|
|
':', /* dead_doublegrave */
|
|
|
|
'n', /* dead_invertedbreve */
|
|
|
|
';', /* dead_belowcomma */
|
|
|
|
'$', /* dead_currency */
|
|
|
|
'@', /* dead_greek */
|
|
|
|
};
|
2010-03-22 05:31:26 +00:00
|
|
|
|
|
|
|
k_deadunicode(vc, ret_diacr[value], up_flag);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (up_flag)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
set_console(value);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (up_flag)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
|
|
|
if ((unsigned)value < ARRAY_SIZE(func_table)) {
|
2020-10-19 08:55:17 +00:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&func_buf_lock, flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (func_table[value])
|
|
|
|
puts_queue(vc, func_table[value]);
|
2020-10-19 08:55:17 +00:00
|
|
|
spin_unlock_irqrestore(&func_buf_lock, flags);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
} else
|
2010-03-22 05:31:26 +00:00
|
|
|
pr_err("k_fn called with value=%d\n", value);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-11-05 03:09:08 +00:00
|
|
|
static const char cur_chars[] = "BDCA";
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (up_flag)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-06-05 04:18:00 +00:00
|
|
|
static const char pad_chars[] = "0123456789+-*/\015,.?()#";
|
|
|
|
static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (up_flag)
|
|
|
|
return; /* no action, if this is a key release */
|
|
|
|
|
|
|
|
/* kludge... shift forces cursor/number keys */
|
|
|
|
if (vc_kbd_mode(kbd, VC_APPLIC) && !shift_down[KG_SHIFT]) {
|
|
|
|
applkey(vc, app_map[value], 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
if (!vc_kbd_led(kbd, VC_NUMLOCK)) {
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
switch (value) {
|
2010-03-22 05:31:26 +00:00
|
|
|
case KVAL(K_PCOMMA):
|
|
|
|
case KVAL(K_PDOT):
|
|
|
|
k_fn(vc, KVAL(K_REMOVE), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P0):
|
|
|
|
k_fn(vc, KVAL(K_INSERT), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P1):
|
|
|
|
k_fn(vc, KVAL(K_SELECT), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P2):
|
|
|
|
k_cur(vc, KVAL(K_DOWN), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P3):
|
|
|
|
k_fn(vc, KVAL(K_PGDN), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P4):
|
|
|
|
k_cur(vc, KVAL(K_LEFT), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P6):
|
|
|
|
k_cur(vc, KVAL(K_RIGHT), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P7):
|
|
|
|
k_fn(vc, KVAL(K_FIND), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P8):
|
|
|
|
k_cur(vc, KVAL(K_UP), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P9):
|
|
|
|
k_fn(vc, KVAL(K_PGUP), 0);
|
|
|
|
return;
|
|
|
|
case KVAL(K_P5):
|
|
|
|
applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
|
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-03-22 05:31:26 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
put_queue(vc, pad_chars[value]);
|
|
|
|
if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
|
2020-11-09 10:56:00 +00:00
|
|
|
put_queue(vc, '\n');
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int old_state = shift_state;
|
|
|
|
|
|
|
|
if (rep)
|
|
|
|
return;
|
|
|
|
/*
|
|
|
|
* Mimic typewriter:
|
|
|
|
* a CapsShift key acts like Shift but undoes CapsLock
|
|
|
|
*/
|
|
|
|
if (value == KVAL(K_CAPSSHIFT)) {
|
|
|
|
value = KVAL(K_SHIFT);
|
|
|
|
if (!up_flag)
|
|
|
|
clr_vc_kbd_led(kbd, VC_CAPSLOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (up_flag) {
|
|
|
|
/*
|
|
|
|
* handle the case that two shift or control
|
|
|
|
* keys are depressed simultaneously
|
|
|
|
*/
|
|
|
|
if (shift_down[value])
|
|
|
|
shift_down[value]--;
|
|
|
|
} else
|
|
|
|
shift_down[value]++;
|
|
|
|
|
|
|
|
if (shift_down[value])
|
2020-11-09 10:55:59 +00:00
|
|
|
shift_state |= BIT(value);
|
2005-04-16 22:20:36 +00:00
|
|
|
else
|
2020-11-09 10:55:59 +00:00
|
|
|
shift_state &= ~BIT(value);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* kludge */
|
2020-05-25 23:27:40 +00:00
|
|
|
if (up_flag && shift_state != old_state && npadch_active) {
|
2005-04-16 22:20:36 +00:00
|
|
|
if (kbd->kbdmode == VC_UNICODE)
|
2020-05-25 23:27:40 +00:00
|
|
|
to_utf8(vc, npadch_value);
|
2005-04-16 22:20:36 +00:00
|
|
|
else
|
2020-05-25 23:27:40 +00:00
|
|
|
put_queue(vc, npadch_value & 0xff);
|
|
|
|
npadch_active = false;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (up_flag)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (vc_kbd_mode(kbd, VC_META)) {
|
|
|
|
put_queue(vc, '\033');
|
|
|
|
put_queue(vc, value);
|
|
|
|
} else
|
2020-11-09 10:55:59 +00:00
|
|
|
put_queue(vc, value | BIT(7));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2020-05-25 23:27:40 +00:00
|
|
|
unsigned int base;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (up_flag)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (value < 10) {
|
|
|
|
/* decimal input of code, while Alt depressed */
|
|
|
|
base = 10;
|
|
|
|
} else {
|
|
|
|
/* hexadecimal input of code, while AltGr depressed */
|
|
|
|
value -= 10;
|
|
|
|
base = 16;
|
|
|
|
}
|
|
|
|
|
2020-05-25 23:27:40 +00:00
|
|
|
if (!npadch_active) {
|
|
|
|
npadch_value = 0;
|
|
|
|
npadch_active = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
npadch_value = npadch_value * base + value;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (up_flag || rep)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
chg_vc_kbd_lock(kbd, value);
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
k_shift(vc, value, up_flag);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (up_flag || rep)
|
|
|
|
return;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
chg_vc_kbd_slock(kbd, value);
|
|
|
|
/* try to make Alt, oops, AltGr and such work */
|
|
|
|
if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
|
|
|
|
kbd->slockstate = 0;
|
|
|
|
chg_vc_kbd_slock(kbd, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-02 05:10:28 +00:00
|
|
|
/* by default, 300ms interval for combination release */
|
2006-04-26 04:14:10 +00:00
|
|
|
static unsigned brl_timeout = 300;
|
|
|
|
MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
|
|
|
|
module_param(brl_timeout, uint, 0644);
|
|
|
|
|
|
|
|
static unsigned brl_nbchords = 1;
|
|
|
|
MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
|
|
|
|
module_param(brl_nbchords, uint, 0644);
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag)
|
2006-04-26 04:14:10 +00:00
|
|
|
{
|
|
|
|
static unsigned long chords;
|
|
|
|
static unsigned committed;
|
|
|
|
|
|
|
|
if (!brl_nbchords)
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag);
|
2006-04-26 04:14:10 +00:00
|
|
|
else {
|
|
|
|
committed |= pattern;
|
|
|
|
chords++;
|
|
|
|
if (chords == brl_nbchords) {
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
k_unicode(vc, BRL_UC_ROW | committed, up_flag);
|
2006-04-26 04:14:10 +00:00
|
|
|
chords = 0;
|
|
|
|
committed = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
|
2006-04-02 05:10:28 +00:00
|
|
|
{
|
2010-03-22 05:31:26 +00:00
|
|
|
static unsigned pressed, committing;
|
2006-04-02 05:10:28 +00:00
|
|
|
static unsigned long releasestart;
|
|
|
|
|
|
|
|
if (kbd->kbdmode != VC_UNICODE) {
|
|
|
|
if (!up_flag)
|
2014-11-10 06:46:35 +00:00
|
|
|
pr_warn("keyboard mode must be unicode for braille patterns\n");
|
2006-04-02 05:10:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!value) {
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
k_unicode(vc, BRL_UC_ROW, up_flag);
|
2006-04-02 05:10:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value > 8)
|
|
|
|
return;
|
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
if (!up_flag) {
|
2020-11-09 10:55:59 +00:00
|
|
|
pressed |= BIT(value - 1);
|
2006-04-02 05:10:28 +00:00
|
|
|
if (!brl_timeout)
|
|
|
|
committing = pressed;
|
2010-03-22 05:31:26 +00:00
|
|
|
} else if (brl_timeout) {
|
|
|
|
if (!committing ||
|
|
|
|
time_after(jiffies,
|
|
|
|
releasestart + msecs_to_jiffies(brl_timeout))) {
|
|
|
|
committing = pressed;
|
|
|
|
releasestart = jiffies;
|
|
|
|
}
|
2020-11-09 10:55:59 +00:00
|
|
|
pressed &= ~BIT(value - 1);
|
2010-03-22 05:31:26 +00:00
|
|
|
if (!pressed && committing) {
|
|
|
|
k_brlcommit(vc, committing, 0);
|
|
|
|
committing = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (committing) {
|
|
|
|
k_brlcommit(vc, committing, 0);
|
|
|
|
committing = 0;
|
|
|
|
}
|
2020-11-09 10:55:59 +00:00
|
|
|
pressed &= ~BIT(value - 1);
|
2006-04-02 05:10:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-17 04:19:44 +00:00
|
|
|
#if IS_ENABLED(CONFIG_INPUT_LEDS) && IS_ENABLED(CONFIG_LEDS_TRIGGERS)
|
|
|
|
|
|
|
|
struct kbd_led_trigger {
|
|
|
|
struct led_trigger trigger;
|
|
|
|
unsigned int mask;
|
|
|
|
};
|
|
|
|
|
2018-07-02 20:05:21 +00:00
|
|
|
static int kbd_led_trigger_activate(struct led_classdev *cdev)
|
2015-03-17 04:19:44 +00:00
|
|
|
{
|
|
|
|
struct kbd_led_trigger *trigger =
|
|
|
|
container_of(cdev->trigger, struct kbd_led_trigger, trigger);
|
|
|
|
|
|
|
|
tasklet_disable(&keyboard_tasklet);
|
2015-06-06 18:44:39 +00:00
|
|
|
if (ledstate != -1U)
|
2015-03-17 04:19:44 +00:00
|
|
|
led_trigger_event(&trigger->trigger,
|
|
|
|
ledstate & trigger->mask ?
|
|
|
|
LED_FULL : LED_OFF);
|
|
|
|
tasklet_enable(&keyboard_tasklet);
|
2018-07-02 20:05:21 +00:00
|
|
|
|
|
|
|
return 0;
|
2015-03-17 04:19:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define KBD_LED_TRIGGER(_led_bit, _name) { \
|
|
|
|
.trigger = { \
|
|
|
|
.name = _name, \
|
|
|
|
.activate = kbd_led_trigger_activate, \
|
|
|
|
}, \
|
|
|
|
.mask = BIT(_led_bit), \
|
|
|
|
}
|
|
|
|
|
2015-06-06 18:44:39 +00:00
|
|
|
#define KBD_LOCKSTATE_TRIGGER(_led_bit, _name) \
|
|
|
|
KBD_LED_TRIGGER((_led_bit) + 8, _name)
|
|
|
|
|
2015-03-17 04:19:44 +00:00
|
|
|
static struct kbd_led_trigger kbd_led_triggers[] = {
|
2016-11-15 23:55:57 +00:00
|
|
|
KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrolllock"),
|
2015-03-17 04:19:44 +00:00
|
|
|
KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"),
|
|
|
|
KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"),
|
|
|
|
KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"),
|
2015-06-06 18:44:39 +00:00
|
|
|
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_SHIFTLOCK, "kbd-shiftlock"),
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_ALTGRLOCK, "kbd-altgrlock"),
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_CTRLLOCK, "kbd-ctrllock"),
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_ALTLOCK, "kbd-altlock"),
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"),
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"),
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_CTRLLLOCK, "kbd-ctrlllock"),
|
|
|
|
KBD_LOCKSTATE_TRIGGER(VC_CTRLRLOCK, "kbd-ctrlrlock"),
|
2015-03-17 04:19:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void kbd_propagate_led_state(unsigned int old_state,
|
|
|
|
unsigned int new_state)
|
|
|
|
{
|
|
|
|
struct kbd_led_trigger *trigger;
|
|
|
|
unsigned int changed = old_state ^ new_state;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
|
|
|
|
trigger = &kbd_led_triggers[i];
|
|
|
|
|
|
|
|
if (changed & trigger->mask)
|
|
|
|
led_trigger_event(&trigger->trigger,
|
|
|
|
new_state & trigger->mask ?
|
|
|
|
LED_FULL : LED_OFF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kbd_update_leds_helper(struct input_handle *handle, void *data)
|
|
|
|
{
|
|
|
|
unsigned int led_state = *(unsigned int *)data;
|
|
|
|
|
|
|
|
if (test_bit(EV_LED, handle->dev->evbit))
|
|
|
|
kbd_propagate_led_state(~led_state, led_state);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kbd_init_leds(void)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) {
|
|
|
|
error = led_trigger_register(&kbd_led_triggers[i].trigger);
|
|
|
|
if (error)
|
|
|
|
pr_err("error %d while registering trigger %s\n",
|
|
|
|
error, kbd_led_triggers[i].trigger.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
static int kbd_update_leds_helper(struct input_handle *handle, void *data)
|
|
|
|
{
|
|
|
|
unsigned int leds = *(unsigned int *)data;
|
|
|
|
|
|
|
|
if (test_bit(EV_LED, handle->dev->evbit)) {
|
2020-11-09 10:55:59 +00:00
|
|
|
input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & BIT(0)));
|
|
|
|
input_inject_event(handle, EV_LED, LED_NUML, !!(leds & BIT(1)));
|
|
|
|
input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & BIT(2)));
|
2015-03-17 04:19:44 +00:00
|
|
|
input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kbd_propagate_led_state(unsigned int old_state,
|
|
|
|
unsigned int new_state)
|
|
|
|
{
|
|
|
|
input_handler_for_each_handle(&kbd_handler, &new_state,
|
|
|
|
kbd_update_leds_helper);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kbd_init_leds(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
|
|
|
|
* or (ii) whatever pattern of lights people want to show using KDSETLED,
|
|
|
|
* or (iii) specified bits of specified words in kernel memory.
|
|
|
|
*/
|
2012-07-17 16:06:41 +00:00
|
|
|
static unsigned char getledstate(void)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2015-06-06 18:44:39 +00:00
|
|
|
return ledstate & 0xff;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2014-09-06 01:57:57 +00:00
|
|
|
void setledstate(struct kbd_struct *kb, unsigned int led)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-02-28 14:49:23 +00:00
|
|
|
unsigned long flags;
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_lock_irqsave(&led_lock, flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!(led & ~7)) {
|
|
|
|
ledioctl = led;
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->ledmode = LED_SHOW_IOCTL;
|
2005-04-16 22:20:36 +00:00
|
|
|
} else
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->ledmode = LED_SHOW_FLAGS;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
set_leds();
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_unlock_irqrestore(&led_lock, flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned char getleds(void)
|
|
|
|
{
|
2014-09-06 01:57:57 +00:00
|
|
|
struct kbd_struct *kb = kbd_table + fg_console;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-09-06 01:57:57 +00:00
|
|
|
if (kb->ledmode == LED_SHOW_IOCTL)
|
2005-04-16 22:20:36 +00:00
|
|
|
return ledioctl;
|
|
|
|
|
2014-09-06 01:57:57 +00:00
|
|
|
return kb->ledflagstate;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
/**
|
|
|
|
* vt_get_leds - helper for braille console
|
|
|
|
* @console: console to read
|
|
|
|
* @flag: flag we want to check
|
|
|
|
*
|
|
|
|
* Check the status of a keyboard led flag and report it back
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
int vt_get_leds(unsigned int console, int flag)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
int ret;
|
2012-07-17 16:06:41 +00:00
|
|
|
unsigned long flags;
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_lock_irqsave(&led_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
ret = vc_kbd_led(kb, flag);
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_unlock_irqrestore(&led_lock, flags);
|
2012-02-28 14:49:23 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(vt_get_leds);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_set_led_state - set LED state of a console
|
|
|
|
* @console: console to set
|
|
|
|
* @leds: LED bits
|
|
|
|
*
|
|
|
|
* Set the LEDs on a console. This is a wrapper for the VT layer
|
|
|
|
* so that we can keep kbd knowledge internal
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
void vt_set_led_state(unsigned int console, int leds)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2014-09-06 01:57:57 +00:00
|
|
|
setledstate(kb, leds);
|
2012-02-28 14:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_kbd_con_start - Keyboard side of console start
|
|
|
|
* @console: console
|
|
|
|
*
|
|
|
|
* Handle console start. This is a wrapper for the VT layer
|
|
|
|
* so that we can keep kbd knowledge internal
|
2012-05-01 15:12:19 +00:00
|
|
|
*
|
|
|
|
* FIXME: We eventually need to hold the kbd lock here to protect
|
|
|
|
* the LED updating. We can't do it yet because fn_hold calls stop_tty
|
|
|
|
* and start_tty under the kbd_event_lock, while normal tty paths
|
|
|
|
* don't hold the lock. We probably need to split out an LED lock
|
|
|
|
* but not during an -rc release!
|
2012-02-28 14:49:23 +00:00
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
void vt_kbd_con_start(unsigned int console)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-07-17 16:06:41 +00:00
|
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&led_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
clr_vc_kbd_led(kb, VC_SCROLLOCK);
|
2012-02-28 14:49:23 +00:00
|
|
|
set_leds();
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_unlock_irqrestore(&led_lock, flags);
|
2012-02-28 14:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_kbd_con_stop - Keyboard side of console stop
|
|
|
|
* @console: console
|
|
|
|
*
|
|
|
|
* Handle console stop. This is a wrapper for the VT layer
|
|
|
|
* so that we can keep kbd knowledge internal
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
void vt_kbd_con_stop(unsigned int console)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-07-17 16:06:41 +00:00
|
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&led_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
set_vc_kbd_led(kb, VC_SCROLLOCK);
|
2012-02-28 14:49:23 +00:00
|
|
|
set_leds();
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_unlock_irqrestore(&led_lock, flags);
|
2012-02-28 14:49:23 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
2015-03-17 04:19:44 +00:00
|
|
|
* This is the tasklet that updates LED state of LEDs using standard
|
|
|
|
* keyboard triggers. The reason we use tasklet is that we need to
|
|
|
|
* handle the scenario when keyboard handler is not registered yet
|
|
|
|
* but we already getting updates from the VT to update led state.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2021-01-27 16:42:22 +00:00
|
|
|
static void kbd_bh(struct tasklet_struct *unused)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2015-06-06 18:44:39 +00:00
|
|
|
unsigned int leds;
|
2012-07-17 16:06:41 +00:00
|
|
|
unsigned long flags;
|
2015-03-17 04:19:44 +00:00
|
|
|
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_lock_irqsave(&led_lock, flags);
|
|
|
|
leds = getleds();
|
2015-06-06 18:44:39 +00:00
|
|
|
leds |= (unsigned int)kbd->lockstate << 8;
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_unlock_irqrestore(&led_lock, flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
tty: Fix the keyboard led light display problem
Use the "ctrl+alt+Fn" key combination to switch the system from tty to
desktop or switch the system from desktop to tty. After the switch is
completed, it is found that the state of the keyboard lock is
inconsistent with the state of the keyboard Led light.The reasons are
as follows:
* The desktop environment (Xorg and other services) is bound to a tty
(assuming it is tty1), and the kb->kbdmode attribute value of tty1
will be set to VC_OFF. According to the current code logic, in the
desktop environment, the values of ledstate and kb->ledflagstate
of tty1 will not be modified anymore, so they are always 0.
* When switching between each tty, the final value of ledstate set by
the previous tty is compared with the kb->ledflagstate value of the
current tty to determine whether to set the state of the keyboard
light. The process of switching between desktop and tty is also the
process of switching between tty1 and other ttys. There are two
situations:
- (1) In the desktop environment, tty1 will not set the ledstate,
which will cause when switching from the desktop to other ttys,
if the desktop lights up the keyboard's led, after the switch is
completed, the keyboard's led light will always be on;
- (2) When switching from another tty to the desktop, this
mechanism will trigger tty1 to set the led state. If other tty
lights up the led of the keyboard before switching to the desktop,
the led will be forcibly turned off. This situation should
be avoided.
* The current patch is to solve these problems: When VT is switched,
the keyboard led needs to be set once.Ensure that after the
switch is completed, the state of the keyboard LED is consistent
with the state of the keyboard lock.
Suggested-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
Link: https://lore.kernel.org/r/20211215125125.10554-1-changlianzhi@uniontech.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2021-12-15 12:51:25 +00:00
|
|
|
if (vt_switch) {
|
|
|
|
ledstate = ~leds;
|
|
|
|
vt_switch = false;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (leds != ledstate) {
|
2015-03-17 04:19:44 +00:00
|
|
|
kbd_propagate_led_state(ledstate, leds);
|
2009-12-02 05:54:35 +00:00
|
|
|
ledstate = leds;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
|
2005-12-23 05:03:47 +00:00
|
|
|
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
|
|
|
|
defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
|
2017-05-09 17:07:13 +00:00
|
|
|
(defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2020-10-29 11:32:20 +00:00
|
|
|
static inline bool kbd_is_hw_raw(const struct input_dev *dev)
|
|
|
|
{
|
|
|
|
if (!test_bit(EV_MSC, dev->evbit) || !test_bit(MSC_RAW, dev->mscbit))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return dev->id.bustype == BUS_I8042 &&
|
|
|
|
dev->id.vendor == 0x0001 && dev->id.product == 0x0001;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-06-05 04:18:00 +00:00
|
|
|
static const unsigned short x86_keycodes[256] =
|
2005-04-16 22:20:36 +00:00
|
|
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
|
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
|
|
|
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
|
|
|
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
|
|
|
80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
|
2006-07-19 05:14:25 +00:00
|
|
|
284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
|
2005-04-16 22:20:36 +00:00
|
|
|
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
|
|
|
|
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
|
2007-07-03 05:55:18 +00:00
|
|
|
103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
|
|
|
|
291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
|
2005-04-16 22:20:36 +00:00
|
|
|
264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
|
|
|
|
377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
|
|
|
|
308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
|
|
|
|
332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
|
|
|
|
|
2005-12-23 05:03:47 +00:00
|
|
|
#ifdef CONFIG_SPARC
|
2010-03-22 05:31:26 +00:00
|
|
|
static int sparc_l1_a_state;
|
2005-04-16 22:20:36 +00:00
|
|
|
extern void sun_do_break(void);
|
|
|
|
#endif
|
|
|
|
|
2005-09-10 17:03:38 +00:00
|
|
|
static int emulate_raw(struct vc_data *vc, unsigned int keycode,
|
2005-04-16 22:20:36 +00:00
|
|
|
unsigned char up_flag)
|
|
|
|
{
|
2006-07-19 05:14:25 +00:00
|
|
|
int code;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
switch (keycode) {
|
2006-07-19 05:14:25 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
case KEY_PAUSE:
|
|
|
|
put_queue(vc, 0xe1);
|
|
|
|
put_queue(vc, 0x1d | up_flag);
|
|
|
|
put_queue(vc, 0x45 | up_flag);
|
|
|
|
break;
|
2006-07-19 05:14:25 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
case KEY_HANGEUL:
|
|
|
|
if (!up_flag)
|
|
|
|
put_queue(vc, 0xf2);
|
|
|
|
break;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
case KEY_HANJA:
|
|
|
|
if (!up_flag)
|
|
|
|
put_queue(vc, 0xf1);
|
|
|
|
break;
|
2006-07-19 05:14:25 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
case KEY_SYSRQ:
|
|
|
|
/*
|
|
|
|
* Real AT keyboards (that's what we're trying
|
2016-11-07 13:43:14 +00:00
|
|
|
* to emulate here) emit 0xe0 0x2a 0xe0 0x37 when
|
2010-03-22 05:31:26 +00:00
|
|
|
* pressing PrtSc/SysRq alone, but simply 0x54
|
|
|
|
* when pressing Alt+PrtSc/SysRq.
|
|
|
|
*/
|
|
|
|
if (test_bit(KEY_LEFTALT, key_down) ||
|
|
|
|
test_bit(KEY_RIGHTALT, key_down)) {
|
|
|
|
put_queue(vc, 0x54 | up_flag);
|
|
|
|
} else {
|
|
|
|
put_queue(vc, 0xe0);
|
|
|
|
put_queue(vc, 0x2a | up_flag);
|
|
|
|
put_queue(vc, 0xe0);
|
|
|
|
put_queue(vc, 0x37 | up_flag);
|
|
|
|
}
|
|
|
|
break;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
default:
|
|
|
|
if (keycode > 255)
|
|
|
|
return -1;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
code = x86_keycodes[keycode];
|
|
|
|
if (!code)
|
|
|
|
return -1;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
if (code & 0x100)
|
|
|
|
put_queue(vc, 0xe0);
|
|
|
|
put_queue(vc, (code & 0x7f) | up_flag);
|
|
|
|
|
|
|
|
break;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2020-10-29 11:32:20 +00:00
|
|
|
static inline bool kbd_is_hw_raw(const struct input_dev *dev)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
|
|
|
|
{
|
|
|
|
if (keycode > 127)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
put_queue(vc, keycode | up_flag);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void kbd_rawcode(unsigned char data)
|
|
|
|
{
|
|
|
|
struct vc_data *vc = vc_cons[fg_console].d;
|
2010-03-22 05:31:26 +00:00
|
|
|
|
2021-07-26 13:43:21 +00:00
|
|
|
kbd = &kbd_table[vc->vc_num];
|
2005-04-16 22:20:36 +00:00
|
|
|
if (kbd->kbdmode == VC_RAW)
|
|
|
|
put_queue(vc, data);
|
|
|
|
}
|
|
|
|
|
2020-10-29 11:32:20 +00:00
|
|
|
static void kbd_keycode(unsigned int keycode, int down, bool hw_raw)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct vc_data *vc = vc_cons[fg_console].d;
|
|
|
|
unsigned short keysym, *key_map;
|
2010-03-22 05:31:26 +00:00
|
|
|
unsigned char type;
|
|
|
|
bool raw_mode;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct tty_struct *tty;
|
|
|
|
int shift_final;
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
|
2010-03-22 05:31:26 +00:00
|
|
|
int rc;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-06-01 20:52:56 +00:00
|
|
|
tty = vc->port.tty;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (tty && (!tty->driver_data)) {
|
|
|
|
/* No driver data? Strange. Okay we fix it then. */
|
|
|
|
tty->driver_data = vc;
|
|
|
|
}
|
|
|
|
|
2021-07-26 13:43:21 +00:00
|
|
|
kbd = &kbd_table[vc->vc_num];
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-12-23 05:03:47 +00:00
|
|
|
#ifdef CONFIG_SPARC
|
2005-04-16 22:20:36 +00:00
|
|
|
if (keycode == KEY_STOP)
|
|
|
|
sparc_l1_a_state = down;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rep = (down == 2);
|
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
raw_mode = (kbd->kbdmode == VC_RAW);
|
|
|
|
if (raw_mode && !hw_raw)
|
2005-04-16 22:20:36 +00:00
|
|
|
if (emulate_raw(vc, keycode, !down << 7))
|
2007-04-12 05:30:52 +00:00
|
|
|
if (keycode < BTN_MISC && printk_ratelimit())
|
2014-11-10 06:46:35 +00:00
|
|
|
pr_warn("can't emulate rawmode for keycode %d\n",
|
|
|
|
keycode);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-12-23 05:03:47 +00:00
|
|
|
#ifdef CONFIG_SPARC
|
2005-04-16 22:20:36 +00:00
|
|
|
if (keycode == KEY_A && sparc_l1_a_state) {
|
2010-03-22 05:31:26 +00:00
|
|
|
sparc_l1_a_state = false;
|
2005-04-16 22:20:36 +00:00
|
|
|
sun_do_break();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (kbd->kbdmode == VC_MEDIUMRAW) {
|
|
|
|
/*
|
|
|
|
* This is extended medium raw mode, with keys above 127
|
|
|
|
* encoded as 0, high 7 bits, low 7 bits, with the 0 bearing
|
|
|
|
* the 'up' flag if needed. 0 is reserved, so this shouldn't
|
|
|
|
* interfere with anything else. The two bytes after 0 will
|
|
|
|
* always have the up flag set not to interfere with older
|
|
|
|
* applications. This allows for 16384 different keycodes,
|
|
|
|
* which should be enough.
|
|
|
|
*/
|
|
|
|
if (keycode < 128) {
|
|
|
|
put_queue(vc, keycode | (!down << 7));
|
|
|
|
} else {
|
|
|
|
put_queue(vc, !down << 7);
|
2020-11-09 10:55:59 +00:00
|
|
|
put_queue(vc, (keycode >> 7) | BIT(7));
|
|
|
|
put_queue(vc, keycode | BIT(7));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-03-22 05:31:26 +00:00
|
|
|
raw_mode = true;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2020-11-09 10:56:01 +00:00
|
|
|
assign_bit(keycode, key_down, down);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-09-10 17:03:38 +00:00
|
|
|
if (rep &&
|
|
|
|
(!vc_kbd_mode(kbd, VC_REPEAT) ||
|
2008-04-30 07:54:13 +00:00
|
|
|
(tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Don't repeat a key if the input buffers are not empty and the
|
2005-09-10 17:03:38 +00:00
|
|
|
* characters get aren't echoed locally. This makes key repeat
|
2005-04-16 22:20:36 +00:00
|
|
|
* usable with slow applications and under heavy loads.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
|
2008-04-15 05:30:32 +00:00
|
|
|
param.ledstate = kbd->ledflagstate;
|
2005-04-16 22:20:36 +00:00
|
|
|
key_map = key_maps[shift_final];
|
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
rc = atomic_notifier_call_chain(&keyboard_notifier_list,
|
|
|
|
KBD_KEYCODE, ¶m);
|
|
|
|
if (rc == NOTIFY_STOP || !key_map) {
|
|
|
|
atomic_notifier_call_chain(&keyboard_notifier_list,
|
|
|
|
KBD_UNBOUND_KEYCODE, ¶m);
|
2012-02-28 14:49:23 +00:00
|
|
|
do_compute_shiftstate();
|
2005-04-16 22:20:36 +00:00
|
|
|
kbd->slockstate = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
if (keycode < NR_KEYS)
|
2006-04-02 05:10:28 +00:00
|
|
|
keysym = key_map[keycode];
|
2010-03-22 05:31:26 +00:00
|
|
|
else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
|
|
|
|
keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
|
|
|
|
else
|
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
type = KTYP(keysym);
|
|
|
|
|
|
|
|
if (type < 0xf0) {
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
param.value = keysym;
|
2010-03-22 05:31:26 +00:00
|
|
|
rc = atomic_notifier_call_chain(&keyboard_notifier_list,
|
|
|
|
KBD_UNICODE, ¶m);
|
|
|
|
if (rc != NOTIFY_STOP)
|
|
|
|
if (down && !raw_mode)
|
2019-04-11 11:50:54 +00:00
|
|
|
k_unicode(vc, keysym, !down);
|
2005-04-16 22:20:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
type -= 0xf0;
|
|
|
|
|
|
|
|
if (type == KT_LETTER) {
|
|
|
|
type = KT_LATIN;
|
|
|
|
if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
|
2020-11-09 10:55:59 +00:00
|
|
|
key_map = key_maps[shift_final ^ BIT(KG_SHIFT)];
|
2005-04-16 22:20:36 +00:00
|
|
|
if (key_map)
|
|
|
|
keysym = key_map[keycode];
|
|
|
|
}
|
|
|
|
}
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
|
2010-03-22 05:31:26 +00:00
|
|
|
param.value = keysym;
|
|
|
|
rc = atomic_notifier_call_chain(&keyboard_notifier_list,
|
|
|
|
KBD_KEYSYM, ¶m);
|
|
|
|
if (rc == NOTIFY_STOP)
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
return;
|
|
|
|
|
2011-02-04 21:55:50 +00:00
|
|
|
if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT)
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 13:55:46 +00:00
|
|
|
(*k_handler[type])(vc, keysym & 0xff, !down);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-04-15 05:30:32 +00:00
|
|
|
param.ledstate = kbd->ledflagstate;
|
Console keyboard events and accessibility
Some blind people use a kernel engine called Speakup which uses hardware
synthesis to speak what gets displayed on the screen. They use the
PC keyboard to control this engine (start/stop, accelerate, ...) and
also need to get keyboard feedback (to make sure to know what they are
typing, the caps lock status, etc.)
Up to now, the way it was done was very ugly. Below is a patch to add a
notifier list for permitting a far better implementation, see ChangeLog
above for details.
You may wonder why this can't be done at the input layer. The problem
is that what people want to monitor is the console keyboard, i.e. all
input keyboards that got attached to the console, and with the currently
active keymap (i.e. keysyms, not only keycodes).
This adds a keyboard notifier that such modules can use to get the keyboard
events and possibly eat them, at several stages:
- keycodes: even before translation into keysym.
- unbound keycodes: when no keysym is bound.
- unicode: when the keycode would get translated into a unicode character.
- keysym: when the keycode would get translated into a keysym.
- post_keysym: after the keysym got interpreted, so as to see the result
(caps lock, etc.)
This also provides access to k_handler so as to permit simulation of
keypresses.
[akpm@linux-foundation.org: various fixes]
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-19 06:39:12 +00:00
|
|
|
atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, ¶m);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (type != KT_SLOCK)
|
|
|
|
kbd->slockstate = 0;
|
|
|
|
}
|
|
|
|
|
2005-09-10 17:03:38 +00:00
|
|
|
static void kbd_event(struct input_handle *handle, unsigned int event_type,
|
2005-04-16 22:20:36 +00:00
|
|
|
unsigned int event_code, int value)
|
|
|
|
{
|
2009-11-30 07:40:58 +00:00
|
|
|
/* We are called with interrupts disabled, just take the lock */
|
|
|
|
spin_lock(&kbd_event_lock);
|
|
|
|
|
2020-10-29 11:32:20 +00:00
|
|
|
if (event_type == EV_MSC && event_code == MSC_RAW &&
|
|
|
|
kbd_is_hw_raw(handle->dev))
|
2005-04-16 22:20:36 +00:00
|
|
|
kbd_rawcode(value);
|
2019-11-22 20:42:20 +00:00
|
|
|
if (event_type == EV_KEY && event_code <= KEY_MAX)
|
2020-10-29 11:32:20 +00:00
|
|
|
kbd_keycode(event_code, value, kbd_is_hw_raw(handle->dev));
|
2009-11-30 07:40:58 +00:00
|
|
|
|
|
|
|
spin_unlock(&kbd_event_lock);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
tasklet_schedule(&keyboard_tasklet);
|
|
|
|
do_poke_blanked_console = 1;
|
|
|
|
schedule_console_callback();
|
|
|
|
}
|
|
|
|
|
2010-02-03 05:08:26 +00:00
|
|
|
static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
|
|
|
|
{
|
|
|
|
if (test_bit(EV_SND, dev->evbit))
|
|
|
|
return true;
|
|
|
|
|
2010-07-31 09:28:51 +00:00
|
|
|
if (test_bit(EV_KEY, dev->evbit)) {
|
2020-10-29 11:32:21 +00:00
|
|
|
if (find_next_bit(dev->keybit, BTN_MISC, KEY_RESERVED) <
|
|
|
|
BTN_MISC)
|
|
|
|
return true;
|
|
|
|
if (find_next_bit(dev->keybit, KEY_BRL_DOT10 + 1,
|
|
|
|
KEY_BRL_DOT1) <= KEY_BRL_DOT10)
|
|
|
|
return true;
|
2010-07-31 09:28:51 +00:00
|
|
|
}
|
2010-02-03 05:08:26 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* When a keyboard (or other input device) is found, the kbd_connect
|
|
|
|
* function is called. The function then looks at the device, and if it
|
|
|
|
* likes it, it can open it and get events from it. In this (kbd_connect)
|
|
|
|
* function, we should decide which VT to bind that keyboard to initially.
|
|
|
|
*/
|
2007-04-12 05:29:46 +00:00
|
|
|
static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
|
|
|
|
const struct input_device_id *id)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct input_handle *handle;
|
2007-04-12 05:29:46 +00:00
|
|
|
int error;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-08-05 02:51:51 +00:00
|
|
|
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
|
|
|
|
if (!handle)
|
2007-04-12 05:29:46 +00:00
|
|
|
return -ENOMEM;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
handle->dev = dev;
|
|
|
|
handle->handler = handler;
|
2005-09-10 17:03:38 +00:00
|
|
|
handle->name = "kbd";
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-04-12 05:29:46 +00:00
|
|
|
error = input_register_handle(handle);
|
|
|
|
if (error)
|
|
|
|
goto err_free_handle;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-04-12 05:29:46 +00:00
|
|
|
error = input_open_device(handle);
|
|
|
|
if (error)
|
|
|
|
goto err_unregister_handle;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_unregister_handle:
|
|
|
|
input_unregister_handle(handle);
|
|
|
|
err_free_handle:
|
|
|
|
kfree(handle);
|
|
|
|
return error;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void kbd_disconnect(struct input_handle *handle)
|
|
|
|
{
|
|
|
|
input_close_device(handle);
|
2007-04-12 05:29:46 +00:00
|
|
|
input_unregister_handle(handle);
|
2005-04-16 22:20:36 +00:00
|
|
|
kfree(handle);
|
|
|
|
}
|
|
|
|
|
2006-07-06 04:21:03 +00:00
|
|
|
/*
|
|
|
|
* Start keyboard handler on the new keyboard by refreshing LED state to
|
|
|
|
* match the rest of the system.
|
|
|
|
*/
|
|
|
|
static void kbd_start(struct input_handle *handle)
|
|
|
|
{
|
|
|
|
tasklet_disable(&keyboard_tasklet);
|
2009-12-02 05:54:35 +00:00
|
|
|
|
2015-06-06 18:44:39 +00:00
|
|
|
if (ledstate != -1U)
|
|
|
|
kbd_update_leds_helper(handle, &ledstate);
|
2009-12-02 05:54:35 +00:00
|
|
|
|
2006-07-06 04:21:03 +00:00
|
|
|
tasklet_enable(&keyboard_tasklet);
|
|
|
|
}
|
|
|
|
|
2006-09-14 05:31:59 +00:00
|
|
|
static const struct input_device_id kbd_ids[] = {
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-02-24 12:47:29 +00:00
|
|
|
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
|
|
|
|
.evbit = { BIT_MASK(EV_KEY) },
|
|
|
|
},
|
2005-09-10 17:03:38 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-02-24 12:47:29 +00:00
|
|
|
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
|
|
|
|
.evbit = { BIT_MASK(EV_SND) },
|
|
|
|
},
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
{ }, /* Terminating entry */
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULE_DEVICE_TABLE(input, kbd_ids);
|
|
|
|
|
|
|
|
static struct input_handler kbd_handler = {
|
|
|
|
.event = kbd_event,
|
2010-02-03 05:08:26 +00:00
|
|
|
.match = kbd_match,
|
2005-04-16 22:20:36 +00:00
|
|
|
.connect = kbd_connect,
|
|
|
|
.disconnect = kbd_disconnect,
|
2006-07-06 04:21:03 +00:00
|
|
|
.start = kbd_start,
|
2005-04-16 22:20:36 +00:00
|
|
|
.name = "kbd",
|
|
|
|
.id_table = kbd_ids,
|
|
|
|
};
|
|
|
|
|
|
|
|
int __init kbd_init(void)
|
|
|
|
{
|
|
|
|
int i;
|
2006-09-14 05:32:39 +00:00
|
|
|
int error;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-02-24 12:47:29 +00:00
|
|
|
for (i = 0; i < MAX_NR_CONSOLES; i++) {
|
2012-04-13 19:08:26 +00:00
|
|
|
kbd_table[i].ledflagstate = kbd_defleds();
|
|
|
|
kbd_table[i].default_ledflagstate = kbd_defleds();
|
2006-07-19 05:13:26 +00:00
|
|
|
kbd_table[i].ledmode = LED_SHOW_FLAGS;
|
|
|
|
kbd_table[i].lockstate = KBD_DEFLOCK;
|
|
|
|
kbd_table[i].slockstate = 0;
|
|
|
|
kbd_table[i].modeflags = KBD_DEFMODE;
|
2007-10-17 06:29:38 +00:00
|
|
|
kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
|
2006-07-19 05:13:26 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2015-03-17 04:19:44 +00:00
|
|
|
kbd_init_leds();
|
|
|
|
|
2006-09-14 05:32:39 +00:00
|
|
|
error = input_register_handler(&kbd_handler);
|
|
|
|
if (error)
|
|
|
|
return error;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
tasklet_enable(&keyboard_tasklet);
|
|
|
|
tasklet_schedule(&keyboard_tasklet);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-02-24 12:47:11 +00:00
|
|
|
|
|
|
|
/* Ioctl support code */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_do_diacrit - diacritical table updates
|
|
|
|
* @cmd: ioctl request
|
2014-09-06 01:57:57 +00:00
|
|
|
* @udp: pointer to user data for ioctl
|
2012-02-24 12:47:11 +00:00
|
|
|
* @perm: permissions check computed by caller
|
|
|
|
*
|
|
|
|
* Update the diacritical tables atomically and safely. Lock them
|
|
|
|
* against simultaneous keypresses
|
|
|
|
*/
|
2014-09-06 01:57:57 +00:00
|
|
|
int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
2012-02-24 12:47:11 +00:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
int asize;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case KDGKBDIACR:
|
|
|
|
{
|
2014-09-06 01:57:57 +00:00
|
|
|
struct kbdiacrs __user *a = udp;
|
|
|
|
struct kbdiacr *dia;
|
2012-02-24 12:47:11 +00:00
|
|
|
int i;
|
|
|
|
|
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 20:55:00 +00:00
|
|
|
dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
|
2012-02-24 12:47:11 +00:00
|
|
|
GFP_KERNEL);
|
2014-09-06 01:57:57 +00:00
|
|
|
if (!dia)
|
2012-02-24 12:47:11 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* Lock the diacriticals table, make a copy and then
|
|
|
|
copy it after we unlock */
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
|
|
|
|
asize = accent_table_size;
|
|
|
|
for (i = 0; i < asize; i++) {
|
2014-09-06 01:57:57 +00:00
|
|
|
dia[i].diacr = conv_uni_to_8bit(
|
2012-02-24 12:47:11 +00:00
|
|
|
accent_table[i].diacr);
|
2014-09-06 01:57:57 +00:00
|
|
|
dia[i].base = conv_uni_to_8bit(
|
2012-02-24 12:47:11 +00:00
|
|
|
accent_table[i].base);
|
2014-09-06 01:57:57 +00:00
|
|
|
dia[i].result = conv_uni_to_8bit(
|
2012-02-24 12:47:11 +00:00
|
|
|
accent_table[i].result);
|
|
|
|
}
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
|
|
|
|
if (put_user(asize, &a->kb_cnt))
|
|
|
|
ret = -EFAULT;
|
2014-09-06 01:57:57 +00:00
|
|
|
else if (copy_to_user(a->kbdiacr, dia,
|
2012-02-24 12:47:11 +00:00
|
|
|
asize * sizeof(struct kbdiacr)))
|
|
|
|
ret = -EFAULT;
|
2014-09-06 01:57:57 +00:00
|
|
|
kfree(dia);
|
2012-02-24 12:47:11 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
case KDGKBDIACRUC:
|
|
|
|
{
|
2014-09-06 01:57:57 +00:00
|
|
|
struct kbdiacrsuc __user *a = udp;
|
2012-02-24 12:47:11 +00:00
|
|
|
void *buf;
|
|
|
|
|
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 20:55:00 +00:00
|
|
|
buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
|
2012-02-24 12:47:11 +00:00
|
|
|
GFP_KERNEL);
|
|
|
|
if (buf == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* Lock the diacriticals table, make a copy and then
|
|
|
|
copy it after we unlock */
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
|
|
|
|
asize = accent_table_size;
|
|
|
|
memcpy(buf, accent_table, asize * sizeof(struct kbdiacruc));
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
|
|
|
|
if (put_user(asize, &a->kb_cnt))
|
|
|
|
ret = -EFAULT;
|
|
|
|
else if (copy_to_user(a->kbdiacruc, buf,
|
|
|
|
asize*sizeof(struct kbdiacruc)))
|
|
|
|
ret = -EFAULT;
|
|
|
|
kfree(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
case KDSKBDIACR:
|
|
|
|
{
|
2014-09-06 01:57:57 +00:00
|
|
|
struct kbdiacrs __user *a = udp;
|
|
|
|
struct kbdiacr *dia = NULL;
|
2012-02-24 12:47:11 +00:00
|
|
|
unsigned int ct;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!perm)
|
|
|
|
return -EPERM;
|
|
|
|
if (get_user(ct, &a->kb_cnt))
|
|
|
|
return -EFAULT;
|
|
|
|
if (ct >= MAX_DIACR)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (ct) {
|
2015-10-28 06:26:44 +00:00
|
|
|
|
|
|
|
dia = memdup_user(a->kbdiacr,
|
|
|
|
sizeof(struct kbdiacr) * ct);
|
|
|
|
if (IS_ERR(dia))
|
|
|
|
return PTR_ERR(dia);
|
|
|
|
|
2012-02-24 12:47:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
accent_table_size = ct;
|
|
|
|
for (i = 0; i < ct; i++) {
|
|
|
|
accent_table[i].diacr =
|
2014-09-06 01:57:57 +00:00
|
|
|
conv_8bit_to_uni(dia[i].diacr);
|
2012-02-24 12:47:11 +00:00
|
|
|
accent_table[i].base =
|
2014-09-06 01:57:57 +00:00
|
|
|
conv_8bit_to_uni(dia[i].base);
|
2012-02-24 12:47:11 +00:00
|
|
|
accent_table[i].result =
|
2014-09-06 01:57:57 +00:00
|
|
|
conv_8bit_to_uni(dia[i].result);
|
2012-02-24 12:47:11 +00:00
|
|
|
}
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
kfree(dia);
|
2012-02-24 12:47:11 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
case KDSKBDIACRUC:
|
|
|
|
{
|
2014-09-06 01:57:57 +00:00
|
|
|
struct kbdiacrsuc __user *a = udp;
|
2012-02-24 12:47:11 +00:00
|
|
|
unsigned int ct;
|
|
|
|
void *buf = NULL;
|
|
|
|
|
|
|
|
if (!perm)
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
if (get_user(ct, &a->kb_cnt))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
if (ct >= MAX_DIACR)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (ct) {
|
2016-05-20 12:23:28 +00:00
|
|
|
buf = memdup_user(a->kbdiacruc,
|
|
|
|
ct * sizeof(struct kbdiacruc));
|
|
|
|
if (IS_ERR(buf))
|
|
|
|
return PTR_ERR(buf);
|
2012-02-24 12:47:11 +00:00
|
|
|
}
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
if (ct)
|
|
|
|
memcpy(accent_table, buf,
|
|
|
|
ct * sizeof(struct kbdiacruc));
|
|
|
|
accent_table_size = ct;
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
kfree(buf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2012-02-28 14:49:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_do_kdskbmode - set keyboard mode ioctl
|
|
|
|
* @console: the console to use
|
|
|
|
* @arg: the requested mode
|
|
|
|
*
|
|
|
|
* Update the keyboard mode bits while holding the correct locks.
|
|
|
|
* Return 0 for success or an error code.
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
int vt_do_kdskbmode(unsigned int console, unsigned int arg)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
int ret = 0;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
switch(arg) {
|
|
|
|
case K_RAW:
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->kbdmode = VC_RAW;
|
2012-02-28 14:49:23 +00:00
|
|
|
break;
|
|
|
|
case K_MEDIUMRAW:
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->kbdmode = VC_MEDIUMRAW;
|
2012-02-28 14:49:23 +00:00
|
|
|
break;
|
|
|
|
case K_XLATE:
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->kbdmode = VC_XLATE;
|
2012-02-28 14:49:23 +00:00
|
|
|
do_compute_shiftstate();
|
|
|
|
break;
|
|
|
|
case K_UNICODE:
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->kbdmode = VC_UNICODE;
|
2012-02-28 14:49:23 +00:00
|
|
|
do_compute_shiftstate();
|
|
|
|
break;
|
|
|
|
case K_OFF:
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->kbdmode = VC_OFF;
|
2012-02-28 14:49:23 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_do_kdskbmeta - set keyboard meta state
|
|
|
|
* @console: the console to use
|
|
|
|
* @arg: the requested meta state
|
|
|
|
*
|
|
|
|
* Update the keyboard meta bits while holding the correct locks.
|
|
|
|
* Return 0 for success or an error code.
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
int vt_do_kdskbmeta(unsigned int console, unsigned int arg)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
int ret = 0;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
switch(arg) {
|
|
|
|
case K_METABIT:
|
2014-09-06 01:57:57 +00:00
|
|
|
clr_vc_kbd_mode(kb, VC_META);
|
2012-02-28 14:49:23 +00:00
|
|
|
break;
|
|
|
|
case K_ESCPREFIX:
|
2014-09-06 01:57:57 +00:00
|
|
|
set_vc_kbd_mode(kb, VC_META);
|
2012-02-28 14:49:23 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
|
|
|
|
int perm)
|
|
|
|
{
|
|
|
|
struct kbkeycode tmp;
|
|
|
|
int kc = 0;
|
|
|
|
|
|
|
|
if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
|
|
|
|
return -EFAULT;
|
|
|
|
switch (cmd) {
|
|
|
|
case KDGETKEYCODE:
|
|
|
|
kc = getkeycode(tmp.scancode);
|
|
|
|
if (kc >= 0)
|
|
|
|
kc = put_user(kc, &user_kbkc->keycode);
|
|
|
|
break;
|
|
|
|
case KDSETKEYCODE:
|
|
|
|
if (!perm)
|
|
|
|
return -EPERM;
|
|
|
|
kc = setkeycode(tmp.scancode, tmp.keycode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return kc;
|
|
|
|
}
|
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
static unsigned short vt_kdgkbent(unsigned char kbdmode, unsigned char idx,
|
|
|
|
unsigned char map)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2020-10-29 11:32:11 +00:00
|
|
|
unsigned short *key_map, val;
|
2012-02-28 14:49:23 +00:00
|
|
|
unsigned long flags;
|
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
/* Ensure another thread doesn't free it under us */
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
key_map = key_maps[map];
|
|
|
|
if (key_map) {
|
|
|
|
val = U(key_map[idx]);
|
|
|
|
if (kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
|
|
|
|
val = K_HOLE;
|
|
|
|
} else
|
|
|
|
val = idx ? K_HOLE : K_NOSUCHMAP;
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
return val;
|
|
|
|
}
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
|
|
|
|
unsigned char map, unsigned short val)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
unsigned short *key_map, *new_map, oldval;
|
|
|
|
|
|
|
|
if (!idx && val == K_NOSUCHMAP) {
|
2012-02-28 14:49:23 +00:00
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
2020-10-29 11:32:11 +00:00
|
|
|
/* deallocate map */
|
|
|
|
key_map = key_maps[map];
|
|
|
|
if (map && key_map) {
|
|
|
|
key_maps[map] = NULL;
|
|
|
|
if (key_map[0] == U(K_ALLOCATED)) {
|
|
|
|
kfree(key_map);
|
|
|
|
keymap_count--;
|
2012-02-28 14:49:23 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-29 11:32:11 +00:00
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
if (KTYP(val) < NR_TYPES) {
|
|
|
|
if (KVAL(val) > max_vals[KTYP(val)])
|
|
|
|
return -EINVAL;
|
|
|
|
} else if (kbdmode != VC_UNICODE)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* ++Geert: non-PC keyboards may generate keycode zero */
|
2012-02-28 14:49:23 +00:00
|
|
|
#if !defined(__mc68000__) && !defined(__powerpc__)
|
2020-10-29 11:32:11 +00:00
|
|
|
/* assignment to entry 0 only tests validity of args */
|
|
|
|
if (!idx)
|
|
|
|
return 0;
|
2012-02-28 14:49:23 +00:00
|
|
|
#endif
|
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
|
|
|
|
if (!new_map)
|
|
|
|
return -ENOMEM;
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2020-10-29 11:32:11 +00:00
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
key_map = key_maps[map];
|
|
|
|
if (key_map == NULL) {
|
|
|
|
int j;
|
|
|
|
|
|
|
|
if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
|
|
|
|
!capable(CAP_SYS_RESOURCE)) {
|
2012-02-28 14:49:23 +00:00
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
2020-10-29 11:32:11 +00:00
|
|
|
kfree(new_map);
|
2012-02-28 14:49:23 +00:00
|
|
|
return -EPERM;
|
|
|
|
}
|
2020-10-29 11:32:11 +00:00
|
|
|
key_maps[map] = new_map;
|
|
|
|
key_map = new_map;
|
|
|
|
key_map[0] = U(K_ALLOCATED);
|
|
|
|
for (j = 1; j < NR_KEYS; j++)
|
|
|
|
key_map[j] = U(K_HOLE);
|
|
|
|
keymap_count++;
|
|
|
|
} else
|
|
|
|
kfree(new_map);
|
|
|
|
|
|
|
|
oldval = U(key_map[idx]);
|
|
|
|
if (val == oldval)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Attention Key */
|
|
|
|
if ((oldval == K_SAK || val == K_SAK) && !capable(CAP_SYS_ADMIN)) {
|
2012-02-28 14:49:23 +00:00
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
2020-10-29 11:32:11 +00:00
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
|
|
|
|
key_map[idx] = U(val);
|
|
|
|
if (!map && (KTYP(oldval) == KT_SHIFT || KTYP(val) == KT_SHIFT))
|
|
|
|
do_compute_shiftstate();
|
|
|
|
out:
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
|
2021-07-26 13:43:22 +00:00
|
|
|
unsigned int console)
|
2020-10-29 11:32:11 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2020-10-29 11:32:11 +00:00
|
|
|
struct kbentry kbe;
|
|
|
|
|
|
|
|
if (copy_from_user(&kbe, user_kbe, sizeof(struct kbentry)))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case KDGKBENT:
|
|
|
|
return put_user(vt_kdgkbent(kb->kbdmode, kbe.kb_index,
|
|
|
|
kbe.kb_table),
|
|
|
|
&user_kbe->kb_value);
|
|
|
|
case KDSKBENT:
|
2020-10-29 11:32:12 +00:00
|
|
|
if (!perm || !capable(CAP_SYS_TTY_CONFIG))
|
2020-10-29 11:32:11 +00:00
|
|
|
return -EPERM;
|
|
|
|
return vt_kdskbent(kb->kbdmode, kbe.kb_index, kbe.kb_table,
|
|
|
|
kbe.kb_value);
|
2012-02-28 14:49:23 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
vt: keyboard, extract and simplify vt_kdskbsent
Setting of function key strings is now very complex. It uses a global
buffer 'func_buf' which is prefilled in defkeymap.c_shipped. Then there
is also an index table called 'func_table'. So initially, we have
something like this:
char func_buf[] = "\e[[A\0" // for F1
"\e[[B\0" // for F2
...;
char *func_table[] = {
func_buf + 0, // for F1
func_buf + 5, // for F2
... }
When a user changes some specific func string by KDSKBSENT, it is
changed in 'func_buf'. If it is shorter or equal to the current one, it
is handled by a very quick 'strcpy'.
When the user's string is longer, the whole 'func_buf' is reallocated to
allow expansion somewhere in the middle. The buffer before the user's
string is copied, the user's string appended and the rest appended too.
Now, the index table (func_table) needs to be recomputed, of course.
One more complication is the held spinlock -- we have to unlock,
reallocate, lock again and do the whole thing again to be sure noone
raced with us.
In this patch, we chose completely orthogonal approach: when the user's
string is longer than the current one, we simply assign the 'kstrdup'ed
copy to the index table (func_table) and modify func_buf in no way. We
only need to make sure we free the old entries. So we need a bitmap
is_kmalloc and free the old entries (but not the original func_buf
rodata string).
Also note that we do not waste so much space as previous approach. We
only allocate space for single entries which are longer, while before,
the whole buffer was duplicated plus space for the longer string.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-12-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-10-29 11:32:17 +00:00
|
|
|
static char *vt_kdskbsent(char *kbs, unsigned char cur)
|
|
|
|
{
|
|
|
|
static DECLARE_BITMAP(is_kmalloc, MAX_NR_FUNC);
|
|
|
|
char *cur_f = func_table[cur];
|
|
|
|
|
|
|
|
if (cur_f && strlen(cur_f) >= strlen(kbs)) {
|
|
|
|
strcpy(cur_f, kbs);
|
|
|
|
return kbs;
|
|
|
|
}
|
|
|
|
|
|
|
|
func_table[cur] = kbs;
|
|
|
|
|
|
|
|
return __test_and_set_bit(cur, is_kmalloc) ? cur_f : NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
|
|
|
|
{
|
vt: keyboard, extract and simplify vt_kdskbsent
Setting of function key strings is now very complex. It uses a global
buffer 'func_buf' which is prefilled in defkeymap.c_shipped. Then there
is also an index table called 'func_table'. So initially, we have
something like this:
char func_buf[] = "\e[[A\0" // for F1
"\e[[B\0" // for F2
...;
char *func_table[] = {
func_buf + 0, // for F1
func_buf + 5, // for F2
... }
When a user changes some specific func string by KDSKBSENT, it is
changed in 'func_buf'. If it is shorter or equal to the current one, it
is handled by a very quick 'strcpy'.
When the user's string is longer, the whole 'func_buf' is reallocated to
allow expansion somewhere in the middle. The buffer before the user's
string is copied, the user's string appended and the rest appended too.
Now, the index table (func_table) needs to be recomputed, of course.
One more complication is the held spinlock -- we have to unlock,
reallocate, lock again and do the whole thing again to be sure noone
raced with us.
In this patch, we chose completely orthogonal approach: when the user's
string is longer than the current one, we simply assign the 'kstrdup'ed
copy to the index table (func_table) and modify func_buf in no way. We
only need to make sure we free the old entries. So we need a bitmap
is_kmalloc and free the old entries (but not the original func_buf
rodata string).
Also note that we do not waste so much space as previous approach. We
only allocate space for single entries which are longer, while before,
the whole buffer was duplicated plus space for the longer string.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-12-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-10-29 11:32:17 +00:00
|
|
|
unsigned char kb_func;
|
|
|
|
unsigned long flags;
|
2020-10-29 11:32:16 +00:00
|
|
|
char *kbs;
|
2012-02-28 14:49:23 +00:00
|
|
|
int ret;
|
|
|
|
|
2020-10-29 11:32:16 +00:00
|
|
|
if (get_user(kb_func, &user_kdgkb->kb_func))
|
|
|
|
return -EFAULT;
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2020-10-29 11:32:16 +00:00
|
|
|
kb_func = array_index_nospec(kb_func, MAX_NR_FUNC);
|
2012-02-28 14:49:23 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
2020-10-19 08:55:16 +00:00
|
|
|
case KDGKBSENT: {
|
|
|
|
/* size should have been a struct member */
|
2020-10-19 08:55:17 +00:00
|
|
|
ssize_t len = sizeof(user_kdgkb->kb_string);
|
|
|
|
|
2020-10-29 11:32:16 +00:00
|
|
|
kbs = kmalloc(len, GFP_KERNEL);
|
|
|
|
if (!kbs)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2020-10-19 08:55:17 +00:00
|
|
|
spin_lock_irqsave(&func_buf_lock, flags);
|
2020-10-29 11:32:16 +00:00
|
|
|
len = strlcpy(kbs, func_table[kb_func] ? : "", len);
|
2020-10-19 08:55:17 +00:00
|
|
|
spin_unlock_irqrestore(&func_buf_lock, flags);
|
2020-10-19 08:55:16 +00:00
|
|
|
|
2020-10-29 11:32:16 +00:00
|
|
|
ret = copy_to_user(user_kdgkb->kb_string, kbs, len + 1) ?
|
|
|
|
-EFAULT : 0;
|
2020-10-19 08:55:16 +00:00
|
|
|
|
vt: keyboard, extract and simplify vt_kdskbsent
Setting of function key strings is now very complex. It uses a global
buffer 'func_buf' which is prefilled in defkeymap.c_shipped. Then there
is also an index table called 'func_table'. So initially, we have
something like this:
char func_buf[] = "\e[[A\0" // for F1
"\e[[B\0" // for F2
...;
char *func_table[] = {
func_buf + 0, // for F1
func_buf + 5, // for F2
... }
When a user changes some specific func string by KDSKBSENT, it is
changed in 'func_buf'. If it is shorter or equal to the current one, it
is handled by a very quick 'strcpy'.
When the user's string is longer, the whole 'func_buf' is reallocated to
allow expansion somewhere in the middle. The buffer before the user's
string is copied, the user's string appended and the rest appended too.
Now, the index table (func_table) needs to be recomputed, of course.
One more complication is the held spinlock -- we have to unlock,
reallocate, lock again and do the whole thing again to be sure noone
raced with us.
In this patch, we chose completely orthogonal approach: when the user's
string is longer than the current one, we simply assign the 'kstrdup'ed
copy to the index table (func_table) and modify func_buf in no way. We
only need to make sure we free the old entries. So we need a bitmap
is_kmalloc and free the old entries (but not the original func_buf
rodata string).
Also note that we do not waste so much space as previous approach. We
only allocate space for single entries which are longer, while before,
the whole buffer was duplicated plus space for the longer string.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-12-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-10-29 11:32:17 +00:00
|
|
|
break;
|
2020-10-19 08:55:16 +00:00
|
|
|
}
|
2012-02-28 14:49:23 +00:00
|
|
|
case KDSKBSENT:
|
2020-10-29 11:32:19 +00:00
|
|
|
if (!perm || !capable(CAP_SYS_TTY_CONFIG))
|
2020-10-29 11:32:16 +00:00
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
kbs = strndup_user(user_kdgkb->kb_string,
|
|
|
|
sizeof(user_kdgkb->kb_string));
|
|
|
|
if (IS_ERR(kbs))
|
|
|
|
return PTR_ERR(kbs);
|
2012-02-28 14:49:23 +00:00
|
|
|
|
2019-03-10 21:24:15 +00:00
|
|
|
spin_lock_irqsave(&func_buf_lock, flags);
|
vt: keyboard, extract and simplify vt_kdskbsent
Setting of function key strings is now very complex. It uses a global
buffer 'func_buf' which is prefilled in defkeymap.c_shipped. Then there
is also an index table called 'func_table'. So initially, we have
something like this:
char func_buf[] = "\e[[A\0" // for F1
"\e[[B\0" // for F2
...;
char *func_table[] = {
func_buf + 0, // for F1
func_buf + 5, // for F2
... }
When a user changes some specific func string by KDSKBSENT, it is
changed in 'func_buf'. If it is shorter or equal to the current one, it
is handled by a very quick 'strcpy'.
When the user's string is longer, the whole 'func_buf' is reallocated to
allow expansion somewhere in the middle. The buffer before the user's
string is copied, the user's string appended and the rest appended too.
Now, the index table (func_table) needs to be recomputed, of course.
One more complication is the held spinlock -- we have to unlock,
reallocate, lock again and do the whole thing again to be sure noone
raced with us.
In this patch, we chose completely orthogonal approach: when the user's
string is longer than the current one, we simply assign the 'kstrdup'ed
copy to the index table (func_table) and modify func_buf in no way. We
only need to make sure we free the old entries. So we need a bitmap
is_kmalloc and free the old entries (but not the original func_buf
rodata string).
Also note that we do not waste so much space as previous approach. We
only allocate space for single entries which are longer, while before,
the whole buffer was duplicated plus space for the longer string.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-12-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-10-29 11:32:17 +00:00
|
|
|
kbs = vt_kdskbsent(kbs, kb_func);
|
2019-03-10 21:24:15 +00:00
|
|
|
spin_unlock_irqrestore(&func_buf_lock, flags);
|
vt: keyboard, extract and simplify vt_kdskbsent
Setting of function key strings is now very complex. It uses a global
buffer 'func_buf' which is prefilled in defkeymap.c_shipped. Then there
is also an index table called 'func_table'. So initially, we have
something like this:
char func_buf[] = "\e[[A\0" // for F1
"\e[[B\0" // for F2
...;
char *func_table[] = {
func_buf + 0, // for F1
func_buf + 5, // for F2
... }
When a user changes some specific func string by KDSKBSENT, it is
changed in 'func_buf'. If it is shorter or equal to the current one, it
is handled by a very quick 'strcpy'.
When the user's string is longer, the whole 'func_buf' is reallocated to
allow expansion somewhere in the middle. The buffer before the user's
string is copied, the user's string appended and the rest appended too.
Now, the index table (func_table) needs to be recomputed, of course.
One more complication is the held spinlock -- we have to unlock,
reallocate, lock again and do the whole thing again to be sure noone
raced with us.
In this patch, we chose completely orthogonal approach: when the user's
string is longer than the current one, we simply assign the 'kstrdup'ed
copy to the index table (func_table) and modify func_buf in no way. We
only need to make sure we free the old entries. So we need a bitmap
is_kmalloc and free the old entries (but not the original func_buf
rodata string).
Also note that we do not waste so much space as previous approach. We
only allocate space for single entries which are longer, while before,
the whole buffer was duplicated plus space for the longer string.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-12-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-10-29 11:32:17 +00:00
|
|
|
|
|
|
|
ret = 0;
|
2012-02-28 14:49:23 +00:00
|
|
|
break;
|
|
|
|
}
|
vt: keyboard, extract and simplify vt_kdskbsent
Setting of function key strings is now very complex. It uses a global
buffer 'func_buf' which is prefilled in defkeymap.c_shipped. Then there
is also an index table called 'func_table'. So initially, we have
something like this:
char func_buf[] = "\e[[A\0" // for F1
"\e[[B\0" // for F2
...;
char *func_table[] = {
func_buf + 0, // for F1
func_buf + 5, // for F2
... }
When a user changes some specific func string by KDSKBSENT, it is
changed in 'func_buf'. If it is shorter or equal to the current one, it
is handled by a very quick 'strcpy'.
When the user's string is longer, the whole 'func_buf' is reallocated to
allow expansion somewhere in the middle. The buffer before the user's
string is copied, the user's string appended and the rest appended too.
Now, the index table (func_table) needs to be recomputed, of course.
One more complication is the held spinlock -- we have to unlock,
reallocate, lock again and do the whole thing again to be sure noone
raced with us.
In this patch, we chose completely orthogonal approach: when the user's
string is longer than the current one, we simply assign the 'kstrdup'ed
copy to the index table (func_table) and modify func_buf in no way. We
only need to make sure we free the old entries. So we need a bitmap
is_kmalloc and free the old entries (but not the original func_buf
rodata string).
Also note that we do not waste so much space as previous approach. We
only allocate space for single entries which are longer, while before,
the whole buffer was duplicated plus space for the longer string.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-12-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-10-29 11:32:17 +00:00
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
kfree(kbs);
|
vt: keyboard, extract and simplify vt_kdskbsent
Setting of function key strings is now very complex. It uses a global
buffer 'func_buf' which is prefilled in defkeymap.c_shipped. Then there
is also an index table called 'func_table'. So initially, we have
something like this:
char func_buf[] = "\e[[A\0" // for F1
"\e[[B\0" // for F2
...;
char *func_table[] = {
func_buf + 0, // for F1
func_buf + 5, // for F2
... }
When a user changes some specific func string by KDSKBSENT, it is
changed in 'func_buf'. If it is shorter or equal to the current one, it
is handled by a very quick 'strcpy'.
When the user's string is longer, the whole 'func_buf' is reallocated to
allow expansion somewhere in the middle. The buffer before the user's
string is copied, the user's string appended and the rest appended too.
Now, the index table (func_table) needs to be recomputed, of course.
One more complication is the held spinlock -- we have to unlock,
reallocate, lock again and do the whole thing again to be sure noone
raced with us.
In this patch, we chose completely orthogonal approach: when the user's
string is longer than the current one, we simply assign the 'kstrdup'ed
copy to the index table (func_table) and modify func_buf in no way. We
only need to make sure we free the old entries. So we need a bitmap
is_kmalloc and free the old entries (but not the original func_buf
rodata string).
Also note that we do not waste so much space as previous approach. We
only allocate space for single entries which are longer, while before,
the whole buffer was duplicated plus space for the longer string.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-12-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-10-29 11:32:17 +00:00
|
|
|
|
2012-02-28 14:49:23 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-07-26 13:43:22 +00:00
|
|
|
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
unsigned long flags;
|
|
|
|
unsigned char ucval;
|
|
|
|
|
|
|
|
switch(cmd) {
|
|
|
|
/* the ioctls below read/set the flags usually shown in the leds */
|
|
|
|
/* don't use them - they will go away without warning */
|
|
|
|
case KDGKBLED:
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
ucval = kb->ledflagstate | (kb->default_ledflagstate << 4);
|
2012-02-28 14:49:23 +00:00
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
return put_user(ucval, (char __user *)arg);
|
|
|
|
|
|
|
|
case KDSKBLED:
|
|
|
|
if (!perm)
|
|
|
|
return -EPERM;
|
|
|
|
if (arg & ~0x77)
|
|
|
|
return -EINVAL;
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_lock_irqsave(&led_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->ledflagstate = (arg & 7);
|
|
|
|
kb->default_ledflagstate = ((arg >> 4) & 7);
|
2012-02-28 14:49:23 +00:00
|
|
|
set_leds();
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_unlock_irqrestore(&led_lock, flags);
|
2012-05-14 13:41:31 +00:00
|
|
|
return 0;
|
2012-02-28 14:49:23 +00:00
|
|
|
|
|
|
|
/* the ioctls below only set the lights, not the functions */
|
|
|
|
/* for those, see KDGKBLED and KDSKBLED above */
|
|
|
|
case KDGETLED:
|
|
|
|
ucval = getledstate();
|
|
|
|
return put_user(ucval, (char __user *)arg);
|
|
|
|
|
|
|
|
case KDSETLED:
|
|
|
|
if (!perm)
|
|
|
|
return -EPERM;
|
2014-09-06 01:57:57 +00:00
|
|
|
setledstate(kb, arg);
|
2012-02-28 14:49:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -ENOIOCTLCMD;
|
|
|
|
}
|
|
|
|
|
2021-07-26 13:43:22 +00:00
|
|
|
int vt_do_kdgkbmode(unsigned int console)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
/* This is a spot read so needs no locking */
|
2014-09-06 01:57:57 +00:00
|
|
|
switch (kb->kbdmode) {
|
2012-02-28 14:49:23 +00:00
|
|
|
case VC_RAW:
|
|
|
|
return K_RAW;
|
|
|
|
case VC_MEDIUMRAW:
|
|
|
|
return K_MEDIUMRAW;
|
|
|
|
case VC_UNICODE:
|
|
|
|
return K_UNICODE;
|
|
|
|
case VC_OFF:
|
|
|
|
return K_OFF;
|
|
|
|
default:
|
|
|
|
return K_XLATE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_do_kdgkbmeta - report meta status
|
|
|
|
* @console: console to report
|
|
|
|
*
|
|
|
|
* Report the meta flag status of this console
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
int vt_do_kdgkbmeta(unsigned int console)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
/* Again a spot read so no locking */
|
2014-09-06 01:57:57 +00:00
|
|
|
return vc_kbd_mode(kb, VC_META) ? K_ESCPREFIX : K_METABIT;
|
2012-02-28 14:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_reset_unicode - reset the unicode status
|
|
|
|
* @console: console being reset
|
|
|
|
*
|
|
|
|
* Restore the unicode console state to its default
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
void vt_reset_unicode(unsigned int console)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
|
|
|
kbd_table[console].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-03-03 08:32:29 +00:00
|
|
|
* vt_get_shift_state - shift bit state
|
2012-02-28 14:49:23 +00:00
|
|
|
*
|
|
|
|
* Report the shift bits from the keyboard state. We have to export
|
|
|
|
* this to support some oddities in the vt layer.
|
|
|
|
*/
|
|
|
|
int vt_get_shift_state(void)
|
|
|
|
{
|
|
|
|
/* Don't lock as this is a transient report */
|
|
|
|
return shift_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_reset_keyboard - reset keyboard state
|
|
|
|
* @console: console to reset
|
|
|
|
*
|
|
|
|
* Reset the keyboard bits for a console as part of a general console
|
|
|
|
* reset event
|
|
|
|
*/
|
2021-07-26 13:43:22 +00:00
|
|
|
void vt_reset_keyboard(unsigned int console)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
set_vc_kbd_mode(kb, VC_REPEAT);
|
|
|
|
clr_vc_kbd_mode(kb, VC_CKMODE);
|
|
|
|
clr_vc_kbd_mode(kb, VC_APPLIC);
|
|
|
|
clr_vc_kbd_mode(kb, VC_CRLF);
|
|
|
|
kb->lockstate = 0;
|
|
|
|
kb->slockstate = 0;
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_lock(&led_lock);
|
2014-09-06 01:57:57 +00:00
|
|
|
kb->ledmode = LED_SHOW_FLAGS;
|
|
|
|
kb->ledflagstate = kb->default_ledflagstate;
|
2012-07-17 16:06:41 +00:00
|
|
|
spin_unlock(&led_lock);
|
2012-02-28 14:49:23 +00:00
|
|
|
/* do not do set_leds here because this causes an endless tasklet loop
|
|
|
|
when the keyboard hasn't been initialized yet */
|
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_get_kbd_mode_bit - read keyboard status bits
|
|
|
|
* @console: console to read from
|
|
|
|
* @bit: mode bit to read
|
|
|
|
*
|
|
|
|
* Report back a vt mode bit. We do this without locking so the
|
|
|
|
* caller must be sure that there are no synchronization needs
|
|
|
|
*/
|
|
|
|
|
2021-07-26 13:43:22 +00:00
|
|
|
int vt_get_kbd_mode_bit(unsigned int console, int bit)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2014-09-06 01:57:57 +00:00
|
|
|
return vc_kbd_mode(kb, bit);
|
2012-02-28 14:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_set_kbd_mode_bit - read keyboard status bits
|
|
|
|
* @console: console to read from
|
|
|
|
* @bit: mode bit to read
|
|
|
|
*
|
|
|
|
* Set a vt mode bit. We do this without locking so the
|
|
|
|
* caller must be sure that there are no synchronization needs
|
|
|
|
*/
|
|
|
|
|
2021-07-26 13:43:22 +00:00
|
|
|
void vt_set_kbd_mode_bit(unsigned int console, int bit)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
set_vc_kbd_mode(kb, bit);
|
2012-02-28 14:49:23 +00:00
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vt_clr_kbd_mode_bit - read keyboard status bits
|
|
|
|
* @console: console to read from
|
|
|
|
* @bit: mode bit to read
|
|
|
|
*
|
|
|
|
* Report back a vt mode bit. We do this without locking so the
|
|
|
|
* caller must be sure that there are no synchronization needs
|
|
|
|
*/
|
|
|
|
|
2021-07-26 13:43:22 +00:00
|
|
|
void vt_clr_kbd_mode_bit(unsigned int console, int bit)
|
2012-02-28 14:49:23 +00:00
|
|
|
{
|
2021-07-26 13:43:21 +00:00
|
|
|
struct kbd_struct *kb = &kbd_table[console];
|
2012-02-28 14:49:23 +00:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
2014-09-06 01:57:57 +00:00
|
|
|
clr_vc_kbd_mode(kb, bit);
|
2012-02-28 14:49:23 +00:00
|
|
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
|
|
|
}
|