aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/atkbd.c47
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h11
-rw-r--r--drivers/input/serio/serio.c2
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
566static void atkbd_event_work(struct work_struct *work) 568static 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 */
587static 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
587static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 606static 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
770static void serio_cleanup(struct serio *serio) 770static 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
776static void serio_shutdown(struct device *dev) 778static void serio_shutdown(struct device *dev)