From patchwork Thu Oct 19 10:22:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 155431 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2010:b0:403:3b70:6f57 with SMTP id fe16csp281922vqb; Thu, 19 Oct 2023 03:22:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHROGrS4nZzZ+gdrKhwmwqRyMEp2SSrdCPiVbBxmSU3Zxp7penhc9ph1oLHZVjNJG9XAVjm X-Received: by 2002:a17:90b:118:b0:27d:bc2:7c6e with SMTP id p24-20020a17090b011800b0027d0bc27c6emr1675079pjz.20.1697710971843; Thu, 19 Oct 2023 03:22:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1697710971; cv=none; d=google.com; s=arc-20160816; b=U2iJT6gmTQCLaz1rmiUcC50ch8XSt79j7p//XBKWVHILzFQEhv/pnuckrhvNJMAkqD 9ppq8Yd8f6SGpLhwt5fh3zPIPy8HVCMkUovp2mE+uW93cQjl++pyWNpxH51eEodoDuou U/xGFxUMjCP1FdfxPNeFdx0jaXsJ/3AvUbSeJpHL/GlSZxqQF5IeJLWjgGmuPAJUx35V qoM6yiXXtymjrjiPCSGy3MxjUCtsXuYKGgSBo0RNkuDT08HreMqEppAz6kDMHHp08qJQ /VdTtv49Fqo7C2uWlm/SXyY5/OezaYAjuMBB7mq7Rcb1xevPcGU3dI9688SOvstaHlKD dcCw== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=hmjA0HEYlUuwJKncR5UsQ51jJen21NHSaXoRnKSgrrY=; fh=lVFod2Nh/bVLd9f3LnZD5svEoMpRA0jQsUMvfqIGMU8=; b=tElZnr/vQIPFH5qhvu3MHEXLGcyt+JsHFUBIBYTyA8MWqzmYfcwN+V7ZfgRhC1EPXV Gdbv6YHj67s1LO3vfMfVF1D+NbbGzwZqDv2gRQaKuUimt3y+NkXrHSK0S0j4VfzzVXkK N6JLfHWa46HDryUB1sy6MMgScARcCZ24w7OQ4ZgL4WWpPbixa2FjsOaU99C76fBxDEnd ckHLjxEbaSRlRxuot5vTf0Tn1B8L2Zov6E8vWX/0/mLlQuSpvwr5RtI2mfmsEJ8IcC4N 2XMxebFRu6Wga7vPAqU4ETpQOkQVAgAFeyYpXSEgQapPTt8fUgO6dj1pEpPHE6BtWifk nGTg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VJ8GXYbi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.35 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from groat.vger.email (groat.vger.email. [23.128.96.35]) by mx.google.com with ESMTPS id v19-20020a17090ac91300b0027e022bd420si664841pjt.77.2023.10.19.03.22.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Oct 2023 03:22:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.35 as permitted sender) client-ip=23.128.96.35; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VJ8GXYbi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.35 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by groat.vger.email (Postfix) with ESMTP id 95E4E811F26F; Thu, 19 Oct 2023 03:22:49 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at groat.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345274AbjJSKWR (ORCPT + 24 others); Thu, 19 Oct 2023 06:22:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345249AbjJSKWP (ORCPT ); Thu, 19 Oct 2023 06:22:15 -0400 Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E044FA for ; Thu, 19 Oct 2023 03:22:13 -0700 (PDT) Received: by mail-pj1-x1030.google.com with SMTP id 98e67ed59e1d1-27d0251d305so4784253a91.2 for ; Thu, 19 Oct 2023 03:22:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1697710933; x=1698315733; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hmjA0HEYlUuwJKncR5UsQ51jJen21NHSaXoRnKSgrrY=; b=VJ8GXYbixIqdEPgD7WbhMfgUrcvQOnLomDlFXdlE1s2/8hF7HwrQbxChbqkSJ8L6/n Sdpz+o5NMw8diFBAZvIniynKBeFbbpW6BpqYRQBPqMqbar528XYSs5Gvd6/jYTUqB5Ix 2mWilVgA+Pgxlz69EeA4o9ZTmk+D3iNb5DVkScLkKWLo4qE5d6AkyutzAfVsowaKnRnN WNlNihmb8kp5+/LTfYvbFbuIwFnbbP6J4S71YGHQqM/KUg/w3yktq+unwsEZzFi9YrBG buAL6DDxG5IXIqI9JuHGFiojQqawVXtV27UW+EQXgUBurZ5Fug7mJ1Swv0lQPf+sHVcG SNQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697710933; x=1698315733; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hmjA0HEYlUuwJKncR5UsQ51jJen21NHSaXoRnKSgrrY=; b=apryUP8VO6RVyR95/JmQ0qBINI/+xxc2AZ79CnpVYSdjKrjHBqJij3ukCzqWiH6jjF X1XL7ozO4DK9sXWD4rsWgJ3qFRAUAHCy1D4B+zwx/tlvVteqPJ/sXg2D+3cN3ZWz11r9 +Ni1i2f3rd/VmYOSE/YrIlFEGQloMZc+Aza3VmJw+pyOkbXeK70YlHvY5e3zjVlJHvzQ Vl1ZgRNA+2p1TMnSmz0rNUSP6HFDoys1pm9SXTzgMoJNzdzAYCMnZ3hHifQeS0niKL6b xtFWmAqCSOL+AFpv4IH767VkMOyyKdya3UlT/WMMsFsCKOQJb53vsZkeWk/tIyOlytFM adnQ== X-Gm-Message-State: AOJu0Yzv3DpbuPffK5TbkDtt1FfFxxjIkY3C5Pqfxu7eVMkFTQjfTfNl 1C5PoW0Gs0T5W5TgncGsWaRwdw== X-Received: by 2002:a17:90b:3793:b0:27d:2364:44f6 with SMTP id mz19-20020a17090b379300b0027d236444f6mr1559112pjb.6.1697710932749; Thu, 19 Oct 2023 03:22:12 -0700 (PDT) Received: from localhost ([122.172.80.14]) by smtp.gmail.com with ESMTPSA id 20-20020a17090a005400b0026cecddfc58sm1430945pjb.42.2023.10.19.03.22.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Oct 2023 03:22:12 -0700 (PDT) From: Viresh Kumar To: Viresh Kumar , Nishanth Menon , Stephen Boyd Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , "Rafael J. Wysocki" , Ulf Hansson , Stephan Gerhold , Konrad Dybcio , Manivannan Sadhasivam , linux-kernel@vger.kernel.org Subject: [PATCH 1/2] OPP: Use _set_opp_level() for single genpd case Date: Thu, 19 Oct 2023 15:52:00 +0530 Message-Id: X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on groat.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (groat.vger.email [0.0.0.0]); Thu, 19 Oct 2023 03:22:49 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780178979554134036 X-GMAIL-MSGID: 1780178979554134036 There are two genpd (as required-opp) cases that we need to handle, devices with a single genpd and ones with multiple genpds. The multiple genpds case is clear, where the OPP core calls dev_pm_domain_attach_by_name() for them and uses the virtual devices returned by this helper to call dev_pm_domain_set_performance_state() later to change the performance state. The single genpd case however requires special handling as we need to use the same `dev` structure (instead of a virtual one provided by genpd core) for setting the performance state via dev_pm_domain_set_performance_state(). As we move towards more generic code to take care of the required OPPs, where we will recursively call dev_pm_opp_set_opp() for all the required OPPs, the above special case becomes a problem. Eventually we want to handle all performance state changes via _set_opp_level(), so lets move the single genpd case to that right away. Signed-off-by: Viresh Kumar Reviewed-by: Ulf Hansson --- drivers/opp/core.c | 6 ++++-- drivers/opp/of.c | 25 ++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 84f345c69ea5..aab8c8e79146 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1074,10 +1074,12 @@ static int _opp_set_required_opps_generic(struct device *dev, static int _opp_set_required_opps_genpd(struct device *dev, struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down) { - struct device **genpd_virt_devs = - opp_table->genpd_virt_devs ? opp_table->genpd_virt_devs : &dev; + struct device **genpd_virt_devs = opp_table->genpd_virt_devs; int index, target, delta, ret; + if (!genpd_virt_devs) + return 0; + /* Scaling up? Set required OPPs in normal order, else reverse */ if (!scaling_down) { index = 0; diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 81fa27599d58..e056f31a48b5 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -296,7 +296,7 @@ void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) of_node_put(opp->np); } -static int _link_required_opps(struct dev_pm_opp *opp, +static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_table, struct opp_table *required_table, int index) { struct device_node *np; @@ -314,6 +314,25 @@ static int _link_required_opps(struct dev_pm_opp *opp, return -ENODEV; } + /* + * There are two genpd (as required-opp) cases that we need to handle, + * devices with a single genpd and ones with multiple genpds. + * + * The single genpd case requires special handling as we need to use the + * same `dev` structure (instead of a virtual one provided by genpd + * core) for setting the performance state. Lets treat this as a case + * where the OPP's level is directly available without required genpd + * link in the DT. + * + * Just update the `level` with the right value, which + * dev_pm_opp_set_opp() will take care of in the normal path itself. + */ + if (required_table->is_genpd && opp_table->required_opp_count == 1 && + !opp_table->genpd_virt_devs) { + if (!WARN_ON(opp->level)) + opp->level = opp->required_opps[0]->level; + } + return 0; } @@ -338,7 +357,7 @@ static int _of_opp_alloc_required_opps(struct opp_table *opp_table, if (IS_ERR_OR_NULL(required_table)) continue; - ret = _link_required_opps(opp, required_table, i); + ret = _link_required_opps(opp, opp_table, required_table, i); if (ret) goto free_required_opps; } @@ -359,7 +378,7 @@ static int lazy_link_required_opps(struct opp_table *opp_table, int ret; list_for_each_entry(opp, &opp_table->opp_list, node) { - ret = _link_required_opps(opp, new_table, index); + ret = _link_required_opps(opp, opp_table, new_table, index); if (ret) return ret; } From patchwork Thu Oct 19 10:22:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 155432 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2010:b0:403:3b70:6f57 with SMTP id fe16csp282007vqb; Thu, 19 Oct 2023 03:23:01 -0700 (PDT) X-Google-Smtp-Source: AGHT+IE0D7uwcMOK8qncFpuZE/Xi4Yha/DmWKB2U0W/6zzyiuKnb3zm/IIB8GQgnTk3As0Qy7U6e X-Received: by 2002:a05:6a20:c581:b0:166:ef18:658e with SMTP id gn1-20020a056a20c58100b00166ef18658emr1056822pzb.62.1697710981096; Thu, 19 Oct 2023 03:23:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1697710981; cv=none; d=google.com; s=arc-20160816; b=aG9jzzrabuIcEdqNQ3EYvWZT22B37/y4gapIkhfoMs1SO/lp2bF6CgKZTA6oIM14FC bNnNlF8jEKEZ3+nottxryEvkoVpNqo+3J9Cq1mHakniwmfHhcPULtMOY9yZ/aRFS+cvq ThCUToHNGc4Q+hiDCK2KOBRF2hUdqpn3SdPEJwSoY1fmy5LR2ovpHAbSUYyN01bGTtG7 cs0NjLAWXKBjDpKRhmos1LYO+61RTeLsw0+OCg9U7eaaXC8uIKZtXwHi3TXRKuvYz6uC UOguzTKpVZPsAv8ZCR2x2ggATV9uJPET/DxWp2o7wwnm/ISj3Wfpp9dg5DwA5MXJWMp7 X5gA== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=R5cNSrE9rhEL2kYfgL1rTFcIHVYfLkBG+dEUsUc/tOs=; fh=Un7JazYSm8/kcjPcd/W8jKETxQG7VjjVg/N0ak4gg3I=; b=bNtrE1vPfurmRNlHtG1ScyCFtB4PL6nL2ka671p0K6kbW1WRdSjqDk6Cgp1l4NE4NJ avFXiAcpcVSc60Md7jzxO8yoaSZY4mtCUJUfCUygMxBNIZYikY4W7N7A1Lt15imi+bH2 wTpqkT8etgc/LxIMlLOtmSsGyOUxnnYv7/6V3unwv7MeXhzpaaFmy1py+LCweblRO3M4 qETH0K90+35Zags0B/K8UpslqiJY+ohloUk60PevscMPJjVMAjxC3LBsof4gSRAPudPT ZnPGUlsWVWQ0oIAGG9PGZebRGZiuxPcEMVeh5q+MzUavs/H6XvkTsA/C/bNzzfG5v8MR rUWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=IMoLl15+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from fry.vger.email (fry.vger.email. [23.128.96.38]) by mx.google.com with ESMTPS id g5-20020a170902740500b001c9abb72958si1829490pll.590.2023.10.19.03.23.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Oct 2023 03:23:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) client-ip=23.128.96.38; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=IMoLl15+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id DF78080BD773; Thu, 19 Oct 2023 03:22:57 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345284AbjJSKWY (ORCPT + 24 others); Thu, 19 Oct 2023 06:22:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50698 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345283AbjJSKWU (ORCPT ); Thu, 19 Oct 2023 06:22:20 -0400 Received: from mail-ot1-x335.google.com (mail-ot1-x335.google.com [IPv6:2607:f8b0:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 216BB11D for ; Thu, 19 Oct 2023 03:22:17 -0700 (PDT) Received: by mail-ot1-x335.google.com with SMTP id 46e09a7af769-6c4b9e09521so5074734a34.3 for ; Thu, 19 Oct 2023 03:22:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1697710936; x=1698315736; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=R5cNSrE9rhEL2kYfgL1rTFcIHVYfLkBG+dEUsUc/tOs=; b=IMoLl15+CX7GipPVKmi5a23E+sP0IzobwUSfg+4hUJm0Y3m1M6NcNM1J6aSQCzn5n9 LSrjyF0PSqwIP+jYRXCOsEAg8Z6fYXKLbdi4orapilFhKfJ46Lo6iTTVPIYK3jfcrYUH ODWdWl1J+XTLC+qflNPSjX1kuzwSnu9HklIhGnrjYb2UXbpwo8MmRAGwbh8Ln2ReFbNv N4efLNAPsS5TVYlaOSqm7wIKgAlrTGKIy2/9O8/75SwI080k4lBw4rSWQ42cdJ+O9UaG D9FRjqhFb8c6GCaWeBUtZPcvSHqr8KB+DzaMEG8LFUpdifiJWTK+apf1kU8sXqpVpm6p eMmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697710936; x=1698315736; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=R5cNSrE9rhEL2kYfgL1rTFcIHVYfLkBG+dEUsUc/tOs=; b=laaziU1HUKZWLyI5iFWhXy69NAFrL+R52cW8JrxcJ+xbxEVdIUCqdCh42OwaTF03aX HWNcxN9/ZpiqhmZaWF+hVaBsrZUCTvskZmov3UkWpaTuf1h976S60Szta0WQpaNV8F2h MMJ5TMz4Kd5rtsNIUpdskd0fwr6WsZsmMWFszYJtX7vomS9IKA3u7T8s6BOA5gzCT61E 0XSUYdogcHjB0nFvGE0ChMm+ZeFxt19TMy20TgqTGspFi4Xjbse4cHlkjdaK1V9uRWhw FXQ7kgj5h3Atjha4VlV+F8Y0brymEJ2p/39v9GkW81w5amQtXXkw/wFwOv78qg873z69 bKbw== X-Gm-Message-State: AOJu0YxIFMt1KVo3YDsWfrVlne6hbc2eTHx2SPE10oJn5/BMDSf7KzDC pSd/A58+qUSWGlDe83ESH+2ibg== X-Received: by 2002:a05:6830:1e46:b0:6ce:2c8e:79f2 with SMTP id e6-20020a0568301e4600b006ce2c8e79f2mr588925otj.8.1697710936325; Thu, 19 Oct 2023 03:22:16 -0700 (PDT) Received: from localhost ([122.172.80.14]) by smtp.gmail.com with ESMTPSA id f186-20020a6251c3000000b00692754580f0sm4963587pfb.187.2023.10.19.03.22.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Oct 2023 03:22:15 -0700 (PDT) From: Viresh Kumar To: Viresh Kumar , Nishanth Menon , Stephen Boyd , "Rafael J. Wysocki" Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Ulf Hansson , Stephan Gerhold , Konrad Dybcio , Manivannan Sadhasivam , linux-kernel@vger.kernel.org Subject: [PATCH 2/2] OPP: Call dev_pm_opp_set_opp() for required OPPs Date: Thu, 19 Oct 2023 15:52:01 +0530 Message-Id: <6de4fcb5bb943a131d0cdf0a858bd35af02a2f88.1697710527.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Thu, 19 Oct 2023 03:22:57 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780178989309553063 X-GMAIL-MSGID: 1780178989309553063 Configuring the required OPP was never properly implemented, we just took an exception for genpds and configured them directly, while leaving out all other required OPP types. Now that a standard call to dev_pm_opp_set_opp() takes care of configuring the opp->level too, the special handling for genpds can be avoided by simply calling dev_pm_opp_set_opp() for the required OPPs, which shall eventually configure the corresponding level for genpds. This also makes it possible for us to configure other type of required OPPs (no concrete users yet though), via the same path. This is how other frameworks take care of parent nodes, like clock, regulators, etc, where we recursively call the same helper. In order to call dev_pm_opp_set_opp() for the virtual genpd devices, they must share the OPP table of the genpd. Call _add_opp_dev() for them to get that done. This commit also extends the struct dev_pm_opp_config to pass required devices, for non-genpd cases, which can be used to call dev_pm_opp_set_opp() for the non-genpd required devices. Signed-off-by: Viresh Kumar Reviewed-by: Ulf Hansson --- drivers/opp/core.c | 144 ++++++++++++++++++----------------------- drivers/opp/of.c | 12 ++-- drivers/opp/opp.h | 8 +-- include/linux/pm_opp.h | 7 +- 4 files changed, 76 insertions(+), 95 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index aab8c8e79146..056b51abc501 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1046,42 +1046,19 @@ static int _set_opp_bw(const struct opp_table *opp_table, return 0; } -static int _set_performance_state(struct device *dev, struct device *pd_dev, - struct dev_pm_opp *opp, int i) -{ - unsigned int pstate = likely(opp) ? opp->required_opps[i]->level: 0; - int ret; - - if (!pd_dev) - return 0; - - ret = dev_pm_domain_set_performance_state(pd_dev, pstate); - if (ret) { - dev_err(dev, "Failed to set performance state of %s: %d (%d)\n", - dev_name(pd_dev), pstate, ret); - } - - return ret; -} - -static int _opp_set_required_opps_generic(struct device *dev, - struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down) -{ - dev_err(dev, "setting required-opps isn't supported for non-genpd devices\n"); - return -ENOENT; -} - -static int _opp_set_required_opps_genpd(struct device *dev, - struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down) +/* This is only called for PM domain for now */ +static int _set_required_opps(struct device *dev, struct opp_table *opp_table, + struct dev_pm_opp *opp, bool up) { - struct device **genpd_virt_devs = opp_table->genpd_virt_devs; + struct device **devs = opp_table->required_devs; int index, target, delta, ret; - if (!genpd_virt_devs) - return 0; + /* required-opps not fully initialized yet */ + if (lazy_linking_pending(opp_table)) + return -EBUSY; /* Scaling up? Set required OPPs in normal order, else reverse */ - if (!scaling_down) { + if (up) { index = 0; target = opp_table->required_opp_count; delta = 1; @@ -1092,9 +1069,11 @@ static int _opp_set_required_opps_genpd(struct device *dev, } while (index != target) { - ret = _set_performance_state(dev, genpd_virt_devs[index], opp, index); - if (ret) - return ret; + if (devs[index]) { + ret = dev_pm_opp_set_opp(devs[index], opp); + if (ret) + return ret; + } index += delta; } @@ -1102,34 +1081,6 @@ static int _opp_set_required_opps_genpd(struct device *dev, return 0; } -/* This is only called for PM domain for now */ -static int _set_required_opps(struct device *dev, struct opp_table *opp_table, - struct dev_pm_opp *opp, bool up) -{ - /* required-opps not fully initialized yet */ - if (lazy_linking_pending(opp_table)) - return -EBUSY; - - if (opp_table->set_required_opps) - return opp_table->set_required_opps(dev, opp_table, opp, up); - - return 0; -} - -/* Update set_required_opps handler */ -void _update_set_required_opps(struct opp_table *opp_table) -{ - /* Already set */ - if (opp_table->set_required_opps) - return; - - /* All required OPPs will belong to genpd or none */ - if (opp_table->required_opp_tables[0]->is_genpd) - opp_table->set_required_opps = _opp_set_required_opps_genpd; - else - opp_table->set_required_opps = _opp_set_required_opps_generic; -} - static int _set_opp_level(struct device *dev, struct opp_table *opp_table, struct dev_pm_opp *opp) { @@ -2390,19 +2341,13 @@ static void _opp_detach_genpd(struct opp_table *opp_table) { int index; - if (!opp_table->genpd_virt_devs) - return; - for (index = 0; index < opp_table->required_opp_count; index++) { - if (!opp_table->genpd_virt_devs[index]) + if (!opp_table->required_devs[index]) continue; - dev_pm_domain_detach(opp_table->genpd_virt_devs[index], false); - opp_table->genpd_virt_devs[index] = NULL; + dev_pm_domain_detach(opp_table->required_devs[index], false); + opp_table->required_devs[index] = NULL; } - - kfree(opp_table->genpd_virt_devs); - opp_table->genpd_virt_devs = NULL; } /* @@ -2429,15 +2374,10 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev, int index = 0, ret = -EINVAL; const char * const *name = names; - if (opp_table->genpd_virt_devs) + /* Checking only the first one is enough ? */ + if (opp_table->required_devs[0]) return 0; - opp_table->genpd_virt_devs = kcalloc(opp_table->required_opp_count, - sizeof(*opp_table->genpd_virt_devs), - GFP_KERNEL); - if (!opp_table->genpd_virt_devs) - return -ENOMEM; - while (*name) { if (index >= opp_table->required_opp_count) { dev_err(dev, "Index can't be greater than required-opp-count - 1, %s (%d : %d)\n", @@ -2452,13 +2392,25 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev, goto err; } - opp_table->genpd_virt_devs[index] = virt_dev; + /* + * Add the virtual genpd device as a user of the OPP table, so + * we can call dev_pm_opp_set_opp() on it directly. + * + * This will be automatically removed when the OPP table is + * removed, don't need to handle that here. + */ + if (!_add_opp_dev(virt_dev, opp_table->required_opp_tables[index])) { + ret = -ENOMEM; + goto err; + } + + opp_table->required_devs[index] = virt_dev; index++; name++; } if (virt_devs) - *virt_devs = opp_table->genpd_virt_devs; + *virt_devs = opp_table->required_devs; return 0; @@ -2468,10 +2420,34 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev, } +static void _opp_set_required_devs(struct opp_table *opp_table, + struct device **required_devs) +{ + int i; + + /* Another CPU that shares the OPP table has set the required devs ? */ + if (opp_table->required_devs[0]) + return; + + for (i = 0; i < opp_table->required_opp_count; i++) + opp_table->required_devs[i] = required_devs[i]; +} + +static void _opp_put_required_devs(struct opp_table *opp_table) +{ + int i; + + for (i = 0; i < opp_table->required_opp_count; i++) + opp_table->required_devs[i] = NULL; +} + static void _opp_clear_config(struct opp_config_data *data) { - if (data->flags & OPP_CONFIG_GENPD) + if (data->flags & OPP_CONFIG_REQUIRED_DEVS) + _opp_put_required_devs(data->opp_table); + else if (data->flags & OPP_CONFIG_GENPD) _opp_detach_genpd(data->opp_table); + if (data->flags & OPP_CONFIG_REGULATOR) _opp_put_regulators(data->opp_table); if (data->flags & OPP_CONFIG_SUPPORTED_HW) @@ -2585,12 +2561,18 @@ int dev_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config) /* Attach genpds */ if (config->genpd_names) { + if (config->required_devs) + goto err; + ret = _opp_attach_genpd(opp_table, dev, config->genpd_names, config->virt_devs); if (ret) goto err; data->flags |= OPP_CONFIG_GENPD; + } else if (config->required_devs) { + _opp_set_required_devs(opp_table, config->required_devs); + data->flags |= OPP_CONFIG_REQUIRED_DEVS; } ret = xa_alloc(&opp_configs, &id, data, XA_LIMIT(1, INT_MAX), diff --git a/drivers/opp/of.c b/drivers/opp/of.c index e056f31a48b5..27659d23d54d 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -165,7 +165,7 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, struct opp_table **required_opp_tables; struct device_node *required_np, *np; bool lazy = false; - int count, i; + int count, i, size; /* Traversing the first OPP node is all we need */ np = of_get_next_available_child(opp_np, NULL); @@ -179,12 +179,13 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, if (count <= 0) goto put_np; - required_opp_tables = kcalloc(count, sizeof(*required_opp_tables), - GFP_KERNEL); + size = sizeof(*required_opp_tables) + sizeof(*opp_table->required_devs); + required_opp_tables = kcalloc(count, size, GFP_KERNEL); if (!required_opp_tables) goto put_np; opp_table->required_opp_tables = required_opp_tables; + opp_table->required_devs = (void *)(required_opp_tables + count); opp_table->required_opp_count = count; for (i = 0; i < count; i++) { @@ -208,8 +209,6 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, mutex_lock(&opp_table_lock); list_add(&opp_table->lazy, &lazy_opp_tables); mutex_unlock(&opp_table_lock); - } else { - _update_set_required_opps(opp_table); } goto put_np; @@ -328,7 +327,7 @@ static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_tab * dev_pm_opp_set_opp() will take care of in the normal path itself. */ if (required_table->is_genpd && opp_table->required_opp_count == 1 && - !opp_table->genpd_virt_devs) { + !opp_table->required_devs[0]) { if (!WARN_ON(opp->level)) opp->level = opp->required_opps[0]->level; } @@ -441,7 +440,6 @@ static void lazy_link_required_opp_table(struct opp_table *new_table) /* All required opp-tables found, remove from lazy list */ if (!lazy) { - _update_set_required_opps(opp_table); list_del_init(&opp_table->lazy); list_for_each_entry(opp, &opp_table->opp_list, node) diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index 08366f90f16b..23dcb2fbf8c3 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -35,6 +35,7 @@ extern struct list_head opp_tables; #define OPP_CONFIG_PROP_NAME BIT(3) #define OPP_CONFIG_SUPPORTED_HW BIT(4) #define OPP_CONFIG_GENPD BIT(5) +#define OPP_CONFIG_REQUIRED_DEVS BIT(6) /** * struct opp_config_data - data for set config operations @@ -160,9 +161,9 @@ enum opp_table_access { * @rate_clk_single: Currently configured frequency for single clk. * @current_opp: Currently configured OPP for the table. * @suspend_opp: Pointer to OPP to be used during device suspend. - * @genpd_virt_devs: List of virtual devices for multiple genpd support. * @required_opp_tables: List of device OPP tables that are required by OPPs in * this table. + * @required_devs: List of devices for required OPP tables. * @required_opp_count: Number of required devices. * @supported_hw: Array of version number to support. * @supported_hw_count: Number of elements in supported_hw array. @@ -180,7 +181,6 @@ enum opp_table_access { * @path_count: Number of interconnect paths * @enabled: Set to true if the device's resources are enabled/configured. * @is_genpd: Marks if the OPP table belongs to a genpd. - * @set_required_opps: Helper responsible to set required OPPs. * @dentry: debugfs dentry pointer of the real device directory (not links). * @dentry_name: Name of the real dentry. * @@ -211,8 +211,8 @@ struct opp_table { struct dev_pm_opp *current_opp; struct dev_pm_opp *suspend_opp; - struct device **genpd_virt_devs; struct opp_table **required_opp_tables; + struct device **required_devs; unsigned int required_opp_count; unsigned int *supported_hw; @@ -229,8 +229,6 @@ struct opp_table { unsigned int path_count; bool enabled; bool is_genpd; - int (*set_required_opps)(struct device *dev, - struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down); #ifdef CONFIG_DEBUG_FS struct dentry *dentry; diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index ccd97bcef269..25f7bcbea7ab 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -74,8 +74,10 @@ typedef int (*config_clks_t)(struct device *dev, struct opp_table *opp_table, * @supported_hw_count: Number of elements in the array. * @regulator_names: Array of pointers to the names of the regulator, NULL terminated. * @genpd_names: Null terminated array of pointers containing names of genpd to - * attach. - * @virt_devs: Pointer to return the array of virtual devices. + * attach. Mutually exclusive with required_devs. + * @virt_devs: Pointer to return the array of genpd virtual devices. Mutually + * exclusive with required_devs. + * @required_devs: Required OPP devices. Mutually exclusive with genpd_names/virt_devs. * * This structure contains platform specific OPP configurations for the device. */ @@ -90,6 +92,7 @@ struct dev_pm_opp_config { const char * const *regulator_names; const char * const *genpd_names; struct device ***virt_devs; + struct device **required_devs; }; /**