Commit a76a8a35 authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/spare/repo/linux-2.5

into redhat.com:/spare/repo/libata-2.5
parents d75f0d82 dbf8623b
......@@ -790,7 +790,8 @@ running once the system is up.
before loading.
See Documentation/ramdisk.txt.
psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions
psmouse_proto= [HW,MOUSE] Highest PS2 mouse protocol extension to
probe for (bare|imps|exps).
psmouse_resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many
......
......@@ -505,6 +505,20 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
return 1;
}
int can_request_irq(unsigned int irq, unsigned long irqflags)
{
struct irqaction *action;
if (irq >= NR_IRQS)
return 0;
action = irq_desc[irq].action;
if (action) {
if (irqflags & action->flags & SA_SHIRQ)
action = NULL;
}
return !action;
}
/**
* request_irq - allocate an interrupt line
* @irq: Interrupt line to allocate
......
......@@ -541,8 +541,10 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long
goto survive;
}
if (retval != 1)
if (retval != 1) {
up_read(&current->mm->mmap_sem);
break;
}
maddr = kmap_atomic(pg, KM_USER0);
memcpy(maddr + offset, from, len);
......
......@@ -695,11 +695,6 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
return NULL;
}
static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
return IRQ_NONE;
}
static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
{
u8 pin;
......@@ -761,13 +756,10 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
for (i = 0; i < 16; i++) {
if (!(mask & (1 << i)))
continue;
if (pirq_penalty[i] < pirq_penalty[newirq] &&
!request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
free_irq(i, dev);
if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, SA_SHIRQ))
newirq = i;
}
}
}
DBG(" -> newirq=%d", newirq);
/* Check if it is hardcoded */
......
......@@ -2460,7 +2460,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
if (!uptodate) {
error = -EIO;
if (!(req->flags & REQ_QUIET))
if (blk_fs_request(req) && !(req->flags & REQ_QUIET))
printk("end_request: I/O error, dev %s, sector %llu\n",
req->rq_disk ? req->rq_disk->disk_name : "?",
(unsigned long long)req->sector);
......
......@@ -941,16 +941,16 @@ static unsigned short x86_keycodes[256] =
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, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 92,334,512,116,377,109,111,373,347,348,349,
360, 93, 94, 95, 98,376,100,101,321,316,354,286,289,102,351,355,
80, 81, 82, 83, 84, 93, 86, 87, 88, 94, 95, 85,259,375,260, 90,
284,285,309,311,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,116,377,109,111,126,347,348,349,
360,261,262,263,298,376,100,101,321,316,373,286,289,102,351,355,
103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
291,108,381,281,290,272,292,305,280, 99,112,257,258,359,270,114,
118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269,
271,273,276,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,326,330,
332,340,365,342,343,344,345,346,356,113,341,368,369,370,371,372 };
291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
264,117,271,374,379,115,125,273,121,123, 92,265,266,267,268,269,
120,119,118,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 };
#ifdef CONFIG_MAC_EMUMOUSEBTN
extern int mac_hid_mouse_emulate_buttons(int, int, int);
......@@ -972,11 +972,18 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
if (keycode > 255 || !x86_keycodes[keycode])
return -1;
if (keycode == KEY_PAUSE) {
switch (keycode) {
case KEY_PAUSE:
put_queue(vc, 0xe1);
put_queue(vc, 0x1d | up_flag);
put_queue(vc, 0x45 | up_flag);
return 0;
case KEY_LANG1:
if (!up_flag) put_queue(vc, 0xf1);
return 0;
case KEY_LANG2:
if (!up_flag) put_queue(vc, 0xf2);
return 0;
}
if (keycode == KEY_SYSRQ && sysrq_alt) {
......
......@@ -447,6 +447,7 @@ void input_register_device(struct input_dev *dev)
list_add_tail(&dev->node, &input_dev_list);
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
if ((handle = handler->connect(handler, dev, id)))
input_link_handle(handle);
......@@ -507,6 +508,7 @@ void input_register_handler(struct input_handler *handler)
list_add_tail(&handler->node, &input_handler_list);
list_for_each_entry(dev, &input_dev_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
if ((handle = handler->connect(handler, dev, id)))
input_link_handle(handle);
......
......@@ -380,10 +380,6 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
struct joydev *joydev;
int i, j, t, minor;
/* Avoid tablets */
if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit))
return NULL;
for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
if (minor == JOYDEV_MINORS) {
printk(KERN_ERR "joydev: no more free joydev devices\n");
......@@ -464,6 +460,15 @@ static void joydev_disconnect(struct input_handle *handle)
joydev_free(joydev);
}
static struct input_device_id joydev_blacklist[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT(EV_KEY) },
.keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
}, /* Avoid itouchpads, touchscreens and tablets */
{ }, /* Terminating entry */
};
static struct input_device_id joydev_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
......@@ -493,6 +498,7 @@ static struct input_handler joydev_handler = {
.minor = JOYDEV_MINOR_BASE,
.name = "joydev",
.id_table = joydev_ids,
.blacklist = joydev_blacklist,
};
static int __init joydev_init(void)
......
This diff is collapsed.
......@@ -23,27 +23,18 @@ config MOUSE_PS2
mice with wheels and extra buttons, Microsoft, Logitech or Genius
compatible.
Synaptics TouchPad users might be interested in a specialized
XFree86 driver at:
http://w1.894.telia.com/~u89404340/touchpad/index.html
and a new verion of GPM at:
http://www.geocities.com/dt_or/gpm/gpm.html
to take advantage of the advanced features of the touchpad.
If unsure, say Y.
To compile this driver as a module, choose M here: the
module will be called psmouse.
config MOUSE_PS2_SYNAPTICS
bool "Synaptics TouchPad"
default n
depends on INPUT && INPUT_MOUSE && MOUSE_PS2
---help---
Say Y here if you have a Synaptics TouchPad connected to your system.
This touchpad is found on many modern laptop computers.
Note that you also need a user space driver to interpret the data
generated by the kernel. A compatible driver for XFree86 is available
from http://w1.894.telia.com/~u89404340/touchpad/index.html
The gpm program is not yet able to interpret the data from this
driver, so if you need to use the touchpad in the console, you have to
say N for now.
config MOUSE_SERIAL
tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE
......
......@@ -10,6 +10,7 @@
*/
#include <linux/input.h>
#include <linux/serio.h>
#include "psmouse.h"
#include "logips2pp.h"
......@@ -142,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
* touchpad.
*/
int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
{
int i;
static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 };
......@@ -226,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
return 0;
}
/*
* Logitech magic init.
*/
int ps2pp_detect(struct psmouse *psmouse)
{
unsigned char param[4];
param[0] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
param[1] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
return param[1] != 0 ? ps2pp_detect_model(psmouse, param) : 0;
}
......@@ -13,5 +13,5 @@
struct psmouse;
void ps2pp_process_packet(struct psmouse *psmouse);
void ps2pp_set_800dpi(struct psmouse *psmouse);
int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param);
int ps2pp_detect(struct psmouse *psmouse);
#endif
This diff is collapsed.
......@@ -22,10 +22,20 @@
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
struct psmouse;
struct psmouse_ptport {
struct serio serio;
void (*activate)(struct psmouse *parent);
void (*deactivate)(struct psmouse *parent);
};
struct psmouse {
void *private;
struct input_dev dev;
struct serio *serio;
struct psmouse_ptport *ptport;
char *vendor;
char *name;
unsigned char cmdbuf[8];
......@@ -41,6 +51,9 @@ struct psmouse {
char error;
char devname[64];
char phys[32];
int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse);
};
#define PSMOUSE_PS2 1
......
......@@ -2,7 +2,8 @@
* Synaptics TouchPad PS/2 mouse driver
*
* 2003 Dmitry Torokhov <dtor@mail.ru>
* Added support for pass-through port
* Added support for pass-through port. Special thanks to Peter Berg Larsen
* for explaining various Synaptics quirks.
*
* 2003 Peter Osterlund <petero2@telia.com>
* Ported to 2.5 input device infrastructure.
......@@ -194,9 +195,7 @@ static void print_ident(struct synaptics_data *priv)
static int synaptics_query_hardware(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
int retries = 0;
int mode;
while ((retries++ < 3) && synaptics_reset(psmouse))
printk(KERN_ERR "synaptics reset failed\n");
......@@ -208,7 +207,14 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
if (synaptics_capability(psmouse))
return -1;
mode = SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
return 0;
}
static int synaptics_set_mode(struct psmouse *psmouse, int mode)
{
struct synaptics_data *priv = psmouse->private;
mode |= SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
if (SYN_ID_MAJOR(priv->identity) >= 4)
mode |= SYN_BIT_DISABLE_GESTURE;
if (SYN_CAP_EXTENDED(priv->capabilities))
......@@ -265,49 +271,38 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
}
}
int synaptics_pt_init(struct psmouse *psmouse)
static void synaptics_pt_activate(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
struct serio *port;
struct psmouse *child;
struct psmouse *child = psmouse->ptport->serio.private;
if (psmouse->type != PSMOUSE_SYNAPTICS)
return -1;
if (!SYN_CAP_EXTENDED(priv->capabilities))
return -1;
if (!SYN_CAP_PASS_THROUGH(priv->capabilities))
return -1;
/* adjust the touchpad to child's choice of protocol */
if (child && child->type >= PSMOUSE_GENPS) {
if (synaptics_set_mode(psmouse, SYN_BIT_FOUR_BYTE_CLIENT))
printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
}
}
static void synaptics_pt_create(struct psmouse *psmouse)
{
struct psmouse_ptport *port;
priv->ptport = port = kmalloc(sizeof(struct serio), GFP_KERNEL);
psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL);
if (!port) {
printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n");
return -1;
printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
return;
}
memset(port, 0, sizeof(struct serio));
port->type = SERIO_PS_PSTHRU;
port->name = "Synaptics pass-through";
port->phys = "synaptics-pt/serio0";
port->write = synaptics_pt_write;
port->open = synaptics_pt_open;
port->close = synaptics_pt_close;
port->driver = psmouse;
memset(port, 0, sizeof(struct psmouse_ptport));
printk(KERN_INFO "serio: %s port at %s\n", port->name, psmouse->phys);
serio_register_slave_port(port);
port->serio.type = SERIO_PS_PSTHRU;
port->serio.name = "Synaptics pass-through";
port->serio.phys = "synaptics-pt/serio0";
port->serio.write = synaptics_pt_write;
port->serio.open = synaptics_pt_open;
port->serio.close = synaptics_pt_close;
port->serio.driver = psmouse;
/* adjust the touchpad to child's choice of protocol */
child = port->private;
if (child && child->type >= PSMOUSE_GENPS) {
if (synaptics_mode_cmd(psmouse, (SYN_BIT_ABSOLUTE_MODE |
SYN_BIT_HIGH_RATE |
SYN_BIT_DISABLE_GESTURE |
SYN_BIT_FOUR_BYTE_CLIENT |
SYN_BIT_W_MODE)))
printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
}
return 0;
port->activate = synaptics_pt_activate;
}
/*****************************************************************************
......@@ -371,13 +366,57 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit(REL_Y, dev->relbit);
}
int synaptics_init(struct psmouse *psmouse)
static void synaptics_disconnect(struct psmouse *psmouse)
{
struct synaptics_data *priv;
synaptics_mode_cmd(psmouse, 0);
kfree(psmouse->private);
}
#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
static int synaptics_reconnect(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
struct synaptics_data old_priv = *priv;
if (!synaptics_detect(psmouse))
return -1;
if (synaptics_query_hardware(psmouse)) {
printk(KERN_ERR "Unable to query Synaptics hardware.\n");
return -1;
#endif
}
if (old_priv.identity != priv->identity ||
old_priv.model_id != priv->model_id ||
old_priv.capabilities != priv->capabilities ||
old_priv.ext_cap != priv->ext_cap)
return -1;
if (synaptics_set_mode(psmouse, 0)) {
printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
return -1;
}
return 0;
}
int synaptics_detect(struct psmouse *psmouse)
{
unsigned char param[4];
param[0] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
return param[1] == 0x47;
}
int synaptics_init(struct psmouse *psmouse)
{
struct synaptics_data *priv;
psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
if (!priv)
......@@ -385,13 +424,24 @@ int synaptics_init(struct psmouse *psmouse)
memset(priv, 0, sizeof(struct synaptics_data));
if (synaptics_query_hardware(psmouse)) {
printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n");
printk(KERN_ERR "Unable to query Synaptics hardware.\n");
goto init_fail;
}
if (synaptics_set_mode(psmouse, 0)) {
printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
goto init_fail;
}
if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities))
synaptics_pt_create(psmouse);
print_ident(priv);
set_input_params(&psmouse->dev, priv);
psmouse->disconnect = synaptics_disconnect;
psmouse->reconnect = synaptics_reconnect;
return 0;
init_fail:
......@@ -399,36 +449,13 @@ int synaptics_init(struct psmouse *psmouse)
return -1;
}
void synaptics_disconnect(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
if (psmouse->type == PSMOUSE_SYNAPTICS && priv) {
synaptics_mode_cmd(psmouse, 0);
if (priv->ptport) {
serio_unregister_slave_port(priv->ptport);
kfree(priv->ptport);
}
kfree(priv);
}
}
/*****************************************************************************
* Functions to interpret the absolute mode packets
****************************************************************************/
static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
{
hw->up = 0;
hw->down = 0;
hw->b0 = 0;
hw->b1 = 0;
hw->b2 = 0;
hw->b3 = 0;
hw->b4 = 0;
hw->b5 = 0;
hw->b6 = 0;
hw->b7 = 0;
memset(hw, 0, sizeof(struct synaptics_hw_state));
if (SYN_MODEL_NEWABS(priv->model_id)) {
hw->x = (((buf[3] & 0x10) << 8) |
......@@ -570,64 +597,47 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_sync(dev);
}
static int synaptics_validate_byte(struct psmouse *psmouse)
{
static unsigned char newabs_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
static unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
struct synaptics_data *priv = psmouse->private;
int idx = psmouse->pktcnt - 1;
if (SYN_MODEL_NEWABS(priv->model_id))
return (psmouse->packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
else
return (psmouse->packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
}
void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
struct input_dev *dev = &psmouse->dev;
struct synaptics_data *priv = psmouse->private;
unsigned char data = psmouse->packet[psmouse->pktcnt - 1];
int newabs = SYN_MODEL_NEWABS(priv->model_id);
input_regs(dev, regs);
switch (psmouse->pktcnt) {
case 1:
if (newabs ? ((data & 0xC8) != 0x80) : ((data & 0xC0) != 0xC0)) {
printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n");
goto bad_sync;
}
break;
case 2:
if (!newabs && ((data & 0x60) != 0x00)) {
printk(KERN_WARNING "Synaptics driver lost sync at 2nd byte\n");
goto bad_sync;
}
break;
case 4:
if (newabs ? ((data & 0xC8) != 0xC0) : ((data & 0xC0) != 0x80)) {
printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n");
goto bad_sync;
}
break;
case 5:
if (!newabs && ((data & 0x60) != 0x00)) {
printk(KERN_WARNING "Synaptics driver lost sync at 5th byte\n");
goto bad_sync;
}
break;
default:
if (psmouse->pktcnt < 6)
break; /* Wait for full packet */
if (psmouse->pktcnt >= 6) { /* Full packet received */
if (priv->out_of_sync) {
priv->out_of_sync = 0;
printk(KERN_NOTICE "Synaptics driver resynced.\n");
}
if (priv->ptport && synaptics_is_pt_packet(psmouse->packet))
synaptics_pass_pt_packet(priv->ptport, psmouse->packet);
if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
else
synaptics_process_packet(psmouse);
psmouse->pktcnt = 0;
break;
}
return;
bad_sync:
priv->out_of_sync++;
} else if (psmouse->pktcnt && !synaptics_validate_byte(psmouse)) {
printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt);
psmouse->pktcnt = 0;
if (psmouse_resetafter > 0 && priv->out_of_sync == psmouse_resetafter) {
if (++priv->out_of_sync == psmouse_resetafter) {
psmouse->state = PSMOUSE_IGNORE;
serio_rescan(psmouse->serio);
printk(KERN_NOTICE "synaptics: issuing reconnect request\n");
serio_reconnect(psmouse->serio);
}
}
}
......@@ -9,11 +9,9 @@
#ifndef _SYNAPTICS_H
#define _SYNAPTICS_H
extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
extern int synaptics_detect(struct psmouse *psmouse);
extern int synaptics_init(struct psmouse *psmouse);
extern int synaptics_pt_init(struct psmouse *psmouse);
extern void synaptics_disconnect(struct psmouse *psmouse);
/* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00
......@@ -105,8 +103,6 @@ struct synaptics_data {
/* Data for normal processing */
unsigned int out_of_sync; /* # of packets out of sync */
int old_w; /* Previous w value */
struct serio *ptport; /* pass-through port */
};
#endif /* _SYNAPTICS_H */
This diff is collapsed.
......@@ -49,14 +49,17 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(serio_register_port);
EXPORT_SYMBOL(serio_register_slave_port);
EXPORT_SYMBOL(serio_register_port_delayed);
EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_unregister_slave_port);
EXPORT_SYMBOL(serio_unregister_port_delayed);
EXPORT_SYMBOL(__serio_unregister_port);
EXPORT_SYMBOL(serio_register_device);
EXPORT_SYMBOL(serio_unregister_device);
EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close);
EXPORT_SYMBOL(serio_rescan);
EXPORT_SYMBOL(serio_reconnect);
struct serio_event {
int type;
......@@ -83,10 +86,22 @@ static void serio_find_dev(struct serio *serio)
}
#define SERIO_RESCAN 1
#define SERIO_RECONNECT 2
#define SERIO_REGISTER_PORT 3
#define SERIO_UNREGISTER_PORT 4
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static DECLARE_COMPLETION(serio_exited);
static void serio_invalidate_pending_events(struct serio *serio)
{
struct serio_event *event;
list_for_each_entry(event, &serio_event_list, node)
if (event->serio == serio)
event->serio = NULL;
}
void serio_handle_events(void)
{
struct list_head *node, *next;
......@@ -95,17 +110,35 @@ void serio_handle_events(void)
list_for_each_safe(node, next, &serio_event_list) {
event = container_of(node, struct serio_event, node);
down(&serio_sem);
if (event->serio == NULL)
goto event_done;
switch (event->type) {
case SERIO_REGISTER_PORT :
__serio_register_port(event->serio);
break;
case SERIO_UNREGISTER_PORT :
__serio_unregister_port(event->serio);
break;
case SERIO_RECONNECT :
if (event->serio->dev && event->serio->dev->reconnect)
if (event->serio->dev->reconnect(event->serio) == 0)
break;
/* reconnect failed - fall through to rescan */
case SERIO_RESCAN :
down(&serio_sem);
if (event->serio->dev && event->serio->dev->disconnect)
event->serio->dev->disconnect(event->serio);
serio_find_dev(event->serio);
up(&serio_sem);
break;
default:
break;
}
event_done:
up(&serio_sem);
list_del_init(node);
kfree(event);
}
......@@ -130,18 +163,27 @@ static int serio_thread(void *nothing)
complete_and_exit(&serio_exited, 0);
}
void serio_rescan(struct serio *serio)
static void serio_queue_event(struct serio *serio, int event_type)
{
struct serio_event *event;
if (!(event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC)))
return;
event->type = SERIO_RESCAN;
if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
event->type = event_type;
event->serio = serio;
list_add_tail(&event->node, &serio_event_list);
wake_up(&serio_wait);
}
}
void serio_rescan(struct serio *serio)
{
serio_queue_event(serio, SERIO_RESCAN);
}
void serio_reconnect(struct serio *serio)
{
serio_queue_event(serio, SERIO_RECONNECT);
}
irqreturn_t serio_interrupt(struct serio *serio,
......@@ -163,17 +205,26 @@ irqreturn_t serio_interrupt(struct serio *serio,
void serio_register_port(struct serio *serio)
{
down(&serio_sem);
list_add_tail(&serio->node, &serio_list);
serio_find_dev(serio);
__serio_register_port(serio);
up(&serio_sem);
}
/*
* Same as serio_register_port but does not try to acquire serio_sem.
* Should be used when registering a serio from other input device's
* Submits register request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
* taken or not and when delayed execution is feasible.
*/
void serio_register_port_delayed(struct serio *serio)
{
serio_queue_event(serio, SERIO_REGISTER_PORT);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* connect() function.
*/
void serio_register_slave_port(struct serio *serio)
void __serio_register_port(struct serio *serio)
{
list_add_tail(&serio->node, &serio_list);
serio_find_dev(serio);
......@@ -182,19 +233,28 @@ void serio_register_slave_port(struct serio *serio)
void serio_unregister_port(struct serio *serio)
{
down(&serio_sem);
list_del_init(&serio->node);
if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio);
__serio_unregister_port(serio);
up(&serio_sem);
}
/*
* Same as serio_unregister_port but does not try to acquire serio_sem.
* Should be used when unregistering a serio from other input device's
* Submits unregister request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
* taken or not and when delayed execution is feasible.
*/
void serio_unregister_port_delayed(struct serio *serio)
{
serio_queue_event(serio, SERIO_UNREGISTER_PORT);
}
/*
* Should only be called directly if serio_sem has already been taken,
* for example when unregistering a serio from other input device's
* disconnect() function.
*/
void serio_unregister_slave_port(struct serio *serio)
void __serio_unregister_port(struct serio *serio)
{
serio_invalidate_pending_events(serio);
list_del_init(&serio->node);
if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio);
......
......@@ -2182,6 +2182,9 @@ static int uhci_reset(struct usb_hcd *hcd)
uhci->io_addr = (unsigned long) hcd->regs;
/* Turn off all interrupts */
outw(0, uhci->io_addr + USBINTR);
/* Maybe kick BIOS off this hardware. Then reset, so we won't get
* interrupts from any previous setup.
*/
......
......@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int);
extern void release_x86_irqs(struct task_struct *);
extern int can_request_irq(unsigned int, unsigned long flags);
#ifdef CONFIG_X86_LOCAL_APIC
#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
......
......@@ -870,6 +870,7 @@ struct input_handler {
char *name;
struct input_device_id *id_table;
struct input_device_id *blacklist;
struct list_head h_list;
struct list_head node;
......
......@@ -2,7 +2,6 @@
#define __LINUX_KEYBOARD_H
#include <linux/wait.h>
#include <linux/input.h>
#define KG_SHIFT 0
#define KG_CTRL 2
......@@ -17,7 +16,7 @@
#define NR_SHIFT 9
#define NR_KEYS (KEY_MAX+1)
#define NR_KEYS 255
#define MAX_NR_KEYMAPS 256
/* This means 128Kb if all keymaps are allocated. Only the superuser
may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
......
......@@ -49,6 +49,7 @@ struct serio_dev {
irqreturn_t (*interrupt)(struct serio *, unsigned char,
unsigned int, struct pt_regs *);
void (*connect)(struct serio *, struct serio_dev *dev);
int (*reconnect)(struct serio *);
void (*disconnect)(struct serio *);
void (*cleanup)(struct serio *);
......@@ -58,12 +59,15 @@ struct serio_dev {
int serio_open(struct serio *serio, struct serio_dev *dev);
void serio_close(struct serio *serio);
void serio_rescan(struct serio *serio);
void serio_reconnect(struct serio *serio);
irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
void serio_register_port(struct serio *serio);
void serio_register_slave_port(struct serio *serio);
void serio_register_port_delayed(struct serio *serio);
void __serio_register_port(struct serio *serio);
void serio_unregister_port(struct serio *serio);
void serio_unregister_slave_port(struct serio *serio);
void serio_unregister_port_delayed(struct serio *serio);
void __serio_unregister_port(struct serio *serio);
void serio_register_device(struct serio_dev *dev);
void serio_unregister_device(struct serio_dev *dev);
......
......@@ -1470,6 +1470,7 @@ void scheduling_functions_start_here(void) { }
*/
asmlinkage void schedule(void)
{
long *switch_count;
task_t *prev, *next;
runqueue_t *rq;
prio_array_t *array;
......@@ -1516,33 +1517,26 @@ asmlinkage void schedule(void)
* if entering off of a kernel preemption go straight
* to picking the next task.
*/
if (unlikely(preempt_count() & PREEMPT_ACTIVE))
goto pick_next_task;
switch (prev->state) {
case TASK_INTERRUPTIBLE:
if (unlikely(signal_pending(prev))) {
switch_count = &prev->nivcsw;
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
switch_count = &prev->nvcsw;
if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
unlikely(signal_pending(prev))))
prev->state = TASK_RUNNING;
break;
}
default:
else
deactivate_task(prev, rq);
prev->nvcsw++;
break;
case TASK_RUNNING:
prev->nivcsw++;
}
pick_next_task:
if (unlikely(!rq->nr_running)) {
#ifdef CONFIG_SMP
load_balance(rq, 1, cpu_to_node_mask(smp_processor_id()));
if (rq->nr_running)
goto pick_next_task;
#endif
if (!rq->nr_running) {
next = rq->idle;
rq->expired_timestamp = 0;
goto switch_tasks;
}
}
array = rq->active;
if (unlikely(!array->nr_active)) {
......@@ -1588,6 +1582,7 @@ asmlinkage void schedule(void)
next->timestamp = now;
rq->nr_switches++;
rq->curr = next;
++*switch_count;
prepare_arch_switch(rq, next);
prev = context_switch(rq, prev, next);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment