From patchwork Sat Feb 3 15:58:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhang Bo X-Patchwork-Id: 10198599 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A6DAD602CA for ; Sat, 3 Feb 2018 15:59:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 88D4128F5A for ; Sat, 3 Feb 2018 15:59:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7B3B728FDE; Sat, 3 Feb 2018 15:59:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_BL_SPAMCOP_NET, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 02D0928F5A for ; Sat, 3 Feb 2018 15:59:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751644AbeBCP7b (ORCPT ); Sat, 3 Feb 2018 10:59:31 -0500 Received: from m50-112.126.com ([123.125.50.112]:57224 "EHLO m50-112.126.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751932AbeBCP7a (ORCPT ); Sat, 3 Feb 2018 10:59:30 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; s=s110527; h=From:Subject:Date:Message-Id; bh=I+IYH4bKkOrGq3vi3N Aw3BYdNFsKcnwkDh1DW8aM41k=; b=Fq5KUWWOc0qkPYm38L6SwdokfNP/PYjPS9 +NxH3+xgq/h5wENtxVEHPQEyevXq43mn7ZkkNg7Hr2TOpKN28rLVCQOWoRSC5KNV wZkoU9igxXVXCKyeEJ95LKrDSYbZJtrBqB1ZKQyfNMm0xhTjETgZutvJ5+3fSxK5 dd2yKs2jI= Received: from bogon.DHCP (unknown [123.139.75.126]) by smtp6 (Coremail) with SMTP id j9KowABHJjci3HVaxE+EAA--.4198S4; Sat, 03 Feb 2018 23:58:27 +0800 (CST) From: Zhang Bo To: dmitry.torokhov@gmail.com Cc: robh@kernel.org, DRivshin@allworx.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, zhang.bo19@zte.com.cn, andy.shevchenko@gmail.com, zbsdta@126.com Subject: [PATCH v2] Input: matrix_keypad - fix keypad does not response Date: Sat, 3 Feb 2018 23:58:16 +0800 Message-Id: <20180203155816.18221-1-zbsdta@126.com> X-Mailer: git-send-email 2.14.3 X-CM-TRANSID: j9KowABHJjci3HVaxE+EAA--.4198S4 X-Coremail-Antispam: 1Uf129KBjvJXoWxGryrGFyxKr1UZFW3Jw43Jrb_yoW5Gr1kpr W3G3Wqyr4UJ3Wj93yvqrWkuas8Gw4kZry2grn5W348Jrn0vr1UGrn3K3ySga4UArW0yanr ZF4kZw15G3WqyF7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07U5kuxUUUUU= X-Originating-IP: [123.139.75.126] X-CM-SenderInfo: h2evv3bd6rjloofrz/1tbikAPhSVpD3+vV1QAAsW Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If matrix_keypad_stop() is calling and the keypad interrupt is triggered, disable_row_irqs() is called by both matrix_keypad_interrupt() and matrix_keypad_stop() at the same time. then disable_row_irqs() is called twice, and the device enter suspend state before keypad->work is executed. At this condition the device will start keypad and enable irq once after resume. and then irqs are disabled yet because irqs are disabled twice and only enable once. Take lock around keypad->stopped and queue delayed work in matrix_keypad_start() and matrix_keypad_stop() to ensure irqs operation and scheduling scan work are in atomic operation. Signed-off-by: Zhang Bo --- Changes in v2: - Change commit message and full name in the signed-off-by tag. drivers/input/keyboard/matrix_keypad.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 1f316d66e6f7..13fe51824637 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -169,7 +169,8 @@ static void matrix_keypad_scan(struct work_struct *work) /* Enable IRQs again */ spin_lock_irq(&keypad->lock); keypad->scan_pending = false; - enable_row_irqs(keypad); + if (keypad->stopped == false) + enable_row_irqs(keypad); spin_unlock_irq(&keypad->lock); } @@ -202,14 +203,16 @@ static int matrix_keypad_start(struct input_dev *dev) { struct matrix_keypad *keypad = input_get_drvdata(dev); + spin_lock_irq(&keypad->lock); keypad->stopped = false; - mb(); /* * Schedule an immediate key scan to capture current key state; * columns will be activated and IRQs be enabled after the scan. */ - schedule_delayed_work(&keypad->work, 0); + if (keypad->scan_pending == false) + schedule_delayed_work(&keypad->work, 0); + spin_unlock_irq(&keypad->lock); return 0; } @@ -218,14 +221,17 @@ static void matrix_keypad_stop(struct input_dev *dev) { struct matrix_keypad *keypad = input_get_drvdata(dev); + spin_lock_irq(&keypad->lock); keypad->stopped = true; - mb(); - flush_work(&keypad->work.work); /* * matrix_keypad_scan() will leave IRQs enabled; * we should disable them now. */ - disable_row_irqs(keypad); + if (keypad->scan_pending == false) + disable_row_irqs(keypad); + spin_unlock_irq(&keypad->lock); + + flush_work(&keypad->work.work); } #ifdef CONFIG_PM_SLEEP