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. ...@@ -790,7 +790,8 @@ running once the system is up.
before loading. before loading.
See Documentation/ramdisk.txt. 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= psmouse_resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many [HW,MOUSE] Try to reset Synaptics Touchpad after so many
......
...@@ -505,6 +505,20 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs) ...@@ -505,6 +505,20 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
return 1; 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 * request_irq - allocate an interrupt line
* @irq: Interrupt line to allocate * @irq: Interrupt line to allocate
......
...@@ -541,8 +541,10 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long ...@@ -541,8 +541,10 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long
goto survive; goto survive;
} }
if (retval != 1) if (retval != 1) {
up_read(&current->mm->mmap_sem);
break; break;
}
maddr = kmap_atomic(pg, KM_USER0); maddr = kmap_atomic(pg, KM_USER0);
memcpy(maddr + offset, from, len); memcpy(maddr + offset, from, len);
......
...@@ -695,11 +695,6 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev) ...@@ -695,11 +695,6 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
return NULL; 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) static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
{ {
u8 pin; u8 pin;
...@@ -761,11 +756,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -761,11 +756,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if (!(mask & (1 << i))) if (!(mask & (1 << i)))
continue; continue;
if (pirq_penalty[i] < pirq_penalty[newirq] && if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, SA_SHIRQ))
!request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
free_irq(i, dev);
newirq = i; newirq = i;
}
} }
} }
DBG(" -> newirq=%d", newirq); DBG(" -> newirq=%d", newirq);
......
...@@ -2460,7 +2460,7 @@ static int __end_that_request_first(struct request *req, int uptodate, ...@@ -2460,7 +2460,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
if (!uptodate) { if (!uptodate) {
error = -EIO; 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", printk("end_request: I/O error, dev %s, sector %llu\n",
req->rq_disk ? req->rq_disk->disk_name : "?", req->rq_disk ? req->rq_disk->disk_name : "?",
(unsigned long long)req->sector); (unsigned long long)req->sector);
......
...@@ -941,16 +941,16 @@ static unsigned short x86_keycodes[256] = ...@@ -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, 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, 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, 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, 80, 81, 82, 83, 84, 93, 86, 87, 88, 94, 95, 85,259,375,260, 90,
284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339, 284,285,309,311,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, 367,288,302,304,350, 89,334,326,116,377,109,111,126,347,348,349,
360, 93, 94, 95, 98,376,100,101,321,316,354,286,289,102,351,355, 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, 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, 291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269, 264,117,271,374,379,115,125,273,121,123, 92,265,266,267,268,269,
271,273,276,277,278,282,283,295,296,297,299,300,301,293,303,307, 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,326,330, 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,113,341,368,369,370,371,372 }; 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
#ifdef CONFIG_MAC_EMUMOUSEBTN #ifdef CONFIG_MAC_EMUMOUSEBTN
extern int mac_hid_mouse_emulate_buttons(int, int, int); 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, ...@@ -972,11 +972,18 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
if (keycode > 255 || !x86_keycodes[keycode]) if (keycode > 255 || !x86_keycodes[keycode])
return -1; return -1;
if (keycode == KEY_PAUSE) { switch (keycode) {
put_queue(vc, 0xe1); case KEY_PAUSE:
put_queue(vc, 0x1d | up_flag); put_queue(vc, 0xe1);
put_queue(vc, 0x45 | up_flag); put_queue(vc, 0x1d | up_flag);
return 0; 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) { if (keycode == KEY_SYSRQ && sysrq_alt) {
......
...@@ -447,9 +447,10 @@ void input_register_device(struct input_dev *dev) ...@@ -447,9 +447,10 @@ void input_register_device(struct input_dev *dev)
list_add_tail(&dev->node, &input_dev_list); list_add_tail(&dev->node, &input_dev_list);
list_for_each_entry(handler, &input_handler_list, node) list_for_each_entry(handler, &input_handler_list, node)
if ((id = input_match_device(handler->id_table, dev))) if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((handle = handler->connect(handler, dev, id))) if ((id = input_match_device(handler->id_table, dev)))
input_link_handle(handle); if ((handle = handler->connect(handler, dev, id)))
input_link_handle(handle);
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
input_call_hotplug("add", dev); input_call_hotplug("add", dev);
...@@ -507,9 +508,10 @@ void input_register_handler(struct input_handler *handler) ...@@ -507,9 +508,10 @@ void input_register_handler(struct input_handler *handler)
list_add_tail(&handler->node, &input_handler_list); list_add_tail(&handler->node, &input_handler_list);
list_for_each_entry(dev, &input_dev_list, node) list_for_each_entry(dev, &input_dev_list, node)
if ((id = input_match_device(handler->id_table, dev))) if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((handle = handler->connect(handler, dev, id))) if ((id = input_match_device(handler->id_table, dev)))
input_link_handle(handle); if ((handle = handler->connect(handler, dev, id)))
input_link_handle(handle);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
input_devices_state++; input_devices_state++;
......
...@@ -380,10 +380,6 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct ...@@ -380,10 +380,6 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
struct joydev *joydev; struct joydev *joydev;
int i, j, t, minor; 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++); for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
if (minor == JOYDEV_MINORS) { if (minor == JOYDEV_MINORS) {
printk(KERN_ERR "joydev: no more free joydev devices\n"); printk(KERN_ERR "joydev: no more free joydev devices\n");
...@@ -464,6 +460,15 @@ static void joydev_disconnect(struct input_handle *handle) ...@@ -464,6 +460,15 @@ static void joydev_disconnect(struct input_handle *handle)
joydev_free(joydev); 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[] = { static struct input_device_id joydev_ids[] = {
{ {
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
...@@ -493,6 +498,7 @@ static struct input_handler joydev_handler = { ...@@ -493,6 +498,7 @@ static struct input_handler joydev_handler = {
.minor = JOYDEV_MINOR_BASE, .minor = JOYDEV_MINOR_BASE,
.name = "joydev", .name = "joydev",
.id_table = joydev_ids, .id_table = joydev_ids,
.blacklist = joydev_blacklist,
}; };
static int __init joydev_init(void) static int __init joydev_init(void)
......
This diff is collapsed.
...@@ -23,27 +23,18 @@ config MOUSE_PS2 ...@@ -23,27 +23,18 @@ config MOUSE_PS2
mice with wheels and extra buttons, Microsoft, Logitech or Genius mice with wheels and extra buttons, Microsoft, Logitech or Genius
compatible. 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. If unsure, say Y.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called psmouse. 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 config MOUSE_SERIAL
tristate "Serial mouse" tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE depends on INPUT && INPUT_MOUSE
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/input.h> #include <linux/input.h>
#include <linux/serio.h>
#include "psmouse.h" #include "psmouse.h"
#include "logips2pp.h" #include "logips2pp.h"
...@@ -142,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *psmouse) ...@@ -142,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *psmouse)
* touchpad. * touchpad.
*/ */
int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param) static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
{ {
int i; int i;
static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 }; 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) ...@@ -226,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
return 0; 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 @@ ...@@ -13,5 +13,5 @@
struct psmouse; struct psmouse;
void ps2pp_process_packet(struct psmouse *psmouse); void ps2pp_process_packet(struct psmouse *psmouse);
void ps2pp_set_800dpi(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 #endif
This diff is collapsed.
...@@ -22,10 +22,20 @@ ...@@ -22,10 +22,20 @@
#define PSMOUSE_ACTIVATED 1 #define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2 #define PSMOUSE_IGNORE 2
struct psmouse;
struct psmouse_ptport {
struct serio serio;
void (*activate)(struct psmouse *parent);
void (*deactivate)(struct psmouse *parent);
};
struct psmouse { struct psmouse {
void *private; void *private;
struct input_dev dev; struct input_dev dev;
struct serio *serio; struct serio *serio;
struct psmouse_ptport *ptport;
char *vendor; char *vendor;
char *name; char *name;
unsigned char cmdbuf[8]; unsigned char cmdbuf[8];
...@@ -41,6 +51,9 @@ struct psmouse { ...@@ -41,6 +51,9 @@ struct psmouse {
char error; char error;
char devname[64]; char devname[64];
char phys[32]; char phys[32];
int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse);
}; };
#define PSMOUSE_PS2 1 #define PSMOUSE_PS2 1
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
* Synaptics TouchPad PS/2 mouse driver * Synaptics TouchPad PS/2 mouse driver
* *
* 2003 Dmitry Torokhov <dtor@mail.ru> * 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> * 2003 Peter Osterlund <petero2@telia.com>
* Ported to 2.5 input device infrastructure. * Ported to 2.5 input device infrastructure.
...@@ -194,9 +195,7 @@ static void print_ident(struct synaptics_data *priv) ...@@ -194,9 +195,7 @@ static void print_ident(struct synaptics_data *priv)
static int synaptics_query_hardware(struct psmouse *psmouse) static int synaptics_query_hardware(struct psmouse *psmouse)
{ {
struct synaptics_data *priv = psmouse->private;
int retries = 0; int retries = 0;
int mode;
while ((retries++ < 3) && synaptics_reset(psmouse)) while ((retries++ < 3) && synaptics_reset(psmouse))
printk(KERN_ERR "synaptics reset failed\n"); printk(KERN_ERR "synaptics reset failed\n");
...@@ -208,7 +207,14 @@ static int synaptics_query_hardware(struct psmouse *psmouse) ...@@ -208,7 +207,14 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
if (synaptics_capability(psmouse)) if (synaptics_capability(psmouse))
return -1; 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) if (SYN_ID_MAJOR(priv->identity) >= 4)
mode |= SYN_BIT_DISABLE_GESTURE; mode |= SYN_BIT_DISABLE_GESTURE;
if (SYN_CAP_EXTENDED(priv->capabilities)) if (SYN_CAP_EXTENDED(priv->capabilities))
...@@ -265,49 +271,38 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet ...@@ -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 psmouse *child = psmouse->ptport->serio.private;
struct serio *port;
struct psmouse *child;
if (psmouse->type != PSMOUSE_SYNAPTICS) /* adjust the touchpad to child's choice of protocol */
return -1; if (child && child->type >= PSMOUSE_GENPS) {
if (!SYN_CAP_EXTENDED(priv->capabilities)) if (synaptics_set_mode(psmouse, SYN_BIT_FOUR_BYTE_CLIENT))
return -1; printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
if (!SYN_CAP_PASS_THROUGH(priv->capabilities)) }
return -1; }
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) { if (!port) {
printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n"); printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
return -1; return;
} }
memset(port, 0, sizeof(struct serio)); memset(port, 0, sizeof(struct psmouse_ptport));
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;
printk(KERN_INFO "serio: %s port at %s\n", port->name, psmouse->phys); port->serio.type = SERIO_PS_PSTHRU;
serio_register_slave_port(port); 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 */ port->activate = synaptics_pt_activate;
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;
} }
/***************************************************************************** /*****************************************************************************
...@@ -371,27 +366,82 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) ...@@ -371,27 +366,82 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit(REL_Y, dev->relbit); clear_bit(REL_Y, dev->relbit);
} }
static void synaptics_disconnect(struct psmouse *psmouse)
{
synaptics_mode_cmd(psmouse, 0);
kfree(psmouse->private);
}
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;
}
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) int synaptics_init(struct psmouse *psmouse)
{ {
struct synaptics_data *priv; struct synaptics_data *priv;
#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
return -1;
#endif
psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL); psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
if (!priv) if (!priv)
return -1; return -1;
memset(priv, 0, sizeof(struct synaptics_data)); memset(priv, 0, sizeof(struct synaptics_data));
if (synaptics_query_hardware(psmouse)) { 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; goto init_fail;
} }
if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities))
synaptics_pt_create(psmouse);
print_ident(priv); print_ident(priv);
set_input_params(&psmouse->dev, priv); set_input_params(&psmouse->dev, priv);
psmouse->disconnect = synaptics_disconnect;
psmouse->reconnect = synaptics_reconnect;
return 0; return 0;
init_fail: init_fail:
...@@ -399,36 +449,13 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -399,36 +449,13 @@ int synaptics_init(struct psmouse *psmouse)
return -1; 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 * 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) static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
{ {
hw->up = 0; memset(hw, 0, sizeof(struct synaptics_hw_state));
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;
if (SYN_MODEL_NEWABS(priv->model_id)) { if (SYN_MODEL_NEWABS(priv->model_id)) {
hw->x = (((buf[3] & 0x10) << 8) | hw->x = (((buf[3] & 0x10) << 8) |
...@@ -570,64 +597,47 @@ static void synaptics_process_packet(struct psmouse *psmouse) ...@@ -570,64 +597,47 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_sync(dev); 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) void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{ {
struct input_dev *dev = &psmouse->dev; struct input_dev *dev = &psmouse->dev;
struct synaptics_data *priv = psmouse->private; 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); input_regs(dev, regs);
switch (psmouse->pktcnt) { if (psmouse->pktcnt >= 6) { /* Full packet received */
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 (priv->out_of_sync) { if (priv->out_of_sync) {
priv->out_of_sync = 0; priv->out_of_sync = 0;
printk(KERN_NOTICE "Synaptics driver resynced.\n"); printk(KERN_NOTICE "Synaptics driver resynced.\n");
} }
if (priv->ptport && synaptics_is_pt_packet(psmouse->packet)) if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
synaptics_pass_pt_packet(priv->ptport, psmouse->packet); synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
else else
synaptics_process_packet(psmouse); synaptics_process_packet(psmouse);
psmouse->pktcnt = 0;
} else if (psmouse->pktcnt && !synaptics_validate_byte(psmouse)) {
printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt);
psmouse->pktcnt = 0; psmouse->pktcnt = 0;
break; if (++priv->out_of_sync == psmouse_resetafter) {
} psmouse->state = PSMOUSE_IGNORE;
return; printk(KERN_NOTICE "synaptics: issuing reconnect request\n");
serio_reconnect(psmouse->serio);
bad_sync: }
priv->out_of_sync++;
psmouse->pktcnt = 0;
if (psmouse_resetafter > 0 && priv->out_of_sync == psmouse_resetafter) {
psmouse->state = PSMOUSE_IGNORE;
serio_rescan(psmouse->serio);
} }
} }
...@@ -9,11 +9,9 @@ ...@@ -9,11 +9,9 @@
#ifndef _SYNAPTICS_H #ifndef _SYNAPTICS_H
#define _SYNAPTICS_H #define _SYNAPTICS_H
extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs); 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_init(struct psmouse *psmouse);
extern int synaptics_pt_init(struct psmouse *psmouse);
extern void synaptics_disconnect(struct psmouse *psmouse);
/* synaptics queries */ /* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00 #define SYN_QUE_IDENTIFY 0x00
...@@ -105,8 +103,6 @@ struct synaptics_data { ...@@ -105,8 +103,6 @@ struct synaptics_data {
/* Data for normal processing */ /* Data for normal processing */
unsigned int out_of_sync; /* # of packets out of sync */ unsigned int out_of_sync; /* # of packets out of sync */
int old_w; /* Previous w value */ int old_w; /* Previous w value */
struct serio *ptport; /* pass-through port */
}; };
#endif /* _SYNAPTICS_H */ #endif /* _SYNAPTICS_H */
This diff is collapsed.
...@@ -49,14 +49,17 @@ MODULE_LICENSE("GPL"); ...@@ -49,14 +49,17 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(serio_register_port); 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_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_register_device);
EXPORT_SYMBOL(serio_unregister_device); EXPORT_SYMBOL(serio_unregister_device);
EXPORT_SYMBOL(serio_open); EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close); EXPORT_SYMBOL(serio_close);
EXPORT_SYMBOL(serio_rescan); EXPORT_SYMBOL(serio_rescan);
EXPORT_SYMBOL(serio_reconnect);
struct serio_event { struct serio_event {
int type; int type;
...@@ -82,11 +85,23 @@ static void serio_find_dev(struct serio *serio) ...@@ -82,11 +85,23 @@ static void serio_find_dev(struct serio *serio)
} }
} }
#define SERIO_RESCAN 1 #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_WAIT_QUEUE_HEAD(serio_wait);
static DECLARE_COMPLETION(serio_exited); 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) void serio_handle_events(void)
{ {
struct list_head *node, *next; struct list_head *node, *next;
...@@ -95,17 +110,35 @@ void serio_handle_events(void) ...@@ -95,17 +110,35 @@ void serio_handle_events(void)
list_for_each_safe(node, next, &serio_event_list) { list_for_each_safe(node, next, &serio_event_list) {
event = container_of(node, struct serio_event, node); event = container_of(node, struct serio_event, node);
down(&serio_sem);
if (event->serio == NULL)
goto event_done;
switch (event->type) { 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 : case SERIO_RESCAN :
down(&serio_sem);
if (event->serio->dev && event->serio->dev->disconnect) if (event->serio->dev && event->serio->dev->disconnect)
event->serio->dev->disconnect(event->serio); event->serio->dev->disconnect(event->serio);
serio_find_dev(event->serio); serio_find_dev(event->serio);
up(&serio_sem);
break; break;
default: default:
break; break;
} }
event_done:
up(&serio_sem);
list_del_init(node); list_del_init(node);
kfree(event); kfree(event);
} }
...@@ -130,18 +163,27 @@ static int serio_thread(void *nothing) ...@@ -130,18 +163,27 @@ static int serio_thread(void *nothing)
complete_and_exit(&serio_exited, 0); 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; struct serio_event *event;
if (!(event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
return; event->type = event_type;
event->serio = serio;
list_add_tail(&event->node, &serio_event_list);
wake_up(&serio_wait);
}
}
event->type = SERIO_RESCAN; void serio_rescan(struct serio *serio)
event->serio = serio; {
serio_queue_event(serio, SERIO_RESCAN);
}
list_add_tail(&event->node, &serio_event_list); void serio_reconnect(struct serio *serio)
wake_up(&serio_wait); {
serio_queue_event(serio, SERIO_RECONNECT);
} }
irqreturn_t serio_interrupt(struct serio *serio, irqreturn_t serio_interrupt(struct serio *serio,
...@@ -163,17 +205,26 @@ 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) void serio_register_port(struct serio *serio)
{ {
down(&serio_sem); down(&serio_sem);
list_add_tail(&serio->node, &serio_list); __serio_register_port(serio);
serio_find_dev(serio);
up(&serio_sem); up(&serio_sem);
} }
/* /*
* Same as serio_register_port but does not try to acquire serio_sem. * Submits register request to kseriod for subsequent execution.
* Should be used when registering a serio from other input device's * 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. * connect() function.
*/ */
void serio_register_slave_port(struct serio *serio) void __serio_register_port(struct serio *serio)
{ {
list_add_tail(&serio->node, &serio_list); list_add_tail(&serio->node, &serio_list);
serio_find_dev(serio); serio_find_dev(serio);
...@@ -182,19 +233,28 @@ void serio_register_slave_port(struct serio *serio) ...@@ -182,19 +233,28 @@ void serio_register_slave_port(struct serio *serio)
void serio_unregister_port(struct serio *serio) void serio_unregister_port(struct serio *serio)
{ {
down(&serio_sem); down(&serio_sem);
list_del_init(&serio->node); __serio_unregister_port(serio);
if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio);
up(&serio_sem); up(&serio_sem);
} }
/* /*
* Same as serio_unregister_port but does not try to acquire serio_sem. * Submits unregister request to kseriod for subsequent execution.
* Should be used when unregistering a serio from other input device's * 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. * 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); list_del_init(&serio->node);
if (serio->dev && serio->dev->disconnect) if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio); serio->dev->disconnect(serio);
......
...@@ -2182,6 +2182,9 @@ static int uhci_reset(struct usb_hcd *hcd) ...@@ -2182,6 +2182,9 @@ static int uhci_reset(struct usb_hcd *hcd)
uhci->io_addr = (unsigned long) hcd->regs; 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 /* Maybe kick BIOS off this hardware. Then reset, so we won't get
* interrupts from any previous setup. * interrupts from any previous setup.
*/ */
......
...@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int); ...@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int); extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int); extern void enable_irq(unsigned int);
extern void release_x86_irqs(struct task_struct *); extern void release_x86_irqs(struct task_struct *);
extern int can_request_irq(unsigned int, unsigned long flags);
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
......
...@@ -870,6 +870,7 @@ struct input_handler { ...@@ -870,6 +870,7 @@ struct input_handler {
char *name; char *name;
struct input_device_id *id_table; struct input_device_id *id_table;
struct input_device_id *blacklist;
struct list_head h_list; struct list_head h_list;
struct list_head node; struct list_head node;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#define __LINUX_KEYBOARD_H #define __LINUX_KEYBOARD_H
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/input.h>
#define KG_SHIFT 0 #define KG_SHIFT 0
#define KG_CTRL 2 #define KG_CTRL 2
...@@ -17,7 +16,7 @@ ...@@ -17,7 +16,7 @@
#define NR_SHIFT 9 #define NR_SHIFT 9
#define NR_KEYS (KEY_MAX+1) #define NR_KEYS 255
#define MAX_NR_KEYMAPS 256 #define MAX_NR_KEYMAPS 256
/* This means 128Kb if all keymaps are allocated. Only the superuser /* This means 128Kb if all keymaps are allocated. Only the superuser
may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */ may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
......
...@@ -49,6 +49,7 @@ struct serio_dev { ...@@ -49,6 +49,7 @@ struct serio_dev {
irqreturn_t (*interrupt)(struct serio *, unsigned char, irqreturn_t (*interrupt)(struct serio *, unsigned char,
unsigned int, struct pt_regs *); unsigned int, struct pt_regs *);
void (*connect)(struct serio *, struct serio_dev *dev); void (*connect)(struct serio *, struct serio_dev *dev);
int (*reconnect)(struct serio *);
void (*disconnect)(struct serio *); void (*disconnect)(struct serio *);
void (*cleanup)(struct serio *); void (*cleanup)(struct serio *);
...@@ -58,12 +59,15 @@ struct serio_dev { ...@@ -58,12 +59,15 @@ struct serio_dev {
int serio_open(struct serio *serio, struct serio_dev *dev); int serio_open(struct serio *serio, struct serio_dev *dev);
void serio_close(struct serio *serio); void serio_close(struct serio *serio);
void serio_rescan(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); 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_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_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_register_device(struct serio_dev *dev);
void serio_unregister_device(struct serio_dev *dev); void serio_unregister_device(struct serio_dev *dev);
......
...@@ -1470,6 +1470,7 @@ void scheduling_functions_start_here(void) { } ...@@ -1470,6 +1470,7 @@ void scheduling_functions_start_here(void) { }
*/ */
asmlinkage void schedule(void) asmlinkage void schedule(void)
{ {
long *switch_count;
task_t *prev, *next; task_t *prev, *next;
runqueue_t *rq; runqueue_t *rq;
prio_array_t *array; prio_array_t *array;
...@@ -1516,32 +1517,25 @@ asmlinkage void schedule(void) ...@@ -1516,32 +1517,25 @@ asmlinkage void schedule(void)
* if entering off of a kernel preemption go straight * if entering off of a kernel preemption go straight
* to picking the next task. * to picking the next task.
*/ */
if (unlikely(preempt_count() & PREEMPT_ACTIVE)) switch_count = &prev->nivcsw;
goto pick_next_task; if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
switch_count = &prev->nvcsw;
switch (prev->state) { if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
case TASK_INTERRUPTIBLE: unlikely(signal_pending(prev))))
if (unlikely(signal_pending(prev))) {
prev->state = TASK_RUNNING; prev->state = TASK_RUNNING;
break; else
} deactivate_task(prev, rq);
default:
deactivate_task(prev, rq);
prev->nvcsw++;
break;
case TASK_RUNNING:
prev->nivcsw++;
} }
pick_next_task:
if (unlikely(!rq->nr_running)) { if (unlikely(!rq->nr_running)) {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
load_balance(rq, 1, cpu_to_node_mask(smp_processor_id())); load_balance(rq, 1, cpu_to_node_mask(smp_processor_id()));
if (rq->nr_running)
goto pick_next_task;
#endif #endif
next = rq->idle; if (!rq->nr_running) {
rq->expired_timestamp = 0; next = rq->idle;
goto switch_tasks; rq->expired_timestamp = 0;
goto switch_tasks;
}
} }
array = rq->active; array = rq->active;
...@@ -1588,6 +1582,7 @@ asmlinkage void schedule(void) ...@@ -1588,6 +1582,7 @@ asmlinkage void schedule(void)
next->timestamp = now; next->timestamp = now;
rq->nr_switches++; rq->nr_switches++;
rq->curr = next; rq->curr = next;
++*switch_count;
prepare_arch_switch(rq, next); prepare_arch_switch(rq, next);
prev = context_switch(rq, prev, 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