diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 47 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 11 | ||||
-rw-r--r-- | drivers/input/serio/serio.c | 2 |
3 files changed, 43 insertions, 17 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index be1fe46cd308..9950fcb33650 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -219,7 +219,8 @@ struct atkbd { | |||
219 | unsigned long time; | 219 | unsigned long time; |
220 | unsigned long err_count; | 220 | unsigned long err_count; |
221 | 221 | ||
222 | struct work_struct event_work; | 222 | struct delayed_work event_work; |
223 | unsigned long event_jiffies; | ||
223 | struct mutex event_mutex; | 224 | struct mutex event_mutex; |
224 | unsigned long event_mask; | 225 | unsigned long event_mask; |
225 | }; | 226 | }; |
@@ -408,9 +409,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
408 | goto out; | 409 | goto out; |
409 | case ATKBD_RET_ACK: | 410 | case ATKBD_RET_ACK: |
410 | case ATKBD_RET_NAK: | 411 | case ATKBD_RET_NAK: |
411 | printk(KERN_WARNING "atkbd.c: Spurious %s on %s. " | 412 | if (printk_ratelimit()) |
412 | "Some program might be trying access hardware directly.\n", | 413 | printk(KERN_WARNING "atkbd.c: Spurious %s on %s. " |
413 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); | 414 | "Some program might be trying access hardware directly.\n", |
415 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); | ||
414 | goto out; | 416 | goto out; |
415 | case ATKBD_RET_HANGEUL: | 417 | case ATKBD_RET_HANGEUL: |
416 | case ATKBD_RET_HANJA: | 418 | case ATKBD_RET_HANJA: |
@@ -565,7 +567,7 @@ static int atkbd_set_leds(struct atkbd *atkbd) | |||
565 | 567 | ||
566 | static void atkbd_event_work(struct work_struct *work) | 568 | static void atkbd_event_work(struct work_struct *work) |
567 | { | 569 | { |
568 | struct atkbd *atkbd = container_of(work, struct atkbd, event_work); | 570 | struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work); |
569 | 571 | ||
570 | mutex_lock(&atkbd->event_mutex); | 572 | mutex_lock(&atkbd->event_mutex); |
571 | 573 | ||
@@ -579,12 +581,30 @@ static void atkbd_event_work(struct work_struct *work) | |||
579 | } | 581 | } |
580 | 582 | ||
581 | /* | 583 | /* |
584 | * Schedule switch for execution. We need to throttle requests, | ||
585 | * otherwise keyboard may become unresponsive. | ||
586 | */ | ||
587 | static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit) | ||
588 | { | ||
589 | unsigned long delay = msecs_to_jiffies(50); | ||
590 | |||
591 | if (time_after(jiffies, atkbd->event_jiffies + delay)) | ||
592 | delay = 0; | ||
593 | |||
594 | atkbd->event_jiffies = jiffies; | ||
595 | set_bit(event_bit, &atkbd->event_mask); | ||
596 | wmb(); | ||
597 | schedule_delayed_work(&atkbd->event_work, delay); | ||
598 | } | ||
599 | |||
600 | /* | ||
582 | * Event callback from the input module. Events that change the state of | 601 | * Event callback from the input module. Events that change the state of |
583 | * the hardware are processed here. If action can not be performed in | 602 | * the hardware are processed here. If action can not be performed in |
584 | * interrupt context it is offloaded to atkbd_event_work. | 603 | * interrupt context it is offloaded to atkbd_event_work. |
585 | */ | 604 | */ |
586 | 605 | ||
587 | static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 606 | static int atkbd_event(struct input_dev *dev, |
607 | unsigned int type, unsigned int code, int value) | ||
588 | { | 608 | { |
589 | struct atkbd *atkbd = input_get_drvdata(dev); | 609 | struct atkbd *atkbd = input_get_drvdata(dev); |
590 | 610 | ||
@@ -594,19 +614,12 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co | |||
594 | switch (type) { | 614 | switch (type) { |
595 | 615 | ||
596 | case EV_LED: | 616 | case EV_LED: |
597 | set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask); | 617 | atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT); |
598 | wmb(); | ||
599 | schedule_work(&atkbd->event_work); | ||
600 | return 0; | 618 | return 0; |
601 | 619 | ||
602 | case EV_REP: | 620 | case EV_REP: |
603 | 621 | if (!atkbd->softrepeat) | |
604 | if (!atkbd->softrepeat) { | 622 | atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT); |
605 | set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask); | ||
606 | wmb(); | ||
607 | schedule_work(&atkbd->event_work); | ||
608 | } | ||
609 | |||
610 | return 0; | 623 | return 0; |
611 | } | 624 | } |
612 | 625 | ||
@@ -940,7 +953,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
940 | 953 | ||
941 | atkbd->dev = dev; | 954 | atkbd->dev = dev; |
942 | ps2_init(&atkbd->ps2dev, serio); | 955 | ps2_init(&atkbd->ps2dev, serio); |
943 | INIT_WORK(&atkbd->event_work, atkbd_event_work); | 956 | INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); |
944 | mutex_init(&atkbd->event_mutex); | 957 | mutex_init(&atkbd->event_mutex); |
945 | 958 | ||
946 | switch (serio->id.type) { | 959 | switch (serio->id.type) { |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f4a2517925e4..4fca1e7f2678 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -200,6 +200,17 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
200 | }, | 200 | }, |
201 | }, | 201 | }, |
202 | { | 202 | { |
203 | /* | ||
204 | * Like DV4017EA does not raise AUXERR for errors on MUX ports. | ||
205 | */ | ||
206 | .ident = "HP Pavilion ZT1000", | ||
207 | .matches = { | ||
208 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
209 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), | ||
210 | DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"), | ||
211 | }, | ||
212 | }, | ||
213 | { | ||
203 | .ident = "Toshiba P10", | 214 | .ident = "Toshiba P10", |
204 | .matches = { | 215 | .matches = { |
205 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 216 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 5895202b972c..a8f3bc1dff22 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -769,8 +769,10 @@ static int serio_driver_remove(struct device *dev) | |||
769 | 769 | ||
770 | static void serio_cleanup(struct serio *serio) | 770 | static void serio_cleanup(struct serio *serio) |
771 | { | 771 | { |
772 | mutex_lock(&serio->drv_mutex); | ||
772 | if (serio->drv && serio->drv->cleanup) | 773 | if (serio->drv && serio->drv->cleanup) |
773 | serio->drv->cleanup(serio); | 774 | serio->drv->cleanup(serio); |
775 | mutex_unlock(&serio->drv_mutex); | ||
774 | } | 776 | } |
775 | 777 | ||
776 | static void serio_shutdown(struct device *dev) | 778 | static void serio_shutdown(struct device *dev) |