aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/char/keyboard.c139
-rw-r--r--drivers/input/evdev.c10
-rw-r--r--drivers/input/gameport/fm801-gp.c4
-rw-r--r--drivers/input/gameport/gameport.c66
-rw-r--r--drivers/input/input.c57
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c19
-rw-r--r--drivers/input/joystick/spaceball.c2
-rw-r--r--drivers/input/keyboard/atkbd.c103
-rw-r--r--drivers/input/misc/wistron_btns.c20
-rw-r--r--drivers/input/mouse/logips2pp.c3
-rw-r--r--drivers/input/mouse/trackpoint.c52
-rw-r--r--drivers/input/serio/libps2.c5
-rw-r--r--drivers/input/serio/serio.c65
-rw-r--r--drivers/usb/input/ati_remote.c173
-rw-r--r--drivers/usb/input/hid-input.c3
-rw-r--r--drivers/usb/input/hiddev.c72
-rw-r--r--fs/jfs/inode.c16
-rw-r--r--fs/jfs/jfs_inode.h1
-rw-r--r--fs/jfs/super.c118
-rw-r--r--include/linux/input.h24
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-toonie.c17
-rw-r--r--sound/aoa/core/snd-aoa-gpio-feature.c7
-rw-r--r--sound/aoa/core/snd-aoa-gpio-pmf.c2
-rw-r--r--sound/core/oss/mixer_oss.c3
-rw-r--r--sound/core/oss/pcm_oss.c2
-rw-r--r--sound/core/seq/seq_device.c3
-rw-r--r--sound/core/sgbuf.c9
-rw-r--r--sound/drivers/vx/vx_pcm.c7
-rw-r--r--sound/pci/echoaudio/echoaudio.c4
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c11
-rw-r--r--sound/pci/emu10k1/irq.c6
-rw-r--r--sound/ppc/awacs.c3
-rw-r--r--sound/ppc/daca.c3
-rw-r--r--sound/ppc/keywest.c3
-rw-r--r--sound/ppc/powermac.c13
-rw-r--r--sound/ppc/tumbler.c3
-rw-r--r--sound/usb/usbaudio.c6
38 files changed, 691 insertions, 370 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index bac3f706f75..b6c3c544df8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -298,6 +298,13 @@ L: info-linux@geode.amd.com
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
S: Supported
+AOA (Apple Onboard Audio) ALSA DRIVER
+P: Johannes Berg
+M: johannes@sipsolutions.net
+L: linuxppc-dev@ozlabs.org
+L: alsa-devel@alsa-project.org
+S: Maintained
+
APM DRIVER
P: Stephen Rothwell
M: sfr@canb.auug.org.au
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 056ebe84b81..3e90aac3751 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -107,7 +107,6 @@ const int NR_TYPES = ARRAY_SIZE(max_vals);
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
static struct kbd_struct *kbd = kbd_table;
-static struct kbd_struct kbd0;
int spawnpid, spawnsig;
@@ -223,13 +222,13 @@ static void kd_nosound(unsigned long ignored)
{
struct list_head *node;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_TONE, 0);
+ input_inject_event(handle, EV_SND, SND_TONE, 0);
if (test_bit(SND_BELL, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_BELL, 0);
+ input_inject_event(handle, EV_SND, SND_BELL, 0);
}
}
}
@@ -247,11 +246,11 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit)) {
- input_event(handle->dev, EV_SND, SND_TONE, hz);
+ input_inject_event(handle, EV_SND, SND_TONE, hz);
break;
}
if (test_bit(SND_BELL, handle->dev->sndbit)) {
- input_event(handle->dev, EV_SND, SND_BELL, 1);
+ input_inject_event(handle, EV_SND, SND_BELL, 1);
break;
}
}
@@ -272,15 +271,15 @@ int kbd_rate(struct kbd_repeat *rep)
unsigned int d = 0;
unsigned int p = 0;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
struct input_dev *dev = handle->dev;
if (test_bit(EV_REP, dev->evbit)) {
if (rep->delay > 0)
- input_event(dev, EV_REP, REP_DELAY, rep->delay);
+ input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
if (rep->period > 0)
- input_event(dev, EV_REP, REP_PERIOD, rep->period);
+ input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD];
}
@@ -988,7 +987,7 @@ static inline unsigned char getleds(void)
* interrupt routines for this thing allows us to easily mask
* this when we don't want any of the above to happen.
* This allows for easy and efficient race-condition prevention
- * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ...
+ * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
*/
static void kbd_bh(unsigned long dummy)
@@ -998,11 +997,11 @@ static void kbd_bh(unsigned long dummy)
if (leds != ledstate) {
list_for_each(node, &kbd_handler.h_list) {
- struct input_handle * handle = to_handle_h(node);
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
+ struct input_handle *handle = to_handle_h(node);
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
}
}
@@ -1011,23 +1010,6 @@ static void kbd_bh(unsigned long dummy)
DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
-/*
- * This allows a newly plugged keyboard to pick the LED state.
- */
-static void kbd_refresh_leds(struct input_handle *handle)
-{
- unsigned char leds = ledstate;
-
- tasklet_disable(&keyboard_tasklet);
- if (leds != 0xff) {
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
- }
- tasklet_enable(&keyboard_tasklet);
-}
-
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
@@ -1043,7 +1025,7 @@ static const unsigned short x86_keycodes[256] =
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
- 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
+ 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
@@ -1065,38 +1047,55 @@ extern void sun_do_break(void);
static int emulate_raw(struct vc_data *vc, unsigned int keycode,
unsigned char up_flag)
{
- if (keycode > 255 || !x86_keycodes[keycode])
- return -1;
+ int code;
switch (keycode) {
case KEY_PAUSE:
put_queue(vc, 0xe1);
put_queue(vc, 0x1d | up_flag);
put_queue(vc, 0x45 | up_flag);
- return 0;
+ break;
+
case KEY_HANGEUL:
if (!up_flag)
put_queue(vc, 0xf2);
- return 0;
+ break;
+
case KEY_HANJA:
if (!up_flag)
put_queue(vc, 0xf1);
- return 0;
- }
+ break;
- if (keycode == KEY_SYSRQ && sysrq_alt) {
- put_queue(vc, 0x54 | up_flag);
- return 0;
- }
+ case KEY_SYSRQ:
+ /*
+ * Real AT keyboards (that's what we're trying
+ * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
+ * pressing PrtSc/SysRq alone, but simply 0x54
+ * when pressing Alt+PrtSc/SysRq.
+ */
+ if (sysrq_alt) {
+ put_queue(vc, 0x54 | up_flag);
+ } else {
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x2a | up_flag);
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x37 | up_flag);
+ }
+ break;
+
+ default:
+ if (keycode > 255)
+ return -1;
- if (x86_keycodes[keycode] & 0x100)
- put_queue(vc, 0xe0);
+ code = x86_keycodes[keycode];
+ if (!code)
+ return -1;
- put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag);
+ if (code & 0x100)
+ put_queue(vc, 0xe0);
+ put_queue(vc, (code & 0x7f) | up_flag);
- if (keycode == KEY_SYSRQ) {
- put_queue(vc, 0xe0);
- put_queue(vc, 0x37 | up_flag);
+ break;
}
return 0;
@@ -1298,16 +1297,15 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return NULL;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+ if (!handle)
return NULL;
- memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
handle->name = "kbd";
input_open_device(handle);
- kbd_refresh_leds(handle);
return handle;
}
@@ -1318,6 +1316,24 @@ static void kbd_disconnect(struct input_handle *handle)
kfree(handle);
}
+/*
+ * Start keyboard handler on the new keyboard by refreshing LED state to
+ * match the rest of the system.
+ */
+static void kbd_start(struct input_handle *handle)
+{
+ unsigned char leds = ledstate;
+
+ tasklet_disable(&keyboard_tasklet);
+ if (leds != 0xff) {
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
+ }
+ tasklet_enable(&keyboard_tasklet);
+}
+
static struct input_device_id kbd_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
@@ -1338,6 +1354,7 @@ static struct input_handler kbd_handler = {
.event = kbd_event,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
+ .start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
@@ -1346,15 +1363,15 @@ int __init kbd_init(void)
{
int i;
- kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
- kbd0.ledmode = LED_SHOW_FLAGS;
- kbd0.lockstate = KBD_DEFLOCK;
- kbd0.slockstate = 0;
- kbd0.modeflags = KBD_DEFMODE;
- kbd0.kbdmode = VC_XLATE;
-
- for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
- kbd_table[i] = kbd0;
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ kbd_table[i].ledflagstate = KBD_DEFLEDS;
+ kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
+ kbd_table[i].ledmode = LED_SHOW_FLAGS;
+ kbd_table[i].lockstate = KBD_DEFLOCK;
+ kbd_table[i].slockstate = 0;
+ kbd_table[i].modeflags = KBD_DEFMODE;
+ kbd_table[i].kbdmode = VC_XLATE;
+ }
input_register_handler(&kbd_handler);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a29d5ceb00c..4bf48188cc9 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -127,14 +127,10 @@ static int evdev_open(struct inode * inode, struct file * file)
{
struct evdev_list *list;
int i = iminor(inode) - EVDEV_MINOR_BASE;
- int accept_err;
if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
return -ENODEV;
- if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
- return accept_err;
-
if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
@@ -260,7 +256,7 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
if (evdev_event_from_user(buffer + retval, &event))
return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+ input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
retval += evdev_event_size();
}
@@ -428,8 +424,8 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
if (get_user(v, ip + 1))
return -EFAULT;
- input_event(dev, EV_REP, REP_DELAY, u);
- input_event(dev, EV_REP, REP_PERIOD, v);
+ input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
+ input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
return 0;
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 47e93daa0fa..90de5afe03c 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -106,10 +106,10 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
gp->gameport = port;
gp->res_port = request_region(port->io, 0x10, "FM801 GP");
if (!gp->res_port) {
- kfree(gp);
- gameport_free_port(port);
printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
port->io, port->io + 0x0f);
+ gameport_free_port(port);
+ kfree(gp);
return -EBUSY;
}
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 36644bff379..3f47ae55c6f 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -53,6 +53,7 @@ static LIST_HEAD(gameport_list);
static struct bus_type gameport_bus;
+static void gameport_add_driver(struct gameport_driver *drv);
static void gameport_add_port(struct gameport *gameport);
static void gameport_destroy_port(struct gameport *gameport);
static void gameport_reconnect_port(struct gameport *gameport);
@@ -211,8 +212,14 @@ static void gameport_release_driver(struct gameport *gameport)
static void gameport_find_driver(struct gameport *gameport)
{
+ int error;
+
down_write(&gameport_bus.subsys.rwsem);
- device_attach(&gameport->dev);
+ error = device_attach(&gameport->dev);
+ if (error < 0)
+ printk(KERN_WARNING
+ "gameport: device_attach() failed for %s (%s), error: %d\n",
+ gameport->phys, gameport->name, error);
up_write(&gameport_bus.subsys.rwsem);
}
@@ -316,7 +323,6 @@ static void gameport_remove_duplicate_events(struct gameport_event *event)
spin_unlock_irqrestore(&gameport_event_lock, flags);
}
-
static struct gameport_event *gameport_get_event(void)
{
struct gameport_event *event;
@@ -342,7 +348,6 @@ static struct gameport_event *gameport_get_event(void)
static void gameport_handle_event(void)
{
struct gameport_event *event;
- struct gameport_driver *gameport_drv;
mutex_lock(&gameport_mutex);
@@ -369,8 +374,7 @@ static void gameport_handle_event(void)
break;
case GAMEPORT_REGISTER_DRIVER:
- gameport_drv = event->object;
- driver_register(&gameport_drv->driver);
+ gameport_add_driver(event->object);
break;
default:
@@ -532,6 +536,7 @@ static void gameport_init_port(struct gameport *gameport)
if (gameport->parent)
gameport->dev.parent = &gameport->parent->dev;
+ INIT_LIST_HEAD(&gameport->node);
spin_lock_init(&gameport->timer_lock);
init_timer(&gameport->poll_timer);
gameport->poll_timer.function = gameport_run_poll_handler;
@@ -544,6 +549,8 @@ static void gameport_init_port(struct gameport *gameport)
*/
static void gameport_add_port(struct gameport *gameport)
{
+ int error;
+
if (gameport->parent)
gameport->parent->child = gameport;
@@ -558,8 +565,13 @@ static void gameport_add_port(struct gameport *gameport)
printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
gameport->name, gameport->phys, gameport->speed);
- device_add(&gameport->dev);
- gameport->registered = 1;
+ error = device_add(&gameport->dev);
+ if (error)
+ printk(KERN_ERR
+ "gameport: device_add() failed for %s (%s), error: %d\n",
+ gameport->phys, gameport->name, error);
+ else
+ gameport->registered = 1;
}
/*
@@ -583,10 +595,11 @@ static void gameport_destroy_port(struct gameport *gameport)
if (gameport->registered) {
device_del(&gameport->dev);
- list_del_init(&gameport->node);
gameport->registered = 0;
}
+ list_del_init(&gameport->node);
+
gameport_remove_pending_events(gameport);
put_device(&gameport->dev);
}
@@ -704,11 +717,22 @@ static int gameport_driver_remove(struct device *dev)
}
static struct bus_type gameport_bus = {
- .name = "gameport",
- .probe = gameport_driver_probe,
- .remove = gameport_driver_remove,
+ .name = "gameport",
+ .probe = gameport_driver_probe,
+ .remove = gameport_driver_remove,
};
+static void gameport_add_driver(struct gameport_driver *drv)
+{
+ int error;
+
+ error = driver_register(&drv->driver);
+ if (error)
+ printk(KERN_ERR
+ "gameport: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+}
+
void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
{
drv->driver.bus = &gameport_bus;
@@ -778,16 +802,24 @@ void gameport_close(struct gameport *gameport)
static int __init gameport_init(void)
{
- gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
- if (IS_ERR(gameport_task)) {
- printk(KERN_ERR "gameport: Failed to start kgameportd\n");
- return PTR_ERR(gameport_task);
- }
+ int error;
gameport_bus.dev_attrs = gameport_device_attrs;
gameport_bus.drv_attrs = gameport_driver_attrs;
gameport_bus.match = gameport_bus_match;
- bus_register(&gameport_bus);
+ error = bus_register(&gameport_bus);
+ if (error) {
+ printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
+ return error;
+ }
+
+ gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
+ if (IS_ERR(gameport_task)) {
+ bus_unregister(&gameport_bus);
+ error = PTR_ERR(gameport_task);
+ printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error);
+ return error;
+ }
return 0;
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a90486f5e49..9cb4b9a54f0 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -35,6 +35,16 @@ static LIST_HEAD(input_handler_list);
static struct input_handler *input_table[8];
+/**
+ * input_event() - report new input event
+ * @handle: device that generated the event
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * This function should be used by drivers implementing various input devices
+ * See also input_inject_event()
+ */
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle;
@@ -183,6 +193,23 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
}
EXPORT_SYMBOL(input_event);
+/**
+ * input_inject_event() - send input event from input handler
+ * @handle: input handle to send event through
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * Similar to input_event() but will ignore event if device is "grabbed" and handle
+ * injecting event is not the one that owns the device.
+ */
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+{
+ if (!handle->dev->grab || handle->dev->grab == handle)
+ input_event(handle->dev, type, code, value);
+}
+EXPORT_SYMBOL(input_inject_event);
+
static void input_repeat_key(unsigned long data)
{
struct input_dev *dev = (void *) data;
@@ -197,15 +224,6 @@ static void input_repeat_key(unsigned long data)
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
-int input_accept_process(struct input_handle *handle, struct file *file)
-{
- if (handle->dev->accept)
- return handle->dev->accept(handle->dev, file);
-
- return 0;
-}
-EXPORT_SYMBOL(input_accept_process);
-
int input_grab_device(struct input_handle *handle)
{
if (handle->dev->grab)
@@ -218,8 +236,15 @@ EXPORT_SYMBOL(input_grab_device);
void input_release_device(struct input_handle *handle)
{
- if (handle->dev->grab == handle)
- handle->dev->grab = NULL;
+ struct input_dev *dev = handle->dev;
+
+ if (dev->grab == handle) {
+ dev->grab = NULL;
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ if (handle->handler->start)
+ handle->handler->start(handle);
+ }
}
EXPORT_SYMBOL(input_release_device);
@@ -963,8 +988,11 @@ int input_register_device(struct input_dev *dev)
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
@@ -1028,8 +1056,11 @@ void input_register_handler(struct input_handler *handler)
list_for_each_entry(dev, &input_dev_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 6d99e3c3788..b4914e7231f 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -79,6 +79,7 @@ static struct iforce_device iforce_device[] = {
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
+ { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce },
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
};
@@ -222,22 +223,22 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id)
int err = 0;
struct iforce_core_effect* core_effect;
- /* Check who is trying to erase this effect */
- if (iforce->core_effects[effect_id].owner != current->pid) {
- printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
- return -EACCES;
- }
-
if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
return -EINVAL;
- core_effect = iforce->core_effects + effect_id;
+ core_effect = &iforce->core_effects[effect_id];
+
+ /* Check who is trying to erase this effect */
+ if (core_effect->owner != current->pid) {
+ printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner);
+ return -EACCES;
+ }
if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
- err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
+ err = release_resource(&core_effect->mod1_chunk);
if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
- err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
+ err = release_resource(&core_effect->mod2_chunk);
/*TODO: remember to change that if more FF_MOD* bits are added */
core_effect->flags[0] = 0;
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 75eb5ca5999..7a19ee05297 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
*/
#define SPACEBALL_MAX_LENGTH 128
-#define SPACEBALL_MAX_ID 8
+#define SPACEBALL_MAX_ID 9
#define SPACEBALL_1003 1
#define SPACEBALL_2003B 3
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ce1f10e8984..6bfa0cf4b1d 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -482,13 +482,7 @@ out:
return IRQ_HANDLED;
}
-/*
- * atkbd_event_work() is used to complete processing of events that
- * can not be processed by input_event() which is often called from
- * interrupt context.
- */
-
-static void atkbd_event_work(void *data)
+static int atkbd_set_repeat_rate(struct atkbd *atkbd)
{
const short period[32] =
{ 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
@@ -496,41 +490,64 @@ static void atkbd_event_work(void *data)
const short delay[4] =
{ 250, 500, 750, 1000 };
- struct atkbd *atkbd = data;
+ struct input_dev *dev = atkbd->dev;
+ unsigned char param;
+ int i = 0, j = 0;
+
+ while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
+ i++;
+ dev->rep[REP_PERIOD] = period[i];
+
+ while (j < ARRAY_SIZE(period) - 1 && delay[j] < dev->rep[REP_DELAY])
+ j++;
+ dev->rep[REP_DELAY] = delay[j];
+
+ param = i | (j << 5);
+ return ps2_command(&atkbd->ps2dev, &param, ATKBD_CMD_SETREP);
+}
+
+static int atkbd_set_leds(struct atkbd *atkbd)
+{
struct input_dev *dev = atkbd->dev;
unsigned char param[2];
- int i, j;
- mutex_lock(&atkbd->event_mutex);
+ param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
+ | (test_bit(LED_NUML, dev->led) ? 2 : 0)
+ | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
+ if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
+ return -1;
- if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
- param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
- | (test_bit(LED_NUML, dev->led) ? 2 : 0)
- | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
-
- if (atkbd->extra) {
- param[0] = 0;
- param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
- | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
- | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
- | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
- | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
- }
+ if (atkbd->extra) {
+ param[0] = 0;
+ param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
+ | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
+ | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
+ | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
+ | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
+ if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS))
+ return -1;
}
- if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) {
- i = j = 0;
- while (i < 31 && period[i] < dev->rep[REP_PERIOD])
- i++;
- while (j < 3 && delay[j] < dev->rep[REP_DELAY])
- j++;
- dev->rep[REP_PERIOD] = period[i];
- dev->rep[REP_DELAY] = delay[j];
- param[0] = i | (j << 5);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
- }
+ return 0;
+}
+
+/*
+ * atkbd_event_work() is used to complete processing of events that
+ * can not be processed by input_event() which is often called from
+ * interrupt context.
+ */
+
+static void atkbd_event_work(void *data)
+{
+ struct atkbd *atkbd = data;
+
+ mutex_lock(&atkbd->event_mutex);
+
+ if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_leds(atkbd);
+
+ if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_repeat_rate(atkbd);
mutex_unlock(&atkbd->event_mutex);
}
@@ -975,7 +992,6 @@ static int atkbd_reconnect(struct serio *serio)
{
struct atkbd *atkbd = serio_get_drvdata(serio);
struct serio_driver *drv = serio->drv;
- unsigned char param[1];
if (!atkbd || !drv) {
printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
@@ -985,10 +1001,6 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_disable(atkbd);
if (atkbd->write) {
- param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
- | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0)
- | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0);
-
if (atkbd_probe(atkbd))
return -1;
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
@@ -996,8 +1008,13 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_activate(atkbd);
- if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
- return -1;
+/*
+ * Restore repeat rate and LEDs (that were reset by atkbd_activate)
+ * to pre-resume state
+ */
+ if (!atkbd->softrepeat)
+ atkbd_set_repeat_rate(atkbd);
+ atkbd_set_leds(atkbd);
}
atkbd_enable(atkbd);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index ccf0faeee5c..a8efc1af36c 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -94,7 +94,7 @@ static void call_bios(struct regs *regs)
static ssize_t __init locate_wistron_bios(void __iomem *base)
{
- static const unsigned char __initdata signature[] =
+ static unsigned char __initdata signature[] =
{ 0x42, 0x21, 0x55, 0x30 };
ssize_t offset;
@@ -259,11 +259,11 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
return 1;
}
-static struct key_entry keymap_empty[] = {
+static struct key_entry keymap_empty[] __initdata = {
{ KE_END, 0 }
};
-static struct key_entry keymap_fs_amilo_pro_v2000[] = {
+static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
{ KE_KEY, 0x01, KEY_HELP },
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
@@ -273,7 +273,7 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_fujitsu_n3510[] = {
+static struct key_entry keymap_fujitsu_n3510[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_KEY, 0x36, KEY_WWW },
@@ -285,7 +285,7 @@ static struct key_entry keymap_fujitsu_n3510[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_wistron_ms2111[] = {
+static struct key_entry keymap_wistron_ms2111[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_KEY, 0x13, KEY_PROG3 },
@@ -294,7 +294,7 @@ static struct key_entry keymap_wistron_ms2111[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_wistron_ms2141[] = {
+static struct key_entry keymap_wistron_ms2141[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_WIFI, 0x30, 0 },
@@ -307,7 +307,7 @@ static struct key_entry keymap_wistron_ms2141[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_acer_aspire_1500[] = {
+static struct key_entry keymap_acer_aspire_1500[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_WIFI, 0x30, 0 },
@@ -317,7 +317,7 @@ static struct key_entry keymap_acer_aspire_1500[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_acer_travelmate_240[] = {
+static struct key_entry keymap_acer_travelmate_240[] __initdata = {
{ KE_KEY, 0x31, KEY_MAIL },
{ KE_KEY, 0x36, KEY_WWW },
{ KE_KEY, 0x11, KEY_PROG1 },
@@ -327,7 +327,7 @@ static struct key_entry keymap_acer_travelmate_240[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_aopen_1559as[] = {
+static struct key_entry keymap_aopen_1559as[] __initdata = {
{ KE_KEY, 0x01, KEY_HELP },
{ KE_KEY, 0x06, KEY_PROG3 },
{ KE_KEY, 0x11, KEY_PROG1 },
@@ -343,7 +343,7 @@ static struct key_entry keymap_aopen_1559as[] = {
* a list of buttons and their key codes (reported when loading this module
* with force=1) and the output of dmidecode to $MODULE_AUTHOR.
*/
-static struct dmi_system_id dmi_ids[] = {
+static struct dmi_system_id dmi_ids[] __initdata = {
{
.callback = dmi_matched,
.ident = "Fujitsu-Siemens Amilo Pro V2000",
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 2f0d2884081..54b696cfe1e 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -238,8 +238,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 100, PS2PP_KIND_MX, /* MX510 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
- { 111, PS2PP_KIND_MX, /* MX300 */
- PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
+ { 111, PS2PP_KIND_MX, PS2PP_WHEEL | PS2PP_SIDE_BTN }, /* MX300 reports task button as side */
{ 112, PS2PP_KIND_MX, /* MX500 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 6d9ec9ab1b9..ae5871a0e06 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -183,21 +183,26 @@ static struct attribute_group trackpoint_attr_group = {
.attrs = trackpoint_attrs,
};
-static void trackpoint_disconnect(struct psmouse *psmouse)
+static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id)
{
- sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+ unsigned char param[2] = { 0 };
- kfree(psmouse->private);
- psmouse->private = NULL;
+ if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
+ return -1;
+
+ if (param[0] != TP_MAGIC_IDENT)
+ return -1;
+
+ if (firmware_id)
+ *firmware_id = param[1];
+
+ return 0;
}
static int trackpoint_sync(struct psmouse *psmouse)
{
- unsigned char toggle;
struct trackpoint_data *tp = psmouse->private;
-
- if (!tp)
- return -1;
+ unsigned char toggle;
/* Disable features that may make device unusable with this driver */
trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
@@ -263,27 +268,38 @@ static void trackpoint_defaults(struct trackpoint_data *tp)
tp->ext_dev = TP_DEF_EXT_DEV;
}
+static void trackpoint_disconnect(struct psmouse *psmouse)
+{
+ sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+
+ kfree(psmouse->private);
+ psmouse->private = NULL;
+}
+
+static int trackpoint_reconnect(struct psmouse *psmouse)
+{
+ if (trackpoint_start_protocol(psmouse, NULL))
+ return -1;
+
+ if (trackpoint_sync(psmouse))
+ return -1;
+
+ return 0;
+}
+
int trackpoint_detect(struct psmouse *psmouse, int set_properties)
{
struct trackpoint_data *priv;
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char firmware_id;
unsigned char button_info;
- unsigned char param[2];
-
- param[0] = param[1] = 0;
- if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
- return -1;
-
- if (param[0] != TP_MAGIC_IDENT)
+ if (trackpoint_start_protocol(psmouse, &firmware_id))
return -1;
if (!set_properties)
return 0;
- firmware_id = param[1];
-
if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
button_info = 0;
@@ -296,7 +312,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
psmouse->vendor = "IBM";
psmouse->name = "TrackPoint";
- psmouse->reconnect = trackpoint_sync;
+ psmouse->reconnect = trackpoint_reconnect;
psmouse->disconnect = trackpoint_disconnect;
trackpoint_defaults(priv);
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 61a6f977846..ed202f2f251 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -177,6 +177,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
return -1;
}
+ if (send && !param) {
+ WARN_ON(1);
+ return -1;
+ }
+
mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING);
serio_pause_rx(ps2dev->serio);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 6521034bc93..3e76ad71c9a 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -62,6 +62,7 @@ static LIST_HEAD(serio_list);
static struct bus_type serio_bus;
+static void serio_add_driver(struct serio_driver *drv);
static void serio_add_port(struct serio *serio);
static void serio_destroy_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio);
@@ -140,8 +141,14 @@ static void serio_release_driver(struct serio *serio)
static void serio_find_driver(struct serio *serio)
{
+ int error;
+
down_write(&serio_bus.subsys.rwsem);
- device_attach(&serio->dev);
+ error = device_attach(&serio->dev);
+ if (error < 0)
+ printk(KERN_WARNING
+ "serio: device_attach() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
up_write(&serio_bus.subsys.rwsem);
}
@@ -272,7 +279,6 @@ static struct serio_event *serio_get_event(void)
static void serio_handle_event(void)
{
struct serio_event *event;
- struct serio_driver *serio_drv;
mutex_lock(&serio_mutex);
@@ -304,8 +310,7 @@ static void serio_handle_event(void)
break;
case SERIO_REGISTER_DRIVER:
- serio_drv = event->object;
- driver_register(&serio_drv->driver);
+ serio_add_driver(event->object);
break;
default:
@@ -525,6 +530,7 @@ static void serio_init_port(struct serio *serio)
__module_get(THIS_MODULE);
+ INIT_LIST_HEAD(&serio->node);
spin_lock_init(&serio->lock);
mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev);
@@ -542,6 +548,8 @@ static void serio_init_port(struct serio *serio)
*/
static void serio_add_port(struct serio *serio)
{
+ int error;
+
if (serio->parent) {
serio_pause_rx(serio->parent);
serio->parent->child = serio;
@@ -551,9 +559,19 @@ static void serio_add_port(struct serio *serio)
list_add_tail(&serio->node, &serio_list);
if (serio->start)
serio->start(serio);
- device_add(&serio->dev);
- sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
- serio->registered = 1;
+ error = device_add(&serio->dev);
+ if (error)
+ printk(KERN_ERR
+ "serio: device_add() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
+ else {
+ serio->registered = 1;
+ error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
+ if (error)
+ printk(KERN_ERR
+ "serio: sysfs_create_group() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
+ }
}
/*
@@ -583,10 +601,10 @@ static void serio_destroy_port(struct serio *serio)
if (serio->registered) {
sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
device_del(&serio->dev);
- list_del_init(&serio->node);
serio->registered = 0;
}
+ list_del_init(&serio->node);
serio_remove_pending_events(serio);
put_device(&serio->dev);
}
@@ -756,6 +774,17 @@ static struct bus_type serio_bus = {
.remove = serio_driver_remove,
};
+static void serio_add_driver(struct serio_driver *drv)
+{
+ int error;
+
+ error = driver_register(&drv->driver);
+ if (error)
+ printk(KERN_ERR
+ "serio: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+}
+
void __serio_register_driver(struct serio_driver *drv, struct module *owner)
{
drv->driver.bus = &serio_bus;
@@ -903,18 +932,26 @@ irqreturn_t serio_interrupt(struct serio *serio,
static int __init serio_init(void)
{
- serio_task = kthread_run(serio_thread, NULL, "kseriod");
- if (IS_ERR(serio_task)) {
- printk(KERN_ERR "serio: Failed to start kseriod\n");
- return PTR_ERR(serio_task);
- }
+ int error;
serio_bus.dev_attrs = serio_device_attrs;
serio_bus.drv_attrs = serio_driver_attrs;
serio_bus.match = serio_bus_match;
serio_bus.uevent = serio_uevent;
serio_bus.resume = serio_resume;
- bus_register(&serio_bus);
+ error = bus_register(&serio_bus);
+ if (error) {
+ printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
+ return error;
+ }
+
+ serio_task = kthread_run(serio_thread, NULL, "kseriod");
+ if (IS_ERR(serio_task)) {
+ bus_unregister(&serio_bus);
+ error = PTR_ERR(serio_task);
+ printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error);
+ return error;
+ }
return 0;
}
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index df198cf76f5..3719fcb04b8 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -111,14 +111,28 @@
#define NAME_BUFSIZE 80 /* size of product name, path buffers */
#define DATA_BUFSIZE 63 /* size of URB data buffers */
+/*
+ * Duplicate event filtering time.
+ * Sequential, identical KIND_FILTERED inputs with less than
+ * FILTER_TIME milliseconds between them are considered as repeat
+ * events. The hardware generates 5 events for the first keypress
+ * and we have to take this into account for an accurate repeat
+ * behaviour.
+ */
+#define FILTER_TIME 60 /* msec */
+
static unsigned long channel_mask;
-module_param(channel_mask, ulong, 0444);
+module_param(channel_mask, ulong, 0644);
MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
static int debug;
-module_param(debug, int, 0444);
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
+static int repeat_filter = FILTER_TIME;
+module_param(repeat_filter, int, 0644);
+MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
+
#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
#undef err
#define err(format, arg...) printk(KERN_ERR format , ## arg)
@@ -143,18 +157,6 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table);
static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
-/* Acceleration curve for directional control pad */
-static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
-
-/* Duplicate event filtering time.
- * Sequential, identical KIND_FILTERED inputs with less than
- * FILTER_TIME jiffies between them are considered as repeat
- * events. The hardware generates 5 events for the first keypress
- * and we have to take this into account for an accurate repeat
- * behaviour.
- */
-#define FILTER_TIME 60 /* msec */
-
struct ati_remote {
struct input_dev *idev;
struct usb_device *udev;
@@ -412,6 +414,43 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2)
}
/*
+ * ati_remote_compute_accel
+ *
+ * Implements acceleration curve for directional control pad
+ * If elapsed time since last event is > 1/4 second, user "stopped",
+ * so reset acceleration. Otherwise, user is probably holding the control
+ * pad down, so we increase acceleration, ramping up over two seconds to
+ * a maximum speed.
+ */
+static int ati_remote_compute_accel(struct ati_remote *ati_remote)
+{
+ static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+ unsigned long now = jiffies;
+ int acc;
+
+ if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) {
+ acc = 1;
+ ati_remote->acc_jiffies = now;
+ }
+ else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125)))
+ acc = accel[0];
+ else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250)))
+ acc = accel[1];
+ else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500)))
+ acc = accel[2];
+ else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000)))
+ acc = accel[3];
+ else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500)))
+ acc = accel[4];
+ else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000)))
+ acc = accel[5];
+ else
+ acc = accel[6];
+
+ return acc;
+}
+
+/*
* ati_remote_report_input
*/
static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
@@ -464,9 +503,9 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
if (ati_remote_tbl[index].kind == KIND_FILTERED) {
/* Filter duplicate events which happen "too close" together. */
- if ((ati_remote->old_data[0] == data[1]) &&
- (ati_remote->old_data[1] == data[2]) &&
- time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(FILTER_TIME))) {
+ if (ati_remote->old_data[0] == data[1] &&
+ ati_remote->old_data[1] == data[2] &&
+ time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) {
ati_remote->repeat_count++;
} else {
ati_remote->repeat_count = 0;
@@ -476,75 +515,61 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
ati_remote->old_data[1] = data[2];
ati_remote->old_jiffies = jiffies;
- if ((ati_remote->repeat_count > 0)
- && (ati_remote->repeat_count < 5))
+ if (ati_remote->repeat_count > 0 &&
+ ati_remote->repeat_count < 5)
return;
input_regs(dev, regs);
input_event(dev, ati_remote_tbl[index].type,
ati_remote_tbl[index].code, 1);
+ input_sync(dev);
input_event(dev, ati_remote_tbl[index].type,
ati_remote_tbl[index].code, 0);
input_sync(dev);
- return;
- }
+ } else {
- /*
- * Other event kinds are from the directional control pad, and have an
- * acceleration factor applied to them. Without this acceleration, the
- * control pad is mostly unusable.
- *
- * If elapsed time since last event is > 1/4 second, user "stopped",
- * so reset acceleration. Otherwise, user is probably holding the control
- * pad down, so we increase acceleration, ramping up over two seconds to
- * a maximum speed. The acceleration curve is #defined above.
- */
- if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) {
- acc = 1;
- ati_remote->acc_jiffies = jiffies;
- }
- else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0];
- else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1];
- else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2];
- else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3];
- else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4];
- else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5];
- else acc = accel[6];
-
- input_regs(dev, regs);
- switch (ati_remote_tbl[index].kind) {
- case KIND_ACCEL:
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code,
- ati_remote_tbl[index].value * acc);
- break;
- case KIND_LU:
- input_report_rel(dev, REL_X, -acc);
- input_report_rel(dev, REL_Y, -acc);
- break;
- case KIND_RU:
- input_report_rel(dev, REL_X, acc);
- input_report_rel(dev, REL_Y, -acc);
- break;
- case KIND_LD:
- input_report_rel(dev, REL_X, -acc);
- input_report_rel(dev, REL_Y, acc);
- break;
- case KIND_RD:
- input_report_rel(dev, REL_X, acc);
- input_report_rel(dev, REL_Y, acc);
- break;
- default:
- dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
- ati_remote_tbl[index].kind);
- }
- input_sync(dev);
+ /*
+ * Other event kinds are from the directional control pad, and have an
+ * acceleration factor applied to them. Without this acceleration, the
+ * control pad is mostly unusable.
+ */
+ acc = ati_remote_compute_accel(ati_remote);
+
+ input_regs(dev, regs);
+ switch (ati_remote_tbl[index].kind) {
+ case KIND_ACCEL:
+ input_event(dev, ati_remote_tbl[index].type,
+ ati_remote_tbl[index].code,
+ ati_remote_tbl[index].value * acc);
+ break;
+ case KIND_LU:
+ input_report_rel(dev, REL_X, -acc);
+ input_report_rel(dev, REL_Y, -acc);
+ break;
+ case KIND_RU:
+ input_report_rel(dev, REL_X, acc);
+ input_report_rel(dev, REL_Y, -acc);
+ break;
+ case KIND_LD:
+ input_report_rel(dev, REL_X, -acc);
+ input_report_rel(dev, REL_Y, acc);
+ break;
+ case KIND_RD:
+ input_report_rel(dev, REL_X, acc);
+ input_report_rel(dev, REL_Y, acc);
+ break;
+ default:
+ dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
+ ati_remote_tbl[index].kind);
+ }
+ input_sync(dev);
- ati_remote->old_jiffies = jiffies;
- ati_remote->old_data[0] = data[1];
- ati_remote->old_data[1] = data[2];
+ ati_remote->old_jiffies = jiffies;
+ ati_remote->old_data[0] = data[1];
+ ati_remote->old_data[1] = data[2];
+ }
}
/*
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 028e1ad89f5..7208839f2db 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -607,7 +607,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
- if (usage->hat_min < usage->hat_max || usage->hat_dir) {
+ if (usage->type == EV_ABS &&
+ (usage->hat_min < usage->hat_max || usage->hat_dir)) {
int i;
for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
input_set_abs_params(input, i, -1, 1, 0, 0);
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 70477f02cc2..f6b839c257a 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -49,7 +49,7 @@ struct hiddev {
int open;
wait_queue_head_t wait;
struct hid_device *hid;
- struct hiddev_list *list;
+ struct list_head list;
};
struct hiddev_list {
@@ -59,7 +59,7 @@ struct hiddev_list {
unsigned flags;
struct fasync_struct *fasync;
struct hiddev *hiddev;
- struct hiddev_list *next;
+ struct list_head node;
};
static struct hiddev *hiddev_table[HIDDEV_MINORS];
@@ -73,12 +73,15 @@ static struct hiddev *hiddev_table[HIDDEV_MINORS];
static struct hid_report *
hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
{
- unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK;
+ unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK;
+ unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK;
struct hid_report_enum *report_enum;
+ struct hid_report *report;
struct list_head *list;
if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
- rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL;
+ rinfo->report_type > HID_REPORT_TYPE_MAX)
+ return NULL;
report_enum = hid->report_enum +
(rinfo->report_type - HID_REPORT_TYPE_MIN);
@@ -88,21 +91,25 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
break;
case HID_REPORT_ID_FIRST:
- list = report_enum->report_list.next;
- if (list == &report_enum->report_list)
+ if (list_empty(&report_enum->report_list))
return NULL;
- rinfo->report_id = ((struct hid_report *) list)->id;
+
+ list = report_enum->report_list.next;
+ report = list_entry(list, struct hid_report, list);
+ rinfo->report_id = report->id;
break;
case HID_REPORT_ID_NEXT:
- list = (struct list_head *)
- report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK];
- if (list == NULL)
+ report = report_enum->report_id_hash[rid];
+ if (!report)
return NULL;
- list = list->next;
+
+ list = report->list.next;
if (list == &report_enum->report_list)
return NULL;
- rinfo->report_id = ((struct hid_report *) list)->id;
+
+ report = list_entry(list, struct hid_report, list);
+ rinfo->report_id = report->id;
break;
default:
@@ -125,12 +132,13 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
struct hid_field *field;
if (uref->report_type < HID_REPORT_TYPE_MIN ||
- uref->report_type > HID_REPORT_TYPE_MAX) return NULL;
+ uref->report_type > HID_REPORT_TYPE_MAX)
+ return NULL;
report_enum = hid->report_enum +
(uref->report_type - HID_REPORT_TYPE_MIN);
- list_for_each_entry(report, &report_enum->report_list, list)
+ list_for_each_entry(report, &report_enum->report_list, list) {
for (i = 0; i < report->maxfield; i++) {
field = report->field[i];
for (j = 0; j < field->maxusage; j++) {
@@ -142,6 +150,7 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
}
}
}
+ }
return NULL;
}
@@ -150,9 +159,9 @@ static void hiddev_send_event(struct hid_device *hid,
struct hiddev_usage_ref *uref)
{
struct hiddev *hiddev = hid->hiddev;
- struct hiddev_list *list = hiddev->list;
+ struct hiddev_list *list;
- while (list) {
+ list_for_each_entry(list, &hiddev->list, node) {
if (uref->field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
list->buffer[list->head] = *uref;
@@ -160,8 +169,6 @@ static void hiddev_send_event(struct hid_device *hid,
(HIDDEV_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
-
- list = list->next;
}
wake_up_interruptible(&hiddev->wait);
@@ -180,7 +187,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
uref.report_type =
(type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
- ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+ ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
uref.report_id = field->report->id;
uref.field_index = field->index;
uref.usage_index = (usage - field->usage);
@@ -200,7 +207,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
uref.report_type =
(type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
- ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+ ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
uref.report_id = report->id;
uref.field_index = HID_FIELD_INDEX_NONE;
@@ -213,7 +220,9 @@ static int hiddev_fasync(int fd, struct file *file, int on)
{
int retval;
struct hiddev_list *list = file->private_data;
+
retval = fasync_helper(fd, file, on, &list->fasync);
+
return retval < 0 ? retval : 0;
}
@@ -224,14 +233,9 @@ static int hiddev_fasync(int fd, struct file *file, int on)
static int hiddev_release(struct inode * inode, struct file * file)
{
struct hiddev_list *list = file->private_data;
- struct hiddev_list **listptr;
- listptr = &list->hiddev->list;
hiddev_fasync(-1, file, 0);
-
- while (*listptr && (*listptr != list))
- listptr = &((*listptr)->next);
- *listptr = (*listptr)->next;
+ list_del(&list->node);
if (!--list->hiddev->open) {
if (list->hiddev->exist)
@@ -248,7 +252,8 @@ static int hiddev_release(struct inode * inode, struct file * file)
/*
* open file op
*/
-static int hiddev_open(struct inode * inode, struct file * file) {
+static int hiddev_open(struct inode *inode, struct file *file)
+{
struct hiddev_list *list;
int i = iminor(inode) - HIDDEV_MINOR_BASE;
@@ -260,9 +265,7 @@ static int hiddev_open(struct inode * inode, struct file * file) {
return -ENOMEM;
list->hiddev = hiddev_table[i];
- list->next = hiddev_table[i]->list;
- hiddev_table[i]->list = list;
-
+ list_add_tail(&list->node, &hiddev_table[i]->list);
file->private_data = list;
if (!list->hiddev->open++)
@@ -362,6 +365,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
static unsigned int hiddev_poll(struct file *file, poll_table *wait)
{
struct hiddev_list *list = file->private_data;
+
poll_wait(file, &list->hiddev->wait, wait);
if (list->head != list->tail)
return POLLIN | POLLRDNORM;
@@ -382,7 +386,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct hiddev_collection_info cinfo;
struct hiddev_report_info rinfo;
struct hiddev_field_info finfo;
- struct hiddev_usage_ref_multi *uref_multi=NULL;
+ struct hiddev_usage_ref_multi *uref_multi = NULL;
struct hiddev_usage_ref *uref;
struct hiddev_devinfo dinfo;
struct hid_report *report;
@@ -764,15 +768,15 @@ int hiddev_connect(struct hid_device *hid)
}
init_waitqueue_head(&hiddev->wait);
-
- hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
-
+ INIT_LIST_HEAD(&hiddev->list);
hiddev->hid = hid;
hiddev->exist = 1;
hid->minor = hid->intf->minor;
hid->hiddev = hiddev;
+ hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+
return 0;
}
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 43e3f566aad..a223cf4faa9 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -168,16 +168,15 @@ void jfs_dirty_inode(struct inode *inode)
set_cflag(COMMIT_Dirty, inode);
}
-static int
-jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
- struct buffer_head *bh_result, int create)
+int jfs_get_block(struct inode *ip, sector_t lblock,
+ struct buffer_head *bh_result, int create)
{
s64 lblock64 = lblock;
int rc = 0;
xad_t xad;
s64 xaddr;
int xflag;
- s32 xlen = max_blocks;
+ s32 xlen = bh_result->b_size >> ip->i_blkbits;
/*
* Take appropriate lock on inode
@@ -188,7 +187,7 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
IREAD_LOCK(ip);
if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
- (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
+ (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) &&
xaddr) {
if (xflag & XAD_NOTRECORDED) {
if (!create)
@@ -255,13 +254,6 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
return rc;
}
-static int jfs_get_block(struct inode *ip, sector_t lblock,
- struct buffer_head *bh_result, int create)
-{
- return jfs_get_blocks(ip, lblock, bh_result->b_size >> ip->i_blkbits,
- bh_result, create);
-}
-
static int jfs_writepage(struct page *page, struct writeback_control *wbc)
{
return nobh_writepage(page, jfs_get_block, wbc);
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index b5c7da6190d..1fc48df670c 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -32,6 +32,7 @@ extern void jfs_truncate_nolock(struct inode *, loff_t);
extern void jfs_free_zero_link(struct inode *);
extern struct dentry *jfs_get_parent(struct dentry *dentry);
extern void jfs_set_inode_flags(struct inode *);
+extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern const struct address_space_operations jfs_aops;
extern struct inode_operations jfs_dir_inode_operations;
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 4f6cfebc82d..143bcd1d5ea 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -26,6 +26,7 @@
#include <linux/moduleparam.h>
#include <linux/kthread.h>
#include <linux/posix_acl.h>
+#include <linux/buffer_head.h>
#include <asm/uaccess.h>
#include <linux/seq_file.h>
@@ -298,7 +299,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
break;
}
-#if defined(CONFIG_QUOTA)
+#ifdef CONFIG_QUOTA
case Opt_quota:
case Opt_usrquota:
*flag |= JFS_USRQUOTA;
@@ -597,7 +598,7 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
if (sbi->flag & JFS_NOINTEGRITY)
seq_puts(seq, ",nointegrity");
-#if defined(CONFIG_QUOTA)
+#ifdef CONFIG_QUOTA
if (sbi->flag & JFS_USRQUOTA)
seq_puts(seq, ",usrquota");
@@ -608,6 +609,113 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
return 0;
}
+#ifdef CONFIG_QUOTA
+
+/* Read data from quotafile - avoid pagecache and such because we cannot afford
+ * acquiring the locks... As quota files are never truncated and quota code
+ * itself serializes the operations (and noone else should touch the files)
+ * we don't have to be afraid of races */
+static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data,
+ size_t len, loff_t off)
+{
+ struct inode *inode = sb_dqopt(sb)->files[type];
+ sector_t blk = off >> sb->s_blocksize_bits;
+ int err = 0;
+ int offset = off & (sb->s_blocksize - 1);
+ int tocopy;
+ size_t toread;
+ struct buffer_head tmp_bh;
+ struct buffer_head *bh;
+ loff_t i_size = i_size_read(inode);
+
+ if (off > i_size)
+ return 0;
+ if (off+len > i_size)
+ len = i_size-off;
+ toread = len;
+ while (toread > 0) {
+ tocopy = sb->s_blocksize - offset < toread ?
+ sb->s_blocksize - offset : toread;
+
+ tmp_bh.b_state = 0;
+ tmp_bh.b_size = 1 << inode->i_blkbits;
+ err = jfs_get_block(inode, blk, &tmp_bh, 0);
+ if (err)
+ return err;
+ if (!buffer_mapped(&tmp_bh)) /* A hole? */
+ memset(data, 0, tocopy);
+ else {
+ bh = sb_bread(sb, tmp_bh.b_blocknr);
+ if (!bh)
+ return -EIO;
+ memcpy(data, bh->b_data+offset, tocopy);
+ brelse(bh);
+ }
+ offset = 0;
+ toread -= tocopy;
+ data += tocopy;
+ blk++;
+ }
+ return len;
+}
+
+/* Write to quotafile */
+static ssize_t jfs_quota_write(struct super_block *sb, int type,
+ const char *data, size_t len, loff_t off)
+{
+ struct inode *inode = sb_dqopt(sb)->files[type];
+ sector_t blk = off >> sb->s_blocksize_bits;
+ int err = 0;
+ int offset = off & (sb->s_blocksize - 1);
+ int tocopy;
+ size_t towrite = len;
+ struct buffer_head tmp_bh;
+ struct buffer_head *bh;
+
+ mutex_lock(&inode->i_mutex);
+ while (towrite > 0) {
+ tocopy = sb->s_blocksize - offset < towrite ?
+ sb->s_blocksize - offset : towrite;
+
+ tmp_bh.b_state = 0;
+ tmp_bh.b_size = 1 << inode->i_blkbits;
+ err = jfs_get_block(inode, blk, &tmp_bh, 1);
+ if (err)
+ goto out;
+ if (offset || tocopy != sb->s_blocksize)
+ bh = sb_bread(sb, tmp_bh.b_blocknr);
+ else
+ bh = sb_getblk(sb, tmp_bh.b_blocknr);
+ if (!bh) {
+ err = -EIO;
+ goto out;
+ }
+ lock_buffer(bh);
+ memcpy(bh->b_data+offset, data, tocopy);
+ flush_dcache_page(bh->b_page);
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ brelse(bh);
+ offset = 0;
+ towrite -= tocopy;
+ data += tocopy;
+ blk++;
+ }
+out:
+ if (len == towrite)
+ return err;
+ if (inode->i_size < off+len-towrite)
+ i_size_write(inode, off+len-towrite);
+ inode->i_version++;
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+ mutex_unlock(&inode->i_mutex);
+ return len - towrite;
+}
+
+#endif
+
static struct super_operations jfs_super_operations = {
.alloc_inode = jfs_alloc_inode,
.destroy_inode = jfs_destroy_inode,
@@ -621,7 +729,11 @@ static struct super_operations jfs_super_operations = {
.unlockfs = jfs_unlockfs,
.statfs = jfs_statfs,
.remount_fs = jfs_remount,
- .show_options = jfs_show_options
+ .show_options = jfs_show_options,
+#ifdef CONFIG_QUOTA
+ .quota_read = jfs_quota_read,
+ .quota_write = jfs_quota_write,
+#endif
};
static struct export_operations jfs_export_operations = {
diff --git a/include/linux/input.h b/include/linux/input.h
index 56f1e0e1e59..b3253ab72ff 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -893,7 +893,6 @@ struct input_dev {
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
- int (*accept)(struct input_dev *dev, struct file *file);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
@@ -961,6 +960,26 @@ struct input_dev {
struct input_handle;
+/**
+ * struct input_handler - implements one of interfaces for input devices
+ * @private: driver-specific data
+ * @event: event handler
+ * @connect: called when attaching a handler to an input device
+ * @disconnect: disconnects a handler from input device
+ * @start: starts handler for given handle. This function is called by
+ * input core right after connect() method and also when a process
+ * that "grabbed" a device releases it
+ * @fops: file operations this driver implements
+ * @minor: beginning of range of 32 minors for devices this driver
+ * can provide
+ * @name: name of the handler, to be shown in /proc/bus/input/handlers
+ * @id_table: pointer to a table of input_device_ids this driver can
+ * handle
+ * @blacklist: prointer to a table of input_device_ids this driver should
+ * ignore even if they match @id_table
+ * @h_list: list of input handles associated with the handler
+ * @node: for placing the driver onto input_handler_list
+ */
struct input_handler {
void *private;
@@ -968,6 +987,7 @@ struct input_handler {
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
+ void (*start)(struct input_handle *handle);
const struct file_operations *fops;
int minor;
@@ -1030,10 +1050,10 @@ void input_release_device(struct input_handle *);
int input_open_device(struct input_handle *);
void input_close_device(struct input_handle *);
-int input_accept_process(struct input_handle *handle, struct file *file);
int input_flush_device(struct input_handle* handle, struct file* file);
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c
index bcc555647e7..3c7d1d8a9a6 100644
--- a/sound/aoa/codecs/snd-aoa-codec-toonie.c
+++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c
@@ -51,6 +51,13 @@ static struct transfer_info toonie_transfers[] = {
{}
};
+static int toonie_usable(struct codec_info_item *cii,
+ struct transfer_info *ti,
+ struct transfer_info *out)
+{
+ return 1;
+}
+
#ifdef CONFIG_PM
static int toonie_suspend(struct codec_info_item *cii, pm_message_t state)
{
@@ -69,6 +76,7 @@ static struct codec_info toonie_codec_info = {
.sysclock_factor = 256,
.bus_factor = 64,
.owner = THIS_MODULE,
+ .usable = toonie_usable,
#ifdef CONFIG_PM
.suspend = toonie_suspend,
.resume = toonie_resume,
@@ -79,19 +87,20 @@ static int toonie_init_codec(struct aoa_codec *codec)
{
struct toonie *toonie = codec_to_toonie(codec);
+ /* nothing connected? what a joke! */
+ if (toonie->codec.connected != 1)
+ return -ENOTCONN;
+
if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) {
printk(KERN_ERR PFX "failed to create toonie snd device!\n");
return -ENODEV;
}
- /* nothing connected? what a joke! */
- if (toonie->codec.connected != 1)
- return -ENOTCONN;
-
if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev,
aoa_get_card(),
&toonie_codec_info, toonie)) {
printk(KERN_ERR PFX "error creating toonie pcm\n");
+ snd_device_free(aoa_get_card(), toonie);
return -ENODEV;
}
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
index 7ae0c0bdfad..f69d33357a2 100644
--- a/sound/aoa/core/snd-aoa-gpio-feature.c
+++ b/sound/aoa/core/snd-aoa-gpio-feature.c
@@ -112,7 +112,10 @@ static struct device_node *get_gpio(char *name,
static void get_irq(struct device_node * np, int *irqptr)
{
- *irqptr = irq_of_parse_and_map(np, 0);
+ if (np)
+ *irqptr = irq_of_parse_and_map(np, 0);
+ else
+ *irqptr = NO_IRQ;
}
/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */
@@ -322,7 +325,7 @@ static int ftr_set_notify(struct gpio_runtime *rt,
return -EINVAL;
}
- if (irq == -1)
+ if (irq == NO_IRQ)
return -ENODEV;
mutex_lock(&notif->mutex);
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
index 3d57fd1aec4..2836c321839 100644
--- a/sound/aoa/core/snd-aoa-gpio-pmf.c
+++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
@@ -18,7 +18,7 @@ static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\
\
if (unlikely(!rt)) return; \
rc = pmf_call_function(rt->node, #name "-mute", &args); \
- if (rc) \
+ if (rc && rc != -ENODEV) \
printk(KERN_WARNING "pmf_gpio_set_" #name \
" failed, rc: %d\n", rc); \
rt->implementation_private &= ~(1<<bit); \
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 71b5080fa66..75a9505c744 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -988,13 +988,12 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix
if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) {
struct snd_ctl_elem_info *uinfo;
- uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
if (! uinfo) {
up_read(&mixer->card->controls_rwsem);
return -ENOMEM;
}
- memset(uinfo, 0, sizeof(*uinfo));
if (kctl->info(kctl, uinfo)) {
up_read(&mixer->card->controls_rwsem);
return 0;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index f5ff4f4a16e..472fce0ee0e 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2228,6 +2228,8 @@ static int snd_pcm_oss_open_file(struct file *file,
for (idx = 0; idx < 2; idx++) {
if (setup[idx].disable)
continue;
+ if (! pcm->streams[idx].substream_count)
+ continue; /* no matching substream */
if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
if (! (f_mode & FMODE_WRITE))
continue;
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 4260de90f36..102ff548ce6 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -372,10 +372,9 @@ static struct ops_list * create_driver(char *id)
{
struct ops_list *ops;
- ops = kmalloc(sizeof(*ops), GFP_KERNEL);
+ ops = kzalloc(sizeof(*ops), GFP_KERNEL);
if (ops == NULL)
return ops;
- memset(ops, 0, sizeof(*ops));
/* set up driver entry */
strlcpy(ops->id, id, sizeof(ops->id));
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index 6e4d4ab3463..c30669f14ac 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -68,21 +68,18 @@ void *snd_malloc_sgbuf_pages(struct device *device,
dmab->area = NULL;
dmab->addr = 0;
- dmab->private_data = sgbuf = kmalloc(sizeof(*sgbuf), GFP_KERNEL);
+ dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
if (! sgbuf)
return NULL;
- memset(sgbuf, 0, sizeof(*sgbuf));
sgbuf->dev = device;
pages = snd_sgbuf_aligned_pages(size);
sgbuf->tblsize = sgbuf_align_table(pages);
- sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
+ sgbuf->table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->table), GFP_KERNEL);
if (! sgbuf->table)
goto _failed;
- memset(sgbuf->table, 0, sizeof(*sgbuf->table) * sgbuf->tblsize);
- sgbuf->page_table = kmalloc(sizeof(*sgbuf->page_table) * sgbuf->tblsize, GFP_KERNEL);
+ sgbuf->page_table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->page_table), GFP_KERNEL);
if (! sgbuf->page_table)
goto _failed;
- memset(sgbuf->page_table, 0, sizeof(*sgbuf->page_table) * sgbuf->tblsize);
/* allocate each page */
for (i = 0; i < pages; i++) {
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index c4af84995d0..7e65a103fbb 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -1252,18 +1252,15 @@ static int vx_init_audio_io(struct vx_core *chip)
chip->audio_info = rmh.Stat[1];
/* allocate pipes */
- chip->playback_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_outs, GFP_KERNEL);
+ chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL);
if (!chip->playback_pipes)
return -ENOMEM;
- chip->capture_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_ins, GFP_KERNEL);
+ chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL);
if (!chip->capture_pipes) {
kfree(chip->playback_pipes);
return -ENOMEM;
}
- memset(chip->playback_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_outs);
- memset(chip->capture_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_ins);
-
preferred = chip->ibl.size;
chip->ibl.size = 0;
vx_set_ibl(chip, &chip->ibl); /* query the info */
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 27a8dbe6f6a..c3dafa29054 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -236,9 +236,9 @@ static int pcm_open(struct snd_pcm_substream *substream,
chip = snd_pcm_substream_chip(substream);
runtime = substream->runtime;
- if (!(pipe = kmalloc(sizeof(struct audiopipe), GFP_KERNEL)))
+ pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL);
+ if (!pipe)
return -ENOMEM;
- memset(pipe, 0, sizeof(struct audiopipe));
pipe->index = -1; /* Not configured yet */
/* Set up hw capabilities and contraints */
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index f9b5c3dc3b3..79f24cdf5fb 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -936,6 +936,17 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.ca0151_chip = 1,
.spk71 = 1,
.spdif_bug = 1} ,
+ /* Dell OEM/Creative Labs Audigy 2 ZS */
+ /* See ALSA bug#1365 */
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102,
+ .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]",
+ .id = "Audigy2",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
.driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
.id = "Audigy2",
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index a8b31286b6d..1076af4c366 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -37,9 +37,13 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int handled = 0;
while ((status = inl(emu->port + IPR)) != 0) {
- //printk("emu10k1 irq - status = 0x%x\n", status);
+ //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status);
orig_status = status;
handled = 1;
+ if ((status & 0xffffffff) == 0xffffffff) {
+ snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n");
+ break;
+ }
if (status & IPR_PCIERROR) {
snd_printk(KERN_ERR "interrupt: PCI error\n");
snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE);
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 82d791be749..05dabe45465 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -801,11 +801,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf;
#ifdef PMAC_AMP_AVAIL
if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) {
- struct awacs_amp *amp = kmalloc(sizeof(*amp), GFP_KERNEL);
+ struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL);
if (! amp)
return -ENOMEM;
chip->mixer_data = amp;
- memset(amp, 0, sizeof(*amp));
chip->mixer_free = awacs_amp_free;
awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
awacs_amp_set_vol(amp, 1, 63, 63, 0);
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index 46eebf5610e..57202b0f033 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -258,10 +258,9 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip)
request_module("i2c-powermac");
#endif /* CONFIG_KMOD */
- mix = kmalloc(sizeof(*mix), GFP_KERNEL);
+ mix = kzalloc(sizeof(*mix), GFP_KERNEL);
if (! mix)
return -ENOMEM;
- memset(mix, 0, sizeof(*mix));
chip->mixer_data = mix;
chip->mixer_free = daca_cleanup;
mix->amp_on = 1; /* default on */
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index fb05938dcbd..59482a4cd44 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -64,11 +64,10 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
if (strncmp(i2c_device_name(adapter), "mac-io", 6))
return 0; /* ignored */
- new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (! new_client)
return -ENOMEM;
- memset(new_client, 0, sizeof(*new_client));
new_client->addr = keywest_ctx->addr;
i2c_set_clientdata(new_client, keywest_ctx);
new_client->adapter = adapter;
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index fa9a44ab487..2264574fa06 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -181,21 +181,14 @@ static int __init alsa_card_pmac_init(void)
if ((err = platform_driver_register(&snd_pmac_driver)) < 0)
return err;
device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0);
- if (!IS_ERR(device)) {
- if (platform_get_drvdata(device))
- return 0;
- platform_device_unregister(device);
- err = -ENODEV;
- } else
- err = PTR_ERR(device);
- platform_driver_unregister(&snd_pmac_driver);
- return err;
+ return 0;
}
static void __exit alsa_card_pmac_exit(void)
{
- platform_device_unregister(device);
+ if (!IS_ERR(device))
+ platform_device_unregister(device);
platform_driver_unregister(&snd_pmac_driver);
}
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 692c6117767..84f6b19c07c 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1316,10 +1316,9 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
request_module("i2c-powermac");
#endif /* CONFIG_KMOD */
- mix = kmalloc(sizeof(*mix), GFP_KERNEL);
+ mix = kzalloc(sizeof(*mix), GFP_KERNEL);
if (! mix)
return -ENOMEM;
- memset(mix, 0, sizeof(*mix));
mix->headphone_irq = -1;
chip->mixer_data = mix;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index d32d83d970c..1b7f499c549 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2260,10 +2260,9 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
}
/* create a new pcm */
- as = kmalloc(sizeof(*as), GFP_KERNEL);
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
if (! as)
return -ENOMEM;
- memset(as, 0, sizeof(*as));
as->pcm_index = chip->pcm_devs;
as->chip = chip;
as->fmt_type = fp->fmt_type;
@@ -2633,13 +2632,12 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
csep = NULL;
}
- fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ fp = kzalloc(sizeof(*fp), GFP_KERNEL);
if (! fp) {
snd_printk(KERN_ERR "cannot malloc\n");
return -ENOMEM;
}
- memset(fp, 0, sizeof(*fp));
fp->iface = iface_no;
fp->altsetting = altno;
fp->altset_idx = i;