Received: by 2002:a25:d7c1:0:0:0:0:0 with SMTP id o184csp733972ybg; Fri, 18 Oct 2019 06:38:36 -0700 (PDT) X-Google-Smtp-Source: APXvYqw1j71Zp0cMK1XrLpBOzV3gzV0OYW2UwwItvGnROLmjJQZYODD20A5gn9JeOoye5MOzMTqy X-Received: by 2002:a17:906:130c:: with SMTP id w12mr8533738ejb.142.1571405916400; Fri, 18 Oct 2019 06:38:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571405916; cv=none; d=google.com; s=arc-20160816; b=Tfo7+UkoR2GXj6q+4tDZHvuz/wmBuzGj+bBKXLPLeCCPC61zwlg6O3E+gwMjmemGdJ Wywi760ZipeT2Nd6KS3xsaUUAiiOXxTsn+73vlqHTYWyQBFEebat44XeJj3Q+wbPgI7y XCRIOPJq1jLJ0zZ5bIIbgfqNcWEOEhm4R4Dfp2m0xIZZGSJvB6JsPFZ3tc6q6s0rrRjT YX4tn4ederR+waCsB5TPmO1h3JwX4TJJq3RmHaeCfWgU9mvdteF4+QLLi/zJwaela3DQ +1kAl0TulhJb9PsgwFBbTU+977sGNZzoItj0TvABwYd9/IdcA7WD1FQaii9afNAgZIjm qGKw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature; bh=Y42TivkNMfetbxPGlFDe/PapDuIuV8Zv/0BU9JPv/Sw=; b=DKG8TbxhKeLtuMAfaCaPUmgwPdwXXWYSSMY+8BIUdyR6Loc6TLm7cJSgeYTUdrcbxg asf0gvzjALmrr6v4is7wTOQRC5XxoVUD1wp2twOMpPIz/YQVgjfutl0vvOllapr5qnKZ n+eEm1R0mVl3FZ6rHc1xJImP5wc5Q5T2n4Gl7gwGUOwxvpZh/uocMwr6Gwmu5WpPxOqz cYMagurmVdZJAMbU9Zv5ACcdlN/CnHW2oGom6LTCHgGmb/6hHBRbamRHQEm3j2l6BscR VEvWEQeMz2hophRq0YPKhhYnG62CuvKHmA+bSrPaez5RYbGhMSaRNMaFYFwSNhWsxzD4 AKOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=x4IY9lhR; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h14si4639707edk.315.2019.10.18.06.38.13; Fri, 18 Oct 2019 06:38:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=x4IY9lhR; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728442AbfJQJlu (ORCPT + 99 others); Thu, 17 Oct 2019 05:41:50 -0400 Received: from mail-pf1-f195.google.com ([209.85.210.195]:40015 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2408594AbfJQJlr (ORCPT ); Thu, 17 Oct 2019 05:41:47 -0400 Received: by mail-pf1-f195.google.com with SMTP id x127so1281733pfb.7 for ; Thu, 17 Oct 2019 02:41:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=Y42TivkNMfetbxPGlFDe/PapDuIuV8Zv/0BU9JPv/Sw=; b=x4IY9lhRWJKpuUcTJmCu4HwELtwtgqIXa/MqsOgleEc4A/1PgUfGyU2PCXBgc4pmWs FPYWR7u92W3RSinCOBRUq5MeGtJqWATdgogW4hUe5VMWopjQGoc6MsaylQIqHOoXQTa9 2IxlG/fLRLQMQuw9xTQKFiRf+F/AB6OoUASmeBlXmHP5I84cU597Kd2ajqncPHGgpzR/ cPO9p3JavSs3mBZaIpsBXp0F7lldyPKCDuMIUAKxcriR8hW2+7zg76IR81fX1feZaAL8 sw/Yvv6JW1p8OCiU4vO+BQFAYd8NJfrH3S6DRT3IaW3aHCTJHgMBHmrmpnKqieLgQH/u 8xJA== 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:user-agent; bh=Y42TivkNMfetbxPGlFDe/PapDuIuV8Zv/0BU9JPv/Sw=; b=sh6k7U6MPHPQ1Vo27IO+zuDO3INt6YLB7EUPTyUDHYJ25iagrND3/GsTp9OUMQ+JWb BMm+o7tMA49VSyQSwwDoH+VY+c4IETvGwCv1YFCQW8O2YjEKPkJIBzPMwqU4EBkJ0T0Q Ea7wR37Z41tkUu6HxtRC68KruGd9RBKNnwEdu5td0KIUbbtm/gbMPCqP+dz0FxgSwA4O Y2Fvabk/20hLz+cgY4J+77zdbSQmGvnM+N9rCBKn5uJHD/lvcCROw0K5CzO0d4Qwdlk5 2mfk69HopC5t8Oqglk6s+QMIuuhER1jkwwjE1oU/ud4OkjLGVx77ZnYGm6hHdqmO/TBM gy4A== X-Gm-Message-State: APjAAAVxqlIJyvP+K9jnVWtgoZn5lHxfqIXgFvQK0Ej7VDB1JTYvJx15 i0GlRT17FRpSApl/bBBviGRobA== X-Received: by 2002:aa7:9715:: with SMTP id a21mr2775707pfg.144.1571305306934; Thu, 17 Oct 2019 02:41:46 -0700 (PDT) Received: from localhost ([122.172.151.112]) by smtp.gmail.com with ESMTPSA id ep10sm14612289pjb.2.2019.10.17.02.41.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Oct 2019 02:41:45 -0700 (PDT) Date: Thu, 17 Oct 2019 15:11:43 +0530 From: Viresh Kumar To: "Rafael J. Wysocki" Cc: Linux PM , Linux ACPI , LKML , Sudeep Holla , Dmitry Osipenko Subject: Re: [RFT][PATCH 1/3] PM: QoS: Introduce frequency QoS Message-ID: <20191017094143.fhmhgltv6ujccxlp@vireshk-i7> References: <2811202.iOFZ6YHztY@kreacher> <4551555.oysnf1Sd0E@kreacher> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4551555.oysnf1Sd0E@kreacher> User-Agent: NeoMutt/20180716-391-311a52 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 16-10-19, 12:41, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki > > Introduce frequency QoS, based on the "raw" low-level PM QoS, to > represent min and max frequency requests and aggregate constraints. > > The min and max frequency requests are to be represented by > struct freq_qos_request objects and the aggregate constraints are to > be represented by struct freq_constraints objects. The latter are > expected to be initialized with the help of freq_constraints_init(). > > The freq_qos_read_value() helper is defined to retrieve the aggregate > constraints values from a given struct freq_constraints object and > there are the freq_qos_add_request(), freq_qos_update_request() and > freq_qos_remove_request() helpers to manipulate the min and max > frequency requests. It is assumed that the the helpers will not > run concurrently with each other for the same struct freq_qos_request > object, so if that may be the case, their uses must ensure proper > synchronization between them (e.g. through locking). > > In addition, freq_qos_add_notifier() and freq_qos_remove_notifier() > are provided to add and remove notifiers that will trigger on aggregate > constraint changes to and from a given struct freq_constraints object, > respectively. > > Signed-off-by: Rafael J. Wysocki > --- > include/linux/pm_qos.h | 44 ++++++++ > kernel/power/qos.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 284 insertions(+) > > Index: linux-pm/include/linux/pm_qos.h > =================================================================== > --- linux-pm.orig/include/linux/pm_qos.h > +++ linux-pm/include/linux/pm_qos.h > @@ -267,4 +267,48 @@ static inline s32 dev_pm_qos_raw_resume_ > } > #endif > > +#define FREQ_QOS_MIN_DEFAULT_VALUE 0 > +#define FREQ_QOS_MAX_DEFAULT_VALUE (-1) > + > +enum freq_qos_req_type { > + FREQ_QOS_MIN = 1, > + FREQ_QOS_MAX, > +}; > + > +struct freq_constraints { > + struct pm_qos_constraints min_freq; > + struct blocking_notifier_head min_freq_notifiers; > + struct pm_qos_constraints max_freq; > + struct blocking_notifier_head max_freq_notifiers; > +}; > + > +struct freq_qos_request { > + enum freq_qos_req_type type; > + struct plist_node pnode; > + struct freq_constraints *qos; > +}; > + > +static inline int freq_qos_request_active(struct freq_qos_request *req) > +{ > + return !IS_ERR_OR_NULL(req->qos); > +} > + > +void freq_constraints_init(struct freq_constraints *qos); > + > +s32 freq_qos_read_value(struct freq_constraints *qos, > + enum freq_qos_req_type type); > + > +int freq_qos_add_request(struct freq_constraints *qos, > + struct freq_qos_request *req, > + enum freq_qos_req_type type, s32 value); > +int freq_qos_update_request(struct freq_qos_request *req, s32 new_value); > +int freq_qos_remove_request(struct freq_qos_request *req); > + > +int freq_qos_add_notifier(struct freq_constraints *qos, > + enum freq_qos_req_type type, > + struct notifier_block *notifier); > +int freq_qos_remove_notifier(struct freq_constraints *qos, > + enum freq_qos_req_type type, > + struct notifier_block *notifier); > + > #endif > Index: linux-pm/kernel/power/qos.c > =================================================================== > --- linux-pm.orig/kernel/power/qos.c > +++ linux-pm/kernel/power/qos.c > @@ -650,3 +650,243 @@ static int __init pm_qos_power_init(void > } > > late_initcall(pm_qos_power_init); > + > +/* Definitions related to the frequency QoS below. */ > + > +/** > + * freq_constraints_init - Initialize frequency QoS constraints. > + * @qos: Frequency QoS constraints to initialize. > + */ > +void freq_constraints_init(struct freq_constraints *qos) > +{ > + struct pm_qos_constraints *c; > + > + c = &qos->min_freq; > + plist_head_init(&c->list); > + c->target_value = FREQ_QOS_MIN_DEFAULT_VALUE; > + c->default_value = FREQ_QOS_MIN_DEFAULT_VALUE; > + c->no_constraint_value = FREQ_QOS_MIN_DEFAULT_VALUE; > + c->type = PM_QOS_MAX; should this be MIN ? > + c->notifiers = &qos->min_freq_notifiers; > + BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers); > + > + c = &qos->max_freq; > + plist_head_init(&c->list); > + c->target_value = FREQ_QOS_MAX_DEFAULT_VALUE; > + c->default_value = FREQ_QOS_MAX_DEFAULT_VALUE; > + c->no_constraint_value = FREQ_QOS_MAX_DEFAULT_VALUE; > + c->type = PM_QOS_MIN; and this MAX ? > + c->notifiers = &qos->max_freq_notifiers; > + BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers); > +} > + > +/** > + * freq_qos_read_value - Get frequency QoS constraint for a given list. > + * @qos: Constraints to evaluate. > + * @type: QoS request type. > + */ > +s32 freq_qos_read_value(struct freq_constraints *qos, > + enum freq_qos_req_type type) > +{ > + s32 ret; > + > + switch (type) { > + case FREQ_QOS_MIN: > + ret = IS_ERR_OR_NULL(qos) ? > + FREQ_QOS_MIN_DEFAULT_VALUE : > + pm_qos_read_value(&qos->min_freq); > + break; > + case FREQ_QOS_MAX: > + ret = IS_ERR_OR_NULL(qos) ? > + FREQ_QOS_MAX_DEFAULT_VALUE : > + pm_qos_read_value(&qos->max_freq); > + break; > + default: > + WARN_ON(1); > + ret = 0; > + } > + > + return ret; > +} > + > +/** > + * freq_qos_apply - Add/modify/remove frequency QoS request. > + * @req: Constraint request to apply. > + * @action: Action to perform (add/update/remove). > + * @value: Value to assign to the QoS request. > + */ > +static int freq_qos_apply(struct freq_qos_request *req, > + enum pm_qos_req_action action, s32 value) > +{ > + int ret; > + > + switch(req->type) { > + case FREQ_QOS_MIN: > + ret = pm_qos_update_target(&req->qos->min_freq, &req->pnode, > + action, value); > + break; > + case FREQ_QOS_MAX: > + ret = pm_qos_update_target(&req->qos->max_freq, &req->pnode, > + action, value); > + break; > + default: > + ret = -EINVAL; > + } > + > + return ret; > +} > + > +/** > + * freq_qos_add_request - Insert new frequency QoS request into a given list. > + * @qos: Constraints to update. > + * @req: Preallocated request object. > + * @type: Request type. > + * @value: Request value. > + * > + * Insert a new entry into the @qos list of requests, recompute the effective > + * QoS constraint value for that list and initialize the @req object. The > + * caller needs to save that object for later use in updates and removal. > + * > + * Return 1 if the effective constraint value has changed, 0 if the effective > + * constraint value has not changed, or a negative error code on failures. > + */ > +int freq_qos_add_request(struct freq_constraints *qos, > + struct freq_qos_request *req, > + enum freq_qos_req_type type, s32 value) > +{ > + int ret; > + > + if (IS_ERR_OR_NULL(qos) || !req) > + return -EINVAL; > + > + if (WARN(freq_qos_request_active(req), > + "%s() called for active request\n", __func__)) > + return -EINVAL; > + > + req->qos = qos; > + req->type = type; > + ret = freq_qos_apply(req, PM_QOS_ADD_REQ, value); > + if (ret < 0) { > + req->qos = NULL; > + req->type = 0; > + } > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(freq_qos_add_request); > + > +/** > + * freq_qos_update_request - Modify existing frequency QoS request. > + * @req: Request to modify. > + * @new_value: New request value. > + * > + * Update an existing frequency QoS request along with the effective constraint > + * value for the list of requests it belongs to. > + * > + * Return 1 if the effective constraint value has changed, 0 if the effective > + * constraint value has not changed, or a negative error code on failures. > + */ > +int freq_qos_update_request(struct freq_qos_request *req, s32 new_value) > +{ > + if (!req) > + return -EINVAL; > + > + if (WARN(!freq_qos_request_active(req), > + "%s() called for unknown object\n", __func__)) > + return -EINVAL; > + > + if (req->pnode.prio == new_value) > + return 0; > + > + return freq_qos_apply(req, PM_QOS_UPDATE_REQ, new_value); > +} > +EXPORT_SYMBOL_GPL(freq_qos_update_request); > + > +/** > + * freq_qos_remove_request - Remove frequency QoS request from its list. > + * @req: Request to remove. > + * > + * Remove the given frequency QoS request from the list of constraints it > + * belongs to and recompute the effective constraint value for that list. > + * > + * Return 1 if the effective constraint value has changed, 0 if the effective > + * constraint value has not changed, or a negative error code on failures. > + */ > +int freq_qos_remove_request(struct freq_qos_request *req) > +{ > + if (!req) > + return -EINVAL; > + > + if (WARN(!freq_qos_request_active(req), > + "%s() called for unknown object\n", __func__)) > + return -EINVAL; > + > + return freq_qos_apply(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); > +} > +EXPORT_SYMBOL_GPL(freq_qos_remove_request); > + > +/** > + * freq_qos_add_notifier - Add frequency QoS change notifier. > + * @qos: List of requests to add the notifier to. > + * @type: Request type. > + * @notifier: Notifier block to add. > + */ > +int freq_qos_add_notifier(struct freq_constraints *qos, > + enum freq_qos_req_type type, > + struct notifier_block *notifier) > +{ > + int ret; > + > + if (IS_ERR_OR_NULL(qos) || !notifier) > + return -EINVAL; > + > + switch (type) { > + case FREQ_QOS_MIN: > + ret = blocking_notifier_chain_register(qos->min_freq.notifiers, > + notifier); > + break; > + case FREQ_QOS_MAX: > + ret = blocking_notifier_chain_register(qos->max_freq.notifiers, > + notifier); > + break; > + default: > + WARN_ON(1); > + ret = -EINVAL; > + } > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(freq_qos_add_notifier); > + > +/** > + * freq_qos_remove_notifier - Remove frequency QoS change notifier. > + * @qos: List of requests to remove the notifier from. > + * @type: Request type. > + * @notifier: Notifier block to remove. > + */ > +int freq_qos_remove_notifier(struct freq_constraints *qos, > + enum freq_qos_req_type type, > + struct notifier_block *notifier) > +{ > + int ret; > + > + if (IS_ERR_OR_NULL(qos) || !notifier) > + return -EINVAL; > + > + switch (type) { > + case FREQ_QOS_MIN: > + ret = blocking_notifier_chain_unregister(qos->min_freq.notifiers, > + notifier); > + break; > + case FREQ_QOS_MAX: > + ret = blocking_notifier_chain_unregister(qos->max_freq.notifiers, > + notifier); > + break; > + default: > + WARN_ON(1); > + ret = -EINVAL; > + } > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(freq_qos_remove_notifier); > > -- viresh