Message ID | 33d05330-7c52-e873-bf32-209d40c77632@sberdevices.ru |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp1665041wru; Sat, 29 Oct 2022 23:24:43 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4D+O9jmx+d2geIwUyMY3wOGGbknKt6UucC2L/iYPiwPPAgsE2OTx5JHQdww7Q8Vweopb6d X-Received: by 2002:a17:907:a087:b0:7ad:a4c4:873b with SMTP id hu7-20020a170907a08700b007ada4c4873bmr6636791ejc.58.1667111083469; Sat, 29 Oct 2022 23:24:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667111083; cv=none; d=google.com; s=arc-20160816; b=HOE4EN7kE3Xc0aviQg5dk6kg3OZwIrx2nXDAKicKLcj0spgwyskDaEeOaC2WRAz0D9 LGmn+BwIv1AiurwGdnj7Xfm5Q8xAdPntAMIQ6/p1nm562RoxkFAwxAtlp92jrnHaUkZc /rR8Rjy+ObYjqHFwuNFnkmQJqZ9ET5slNAxkUGZrbhEKzdJmvZrdyrNE2TZAQfh9pVka 1hStU/6nd4ThzgapnsDG/pnLU9v8H1eXKwEFHiCWpR1uTEdEK3s9SHgpriMP9dH1mieG FrXcW6lg4wVhQ+y8XK43nTPFsM8JRBCXj/KeKz5GdZOzIYqgJ0N/6ZCG9ro4BAJc/yPd 1Qqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:content-transfer-encoding :content-id:content-language:accept-language:in-reply-to:message-id :date:thread-index:thread-topic:subject:cc:to:from:dkim-signature; bh=70gQPUCJRtL+Gl1erP4Tp6BQPO1jX8JvWrWFY8MQuHI=; b=q71oWTwvvRlj4RSwvB8/wGmddGkCMd3Ve+4cUYiHSBo+Gb/f3/NvjkL8xeDPLbXVsP wt4PhVNtcSIaQIbzIq2+tFfFl2ewML/PEnjBvz6yzPBbFM6MlUsqsR0j1gJ4ireZSvzU jLWAnBbaMYKs+9JbXkTE5O79iL8tUv32a/bBRZBUDYGbC9qdRYqUcapjazfR17krUov7 BNT3nW4MEK5LrVGQkoDL3D2js5Lav/wVCxBLnUuKSmdHXD+Ikn6sKstoTmhhGsxfzEPY w8DYbdeP7j+ZA102sCwzV+JjgL/OaP4lsjrMZedJTGrsnLyQXnEEkDm3D7l//98YyPwa TO9w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sberdevices.ru header.s=mail header.b=kOnQRetV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=sberdevices.ru Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ev13-20020a056402540d00b0045878eab247si3443581edb.193.2022.10.29.23.24.19; Sat, 29 Oct 2022 23:24:43 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@sberdevices.ru header.s=mail header.b=kOnQRetV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=sberdevices.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229744AbiJ3GHp (ORCPT <rfc822;ezelljr.billy@gmail.com> + 99 others); Sun, 30 Oct 2022 02:07:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45298 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229740AbiJ3GHn (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Sun, 30 Oct 2022 02:07:43 -0400 Received: from mx.sberdevices.ru (mx.sberdevices.ru [45.89.227.171]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 241B410F; Sat, 29 Oct 2022 23:07:41 -0700 (PDT) Received: from s-lin-edge02.sberdevices.ru (localhost [127.0.0.1]) by mx.sberdevices.ru (Postfix) with ESMTP id 8613A5FD0D; Sun, 30 Oct 2022 09:07:39 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sberdevices.ru; s=mail; t=1667110059; bh=70gQPUCJRtL+Gl1erP4Tp6BQPO1jX8JvWrWFY8MQuHI=; h=From:To:Subject:Date:Message-ID:Content-Type:MIME-Version; b=kOnQRetVPv+2UCipFwjhn9VvzjZbNb1MtZPEkL4XSVlkO2q0AgbiBUUxbZzxB6wXH yq/VsHBq0lC8A0RvQ3eLGOuhYQ9Z6013ctIfPPy260AwnRtZJCMuHS4FvxxFiHTD0H 16ZKDb5LwUolBDySp5pnIaGKusXFqbIN3fOaSwY0FwdBlGRoBI3d1InUZt00XuVa8u nchrawSXaximexdtUtxiV97DRznAweF0b0Zly7PJIYrDWOV7F72/wXvQR8BYQh9k+i skjfhiiYz4VV/aqlMXCs6Npx2Fp6uHAkrgzyRUCpA4i+DixbBbUK3ewUxQb5HiIhB5 51F9m8vuwQWXg== Received: from S-MS-EXCH01.sberdevices.ru (S-MS-EXCH01.sberdevices.ru [172.16.1.4]) by mx.sberdevices.ru (Postfix) with ESMTP; Sun, 30 Oct 2022 09:07:39 +0300 (MSK) From: Arseniy Krasnov <AVKrasnov@sberdevices.ru> To: Pavel Machek <pavel@ucw.cz> CC: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>, "linux-leds@vger.kernel.org" <linux-leds@vger.kernel.org>, kernel <kernel@sberdevices.ru> Subject: [RFC PATCH v1 1/1] leds: support to use own workqueue for each LED Thread-Topic: [RFC PATCH v1 1/1] leds: support to use own workqueue for each LED Thread-Index: AQHY7CXVXNE+VpHZTEOLMCYP8pPo3Q== Date: Sun, 30 Oct 2022 06:07:05 +0000 Message-ID: <33d05330-7c52-e873-bf32-209d40c77632@sberdevices.ru> In-Reply-To: <9a0a70a8-0886-1115-6151-72d2cba842cf@sberdevices.ru> Accept-Language: en-US, ru-RU Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.16.1.12] Content-Type: text/plain; charset="utf-8" Content-ID: <B1499C136C8B1C458504460BCBBB17FE@sberdevices.ru> Content-Transfer-Encoding: base64 MIME-Version: 1.0 X-KSMG-Rule-ID: 4 X-KSMG-Message-Action: clean X-KSMG-AntiSpam-Status: not scanned, disabled by settings X-KSMG-AntiSpam-Interceptor-Info: not scanned X-KSMG-AntiPhishing: not scanned, disabled by settings X-KSMG-AntiVirus: Kaspersky Secure Mail Gateway, version 1.1.2.30, bases: 2022/10/30 00:33:00 #20534548 X-KSMG-AntiVirus-Status: Clean, skipped X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748092671023107504?= X-GMAIL-MSGID: =?utf-8?q?1748092671023107504?= |
Series |
[RFC,v1,1/1] leds: support to use own workqueue for each LED
|
|
Commit Message
Arseniy Krasnov
Oct. 30, 2022, 6:07 a.m. UTC
This allows to set own workqueue for each LED. This may be useful, because
default 'system_wq' does not guarantee execution order of each work_struct,
thus for several brightness update requests (for multiple leds), real
brightness switch could be in random order.
Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
---
drivers/leds/led-core.c | 8 ++++++--
include/linux/leds.h | 1 +
2 files changed, 7 insertions(+), 2 deletions(-)
--
2.35.0
Comments
On Sun 2022-10-30 06:07:05, Arseniy Krasnov wrote: > This allows to set own workqueue for each LED. This may be useful, because > default 'system_wq' does not guarantee execution order of each work_struct, > thus for several brightness update requests (for multiple leds), real > brightness switch could be in random order. So.. what? Even if execution order is switched, human eye will not be able to tell the difference. Pavel
On 30.10.2022 15:20, Pavel Machek wrote: > On Sun 2022-10-30 06:07:05, Arseniy Krasnov wrote: >> This allows to set own workqueue for each LED. This may be useful, because >> default 'system_wq' does not guarantee execution order of each work_struct, >> thus for several brightness update requests (for multiple leds), real >> brightness switch could be in random order. > > So.. what? > > Even if execution order is switched, human eye will not be able to > tell the difference. Hello, Problem arises on one of our boards where we have 14 triples of leds(each triple contains R G B). Test case is to play complex animation on all leds: smooth switch from on RGB state to another. Sometimes there are glitches in this process - divergence from expectable RGB state. We fixed this by using ordered workqueue. Thanks, Arseniy > Pavel
Hi! > >> This allows to set own workqueue for each LED. This may be useful, because > >> default 'system_wq' does not guarantee execution order of each work_struct, > >> thus for several brightness update requests (for multiple leds), real > >> brightness switch could be in random order. > > > > So.. what? > > > > Even if execution order is switched, human eye will not be able to > > tell the difference. > Hello, > > Problem arises on one of our boards where we have 14 triples of leds(each > triple contains R G B). Test case is to play complex animation on all leds: > smooth switch from on RGB state to another. Sometimes there are glitches in > this process - divergence from expectable RGB state. We fixed this by using > ordered workqueue. Are there other solutions possible? Like batch and always apply _all_ the updates you have queued from your the worker code? Best regards, Pavel
On 30.10.2022 23:15, Pavel Machek wrote: > Hi! > >>>> This allows to set own workqueue for each LED. This may be useful, because >>>> default 'system_wq' does not guarantee execution order of each work_struct, >>>> thus for several brightness update requests (for multiple leds), real >>>> brightness switch could be in random order. >>> >>> So.. what? >>> >>> Even if execution order is switched, human eye will not be able to >>> tell the difference. >> Hello, >> >> Problem arises on one of our boards where we have 14 triples of leds(each >> triple contains R G B). Test case is to play complex animation on all leds: >> smooth switch from on RGB state to another. Sometimes there are glitches in >> this process - divergence from expectable RGB state. We fixed this by using >> ordered workqueue. > > Are there other solutions possible? Like batch and always apply _all_ > the updates you have queued from your the worker code? IIUC You, it is possible to do this if brightness update requests are performed using write to "brightness" file in /sys/class/led/. But if pattern trigger mode is used(in my case) - I can't synchronize these requests as they are created internally in kernel on timer tick. Thanks, Arseniy > > Best regards, > Pavel >
Hello Pavel and Arseniy, Please find my thoughts below. On Mon, Oct 31, 2022 at 10:01:28AM +0300, Arseniy Krasnov wrote: > On 30.10.2022 23:15, Pavel Machek wrote: > > Hi! > > > >>>> This allows to set own workqueue for each LED. This may be useful, because > >>>> default 'system_wq' does not guarantee execution order of each work_struct, > >>>> thus for several brightness update requests (for multiple leds), real > >>>> brightness switch could be in random order. > >>> > >>> So.. what? > >>> > >>> Even if execution order is switched, human eye will not be able to > >>> tell the difference. > >> Hello, > >> > >> Problem arises on one of our boards where we have 14 triples of leds(each > >> triple contains R G B). Test case is to play complex animation on all leds: > >> smooth switch from on RGB state to another. Sometimes there are glitches in > >> this process - divergence from expectable RGB state. We fixed this by using > >> ordered workqueue. > > > > Are there other solutions possible? Like batch and always apply _all_ > > the updates you have queued from your the worker code? > > IIUC You, it is possible to do this if brightness update requests are performed using > write to "brightness" file in /sys/class/led/. But if pattern trigger mode is used(in my > case) - I can't synchronize these requests as they are created internally in kernel on > timer tick. Even more, system_wq is used when you push brightness changing requests to sysfs node, and it could be re-ordered as well. In other words, from queue perspective sysfs iface and trigger iface have the same behavior. Also we can be faced with another big problem here: let's imagine you have I2C based LED controller driver. Usually, in such drivers you're stuck to the one driver owned mutex, which protects I2C transactions from each other. When you change brightness very often (let's say a hundred thousand times per minute) you schedule many workers to system_wq. Due to system_wq is multicore and unordered it creates many kworkers. Each kworker stucks on the driver mutex and goes to TASK_UNINTERRUPTIBLE state. It affects Load Average value so much. On the our device LA maximum could reach 30-35 units due to such idle kworkers. I'm not sure custom workqueue initialization from specific HW driver is a good solution... But it's much better than nothing. Pavel, please share your thoughts about above problems? Maybe you have more advanced and scalable solution idea, I would appreciate if you could share it with us.
Hello Pavel, Do you have any feedback/thoughts about this one? The problem looks very bad, Load Average value should not grow up due to any userspace triggered led animation. I suppose we stronlgy need to fixup this behavior for sure. Appreciate any help! On Mon, Oct 31, 2022 at 05:47:04PM +0300, Dmitry Rokosov wrote: > Hello Pavel and Arseniy, > > Please find my thoughts below. > > On Mon, Oct 31, 2022 at 10:01:28AM +0300, Arseniy Krasnov wrote: > > On 30.10.2022 23:15, Pavel Machek wrote: > > > Hi! > > > > > >>>> This allows to set own workqueue for each LED. This may be useful, because > > >>>> default 'system_wq' does not guarantee execution order of each work_struct, > > >>>> thus for several brightness update requests (for multiple leds), real > > >>>> brightness switch could be in random order. > > >>> > > >>> So.. what? > > >>> > > >>> Even if execution order is switched, human eye will not be able to > > >>> tell the difference. > > >> Hello, > > >> > > >> Problem arises on one of our boards where we have 14 triples of leds(each > > >> triple contains R G B). Test case is to play complex animation on all leds: > > >> smooth switch from on RGB state to another. Sometimes there are glitches in > > >> this process - divergence from expectable RGB state. We fixed this by using > > >> ordered workqueue. > > > > > > Are there other solutions possible? Like batch and always apply _all_ > > > the updates you have queued from your the worker code? > > > > IIUC You, it is possible to do this if brightness update requests are performed using > > write to "brightness" file in /sys/class/led/. But if pattern trigger mode is used(in my > > case) - I can't synchronize these requests as they are created internally in kernel on > > timer tick. > > Even more, system_wq is used when you push brightness changing requests > to sysfs node, and it could be re-ordered as well. In other words, from > queue perspective sysfs iface and trigger iface have the same behavior. > > Also we can be faced with another big problem here: let's imagine you have > I2C based LED controller driver. Usually, in such drivers you're stuck > to the one driver owned mutex, which protects I2C transactions from each > other. > > When you change brightness very often (let's say a hundred thousand times > per minute) you schedule many workers to system_wq. Due to system_wq is > multicore and unordered it creates many kworkers. Each kworker stucks on > the driver mutex and goes to TASK_UNINTERRUPTIBLE state. It affects Load > Average value so much. On the our device LA maximum could reach 30-35 > units due to such idle kworkers. > > I'm not sure custom workqueue initialization from specific HW driver is > a good solution... But it's much better than nothing. > > Pavel, please share your thoughts about above problems? Maybe you have > more advanced and scalable solution idea, I would appreciate if you > could share it with us.
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 4a97cb745788..e8ecf332793a 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -188,6 +188,9 @@ static void led_blink_setup(struct led_classdev *led_cdev, void led_init_core(struct led_classdev *led_cdev) { + if (!led_cdev->set_brightness_wq) + led_cdev->set_brightness_wq = system_wq; + INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); timer_setup(&led_cdev->blink_timer, led_timer_function, 0); @@ -252,7 +255,8 @@ void led_set_brightness(struct led_classdev *led_cdev, unsigned int brightness) */ if (!brightness) { set_bit(LED_BLINK_DISABLE, &led_cdev->work_flags); - schedule_work(&led_cdev->set_brightness_work); + queue_work(led_cdev->set_brightness_wq, + &led_cdev->set_brightness_work); } else { set_bit(LED_BLINK_BRIGHTNESS_CHANGE, &led_cdev->work_flags); @@ -273,7 +277,7 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int value) /* If brightness setting can sleep, delegate it to a work queue task */ led_cdev->delayed_set_value = value; - schedule_work(&led_cdev->set_brightness_work); + queue_work(led_cdev->set_brightness_wq, &led_cdev->set_brightness_work); } EXPORT_SYMBOL_GPL(led_set_brightness_nopm); diff --git a/include/linux/leds.h b/include/linux/leds.h index ba4861ec73d3..1121bae21fed 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -140,6 +140,7 @@ struct led_classdev { void (*flash_resume)(struct led_classdev *led_cdev); struct work_struct set_brightness_work; + struct workqueue_struct *set_brightness_wq; int delayed_set_value; #ifdef CONFIG_LEDS_TRIGGERS