diff options
| -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) { |
