Commit 361d16e2 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/disk1/davem/BK/sparcwork-2.5

into nuts.ninka.net:/disk1/davem/BK/sparc-2.5
parents e2990ed5 e241138a
...@@ -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) {
......
...@@ -17,7 +17,7 @@ config WATCHDOG ...@@ -17,7 +17,7 @@ config WATCHDOG
implementation entirely in software (which can sometimes fail to implementation entirely in software (which can sometimes fail to
reboot the machine) and a driver for hardware watchdog boards, which reboot the machine) and a driver for hardware watchdog boards, which
are more robust and can also keep track of the temperature inside are more robust and can also keep track of the temperature inside
your computer. For details, read <file:Documentation/watchdog.txt> your computer. For details, read <file:Documentation/watchdog/watchdog.txt>
in the kernel source. in the kernel source.
The watchdog is usually used together with the watchdog daemon The watchdog is usually used together with the watchdog daemon
...@@ -114,7 +114,7 @@ config PCWATCHDOG ...@@ -114,7 +114,7 @@ config PCWATCHDOG
This card simply watches your kernel to make sure it doesn't freeze, This card simply watches your kernel to make sure it doesn't freeze,
and if it does, it reboots your computer after a certain amount of and if it does, it reboots your computer after a certain amount of
time. This driver is like the WDT501 driver but for different time. This driver is like the WDT501 driver but for different
hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC hardware. Please read <file:Documentation/watchdog/pcwd-watchdog.txt>. The PC
watchdog cards can be ordered from <http://www.berkprod.com/>. watchdog cards can be ordered from <http://www.berkprod.com/>.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
......
...@@ -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);
......
...@@ -3910,7 +3910,6 @@ static void bond_free_all(void) ...@@ -3910,7 +3910,6 @@ static void bond_free_all(void)
unregister_netdevice(dev); unregister_netdevice(dev);
bond_deinit(dev); bond_deinit(dev);
free_netdev(dev);
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
...@@ -4008,6 +4007,8 @@ static int __init bond_init(struct net_device *dev) ...@@ -4008,6 +4007,8 @@ static int __init bond_init(struct net_device *dev)
bond_create_proc_info(bond); bond_create_proc_info(bond);
#endif #endif
dev->destructor = free_netdev;
list_add_tail(&bond->bond_list, &bond_dev_list); list_add_tail(&bond->bond_list, &bond_dev_list);
return 0; return 0;
......
...@@ -1092,8 +1092,12 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) ...@@ -1092,8 +1092,12 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
{ {
struct el3_private *lp = (struct el3_private *)dev->priv; struct el3_private *lp = (struct el3_private *)dev->priv;
if (netif_device_present(dev)) if (netif_device_present(dev)) {
unsigned long flags;
spin_lock_irqsave(&lp->window_lock, flags);
update_stats(dev); update_stats(dev);
spin_unlock_irqrestore(&lp->window_lock, flags);
}
return &lp->stats; return &lp->stats;
} }
...@@ -1105,7 +1109,6 @@ static void update_stats(struct net_device *dev) ...@@ -1105,7 +1109,6 @@ static void update_stats(struct net_device *dev)
{ {
struct el3_private *lp = (struct el3_private *)dev->priv; struct el3_private *lp = (struct el3_private *)dev->priv;
ioaddr_t ioaddr = dev->base_addr; ioaddr_t ioaddr = dev->base_addr;
unsigned long flags;
u8 rx, tx, up; u8 rx, tx, up;
DEBUG(2, "%s: updating the statistics.\n", dev->name); DEBUG(2, "%s: updating the statistics.\n", dev->name);
...@@ -1113,8 +1116,6 @@ static void update_stats(struct net_device *dev) ...@@ -1113,8 +1116,6 @@ static void update_stats(struct net_device *dev)
if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */ if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */
return; return;
spin_lock_irqsave(&lp->window_lock, flags);
/* Unlike the 3c509 we need not turn off stats updates while reading. */ /* Unlike the 3c509 we need not turn off stats updates while reading. */
/* Switch to the stats window, and read everything. */ /* Switch to the stats window, and read everything. */
EL3WINDOW(6); EL3WINDOW(6);
...@@ -1139,7 +1140,6 @@ static void update_stats(struct net_device *dev) ...@@ -1139,7 +1140,6 @@ static void update_stats(struct net_device *dev)
lp->stats.tx_bytes += tx + ((up & 0xf0) << 12); lp->stats.tx_bytes += tx + ((up & 0xf0) << 12);
EL3WINDOW(1); EL3WINDOW(1);
spin_unlock_irqrestore(&lp->window_lock, flags);
} }
static int el3_rx(struct net_device *dev, int worklimit) static int el3_rx(struct net_device *dev, int worklimit)
...@@ -1281,6 +1281,8 @@ static int el3_close(struct net_device *dev) ...@@ -1281,6 +1281,8 @@ static int el3_close(struct net_device *dev)
DEBUG(2, "%s: shutting down ethercard.\n", dev->name); DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
if (DEV_OK(link)) { if (DEV_OK(link)) {
unsigned long flags;
/* Turn off statistics ASAP. We update lp->stats below. */ /* Turn off statistics ASAP. We update lp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD); outw(StatsDisable, ioaddr + EL3_CMD);
...@@ -1290,8 +1292,9 @@ static int el3_close(struct net_device *dev) ...@@ -1290,8 +1292,9 @@ static int el3_close(struct net_device *dev)
/* Note: Switching to window 0 may disable the IRQ. */ /* Note: Switching to window 0 may disable the IRQ. */
EL3WINDOW(0); EL3WINDOW(0);
spin_lock_irqsave(&lp->window_lock, flags);
update_stats(dev); update_stats(dev);
spin_unlock_irqrestore(&lp->window_lock, flags);
} }
link->open--; link->open--;
......
...@@ -107,7 +107,7 @@ config TMS380TR ...@@ -107,7 +107,7 @@ config TMS380TR
config TMSPCI config TMSPCI
tristate "Generic TMS380 PCI support" tristate "Generic TMS380 PCI support"
depends on TR && TMS380TR!=n && PCI depends on TR && TMS380TR && PCI
---help--- ---help---
This tms380 module supports generic TMS380-based PCI cards. This tms380 module supports generic TMS380-based PCI cards.
...@@ -122,7 +122,7 @@ config TMSPCI ...@@ -122,7 +122,7 @@ config TMSPCI
config SKISA config SKISA
tristate "SysKonnect TR4/16 ISA support" tristate "SysKonnect TR4/16 ISA support"
depends on TR && TMS380TR!=n && ISA depends on TR && TMS380TR && ISA
help help
This tms380 module supports SysKonnect TR4/16 ISA cards. This tms380 module supports SysKonnect TR4/16 ISA cards.
...@@ -134,7 +134,7 @@ config SKISA ...@@ -134,7 +134,7 @@ config SKISA
config PROTEON config PROTEON
tristate "Proteon ISA support" tristate "Proteon ISA support"
depends on TR && TMS380TR!=n && ISA depends on TR && TMS380TR && ISA
help help
This tms380 module supports Proteon ISA cards. This tms380 module supports Proteon ISA cards.
...@@ -147,7 +147,7 @@ config PROTEON ...@@ -147,7 +147,7 @@ config PROTEON
config ABYSS config ABYSS
tristate "Madge Smart 16/4 PCI Mk2 support" tristate "Madge Smart 16/4 PCI Mk2 support"
depends on TR && TMS380TR!=n && PCI depends on TR && TMS380TR && PCI
help help
This tms380 module supports the Madge Smart 16/4 PCI Mk2 This tms380 module supports the Madge Smart 16/4 PCI Mk2
cards (51-02). cards (51-02).
...@@ -157,7 +157,7 @@ config ABYSS ...@@ -157,7 +157,7 @@ config ABYSS
config MADGEMC config MADGEMC
tristate "Madge Smart 16/4 Ringnode MicroChannel" tristate "Madge Smart 16/4 Ringnode MicroChannel"
depends on TR && TMS380TR!=n && MCA depends on TR && TMS380TR && MCA
help help
This tms380 module supports the Madge Smart 16/4 MC16 and MC32 This tms380 module supports the Madge Smart 16/4 MC16 and MC32
MicroChannel adapters. MicroChannel adapters.
......
...@@ -85,8 +85,8 @@ static const int multicast_filter_limit = 32; ...@@ -85,8 +85,8 @@ static const int multicast_filter_limit = 32;
#define PKT_BUF_SZ 1536 #define PKT_BUF_SZ 1536
#define DRV_MODULE_NAME "typhoon" #define DRV_MODULE_NAME "typhoon"
#define DRV_MODULE_VERSION "1.5.1" #define DRV_MODULE_VERSION "1.5.2"
#define DRV_MODULE_RELDATE "03/06/26" #define DRV_MODULE_RELDATE "03/11/25"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define ERR_PFX KERN_ERR PFX #define ERR_PFX KERN_ERR PFX
...@@ -127,7 +127,7 @@ static const int multicast_filter_limit = 32; ...@@ -127,7 +127,7 @@ static const int multicast_filter_limit = 32;
static char version[] __devinitdata = static char version[] __devinitdata =
"typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David Dillow <dillowd@y12.doe.gov>"); MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)"); MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(rx_copybreak, "i");
...@@ -146,11 +146,12 @@ struct typhoon_card_info { ...@@ -146,11 +146,12 @@ struct typhoon_card_info {
int capabilities; int capabilities;
}; };
#define TYPHOON_CRYPTO_NONE 0 #define TYPHOON_CRYPTO_NONE 0x00
#define TYPHOON_CRYPTO_DES 1 #define TYPHOON_CRYPTO_DES 0x01
#define TYPHOON_CRYPTO_3DES 2 #define TYPHOON_CRYPTO_3DES 0x02
#define TYPHOON_CRYPTO_VARIABLE 4 #define TYPHOON_CRYPTO_VARIABLE 0x04
#define TYPHOON_FIBER 8 #define TYPHOON_FIBER 0x08
#define TYPHOON_WAKEUP_NEEDS_RESET 0x10
enum typhoon_cards { enum typhoon_cards {
TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR, TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR,
...@@ -307,7 +308,8 @@ enum state_values { ...@@ -307,7 +308,8 @@ enum state_values {
/* We'll wait up to six seconds for a reset, and half a second normally. /* We'll wait up to six seconds for a reset, and half a second normally.
*/ */
#define TYPHOON_UDELAY 50 #define TYPHOON_UDELAY 50
#define TYPHOON_RESET_TIMEOUT (6 * HZ) #define TYPHOON_RESET_TIMEOUT_SLEEP (6 * HZ)
#define TYPHOON_RESET_TIMEOUT_NOSLEEP ((6 * 1000000) / TYPHOON_UDELAY)
#define TYPHOON_WAIT_TIMEOUT ((1000000 / 2) / TYPHOON_UDELAY) #define TYPHOON_WAIT_TIMEOUT ((1000000 / 2) / TYPHOON_UDELAY)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
...@@ -375,10 +377,12 @@ static int ...@@ -375,10 +377,12 @@ static int
typhoon_reset(unsigned long ioaddr, int wait_type) typhoon_reset(unsigned long ioaddr, int wait_type)
{ {
int i, err = 0; int i, err = 0;
int timeout = TYPHOON_RESET_TIMEOUT; int timeout;
if(wait_type == WaitNoSleep) if(wait_type == WaitNoSleep)
timeout = (timeout * 1000000) / (HZ * TYPHOON_UDELAY); timeout = TYPHOON_RESET_TIMEOUT_NOSLEEP;
else
timeout = TYPHOON_RESET_TIMEOUT_SLEEP;
writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK); writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS); writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
...@@ -1858,6 +1862,11 @@ typhoon_sleep(struct typhoon *tp, int state, u16 events) ...@@ -1858,6 +1862,11 @@ typhoon_sleep(struct typhoon *tp, int state, u16 events)
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_SLEEPING) < 0) if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_SLEEPING) < 0)
return -ETIMEDOUT; return -ETIMEDOUT;
/* Since we cannot monitor the status of the link while sleeping,
* tell the world it went away.
*/
netif_carrier_off(tp->dev);
pci_enable_wake(tp->pdev, state, 1); pci_enable_wake(tp->pdev, state, 1);
pci_disable_device(pdev); pci_disable_device(pdev);
return pci_set_power_state(pdev, state); return pci_set_power_state(pdev, state);
...@@ -1872,8 +1881,13 @@ typhoon_wakeup(struct typhoon *tp, int wait_type) ...@@ -1872,8 +1881,13 @@ typhoon_wakeup(struct typhoon *tp, int wait_type)
pci_set_power_state(pdev, 0); pci_set_power_state(pdev, 0);
pci_restore_state(pdev, tp->pci_state); pci_restore_state(pdev, tp->pci_state);
/* Post 2.x.x versions of the Sleep Image require a reset before
* we can download the Runtime Image. But let's not make users of
* the old firmware pay for the reset.
*/
writel(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND); writel(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 ||
(tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET))
return typhoon_reset(ioaddr, wait_type); return typhoon_reset(ioaddr, wait_type);
return 0; return 0;
...@@ -2251,7 +2265,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2251,7 +2265,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
void *shared; void *shared;
dma_addr_t shared_dma; dma_addr_t shared_dma;
struct cmd_desc xp_cmd; struct cmd_desc xp_cmd;
struct resp_desc xp_resp; struct resp_desc xp_resp[3];
int i; int i;
int err = 0; int err = 0;
...@@ -2380,15 +2394,15 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2380,15 +2394,15 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS); INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS);
if(typhoon_issue_command(tp, 1, &xp_cmd, 1, &xp_resp) < 0) { if(typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp) < 0) {
printk(ERR_PFX "%s: cannot read MAC address\n", printk(ERR_PFX "%s: cannot read MAC address\n",
pci_name(pdev)); pci_name(pdev));
err = -EIO; err = -EIO;
goto error_out_reset; goto error_out_reset;
} }
*(u16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp.parm1)); *(u16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1));
*(u32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp.parm2)); *(u32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2));
if(!is_valid_ether_addr(dev->dev_addr)) { if(!is_valid_ether_addr(dev->dev_addr)) {
printk(ERR_PFX "%s: Could not obtain valid ethernet address, " printk(ERR_PFX "%s: Could not obtain valid ethernet address, "
...@@ -2396,6 +2410,28 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2396,6 +2410,28 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_out_reset; goto error_out_reset;
} }
/* Read the Sleep Image version last, so the response is valid
* later when we print out the version reported.
*/
INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
printk(ERR_PFX "%s: Could not get Sleep Image version\n",
pdev->slot_name);
goto error_out_reset;
}
tp->capabilities = typhoon_card_info[card_id].capabilities;
tp->xcvr_select = TYPHOON_XCVR_AUTONEG;
/* Typhoon 1.0 Sleep Images return one response descriptor to the
* READ_VERSIONS command. Those versions are OK after waking up
* from sleep without needing a reset. Typhoon 1.1+ Sleep Images
* seem to need a little extra help to get started. Since we don't
* know how to nudge it along, just kick it.
*/
if(xp_resp[0].numDesc != 0)
tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET;
if(typhoon_sleep(tp, 3, 0) < 0) { if(typhoon_sleep(tp, 3, 0) < 0) {
printk(ERR_PFX "%s: cannot put adapter to sleep\n", printk(ERR_PFX "%s: cannot put adapter to sleep\n",
pci_name(pdev)); pci_name(pdev));
...@@ -2403,9 +2439,6 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2403,9 +2439,6 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_out_reset; goto error_out_reset;
} }
tp->capabilities = typhoon_card_info[card_id].capabilities;
tp->xcvr_select = TYPHOON_XCVR_AUTONEG;
/* The chip-specific entries in the device structure. */ /* The chip-specific entries in the device structure. */
dev->open = typhoon_open; dev->open = typhoon_open;
dev->hard_start_xmit = typhoon_start_tx; dev->hard_start_xmit = typhoon_start_tx;
...@@ -2442,6 +2475,32 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2442,6 +2475,32 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x\n", dev->dev_addr[i]); printk("%2.2x\n", dev->dev_addr[i]);
/* xp_resp still contains the response to the READ_VERSIONS command.
* For debugging, let the user know what version he has.
*/
if(xp_resp[0].numDesc == 0) {
/* This is the Typhoon 1.0 type Sleep Image, last 16 bits
* of version is Month/Day of build.
*/
u16 monthday = le32_to_cpu(xp_resp[0].parm2) & 0xffff;
printk(KERN_INFO "%s: Typhoon 1.0 Sleep Image built "
"%02u/%02u/2000\n", dev->name, monthday >> 8,
monthday & 0xff);
} else if(xp_resp[0].numDesc == 2) {
/* This is the Typhoon 1.1+ type Sleep Image
*/
u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2);
u8 *ver_string = (u8 *) &xp_resp[1];
ver_string[25] = 0;
printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version "
"%u.%u.%u.%u %s\n", dev->name, HIPQUAD(sleep_ver),
ver_string);
} else {
printk(KERN_WARNING "%s: Unknown Sleep Image version "
"(%u:%04x)\n", dev->name, xp_resp[0].numDesc,
le32_to_cpu(xp_resp[0].parm2));
}
return 0; return 0;
error_out_reset: error_out_reset:
......
...@@ -748,13 +748,13 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -748,13 +748,13 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
if(priv->station_state != STATION_STATE_READY) { if(priv->station_state != STATION_STATE_READY) {
priv->stats.tx_errors++; priv->stats.tx_errors++;
return 0; goto done;
} }
if (priv->card && priv->present_callback && if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) { !(*priv->present_callback)(priv->card)) {
priv->stats.tx_errors++; priv->stats.tx_errors++;
return 0; goto done;
} }
/* first ensure the timer func cannot run */ /* first ensure the timer func cannot run */
...@@ -804,6 +804,8 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -804,6 +804,8 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->irqlock, flags); spin_unlock_irqrestore(&priv->irqlock, flags);
spin_unlock_bh(&priv->timerlock); spin_unlock_bh(&priv->timerlock);
done:
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
......
...@@ -97,6 +97,7 @@ static Scsi_Host_Template piix_sht = { ...@@ -97,6 +97,7 @@ static Scsi_Host_Template piix_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
}; };
static struct ata_port_operations piix_pata_ops = { static struct ata_port_operations piix_pata_ops = {
......
...@@ -1619,7 +1619,7 @@ static void ata_dev_set_pio(struct ata_port *ap, unsigned int device) ...@@ -1619,7 +1619,7 @@ static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
static void ata_sg_clean(struct ata_queued_cmd *qc) static void ata_sg_clean(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct scatterlist *sg = qc->sg; struct scatterlist *sg = qc->sg;
int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
...@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) ...@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
if (cmd->use_sg) if (cmd->use_sg)
pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir); pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir);
else else
pci_unmap_single(ap->host_set->pdev, sg[0].dma_address, pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]),
sg[0].length, dir); sg_dma_len(&sg[0]), dir);
qc->flags &= ~ATA_QCFLAG_SG; qc->flags &= ~ATA_QCFLAG_SG;
qc->sg = NULL; qc->sg = NULL;
...@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *qc) ...@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
assert(qc->n_elem > 0); assert(qc->n_elem > 0);
for (i = 0; i < qc->n_elem; i++) { for (i = 0; i < qc->n_elem; i++) {
ap->prd[i].addr = cpu_to_le32(sg[i].dma_address); ap->prd[i].addr = cpu_to_le32(sg_dma_address(&sg[i]));
ap->prd[i].flags_len = cpu_to_le32(sg[i].length); ap->prd[i].flags_len = cpu_to_le32(sg_dma_len(&sg[i]));
VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", VPRINTK("PRD[%u] = (0x%X, 0x%X)\n",
i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len)); i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len));
} }
...@@ -1681,7 +1681,7 @@ void ata_fill_sg(struct ata_queued_cmd *qc) ...@@ -1681,7 +1681,7 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
static int ata_sg_setup_one(struct ata_queued_cmd *qc) static int ata_sg_setup_one(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
struct scatterlist *sg = qc->sg; struct scatterlist *sg = qc->sg;
unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
...@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg->page = virt_to_page(cmd->request_buffer); sg->page = virt_to_page(cmd->request_buffer);
sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK; sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
sg->length = cmd->request_bufflen; sg_dma_len(sg) = cmd->request_bufflen;
if (!have_sg) if (!have_sg)
return 0; return 0;
sg->dma_address = pci_map_single(ap->host_set->pdev, sg_dma_address(sg) = pci_map_single(ap->host_set->pdev,
cmd->request_buffer, cmd->request_buffer,
cmd->request_bufflen, dir); cmd->request_bufflen, dir);
...@@ -1720,7 +1720,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1720,7 +1720,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
static int ata_sg_setup(struct ata_queued_cmd *qc) static int ata_sg_setup(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
struct scatterlist *sg; struct scatterlist *sg;
int n_elem; int n_elem;
unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
...@@ -1872,7 +1872,7 @@ static void ata_pio_sector(struct ata_port *ap) ...@@ -1872,7 +1872,7 @@ static void ata_pio_sector(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
struct scatterlist *sg; struct scatterlist *sg;
Scsi_Cmnd *cmd; struct scsi_cmnd *cmd;
unsigned char *buf; unsigned char *buf;
u8 status; u8 status;
...@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_port *ap) ...@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_port *ap)
qc->cursg_ofs++; qc->cursg_ofs++;
if (cmd->use_sg) if (cmd->use_sg)
if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg[qc->cursg].length) { if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
qc->cursg++; qc->cursg++;
qc->cursg_ofs = 0; qc->cursg_ofs = 0;
} }
...@@ -2092,7 +2092,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, ...@@ -2092,7 +2092,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late) void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int tag, do_clear = 0; unsigned int tag, do_clear = 0;
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
...@@ -2163,7 +2163,7 @@ static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append) ...@@ -2163,7 +2163,7 @@ static void ata_qc_push (struct ata_queued_cmd *qc, unsigned int append)
int ata_qc_issue(struct ata_queued_cmd *qc) int ata_qc_issue(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int dma = qc->flags & ATA_QCFLAG_DMA; unsigned int dma = qc->flags & ATA_QCFLAG_DMA;
ata_dev_select(ap, qc->dev->devno, 1, 0); ata_dev_select(ap, qc->dev->devno, 1, 0);
...@@ -2719,7 +2719,7 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) ...@@ -2719,7 +2719,7 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
if (do_unregister) if (do_unregister)
scsi_remove_host(sh); /* FIXME: check return val */ scsi_remove_host(sh);
ata_thread_kill(ap); /* FIXME: check return val */ ata_thread_kill(ap); /* FIXME: check return val */
...@@ -3204,7 +3204,6 @@ void ata_pci_remove_one (struct pci_dev *pdev) ...@@ -3204,7 +3204,6 @@ void ata_pci_remove_one (struct pci_dev *pdev)
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++) {
ap = host_set->ports[i]; ap = host_set->ports[i];
/* FIXME: check return val */
scsi_remove_host(ap->host); scsi_remove_host(ap->host);
} }
...@@ -3215,13 +3214,10 @@ void ata_pci_remove_one (struct pci_dev *pdev) ...@@ -3215,13 +3214,10 @@ void ata_pci_remove_one (struct pci_dev *pdev)
host_set->ports[0]->ops->host_stop(host_set); host_set->ports[0]->ops->host_stop(host_set);
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++) {
Scsi_Host_Template *sht;
ap = host_set->ports[i]; ap = host_set->ports[i];
sht = ap->host->hostt;
ata_scsi_release(ap->host); ata_scsi_release(ap->host);
scsi_host_put(ap->host); /* FIXME: check return val */ scsi_host_put(ap->host);
} }
pci_release_regions(pdev); pci_release_regions(pdev);
...@@ -3279,6 +3275,7 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits) ...@@ -3279,6 +3275,7 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
return (tmp == bits->val) ? 1 : 0; return (tmp == bits->val) ? 1 : 0;
} }
/** /**
* ata_init - * ata_init -
* *
...@@ -3304,6 +3301,7 @@ module_init(ata_init); ...@@ -3304,6 +3301,7 @@ module_init(ata_init);
*/ */
EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_device_add); EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_complete);
......
...@@ -32,10 +32,33 @@ ...@@ -32,10 +32,33 @@
#include "libata.h" #include "libata.h"
/**
* ata_std_bios_param - generic bios head/sector/cylinder calculator
* used by sd. Most BIOSes nowadays expect a XXX/255/16 (CHS)
* mapping. Some situations may arise where the disk is not
* bootable if this is not used.
*
* LOCKING:
*
* RETURNS:
*
*/
int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
geom[0] = 255;
geom[1] = 63;
geom[2] = capacity / (geom[0] * geom[1]);
return 0;
}
struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
struct ata_device *dev, struct ata_device *dev,
Scsi_Cmnd *cmd, struct scsi_cmnd *cmd,
void (*done)(Scsi_Cmnd *)) void (*done)(struct scsi_cmnd *))
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
...@@ -69,7 +92,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, ...@@ -69,7 +92,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
void ata_to_sense_error(struct ata_queued_cmd *qc) void ata_to_sense_error(struct ata_queued_cmd *qc)
{ {
Scsi_Cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
cmd->result = SAM_STAT_CHECK_CONDITION; cmd->result = SAM_STAT_CHECK_CONDITION;
...@@ -282,7 +305,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd, ...@@ -282,7 +305,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd,
*/ */
void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
unsigned int cmd_size) unsigned int cmd_size)
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
...@@ -332,7 +355,7 @@ void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, ...@@ -332,7 +355,7 @@ void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
* Length of response buffer. * Length of response buffer.
*/ */
static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out) static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
{ {
u8 *buf; u8 *buf;
unsigned int buflen; unsigned int buflen;
...@@ -363,7 +386,7 @@ static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out) ...@@ -363,7 +386,7 @@ static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out)
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*/ */
static inline void ata_scsi_rbuf_put(Scsi_Cmnd *cmd) static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd)
{ {
if (cmd->use_sg) { if (cmd->use_sg) {
struct scatterlist *sg; struct scatterlist *sg;
...@@ -394,7 +417,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, ...@@ -394,7 +417,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
{ {
u8 *rbuf; u8 *rbuf;
unsigned int buflen, rc; unsigned int buflen, rc;
Scsi_Cmnd *cmd = args->cmd; struct scsi_cmnd *cmd = args->cmd;
buflen = ata_scsi_rbuf_get(cmd, &rbuf); buflen = ata_scsi_rbuf_get(cmd, &rbuf);
rc = actor(args, rbuf, buflen); rc = actor(args, rbuf, buflen);
...@@ -817,7 +840,7 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf, ...@@ -817,7 +840,7 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*/ */
void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq) void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
{ {
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
cmd->result = SAM_STAT_CHECK_CONDITION; cmd->result = SAM_STAT_CHECK_CONDITION;
...@@ -847,7 +870,7 @@ void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq) ...@@ -847,7 +870,7 @@ void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq)
*/ */
static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev, static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
u8 *scsicmd = cmd->cmnd, status; u8 *scsicmd = cmd->cmnd, status;
...@@ -958,7 +981,7 @@ static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev, ...@@ -958,7 +981,7 @@ static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
* Zero. * Zero.
*/ */
int ata_scsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
u8 *scsicmd = cmd->cmnd; u8 *scsicmd = cmd->cmnd;
struct ata_port *ap; struct ata_port *ap;
......
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
struct ata_scsi_args { struct ata_scsi_args {
struct ata_port *ap; struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
Scsi_Cmnd *cmd; struct scsi_cmnd *cmd;
void (*done)(Scsi_Cmnd *); void (*done)(struct scsi_cmnd *);
}; };
...@@ -51,7 +51,7 @@ extern void ata_thread_wake(struct ata_port *ap, unsigned int thr_state); ...@@ -51,7 +51,7 @@ extern void ata_thread_wake(struct ata_port *ap, unsigned int thr_state);
/* libata-scsi.c */ /* libata-scsi.c */
extern void ata_to_sense_error(struct ata_queued_cmd *qc); extern void ata_to_sense_error(struct ata_queued_cmd *qc);
extern void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev, extern void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
unsigned int cmd_size); unsigned int cmd_size);
extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
...@@ -74,19 +74,19 @@ extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, ...@@ -74,19 +74,19 @@ extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen); unsigned int buflen);
extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf, extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen); unsigned int buflen);
extern void ata_scsi_badcmd(Scsi_Cmnd *cmd, extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(Scsi_Cmnd *), void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq); u8 asc, u8 ascq);
extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen)); u8 *rbuf, unsigned int buflen));
static inline void ata_bad_scsiop(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
ata_scsi_badcmd(cmd, done, 0x20, 0x00); ata_scsi_badcmd(cmd, done, 0x20, 0x00);
} }
static inline void ata_bad_cdb(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
ata_scsi_badcmd(cmd, done, 0x24, 0x00); ata_scsi_badcmd(cmd, done, 0x24, 0x00);
} }
......
This diff is collapsed.
...@@ -87,6 +87,7 @@ static Scsi_Host_Template sil_sht = { ...@@ -87,6 +87,7 @@ static Scsi_Host_Template sil_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
}; };
static struct ata_port_operations sil_ops = { static struct ata_port_operations sil_ops = {
......
...@@ -219,6 +219,7 @@ static Scsi_Host_Template k2_sata_sht = { ...@@ -219,6 +219,7 @@ static Scsi_Host_Template k2_sata_sht = {
#ifdef CONFIG_ALL_PPC #ifdef CONFIG_ALL_PPC
.proc_info = k2_sata_proc_info .proc_info = k2_sata_proc_info
#endif #endif
.bios_param = ata_std_bios_param,
}; };
......
...@@ -78,6 +78,7 @@ static Scsi_Host_Template svia_sht = { ...@@ -78,6 +78,7 @@ static Scsi_Host_Template svia_sht = {
.proc_name = DRV_NAME, .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config, .slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
}; };
static struct ata_port_operations svia_sata_ops = { static struct ata_port_operations svia_sata_ops = {
......
...@@ -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.
*/ */
......
...@@ -1354,6 +1354,9 @@ void hid_init_reports(struct hid_device *hid) ...@@ -1354,6 +1354,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_A4TECH 0x09DA #define USB_VENDOR_ID_A4TECH 0x09DA
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
struct hid_blacklist { struct hid_blacklist {
__u16 idVendor; __u16 idVendor;
__u16 idProduct; __u16 idProduct;
...@@ -1403,6 +1406,7 @@ struct hid_blacklist { ...@@ -1403,6 +1406,7 @@ struct hid_blacklist {
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK }, { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK },
{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
{ 0, 0 } { 0, 0 }
}; };
......
...@@ -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. */
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/ata.h> #include <linux/ata.h>
/* /*
* compile-time options * compile-time options
*/ */
...@@ -66,8 +67,6 @@ ...@@ -66,8 +67,6 @@
/* defines only for the constants which don't work well as enums */ /* defines only for the constants which don't work well as enums */
#define ATA_TAG_POISON 0xfafbfcfdU #define ATA_TAG_POISON 0xfafbfcfdU
#define ATA_DMA_BOUNDARY 0xffffUL
#define ATA_DMA_MASK 0xffffffffULL
enum { enum {
/* various global constants */ /* various global constants */
...@@ -171,6 +170,7 @@ enum { ...@@ -171,6 +170,7 @@ enum {
}; };
/* forward declarations */ /* forward declarations */
struct scsi_device;
struct ata_port_operations; struct ata_port_operations;
struct ata_port; struct ata_port;
struct ata_queued_cmd; struct ata_queued_cmd;
...@@ -247,8 +247,8 @@ struct ata_queued_cmd { ...@@ -247,8 +247,8 @@ struct ata_queued_cmd {
struct ata_port *ap; struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
Scsi_Cmnd *scsicmd; struct scsi_cmnd *scsicmd;
void (*scsidone)(Scsi_Cmnd *); void (*scsidone)(struct scsi_cmnd *);
struct list_head node; struct list_head node;
unsigned long flags; /* ATA_QCFLAG_xxx */ unsigned long flags; /* ATA_QCFLAG_xxx */
...@@ -403,7 +403,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i ...@@ -403,7 +403,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
extern void ata_pci_remove_one (struct pci_dev *pdev); extern void ata_pci_remove_one (struct pci_dev *pdev);
extern int ata_device_add(struct ata_probe_ent *ent); extern int ata_device_add(struct ata_probe_ent *ent);
extern int ata_scsi_detect(Scsi_Host_Template *sht); extern int ata_scsi_detect(Scsi_Host_Template *sht);
extern int ata_scsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_error(struct Scsi_Host *host);
extern int ata_scsi_release(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host);
extern int ata_scsi_slave_config(struct scsi_device *sdev); extern int ata_scsi_slave_config(struct scsi_device *sdev);
...@@ -427,6 +427,9 @@ extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc); ...@@ -427,6 +427,9 @@ extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late); extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late);
extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eng_timeout(struct ata_port *ap);
extern int ata_std_bios_param(struct scsi_device *sdev,
struct block_device *bdev,
sector_t capacity, int geom[]);
static inline unsigned long msecs_to_jiffies(unsigned long msecs) static inline unsigned long msecs_to_jiffies(unsigned long msecs)
......
...@@ -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