diff options
| author | Greg Kroah-Hartman <gregkh@google.com> | 2020-11-22 10:17:08 +0100 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@google.com> | 2020-11-22 10:17:08 +0100 |
| commit | d5c6e5dc0e1d6a32151260ee7d699e5935522daa (patch) | |
| tree | 3ba0d40308e97ef6a5f13cfe28b538618220d304 /drivers/input | |
| parent | 4e6c6e008513d98396bf9f92bf38b83b6980fa54 (diff) | |
| parent | 899c58731b77ce6bbf991286b016be278a23a2da (diff) | |
Merge 4.4.245 into android-4.4-p
Changes in 4.4.245
powerpc/64s: Define MASKABLE_RELON_EXCEPTION_PSERIES_OOL
powerpc/64s: move some exception handlers out of line
powerpc/64s: flush L1D on kernel entry
powerpc: Add a framework for user access tracking
powerpc: Implement user_access_begin and friends
powerpc: Fix __clear_user() with KUAP enabled
powerpc/uaccess: Evaluate macro arguments once, before user access is allowed
powerpc/64s: flush L1D after user accesses
i2c: imx: Fix external abort on interrupt in exit paths
xfs: catch inode allocation state mismatch corruption
xfs: validate cached inodes are free when allocated
powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
Input: sunkbd - avoid use-after-free in teardown paths
mac80211: always wind down STA state
KVM: x86: clflushopt should be treated as a no-op by emulation
Linux 4.4.245
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I78cbd0900d1b7be38a6d7e588bff9189bc8f1718
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/keyboard/sunkbd.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index dc6bb9d5b4f0..191c27dda386 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -115,7 +115,8 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio, switch (data) { case SUNKBD_RET_RESET: - schedule_work(&sunkbd->tq); + if (sunkbd->enabled) + schedule_work(&sunkbd->tq); sunkbd->reset = -1; break; @@ -216,16 +217,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) } /* - * sunkbd_reinit() sets leds and beeps to a state the computer remembers they - * were in. + * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers + * they were in. */ -static void sunkbd_reinit(struct work_struct *work) +static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd) { - struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); - - wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); - serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); serio_write(sunkbd->serio, (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | @@ -238,11 +235,39 @@ static void sunkbd_reinit(struct work_struct *work) SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); } + +/* + * sunkbd_reinit() wait for the keyboard reset to complete and restores state + * of leds and beeps. + */ + +static void sunkbd_reinit(struct work_struct *work) +{ + struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); + + /* + * It is OK that we check sunkbd->enabled without pausing serio, + * as we only want to catch true->false transition that will + * happen once and we will be woken up for it. + */ + wait_event_interruptible_timeout(sunkbd->wait, + sunkbd->reset >= 0 || !sunkbd->enabled, + HZ); + + if (sunkbd->reset >= 0 && sunkbd->enabled) + sunkbd_set_leds_beeps(sunkbd); +} + static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) { serio_pause_rx(sunkbd->serio); sunkbd->enabled = enable; serio_continue_rx(sunkbd->serio); + + if (!enable) { + wake_up_interruptible(&sunkbd->wait); + cancel_work_sync(&sunkbd->tq); + } } /* |
