diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-05 18:55:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-05 18:55:37 -0400 |
commit | cab8e5c4444cb7d9b8035de5d81fbfd5284a02fa (patch) | |
tree | 04af29514a1e879eb254fb758f57a978d9033bd4 /drivers/input/keyboard | |
parent | 0dac723e5c15ddb9bd26c1db21ee64ab71ae4925 (diff) | |
parent | 4e4eda866ec7bd7a151e4884a291221eb74644ae (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: document some of keycodes
Input: add a new EV_SW SW_RADIO event, for radio switches on laptops
Input: serio - take drv_mutex in serio_cleanup()
Input: atkbd - use printk_ratelimit for spurious ACK messages
Input: atkbd - throttle LED switching
Input: i8042 - add HP Pavilion ZT1000 to the MUX blacklist
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 47 |
1 files changed, 30 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 | ||
566 | static void atkbd_event_work(struct work_struct *work) | 568 | static 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 | */ | ||
587 | static 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 | ||
587 | static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 606 | static 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) { |