From patchwork Thu Apr 21 11:43:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H. Nikolaus Schaller" X-Patchwork-Id: 8899691 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 512A3BF29F for ; Thu, 21 Apr 2016 11:45:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7D5D52025A for ; Thu, 21 Apr 2016 11:45:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 95E9120211 for ; Thu, 21 Apr 2016 11:45:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752428AbcDULoJ (ORCPT ); Thu, 21 Apr 2016 07:44:09 -0400 Received: from mo4-p00-ob.smtp.rzone.de ([81.169.146.217]:45591 "EHLO mo4-p00-ob.smtp.rzone.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752367AbcDULoH (ORCPT ); Thu, 21 Apr 2016 07:44:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1461239044; l=2454; s=domk; d=goldelico.com; h=References:In-Reply-To:References:In-Reply-To:Date:Subject:Cc:To: From; bh=Ijc9aMEUuOaqGdvNaX+kzHyRtYqp+0iigOxvAad+n8k=; b=TDyix6IDZl4KNZWC8OH/rMYBsGXsxYaIFufw9/MP2LPnfn4uT5mb0xPVDb44schSAIM AnVwwX6uCRGi92YKXYEc6GeFT60rh/erIe6aix9Zrdobfi2dNxVv3Q/KO0t29vruQYcl5 O0ntlRWSFjT0EWWslpVXXZSPNp4b2qStxRQ= X-RZG-AUTH: :JGIXVUS7cutRB/49FwqZ7WcecEarQROEYabkiUo6mSAGQ+qKIDcoIFI= X-RZG-CLASS-ID: mo00 Received: from localhost.localdomain (p57AE0902.dip0.t-ipconnect.de [87.174.9.2]) by smtp.strato.de (RZmta 37.24 DYNA|AUTH) with ESMTPA id I03fe7s3LBhuEgD; Thu, 21 Apr 2016 13:43:56 +0200 (CEST) From: "H. Nikolaus Schaller" To: Dmitry Torokhov , Fabio Estevam , Peter Ujfalusi , "H. Nikolaus Schaller" Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@pyra-handheld.com, letux-kernel@openphoenux.org Subject: [PATCH v2 4/4] input: twl6040-vibra: fix atomic schedule panic Date: Thu, 21 Apr 2016 13:43:50 +0200 Message-Id: X-Mailer: git-send-email 2.7.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-8.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP commit c6f39257c952 ("mfd: twl6040: Use regmap for register cache") did remove the private cache for the vibra control registers and replaced access within twl6040_get_vibralr_status() by calls to regmap. This is ok, as long as twl6040_get_vibralr_status() uses already cached values or is not called from interrupt context. But we call this in vibra_play() for checking that the vibrator is not configured for audio mode. The result is a "BUG: scheduling while atomic" if the first use of the twl6040 is a vibra effect, because the first fetch is by reading the twl6040 registers through (blocking) i2c and not from the cache. As soon as the regmap has cached the status, further calls are fine. The solution is to move the condition to the work() function which runs in context that can block. The original code returns -EBUSY, but the return value of ->play() functions is ignored anyways. Hence, we do not loose functionality by not returning an error but just reporting the issue to INFO loglevel. Tested-on: Pyra (omap5) prototype Signed-off-by: H. Nikolaus Schaller --- drivers/input/misc/twl6040-vibra.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index f4384b7..5690eb7 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -181,6 +181,14 @@ static void vibra_play_work(struct work_struct *work) { struct vibra_info *info = container_of(work, struct vibra_info, play_work); + int ret; + + /* Do not allow effect, while the routing is set to use audio */ + ret = twl6040_get_vibralr_status(info->twl6040); + if (ret & TWL6040_VIBSEL) { + dev_info(info->dev, "Vibra is configured for audio\n"); + return; + } if (info->weak_speed || info->strong_speed) { if (!info->enabled) @@ -196,14 +204,6 @@ static int vibra_play(struct input_dev *input, void *data, struct ff_effect *effect) { struct vibra_info *info = input_get_drvdata(input); - int ret; - - /* Do not allow effect, while the routing is set to use audio */ - ret = twl6040_get_vibralr_status(info->twl6040); - if (ret & TWL6040_VIBSEL) { - dev_info(&input->dev, "Vibra is configured for audio\n"); - return -EBUSY; - } info->weak_speed = effect->u.rumble.weak_magnitude; info->strong_speed = effect->u.rumble.strong_magnitude;