Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 58209
b: refs/heads/master
c: da4249c
h: refs/heads/master
i:
  58207: 4c7f916
v: v3
  • Loading branch information
Dmitry Torokhov committed Jun 28, 2007
1 parent dc7d759 commit c79d049
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9d9d50bb2efb50594abfc3941a5504b62c514ebd
refs/heads/master: da4249c99fd59c4e224e4f9acaf07669d205bb1d
40 changes: 26 additions & 14 deletions trunk/drivers/input/keyboard/atkbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ struct atkbd {
unsigned long time;
unsigned long err_count;

struct work_struct event_work;
struct delayed_work event_work;
unsigned long event_jiffies;
struct mutex event_mutex;
unsigned long event_mask;
};
Expand Down Expand Up @@ -565,7 +566,7 @@ static int atkbd_set_leds(struct atkbd *atkbd)

static void atkbd_event_work(struct work_struct *work)
{
struct atkbd *atkbd = container_of(work, struct atkbd, event_work);
struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);

mutex_lock(&atkbd->event_mutex);

Expand All @@ -578,13 +579,31 @@ static void atkbd_event_work(struct work_struct *work)
mutex_unlock(&atkbd->event_mutex);
}

/*
* Schedule switch for execution. We need to throttle requests,
* otherwise keyboard may become unresponsive.
*/
static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
{
unsigned long delay = msecs_to_jiffies(50);

if (time_after(jiffies, atkbd->event_jiffies + delay))
delay = 0;

atkbd->event_jiffies = jiffies;
set_bit(event_bit, &atkbd->event_mask);
wmb();
schedule_delayed_work(&atkbd->event_work, delay);
}

/*
* Event callback from the input module. Events that change the state of
* the hardware are processed here. If action can not be performed in
* interrupt context it is offloaded to atkbd_event_work.
*/

static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
static int atkbd_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
struct atkbd *atkbd = input_get_drvdata(dev);

Expand All @@ -594,19 +613,12 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
switch (type) {

case EV_LED:
set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask);
wmb();
schedule_work(&atkbd->event_work);
atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
return 0;

case EV_REP:

if (!atkbd->softrepeat) {
set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask);
wmb();
schedule_work(&atkbd->event_work);
}

if (!atkbd->softrepeat)
atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
return 0;
}

Expand Down Expand Up @@ -940,7 +952,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)

atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
INIT_WORK(&atkbd->event_work, atkbd_event_work);
INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
mutex_init(&atkbd->event_mutex);

switch (serio->id.type) {
Expand Down

0 comments on commit c79d049

Please sign in to comment.