diff options
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/altera_ps2.c | 15 | ||||
-rw-r--r-- | drivers/input/serio/ambakmi.c | 9 | ||||
-rw-r--r-- | drivers/input/serio/at32psif.c | 3 | ||||
-rw-r--r-- | drivers/input/serio/gscps2.c | 6 | ||||
-rw-r--r-- | drivers/input/serio/hil_mlc.c | 8 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 15 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 88 | ||||
-rw-r--r-- | drivers/input/serio/sa1111ps2.c | 10 | ||||
-rw-r--r-- | drivers/input/serio/serio.c | 11 |
9 files changed, 123 insertions, 42 deletions
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index f479ea50919..320b7ca48bf 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -79,11 +79,11 @@ static void altera_ps2_close(struct serio *io) /* * Add one device to this driver. */ -static int altera_ps2_probe(struct platform_device *pdev) +static int __devinit altera_ps2_probe(struct platform_device *pdev) { struct ps2if *ps2if; struct serio *serio; - int error; + int error, irq; ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); serio = kzalloc(sizeof(struct serio), GFP_KERNEL); @@ -108,11 +108,13 @@ static int altera_ps2_probe(struct platform_device *pdev) goto err_free_mem; } - ps2if->irq = platform_get_irq(pdev, 0); - if (ps2if->irq < 0) { + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { error = -ENXIO; goto err_free_mem; } + ps2if->irq = irq; if (!request_mem_region(ps2if->iomem_res->start, resource_size(ps2if->iomem_res), pdev->name)) { @@ -155,7 +157,7 @@ static int altera_ps2_probe(struct platform_device *pdev) /* * Remove one device from this driver. */ -static int altera_ps2_remove(struct platform_device *pdev) +static int __devexit altera_ps2_remove(struct platform_device *pdev) { struct ps2if *ps2if = platform_get_drvdata(pdev); @@ -175,9 +177,10 @@ static int altera_ps2_remove(struct platform_device *pdev) */ static struct platform_driver altera_ps2_driver = { .probe = altera_ps2_probe, - .remove = altera_ps2_remove, + .remove = __devexit_p(altera_ps2_remove), .driver = { .name = DRV_NAME, + .owner = THIS_MODULE, }, }; diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 89b394183a7..92563a681d6 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io) clk_disable(kmi->clk); } -static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) { struct amba_kmi_port *kmi; struct serio *io; @@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) io->port_data = kmi; io->dev.parent = &dev->dev; - kmi->io = io; + kmi->io = io; kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!kmi->base) { ret = -ENOMEM; @@ -162,7 +162,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) return ret; } -static int amba_kmi_remove(struct amba_device *dev) +static int __devexit amba_kmi_remove(struct amba_device *dev) { struct amba_kmi_port *kmi = amba_get_drvdata(dev); @@ -197,10 +197,11 @@ static struct amba_id amba_kmi_idtable[] = { static struct amba_driver ambakmi_driver = { .drv = { .name = "kmi-pl050", + .owner = THIS_MODULE, }, .id_table = amba_kmi_idtable, .probe = amba_kmi_probe, - .remove = amba_kmi_remove, + .remove = __devexit_p(amba_kmi_remove), .resume = amba_kmi_resume, }; diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index a6fb7a3dcc4..b54452a8c77 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c @@ -137,7 +137,7 @@ static int psif_write(struct serio *io, unsigned char val) spin_lock_irqsave(&psif->lock, flags); while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) - msleep(10); + udelay(50); if (timeout >= 0) { psif_writel(psif, THR, val); @@ -352,6 +352,7 @@ static struct platform_driver psif_driver = { .remove = __exit_p(psif_remove), .driver = { .name = "atmel_psif", + .owner = THIS_MODULE, }, .suspend = psif_suspend, .resume = psif_resume, diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index bd0f92d9f40..06addfa7cc4 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -6,7 +6,7 @@ * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> * * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c - * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> + * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> @@ -326,7 +326,7 @@ static void gscps2_close(struct serio *port) * @return: success/error report */ -static int __init gscps2_probe(struct parisc_device *dev) +static int __devinit gscps2_probe(struct parisc_device *dev) { struct gscps2port *ps2port; struct serio *serio; @@ -443,7 +443,7 @@ static struct parisc_driver parisc_ps2_driver = { .name = "gsc_ps2", .id_table = gscps2_device_tbl, .probe = gscps2_probe, - .remove = gscps2_remove, + .remove = __devexit_p(gscps2_remove), }; static int __init gscps2_init(void) diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 7ba9f2b2c04..6cd03ebaf5f 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -993,10 +993,8 @@ int hil_mlc_unregister(hil_mlc *mlc) static int __init hil_mlc_init(void) { - init_timer(&hil_mlcs_kicker); - hil_mlcs_kicker.expires = jiffies + HZ; - hil_mlcs_kicker.function = &hil_mlcs_timer; - add_timer(&hil_mlcs_kicker); + setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0); + mod_timer(&hil_mlcs_kicker, jiffies + HZ); tasklet_enable(&hil_mlcs_tasklet); @@ -1005,7 +1003,7 @@ static int __init hil_mlc_init(void) static void __exit hil_mlc_exit(void) { - del_timer(&hil_mlcs_kicker); + del_timer_sync(&hil_mlcs_kicker); tasklet_disable(&hil_mlcs_tasklet); tasklet_kill(&hil_mlcs_tasklet); diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 7fbffe431bc..2a5982e532f 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -158,6 +158,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { }, }, { + /* Gigabyte M1022M netbook */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "M1022E"), + DMI_MATCH(DMI_BOARD_VERSION, "1.02"), + }, + }, + { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), @@ -516,6 +524,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { */ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { { + /* Acer Aspire 5610 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), + }, + }, + { /* Acer Aspire 5630 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 1df02d25aca..d84a36e545f 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -126,6 +126,8 @@ static unsigned char i8042_suppress_kbd_ack; static struct platform_device *i8042_platform_device; static irqreturn_t i8042_interrupt(int irq, void *dev_id); +static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, + struct serio *serio); void i8042_lock_chip(void) { @@ -139,6 +141,48 @@ void i8042_unlock_chip(void) } EXPORT_SYMBOL(i8042_unlock_chip); +int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *serio)) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&i8042_lock, flags); + + if (i8042_platform_filter) { + ret = -EBUSY; + goto out; + } + + i8042_platform_filter = filter; + +out: + spin_unlock_irqrestore(&i8042_lock, flags); + return ret; +} +EXPORT_SYMBOL(i8042_install_filter); + +int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, + struct serio *port)) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&i8042_lock, flags); + + if (i8042_platform_filter != filter) { + ret = -EINVAL; + goto out; + } + + i8042_platform_filter = NULL; + +out: + spin_unlock_irqrestore(&i8042_lock, flags); + return ret; +} +EXPORT_SYMBOL(i8042_remove_filter); + /* * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to * be ready for reading values from it / writing values to it. @@ -369,6 +413,31 @@ static void i8042_stop(struct serio *serio) } /* + * i8042_filter() filters out unwanted bytes from the input data stream. + * It is called from i8042_interrupt and thus is running with interrupts + * off and i8042_lock held. + */ +static bool i8042_filter(unsigned char data, unsigned char str, + struct serio *serio) +{ + if (unlikely(i8042_suppress_kbd_ack)) { + if ((~str & I8042_STR_AUXDATA) && + (data == 0xfa || data == 0xfe)) { + i8042_suppress_kbd_ack--; + dbg("Extra keyboard ACK - filtered out\n"); + return true; + } + } + + if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { + dbg("Filtered out by platfrom filter\n"); + return true; + } + + return false; +} + +/* * i8042_interrupt() is the most important function in this driver - * it handles the interrupts from the i8042, and sends incoming bytes * to the upper layers. @@ -377,13 +446,16 @@ static void i8042_stop(struct serio *serio) static irqreturn_t i8042_interrupt(int irq, void *dev_id) { struct i8042_port *port; + struct serio *serio; unsigned long flags; unsigned char str, data; unsigned int dfl; unsigned int port_no; + bool filtered; int ret = 1; spin_lock_irqsave(&i8042_lock, flags); + str = i8042_read_status(); if (unlikely(~str & I8042_STR_OBF)) { spin_unlock_irqrestore(&i8042_lock, flags); @@ -391,8 +463,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) ret = 0; goto out; } + data = i8042_read_data(); - spin_unlock_irqrestore(&i8042_lock, flags); if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { static unsigned long last_transmit; @@ -441,21 +513,19 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) } port = &i8042_ports[port_no]; + serio = port->exists ? port->serio : NULL; dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", data, port_no, irq, dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_TIMEOUT ? ", timeout" : ""); - if (unlikely(i8042_suppress_kbd_ack)) - if (port_no == I8042_KBD_PORT_NO && - (data == 0xfa || data == 0xfe)) { - i8042_suppress_kbd_ack--; - goto out; - } + filtered = i8042_filter(data, str, serio); + + spin_unlock_irqrestore(&i8042_lock, flags); - if (likely(port->exists)) - serio_interrupt(port->serio, data, dfl); + if (likely(port->exists && !filtered)) + serio_interrupt(serio, data, dfl); out: return IRQ_RETVAL(ret); diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index f412c69478a..d55874e5d1c 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -180,8 +180,8 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if) } } -static inline unsigned int -ps2_test_one(struct ps2if *ps2if, unsigned int mask) +static unsigned int __devinit ps2_test_one(struct ps2if *ps2if, + unsigned int mask) { unsigned int val; @@ -197,7 +197,7 @@ ps2_test_one(struct ps2if *ps2if, unsigned int mask) * Test the keyboard interface. We basically check to make sure that * we can drive each line to the keyboard independently of each other. */ -static int __init ps2_test(struct ps2if *ps2if) +static int __devinit ps2_test(struct ps2if *ps2if) { unsigned int stat; int ret = 0; @@ -312,7 +312,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) /* * Remove one device from this driver. */ -static int ps2_remove(struct sa1111_dev *dev) +static int __devexit ps2_remove(struct sa1111_dev *dev) { struct ps2if *ps2if = sa1111_get_drvdata(dev); @@ -335,7 +335,7 @@ static struct sa1111_driver ps2_driver = { }, .devid = SA1111_DEVID_PS2, .probe = ps2_probe, - .remove = ps2_remove, + .remove = __devexit_p(ps2_remove), }; static int __init ps2_init(void) diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 0236f0d5fd9..e0f30186d51 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -284,13 +284,7 @@ static void serio_handle_event(void) mutex_lock(&serio_mutex); - /* - * Note that we handle only one event here to give swsusp - * a chance to freeze kseriod thread. Serio events should - * be pretty rare so we are not concerned about taking - * performance hit. - */ - if ((event = serio_get_event())) { + while ((event = serio_get_event())) { switch (event->type) { case SERIO_REGISTER_PORT: @@ -380,10 +374,9 @@ static struct serio *serio_get_pending_child(struct serio *parent) static int serio_thread(void *nothing) { - set_freezable(); do { serio_handle_event(); - wait_event_freezable(serio_wait, + wait_event_interruptible(serio_wait, kthread_should_stop() || !list_empty(&serio_event_list)); } while (!kthread_should_stop()); |