From patchwork Thu Sep 7 00:21:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 9941495 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 3EE90602CC for ; Thu, 7 Sep 2017 00:21:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 35808267EC for ; Thu, 7 Sep 2017 00:21:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A26F2766D; Thu, 7 Sep 2017 00:21:33 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable 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 B6FD527FAE for ; Thu, 7 Sep 2017 00:21:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751798AbdIGAVR (ORCPT ); Wed, 6 Sep 2017 20:21:17 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:37857 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751538AbdIGAVQ (ORCPT ); Wed, 6 Sep 2017 20:21:16 -0400 Received: by mail-pf0-f194.google.com with SMTP id a2so3732463pfj.4; Wed, 06 Sep 2017 17:21:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=RhFablgOagkRtYHI0XQ5ccEeL6gXKN+lXWUOZ733nug=; b=H2dYfGT9onHLqEXFqsN7hiZk5s7u54s5btBcuKfJK9tIP/b4weRuSP5g0AasF3MoAH O9Z6QvP1wO2SeXjLKC5QHrriQ3gP32CPMnQ+Nz8K1jy7duD0WCTFJLOIL6GqD2jty0wZ lijAh4dXFyPgTiD9iUSwMRAhUHq5lrM2RPFuOQu+VxsT1kbP0Bt16ys7mI3PUBKFlKmA mmSPnEErYjasDeZdDgUT4Eqq6CWUQRWaROZQBTpjNBoPCeM5n5yCVT88EcR+zCUXympm SlLjsxbgpAeGRi6FS/iw/50571pjalVWpik8hsOfstngmtyHteyzmHnK04OImQUNbiCz y+AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=RhFablgOagkRtYHI0XQ5ccEeL6gXKN+lXWUOZ733nug=; b=nuMV8sZltMPvJ1KdpPua3K12zWlL4frT5ETaD37hLbG6JNrxkIuFYWQIdctKn/kWCD 26ZtBCmim/se9vTlfbpQFzDGjLDj7qBzbuMPkyxgk3TrUFdnc1MeIWaYF1rSjD4OT67z 7k+17mDl34ZlHPklbMKn6weWGQ+2BcT1BfZKwsfoNJ1zDPvPUZttmkP/eYFWW7oIIoLa kMxEGzhEqe/hwra44M49+jV+NpcdQcWy1lp2payVS2S09poGvACk9WBCn0PYbXgYD2hS 8FEyLXTA5e47XgXgezf43dmR6WdBRPJ6iBjZMeJ9nAMxGm0xHTttqgArswGCIFPU2bZF PsTg== X-Gm-Message-State: AHPjjUi0qpMugE8wqokipYautfb0ksNCL6PDS3/Ffw9hhPy17sP78/vC LUj79xdHXTpF76Bqe8s= X-Google-Smtp-Source: ADKCNb7WzDBvzoXfMCAFc7fZhbWfeXSlUY24Awli4wNAK7hEOIxNEqw5uSCT5P5N0OEYx7llvR5GFw== X-Received: by 10.98.63.140 with SMTP id z12mr952869pfj.218.1504743675290; Wed, 06 Sep 2017 17:21:15 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([100.98.112.21]) by smtp.gmail.com with ESMTPSA id d25sm1282515pfb.1.2017.09.06.17.21.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 06 Sep 2017 17:21:14 -0700 (PDT) From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Rodrigo Rivas Costa , =?UTF-8?q?Cl=C3=A9ment=20VUCHENER?= , Elias Vanderstuyft , linux-kernel@vger.kernel.org Subject: [PATCH 1/6] Input: uinput - avoid FF flush when destroying device Date: Wed, 6 Sep 2017 17:21:07 -0700 Message-Id: <20170907002112.14097-1-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.14.1.581.gf28d330327-goog MIME-Version: 1.0 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 Normally, when input device supporting force feedback effects is being destroyed, we try to "flush" currently playing effects, so that the physical device does not continue vibrating (or executing other effects). Unfortunately this does not work well for uinput as flushing of the effects deadlocks with the destroy action: - if device is being destroyed because the file descriptor is being closed, then there is noone to even service FF requests; - if device is being destroyed because userspace sent UI_DEV_DESTROY, while theoretically it could be possible to service FF requests, userspace is unlikely to do so (they'd need to make sure FF handling happens on a separate thread) even if kernel solves the issue with FF ioctls deadlocking with UI_DEV_DESTROY ioctl on udev->mutex. To avoid lockups like the one below, let's install a custom input device flush handler, and avoid trying to flush force feedback effects when we destroying the device, and instead rely on uinput to shut off the device properly. NMI watchdog: Watchdog detected hard LOCKUP on cpu 3 ... <> [] _raw_spin_lock_irqsave+0x37/0x40 [] complete+0x1d/0x50 [] uinput_request_done+0x3c/0x40 [uinput] [] uinput_request_submit.part.7+0x47/0xb0 [uinput] [] uinput_dev_erase_effect+0x5b/0x76 [uinput] [] erase_effect+0xad/0xf0 [] flush_effects+0x4d/0x90 [] input_flush_device+0x40/0x60 [] evdev_cleanup+0xac/0xc0 [] evdev_disconnect+0x2b/0x60 [] __input_unregister_device+0xac/0x150 [] input_unregister_device+0x47/0x70 [] uinput_destroy_device+0xb5/0xc0 [uinput] [] uinput_ioctl_handler.isra.9+0x65e/0x740 [uinput] [] ? do_futex+0x12b/0xad0 [] uinput_ioctl+0x18/0x20 [uinput] [] do_vfs_ioctl+0x298/0x480 [] ? security_file_ioctl+0x43/0x60 [] SyS_ioctl+0x79/0x90 [] entry_SYSCALL_64_fastpath+0x12/0x71 Reported-by: Rodrigo Rivas Costa Reported-by: Clément VUCHENER Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=193741 Signed-off-by: Dmitry Torokhov --- drivers/input/ff-core.c | 13 ++++++++++--- drivers/input/misc/uinput.c | 18 ++++++++++++++++++ include/linux/input.h | 1 + 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 8f2042432c85..66a46c84e28f 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -237,9 +237,15 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file) EXPORT_SYMBOL_GPL(input_ff_erase); /* - * flush_effects - erase all effects owned by a file handle + * input_ff_flush - erase all effects owned by a file handle + * @dev: input device to erase effect from + * @file: purported owner of the effects + * + * This function erases all force-feedback effects associated with + * the given owner from specified device. Note that @file may be %NULL, + * in which case all effects will be erased. */ -static int flush_effects(struct input_dev *dev, struct file *file) +int input_ff_flush(struct input_dev *dev, struct file *file) { struct ff_device *ff = dev->ff; int i; @@ -255,6 +261,7 @@ static int flush_effects(struct input_dev *dev, struct file *file) return 0; } +EXPORT_SYMBOL_GPL(input_ff_flush); /** * input_ff_event() - generic handler for force-feedback events @@ -343,7 +350,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects) mutex_init(&ff->mutex); dev->ff = ff; - dev->flush = flush_effects; + dev->flush = input_ff_flush; dev->event = input_ff_event; __set_bit(EV_FF, dev->evbit); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 022be0e22eba..2cff40be8860 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -230,6 +230,18 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) return uinput_request_submit(udev, &request); } +static int uinput_dev_flush(struct input_dev *dev, struct file *file) +{ + /* + * If we are called with file == NULL that means we are tearing + * down the device, and therefore we can not handle FF erase + * requests: either we are handling UI_DEV_DESTROY (and holding + * the udev->mutex), or the file descriptor is closed and there is + * nobody on the other side anymore. + */ + return file ? input_ff_flush(dev, file) : 0; +} + static void uinput_destroy_device(struct uinput_device *udev) { const char *name, *phys; @@ -297,6 +309,12 @@ static int uinput_create_device(struct uinput_device *udev) dev->ff->playback = uinput_dev_playback; dev->ff->set_gain = uinput_dev_set_gain; dev->ff->set_autocenter = uinput_dev_set_autocenter; + /* + * The standard input_ff_flush() implementation does + * not quite work for uinput as we can't reasonably + * handle FF requests during device teardown. + */ + dev->flush = uinput_dev_flush; } error = input_register_device(udev->dev); diff --git a/include/linux/input.h b/include/linux/input.h index 5645a0f39b9a..9b03f34807a7 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -537,6 +537,7 @@ int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code, int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file); int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file); +int input_ff_flush(struct input_dev *dev, struct file *file); int input_ff_create_memless(struct input_dev *dev, void *data, int (*play_effect)(struct input_dev *, void *, struct ff_effect *));