diff options
Diffstat (limited to 'drivers/input/keyboard/atkbd.c')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 40 |
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 | ||
566 | static void atkbd_event_work(struct work_struct *work) | 567 | static 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 | */ | ||
586 | static 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 | ||
587 | static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 605 | static 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) { |