aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/keyboard/atkbd.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index be1fe46cd308..9e80012d0d0c 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};
@@ -565,7 +566,7 @@ static int atkbd_set_leds(struct atkbd *atkbd)
565 566
566static void atkbd_event_work(struct work_struct *work) 567static void atkbd_event_work(struct work_struct *work)
567{ 568{
568 struct atkbd *atkbd = container_of(work, struct atkbd, event_work); 569 struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
569 570
570 mutex_lock(&atkbd->event_mutex); 571 mutex_lock(&atkbd->event_mutex);
571 572
@@ -579,12 +580,30 @@ static void atkbd_event_work(struct work_struct *work)
579} 580}
580 581
581/* 582/*
583 * Schedule switch for execution. We need to throttle requests,
584 * otherwise keyboard may become unresponsive.
585 */
586static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
587{
588 unsigned long delay = msecs_to_jiffies(50);
589
590 if (time_after(jiffies, atkbd->event_jiffies + delay))
591 delay = 0;
592
593 atkbd->event_jiffies = jiffies;
594 set_bit(event_bit, &atkbd->event_mask);
595 wmb();
596 schedule_delayed_work(&atkbd->event_work, delay);
597}
598
599/*
582 * Event callback from the input module. Events that change the state of 600 * 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 601 * the hardware are processed here. If action can not be performed in
584 * interrupt context it is offloaded to atkbd_event_work. 602 * interrupt context it is offloaded to atkbd_event_work.
585 */ 603 */
586 604
587static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 605static int atkbd_event(struct input_dev *dev,
606 unsigned int type, unsigned int code, int value)
588{ 607{
589 struct atkbd *atkbd = input_get_drvdata(dev); 608 struct atkbd *atkbd = input_get_drvdata(dev);
590 609
@@ -594,19 +613,12 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
594 switch (type) { 613 switch (type) {
595 614
596 case EV_LED: 615 case EV_LED:
597 set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask); 616 atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
598 wmb();
599 schedule_work(&atkbd->event_work);
600 return 0; 617 return 0;
601 618
602 case EV_REP: 619 case EV_REP:
603 620 if (!atkbd->softrepeat)
604 if (!atkbd->softrepeat) { 621 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; 622 return 0;
611 } 623 }
612 624
@@ -940,7 +952,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
940 952
941 atkbd->dev = dev; 953 atkbd->dev = dev;
942 ps2_init(&atkbd->ps2dev, serio); 954 ps2_init(&atkbd->ps2dev, serio);
943 INIT_WORK(&atkbd->event_work, atkbd_event_work); 955 INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
944 mutex_init(&atkbd->event_mutex); 956 mutex_init(&atkbd->event_mutex);
945 957
946 switch (serio->id.type) { 958 switch (serio->id.type) {