From patchwork Mon Nov 6 12:34:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Eckert X-Patchwork-Id: 741712 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 763A2C4332F for ; Mon, 6 Nov 2023 12:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231618AbjKFMej (ORCPT ); Mon, 6 Nov 2023 07:34:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59586 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231566AbjKFMee (ORCPT ); Mon, 6 Nov 2023 07:34:34 -0500 Received: from mxout70.expurgate.net (mxout70.expurgate.net [194.37.255.70]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA85ABB for ; Mon, 6 Nov 2023 04:34:29 -0800 (PST) Received: from [127.0.0.1] (helo=localhost) by relay.expurgate.net with smtp (Exim 4.92) (envelope-from ) id 1qzyoG-00HTwh-D3 for linux-serial@vger.kernel.org; Mon, 06 Nov 2023 13:34:28 +0100 Received: from [195.243.126.94] (helo=securemail.tdt.de) by relay.expurgate.net with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qzyoG-00CA0N-1u for linux-serial@vger.kernel.org; Mon, 06 Nov 2023 13:34:28 +0100 Received: from securemail.tdt.de (localhost [127.0.0.1]) by securemail.tdt.de (Postfix) with ESMTP id CB81C24004D for ; Mon, 6 Nov 2023 13:34:27 +0100 (CET) Received: from mail.dev.tdt.de (unknown [10.2.4.42]) by securemail.tdt.de (Postfix) with ESMTP id 8FE8D240040; Mon, 6 Nov 2023 13:34:27 +0100 (CET) Received: from localhost.localdomain (unknown [10.2.3.40]) by mail.dev.tdt.de (Postfix) with ESMTPSA id 3BB2E2225B; Mon, 6 Nov 2023 13:34:27 +0100 (CET) From: Florian Eckert To: Eckert.Florian@googlemail.com, gregkh@linuxfoundation.org, jirislaby@kernel.org, pavel@ucw.cz, lee@kernel.org, kabel@kernel.org, u.kleine-koenig@pengutronix.de, m.brock@vanmierlo.com Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, linux-leds@vger.kernel.org Subject: [Patch v7 4/6] leds: ledtrig-tty: replace mutex with completion Date: Mon, 6 Nov 2023 13:34:13 +0100 Message-ID: <20231106123415.3365732-5-fe@dev.tdt.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20231106123415.3365732-1-fe@dev.tdt.de> References: <20231106123415.3365732-1-fe@dev.tdt.de> MIME-Version: 1.0 X-purgate-ID: 151534::1699274068-86F347EA-464BD321/0/0 X-purgate: clean X-purgate-type: clean Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org With this commit, the mutex handling is replaced by the completion handling. When handling mutex, it must always be ensured that the held mutex is also released again. This is more error-prone should the number of code paths increase. This is a preparatory commit to make the trigger more configurable via additional sysfs parameters. With this change, the worker always runs and is no longer stopped if no ttyname is set. Signed-off-by: Florian Eckert --- drivers/leds/trigger/ledtrig-tty.c | 60 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-tty.c b/drivers/leds/trigger/ledtrig-tty.c index 86595add72cd..3badf74fa420 100644 --- a/drivers/leds/trigger/ledtrig-tty.c +++ b/drivers/leds/trigger/ledtrig-tty.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include @@ -12,15 +13,24 @@ struct ledtrig_tty_data { struct led_classdev *led_cdev; struct delayed_work dwork; - struct mutex mutex; + struct completion sysfs; const char *ttyname; struct tty_struct *tty; int rx, tx; }; -static void ledtrig_tty_restart(struct ledtrig_tty_data *trigger_data) +static int ledtrig_tty_waitforcompletion(struct device *dev) { - schedule_delayed_work(&trigger_data->dwork, 0); + struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev); + int ret; + + ret = wait_for_completion_timeout(&trigger_data->sysfs, + msecs_to_jiffies(LEDTRIG_TTY_INTERVAL * 20)); + + if (ret == 0) + return -ETIMEDOUT; + + return ret; } static ssize_t ttyname_show(struct device *dev, @@ -28,14 +38,16 @@ static ssize_t ttyname_show(struct device *dev, { struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev); ssize_t len = 0; + int completion; - mutex_lock(&trigger_data->mutex); + reinit_completion(&trigger_data->sysfs); + completion = ledtrig_tty_waitforcompletion(dev); + if (completion < 0) + return completion; if (trigger_data->ttyname) len = sprintf(buf, "%s\n", trigger_data->ttyname); - mutex_unlock(&trigger_data->mutex); - return len; } @@ -46,7 +58,7 @@ static ssize_t ttyname_store(struct device *dev, struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev); char *ttyname; ssize_t ret = size; - bool running; + int completion; if (size > 0 && buf[size - 1] == '\n') size -= 1; @@ -59,9 +71,10 @@ static ssize_t ttyname_store(struct device *dev, ttyname = NULL; } - mutex_lock(&trigger_data->mutex); - - running = trigger_data->ttyname != NULL; + reinit_completion(&trigger_data->sysfs); + completion = ledtrig_tty_waitforcompletion(dev); + if (completion < 0) + return completion; kfree(trigger_data->ttyname); tty_kref_put(trigger_data->tty); @@ -69,11 +82,6 @@ static ssize_t ttyname_store(struct device *dev, trigger_data->ttyname = ttyname; - mutex_unlock(&trigger_data->mutex); - - if (ttyname && !running) - ledtrig_tty_restart(trigger_data); - return ret; } static DEVICE_ATTR_RW(ttyname); @@ -86,13 +94,8 @@ static void ledtrig_tty_work(struct work_struct *work) struct led_classdev *led_cdev = trigger_data->led_cdev; int ret; - mutex_lock(&trigger_data->mutex); - - if (!trigger_data->ttyname) { - /* exit without rescheduling */ - mutex_unlock(&trigger_data->mutex); - return; - } + if (!trigger_data->ttyname) + goto out; /* try to get the tty corresponding to $ttyname */ if (!trigger_data->tty) { @@ -117,11 +120,8 @@ static void ledtrig_tty_work(struct work_struct *work) } ret = tty_get_icount(trigger_data->tty, &icount); - if (ret) { - dev_warn(led_cdev->dev, "Failed to get icount, stop polling\n"); - mutex_unlock(&trigger_data->mutex); - return; - } + if (ret) + goto out; if (icount.rx != trigger_data->rx || icount.tx != trigger_data->tx) { @@ -134,7 +134,7 @@ static void ledtrig_tty_work(struct work_struct *work) } out: - mutex_unlock(&trigger_data->mutex); + complete_all(&trigger_data->sysfs); schedule_delayed_work(&trigger_data->dwork, msecs_to_jiffies(LEDTRIG_TTY_INTERVAL * 2)); } @@ -157,7 +157,9 @@ static int ledtrig_tty_activate(struct led_classdev *led_cdev) INIT_DELAYED_WORK(&trigger_data->dwork, ledtrig_tty_work); trigger_data->led_cdev = led_cdev; - mutex_init(&trigger_data->mutex); + init_completion(&trigger_data->sysfs); + + schedule_delayed_work(&trigger_data->dwork, 0); return 0; }