Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp95522ybz; Fri, 24 Apr 2020 12:25:15 -0700 (PDT) X-Google-Smtp-Source: APiQypLlRdQBozQwqJYSI9i6PCtZi4m2mAVAQ5lU7nw4o/DCRSd0Ybmf76TODnPzGDYc2foAt1eE X-Received: by 2002:a50:cf05:: with SMTP id c5mr8893434edk.330.1587756315462; Fri, 24 Apr 2020 12:25:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587756315; cv=none; d=google.com; s=arc-20160816; b=HbDl8jnnT73TQ+u2o8gp2r1dXouYhaclr3eBRT9w3RBhaeNYenj+ly0s70I4zFnN4w msZVkuf/tbr28uL6iv7hsS13OJCOOUH8BwAR6jtln329GrheoUghddcC812e1AP8AOLK nivsNmhbMTlrTBC9QQlWkAsvNtP+31huT/1TPOp4N/AexZIQtpKSOsamfEfgL3aFaw06 t1sAd4OmCbVfQIU9Cbk2V7ILvMpYDHeJ1wM8cXE125ybxjkNE6Q/2xGEv+IGJhxyQcnb 7HtLsCA7UEB1Q4PESanL628+2A4N3N//JNtj/69fqKRfuwCfX2o0Rmdye36mwxESURmv LqDg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature; bh=h9WOUp5WscPST9oWEpQEvY13ON01lmbF+7hS1W9VYTc=; b=h+m/7qi4HyLlPHOmcT/gTX8y9lIdzF1DLuxZKgqgPYpHs0g+kT+X2YVnnt6OpfhCs9 101XN3HKn6RN3j7C5cm9Plp8thxhq8g/NeI4S4r79wTg2oGidTsu10vQG59PBPIvANnB eqKQD3YBQLqh89HFJesetapUGZLZKg5Iqy4vDDwXEh67IiyOGsMa6HCtPRJoGKELka5C SV1TIBOhj6QA0i734Mzv7F4Kda8UcaB1hKf93SOOgcekFMYRZgtJNImdH2wZU2RXM16p NHkXfmsKkZ/zM4wsSe4O0GJBnZVRlAoFG8FAHiFh1yA8OoMZsgxGK1vau6acWLqqKZDN tGfA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=f8G3tnqQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id c9si3558471eja.234.2020.04.24.12.24.52; Fri, 24 Apr 2020 12:25:15 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-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=@chromium.org header.s=google header.b=f8G3tnqQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729310AbgDXTUb (ORCPT + 99 others); Fri, 24 Apr 2020 15:20:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32858 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729300AbgDXTU3 (ORCPT ); Fri, 24 Apr 2020 15:20:29 -0400 Received: from mail-pf1-x443.google.com (mail-pf1-x443.google.com [IPv6:2607:f8b0:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1F24EC09B049 for ; Fri, 24 Apr 2020 12:20:28 -0700 (PDT) Received: by mail-pf1-x443.google.com with SMTP id d184so5253133pfd.4 for ; Fri, 24 Apr 2020 12:20:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=h9WOUp5WscPST9oWEpQEvY13ON01lmbF+7hS1W9VYTc=; b=f8G3tnqQ/WqZPljfWTrVZC9n1UKePvFXMcQkjcpQjgETjxr7tYA1VxsR86S6GKMJPw utt7CewjDTBe/ZGg5w3wq0yD30GCiNSCzXKPFQtuV6eS3iKl6dX4aTUjY8Lnmru3wrEM 4bOOkSVOo0QMPs4KfbsDu8mPNyMQKVOsUSvB8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=h9WOUp5WscPST9oWEpQEvY13ON01lmbF+7hS1W9VYTc=; b=aRibLb/0buY460H1UsBfR2H+zUhyGfqhxqakemh9EN9Zr47Y40NA3Ccj/se3ZsCRzY EVHMLTNCOtaM/7++oQgc65ATKWDEW059x1/OkVfKYZQWxLR//hmTp69UISGLJitlvCe5 QhWCvdceEk+9M2kS9xFG17rourHh1eTHvs+HMu5vrCAZzxXhOsT2EpXa5Z8jQHHVMlab Tqe8jcQdsfhUylrhAqrFO0D/Ra6Br6rcmCwodrMQLcJH3iuEJF3x3bic4XOSxlOnzo6h NK3MGjaI0OGQCp7MgxnIfJVmtPJTD1C/E0Yxa0qqCPv9Dx2WVoa8eP78MbxRniDWkjsx fkkA== X-Gm-Message-State: AGi0PubZUp8k3oWwn69gXKvHm6EIyTg6DWnZP1MvETp1raHzHcPaY9K6 tpoi1luCXWKvl56kLZqaiMXBRw== X-Received: by 2002:aa7:9429:: with SMTP id y9mr11767584pfo.8.1587756027512; Fri, 24 Apr 2020 12:20:27 -0700 (PDT) Received: from localhost ([2620:15c:202:1:4fff:7a6b:a335:8fde]) by smtp.gmail.com with ESMTPSA id v64sm6539551pfb.20.2020.04.24.12.20.26 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 24 Apr 2020 12:20:26 -0700 (PDT) Date: Fri, 24 Apr 2020 12:20:25 -0700 From: Matthias Kaehlcke To: Georgi Djakov Cc: vireshk@kernel.org, nm@ti.com, sboyd@kernel.org, robh+dt@kernel.org, rjw@rjwysocki.net, saravanak@google.com, sibis@codeaurora.org, rnayak@codeaurora.org, bjorn.andersson@linaro.org, vincent.guittot@linaro.org, jcrouse@codeaurora.org, evgreen@chromium.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v7 4/7] OPP: Add support for parsing interconnect bandwidth Message-ID: <20200424192025.GA4525@google.com> References: <20200424155404.10746-1-georgi.djakov@linaro.org> <20200424155404.10746-5-georgi.djakov@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20200424155404.10746-5-georgi.djakov@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On Fri, Apr 24, 2020 at 06:54:01PM +0300, Georgi Djakov wrote: > The OPP bindings now support bandwidth values, so add support to parse it > from device tree and store it into the new dev_pm_opp_icc_bw struct, which > is part of the dev_pm_opp. > > Signed-off-by: Georgi Djakov > --- > v7: > * Addressed some review comments from Viresh and Sibi. > * Various other changes. > > v2: https://lore.kernel.org/linux-arm-msm/20190423132823.7915-4-georgi.djakov@linaro.org/ > > drivers/opp/Kconfig | 1 + > drivers/opp/core.c | 16 +++++- > drivers/opp/of.c | 119 ++++++++++++++++++++++++++++++++++++++++- > drivers/opp/opp.h | 9 ++++ > include/linux/pm_opp.h | 12 +++++ > 5 files changed, 153 insertions(+), 4 deletions(-) > > diff --git a/drivers/opp/Kconfig b/drivers/opp/Kconfig > index 35dfc7e80f92..230d2b84436c 100644 > --- a/drivers/opp/Kconfig > +++ b/drivers/opp/Kconfig > @@ -2,6 +2,7 @@ > config PM_OPP > bool > select SRCU > + depends on INTERCONNECT || !INTERCONNECT huh? > ---help--- > SOCs have a standard set of tuples consisting of frequency and > voltage pairs that the device will support per voltage domain. This > diff --git a/drivers/opp/core.c b/drivers/opp/core.c > index c9c1bbe6ae27..8e86811eb7b2 100644 > --- a/drivers/opp/core.c > +++ b/drivers/opp/core.c > @@ -985,6 +985,12 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) > ret); > } > > + /* Find interconnect path(s) for the device */ > + ret = _of_find_paths(opp_table, dev); > + if (ret) > + dev_dbg(dev, "%s: Error finding interconnect paths: %d\n", > + __func__, ret); why dev_dbg and not dev_warn? > + > BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); > INIT_LIST_HEAD(&opp_table->opp_list); > kref_init(&opp_table->kref); > @@ -1229,19 +1235,22 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic); > struct dev_pm_opp *_opp_allocate(struct opp_table *table) > { > struct dev_pm_opp *opp; > - int count, supply_size; > + int count, supply_size, icc_size; > > /* Allocate space for at least one supply */ > count = table->regulator_count > 0 ? table->regulator_count : 1; > supply_size = sizeof(*opp->supplies) * count; > + icc_size = sizeof(*opp->bandwidth) * table->path_count; > > /* allocate new OPP node and supplies structures */ > - opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL); > + opp = kzalloc(sizeof(*opp) + supply_size + icc_size, GFP_KERNEL); > + > if (!opp) > return NULL; > > /* Put the supplies at the end of the OPP structure as an empty array */ > opp->supplies = (struct dev_pm_opp_supply *)(opp + 1); > + opp->bandwidth = (struct dev_pm_opp_icc_bw *)(opp->supplies + 1); IIUC this needs to be: opp->bandwidth = (struct dev_pm_opp_icc_bw *)(opp->supplies + count); maybe s/count/supply_count/ > INIT_LIST_HEAD(&opp->node); > > return opp; > @@ -1276,6 +1285,9 @@ int _opp_compare_key(struct dev_pm_opp *opp1, struct dev_pm_opp *opp2) > { > if (opp1->rate != opp2->rate) > return opp1->rate < opp2->rate ? -1 : 1; > + if (opp1->bandwidth && opp2->bandwidth && > + opp1->bandwidth[0].peak != opp2->bandwidth[0].peak) > + return opp1->bandwidth[0].peak < opp2->bandwidth[0].peak ? -1 : 1; > if (opp1->level != opp2->level) > return opp1->level < opp2->level ? -1 : 1; > return 0; > diff --git a/drivers/opp/of.c b/drivers/opp/of.c > index e33169c7e045..978e445b0cdb 100644 > --- a/drivers/opp/of.c > +++ b/drivers/opp/of.c > @@ -332,6 +332,59 @@ static int _of_opp_alloc_required_opps(struct opp_table *opp_table, > return ret; > } > > +int _of_find_paths(struct opp_table *opp_table, struct device *dev) nit: _of_find_icc_paths() to be more concise? > +{ > + struct device_node *np; > + int ret, i, count, num_paths; > + > + np = of_node_get(dev->of_node); > + if (!np) > + return 0; > + > + count = of_count_phandle_with_args(np, "interconnects", > + "#interconnect-cells"); > + of_node_put(np); > + if (count < 0) > + return 0; > + > + /* two phandles when #interconnect-cells = <1> */ > + if (count % 2) { > + dev_err(dev, "%s: Invalid interconnects values\n", > + __func__); nit: no need for separate line > + return -EINVAL; > + } > + > + num_paths = count / 2; > + opp_table->paths = kcalloc(num_paths, sizeof(*opp_table->paths), > + GFP_KERNEL); Add kfree(opp_table->paths) to _opp_table_kref_release() ? > + if (!opp_table->paths) > + return -ENOMEM; > + > + for (i = 0; i < num_paths; i++) { > + opp_table->paths[i] = of_icc_get_by_index(dev, i); > + if (IS_ERR(opp_table->paths[i])) { > + ret = PTR_ERR(opp_table->paths[i]); > + if (ret != -EPROBE_DEFER) { > + dev_err(dev, "%s: Unable to get path%d: %d\n", > + __func__, i, ret); > + } nit: curly braces not needed > + goto err; > + } > + } > + opp_table->path_count = num_paths; > + > + return 0; > + > +err: > + while (i--) > + icc_put(opp_table->paths[i]); > + > + kfree(opp_table->paths); > + opp_table->paths = NULL; > + > + return ret; > +} > + > static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table, > struct device_node *np) > { > @@ -524,8 +577,11 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table); > static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np, > bool *rate_not_available) > { > + struct property *peak, *avg; > + u32 *peak_bw, *avg_bw; > u64 rate; > - int ret; > + int ret, i, count; > + bool found = false; > > ret = of_property_read_u64(np, "opp-hz", &rate); > if (!ret) { > @@ -535,10 +591,69 @@ static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np, > * bit guaranteed in clk API. > */ > new_opp->rate = (unsigned long)rate; > + found = true; > } > *rate_not_available = !!ret; > > - of_property_read_u32(np, "opp-level", &new_opp->level); > + peak = of_find_property(np, "opp-peak-kBps", NULL); > + if (peak) { > + /* > + * Bandwidth consists of peak and average (optional) values: > + * opp-peak-kBps = ; > + * opp-avg-kBps = ; > + */ > + count = peak->length / sizeof(u32); > + peak_bw = kmalloc_array(count, sizeof(*peak_bw), GFP_KERNEL); > + if (!peak_bw) > + return -ENOMEM; > + > + ret = of_property_read_u32_array(np, "opp-peak-kBps", peak_bw, > + count); > + if (ret) { > + pr_err("%s: Error parsing opp-peak-kBps: %d\n", > + __func__, ret); > + goto free_peak_bw; > + } > + > + for (i = 0; i < count; i++) > + new_opp->bandwidth[i].peak = kBps_to_icc(peak_bw[i]); > + > + found = true; kfree(peak_bw); or re-arrange the kfree()'s below to be in the common code path > + } > + > + avg = of_find_property(np, "opp-avg-kBps", NULL); > + if (peak && avg) { > + count = avg->length / sizeof(u32); > + avg_bw = kmalloc_array(count, sizeof(*avg_bw), GFP_KERNEL); > + if (!avg_bw) { > + ret = -ENOMEM; > + goto free_peak_bw; > + } > + > + ret = of_property_read_u32_array(np, "opp-avg-kBps", avg_bw, > + count); > + if (ret) { > + pr_err("%s: Error parsing opp-avg-kBps: %d\n", > + __func__, ret); > + goto free_avg_bw; > + } > + > + for (i = 0; i < count; i++) > + new_opp->bandwidth[i].avg = kBps_to_icc(avg_bw[i]); kfree(avg_bw); > + } nit: the two code blocks for peak and average bandwidth are mostly redundant. If it weren't for the assignment of 'new_opp->bandwidth[i].avg' vs 'new_opp->bandwidth[i].peak' the above could easily be outsourced into a helper function. With some pointer hacks you could still do this, but not sure if it's worth the effort. > + > + if (of_property_read_u32(np, "opp-level", &new_opp->level)) > + found = true; > + > + if (found) > + return 0; > + > + return ret; > + > +free_avg_bw: > + kfree(avg_bw); > +free_peak_bw: > + kfree(peak_bw); > > return ret; > }