aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2007-06-28 00:46:56 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-06-28 00:46:56 -0400
commitda4249c99fd59c4e224e4f9acaf07669d205bb1d (patch)
treeb1b35d6fa4890f7a1119a6bc658a5827f353a02b
parent9d9d50bb2efb50594abfc3941a5504b62c514ebd (diff)
Input: atkbd - throttle LED switching
On some boxes keyboard controllers are too slow to withstand continuous flow of requests to turn keyboard LEDs on and off and start losing some keypresses or even all of them. Delay executing of LED switching request if we had another one within 50 ms thus easing load on the controller. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-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) {