From patchwork Mon Sep 20 16:44:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kroah-Hartman X-Patchwork-Id: 514377 Delivered-To: patch@linaro.org Received: by 2002:a02:c816:0:0:0:0:0 with SMTP id p22csp2338311jao; Mon, 20 Sep 2021 11:47:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyJg7LPl/nhqV2TmuoYL3AMC//WpYbPnsTWI03AjJJdEX9Xtit69o6LGsWQqBY8TYlIhnI+ X-Received: by 2002:a05:6402:2917:: with SMTP id ee23mr30516209edb.207.1632163647335; Mon, 20 Sep 2021 11:47:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1632163647; cv=none; d=google.com; s=arc-20160816; b=e3miKaJfBdKIxX4mxrLmHuABSml0e4g1c+0NxSpbugM17eJVIDZbu5qqiUNurxJHIE gQEEmhiUBuJXZ1rxx3HURSG6iWc+WbGcMILq8cHC/Fu9/A1b3ix3/bvLw/Z+dbaPaoEI j34fzL2RGCWrIUp3lQ/N0Ze4weUQN4BhVjfwPYMTa59yTysLjGbWTSs/LXF298uSTO7J vAjNOkDnAf3RdC9dSiuqs/y1m+u/B8VHk+Wnzd9He9PDMwHqmNxgEnSMKCYY8xt9evTA PRmATYIDw6dy5awEsRZay4FZS8P541gDqLuXMQzWTyHy7wdVwuOADZBcxm0CX3n2Klda y2sg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=8a/qteVCVMJ87b9DF0LmjQYROwxCMWOlJfUE+xRdp4w=; b=dWa5pToUxygAWn60N3kyQvGvjidgXKkXxsbKHVcftHJs/JMIkwNsOcrSwnim9idYLH 5gzBPNgus48jsZkacJzy+wkAVwiqFuYTGIVKDwIHi3bDQtwuHLmjnaYp7IFf9iGKiUHw Zuv6i11u3OjG0I/CVDg22ixHR/uPQaF5pV97ErYZVFss2fDvhsLIPYj+ZQx6EpV0vZSu utxSZ3bSLwneBxLn7ooV6cr+GrAFdcu9yaS1qOvpWfzyE98CUblgg3vfj/iNB7th+uA5 V6OhyCKT7801sdQgeT0IVSk3cV6QueYYLh/K/5I7QEAAMHhCc/KI2uUqx5RJ2v5rV0Xr zDiA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=RI6YPIOy; spf=pass (google.com: domain of stable-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id f29si18802075ejj.403.2021.09.20.11.47.26; Mon, 20 Sep 2021 11:47:27 -0700 (PDT) Received-SPF: pass (google.com: domain of stable-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=RI6YPIOy; spf=pass (google.com: domain of stable-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1354450AbhITSsw (ORCPT + 11 others); Mon, 20 Sep 2021 14:48:52 -0400 Received: from mail.kernel.org ([198.145.29.99]:33244 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1383999AbhITSqU (ORCPT ); Mon, 20 Sep 2021 14:46:20 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7078963360; Mon, 20 Sep 2021 17:33:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1632159200; bh=6AOpt5nzNFC31BkTqC9tNzGbwV675RFYmdUiW4tChoQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RI6YPIOyDy4KEtv8CV1LlGnF+0K0D6MCovP30/bVvvoiGQk3fq13mWCFbLuhjUehH 1y6EWxPWJlI6Lx77ZyirUV50BJW8ErmGJeEJm81XDH+1Ok7aTtiRHYnNd9FNwD9oLs 6VPoqrQxMigWA2LwnTW4qvfq/Vv+uumA4/yYn0rY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Stephan Gerhold , newbyte@disroot.org, Daniel Thompson , Linus Walleij , Lee Jones , Sasha Levin Subject: [PATCH 5.14 122/168] backlight: ktd253: Stabilize backlight Date: Mon, 20 Sep 2021 18:44:20 +0200 Message-Id: <20210920163925.671764275@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210920163921.633181900@linuxfoundation.org> References: <20210920163921.633181900@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Linus Walleij [ Upstream commit daa37361518bf2d1f591bbdaa7c68b2a43d7af48 ] Remove interrupt disablement during backlight setting. It is way to dangerous and makes platforms instable by having it miss vblank IRQs leading to the graphics derailing. The code is using ndelay() which is not available on platforms such as ARM and will result in 32 * udelay(1) which is substantial. Add some code to detect if an interrupt occurs during the tight loop and in that case just redo it from the top. Fixes: 5317f37e48b9 ("backlight: Add Kinetic KTD253 backlight driver") Cc: Stephan Gerhold Reported-by: newbyte@disroot.org Reviewed-by: Daniel Thompson Signed-off-by: Linus Walleij Signed-off-by: Lee Jones Signed-off-by: Sasha Levin --- drivers/video/backlight/ktd253-backlight.c | 75 ++++++++++++++++------ 1 file changed, 55 insertions(+), 20 deletions(-) -- 2.30.2 diff --git a/drivers/video/backlight/ktd253-backlight.c b/drivers/video/backlight/ktd253-backlight.c index a7df5bcca9da..37aa5a669530 100644 --- a/drivers/video/backlight/ktd253-backlight.c +++ b/drivers/video/backlight/ktd253-backlight.c @@ -25,6 +25,7 @@ #define KTD253_T_LOW_NS (200 + 10) /* Additional 10ns as safety factor */ #define KTD253_T_HIGH_NS (200 + 10) /* Additional 10ns as safety factor */ +#define KTD253_T_OFF_CRIT_NS 100000 /* 100 us, now it doesn't look good */ #define KTD253_T_OFF_MS 3 struct ktd253_backlight { @@ -34,13 +35,50 @@ struct ktd253_backlight { u16 ratio; }; +static void ktd253_backlight_set_max_ratio(struct ktd253_backlight *ktd253) +{ + gpiod_set_value_cansleep(ktd253->gpiod, 1); + ndelay(KTD253_T_HIGH_NS); + /* We always fall back to this when we power on */ +} + +static int ktd253_backlight_stepdown(struct ktd253_backlight *ktd253) +{ + /* + * These GPIO operations absolutely can NOT sleep so no _cansleep + * suffixes, and no using GPIO expanders on slow buses for this! + * + * The maximum number of cycles of the loop is 32 so the time taken + * should nominally be: + * (T_LOW_NS + T_HIGH_NS + loop_time) * 32 + * + * Architectures do not always support ndelay() and we will get a few us + * instead. If we get to a critical time limit an interrupt has likely + * occured in the low part of the loop and we need to restart from the + * top so we have the backlight in a known state. + */ + u64 ns; + + ns = ktime_get_ns(); + gpiod_set_value(ktd253->gpiod, 0); + ndelay(KTD253_T_LOW_NS); + gpiod_set_value(ktd253->gpiod, 1); + ns = ktime_get_ns() - ns; + if (ns >= KTD253_T_OFF_CRIT_NS) { + dev_err(ktd253->dev, "PCM on backlight took too long (%llu ns)\n", ns); + return -EAGAIN; + } + ndelay(KTD253_T_HIGH_NS); + return 0; +} + static int ktd253_backlight_update_status(struct backlight_device *bl) { struct ktd253_backlight *ktd253 = bl_get_data(bl); int brightness = backlight_get_brightness(bl); u16 target_ratio; u16 current_ratio = ktd253->ratio; - unsigned long flags; + int ret; dev_dbg(ktd253->dev, "new brightness/ratio: %d/32\n", brightness); @@ -62,37 +100,34 @@ static int ktd253_backlight_update_status(struct backlight_device *bl) } if (current_ratio == 0) { - gpiod_set_value_cansleep(ktd253->gpiod, 1); - ndelay(KTD253_T_HIGH_NS); - /* We always fall back to this when we power on */ + ktd253_backlight_set_max_ratio(ktd253); current_ratio = KTD253_MAX_RATIO; } - /* - * WARNING: - * The loop to set the correct current level is performed - * with interrupts disabled as it is timing critical. - * The maximum number of cycles of the loop is 32 - * so the time taken will be (T_LOW_NS + T_HIGH_NS + loop_time) * 32, - */ - local_irq_save(flags); while (current_ratio != target_ratio) { /* * These GPIO operations absolutely can NOT sleep so no * _cansleep suffixes, and no using GPIO expanders on * slow buses for this! */ - gpiod_set_value(ktd253->gpiod, 0); - ndelay(KTD253_T_LOW_NS); - gpiod_set_value(ktd253->gpiod, 1); - ndelay(KTD253_T_HIGH_NS); - /* After 1/32 we loop back to 32/32 */ - if (current_ratio == KTD253_MIN_RATIO) + ret = ktd253_backlight_stepdown(ktd253); + if (ret == -EAGAIN) { + /* + * Something disturbed the backlight setting code when + * running so we need to bring the PWM back to a known + * state. This shouldn't happen too much. + */ + gpiod_set_value_cansleep(ktd253->gpiod, 0); + msleep(KTD253_T_OFF_MS); + ktd253_backlight_set_max_ratio(ktd253); + current_ratio = KTD253_MAX_RATIO; + } else if (current_ratio == KTD253_MIN_RATIO) { + /* After 1/32 we loop back to 32/32 */ current_ratio = KTD253_MAX_RATIO; - else + } else { current_ratio--; + } } - local_irq_restore(flags); ktd253->ratio = current_ratio; dev_dbg(ktd253->dev, "new ratio set to %d/32\n", target_ratio);