Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp523657ybz; Fri, 24 Apr 2020 04:45:36 -0700 (PDT) X-Google-Smtp-Source: APiQypKwOTDUjrNXAo7meou3y5FqczDRs+V2Dw3Qg/o9pi+1/8ulsc5/I5hGkDhCFBy1a4J6rCt0 X-Received: by 2002:a50:a685:: with SMTP id e5mr6284622edc.243.1587728736751; Fri, 24 Apr 2020 04:45:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587728736; cv=none; d=google.com; s=arc-20160816; b=gHgVENirk5atGl19I2uCDO7E63hZnexPhPh1ieMk4kYqkmZejAEQ1eTo4CturWGFYU I6Jyhb5xYF5mqcQX3oktf4PMof0SA1IU3GNe+6jtVSp0jwLJNcjkKMjrpiwkNwVzt9kL sDkGt2Pej1XtvBoK4LLfnKpKbndFR1mnZeuLbNxvZJ4kxlCkSCEaAXcEq9hzKNA2AGH5 LqpIV6yBXj1m7FB1LKxxerkaO/cADttabJibyktfpkd44tx6X85gUkz2JTLMv2zOQ+lG Y2smxNueglPZy8zBnTX5czR/gryY9PdwTtAYHYCT0/ZmI29UKkP3W3UwiTSQ20mVPc1o g46g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=0feWfYVxQYrSEupQlVoVOosyiC2LKcVNCDVytVsfcsI=; b=q7aL1hT3rjpVHG62xN5X8d/BBAKysGCEfS/qM/NwvI3Qq/CkYUxV54HlhIAam/Q+r9 0WLgUu5wyt5PXq7M0BrIga0Qa+PW7gyRrv3b5/gSuw1yhV1wpYq6FQSeO/q+j4P2GNk+ YNSNuevCxW/0dI30yGZufBTCaxI7HAtIXrPy+Tx745NeIwgSsy5G4yG8s8soz2dC1IBj xpA7lKeqydSo8WdQ5MGR7AOL+znlgfFZPeIaUBFUqIPQJ/Kjt+jDDWJM45m5nhJyvDeb Q758ZO14nY/N1ZehmluUpAlUvB2ZxMasWYjnMFh4FBOuHzCv5q6jUpUC5Qt9dabRaNnH oERA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@st.com header.s=STMicroelectronics header.b=k2a+ZW4j; 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=st.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id by8si2957282ejb.525.2020.04.24.04.45.12; Fri, 24 Apr 2020 04:45:36 -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=@st.com header.s=STMicroelectronics header.b=k2a+ZW4j; 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=st.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727021AbgDXLl2 (ORCPT + 99 others); Fri, 24 Apr 2020 07:41:28 -0400 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:38538 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726865AbgDXLl0 (ORCPT ); Fri, 24 Apr 2020 07:41:26 -0400 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 03OBWOO5009422; Fri, 24 Apr 2020 13:41:04 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=STMicroelectronics; bh=0feWfYVxQYrSEupQlVoVOosyiC2LKcVNCDVytVsfcsI=; b=k2a+ZW4je8Dasnp7OZgVgDh8l+4SvgkEllW2sAQP55NAcIM4Q3F8pELb2N3M00Cs75Zk jORYbUNTFOU5PdtYO99X3cOSWEjxmzIY9bf6wjuMcDgrx6tnHX4hucBkF5RkL9MIzzJH yIsG0VneX9sWsaZ3PA2DAjTITGrr+9LxkLghDreSvgmoqINhnkRIJb8uuLlVw68MW9y7 ocFIzN8qeCM/SlPsvfo2VQbi6WZN6j2fGB8nKrCAn7D0NSECPk6oMQmt9I1gg3bTH19u 1YWld5bdzgUoIKak9LfTSp2iB1iVDcBeRjxm4stI5GQKhc2hejaiXuZaaH3kzIxCZkWN YA== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 30fq122v61-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 24 Apr 2020 13:41:04 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6296810002A; Fri, 24 Apr 2020 13:41:03 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag3node3.st.com [10.75.127.9]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 4D0F52B3DA1; Fri, 24 Apr 2020 13:41:03 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG3NODE3.st.com (10.75.127.9) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 24 Apr 2020 13:41:02 +0200 From: Benjamin Gaignard To: , , , , , , , CC: , , , , , Benjamin Gaignard Subject: [RFC 1/3] PM: QoS: Introduce cpufreq minimum load QoS Date: Fri, 24 Apr 2020 13:40:56 +0200 Message-ID: <20200424114058.21199-2-benjamin.gaignard@st.com> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20200424114058.21199-1-benjamin.gaignard@st.com> References: <20200424114058.21199-1-benjamin.gaignard@st.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG6NODE1.st.com (10.75.127.16) To SFHDAG3NODE3.st.com (10.75.127.9) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138,18.0.676 definitions=2020-04-24_04:2020-04-23,2020-04-24 signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Introduce cpufreq minimum load QoS, based on the "raw" low-level PM QoS, to represent the minimum expected cpu load by various devices. The cpufreq_minload_qos_limit() helper is defined to retrieve the aggregated constraints. Signed-off-by: Benjamin Gaignard --- include/linux/pm_qos.h | 12 +++ kernel/power/qos.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 4a69d4af3ff8..e2cc099322e3 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -316,4 +316,16 @@ int freq_qos_remove_notifier(struct freq_constraints *qos, enum freq_qos_req_type type, struct notifier_block *notifier); +/* Definitions related to the cpufreq minimum load QoS. */ + +#define CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE 0 +#define CPUFREQ_GOV_QOS_MIN_LOAD_MAX_VALUE 10 + +s32 cpufreq_minload_qos_limit(void); +bool cpufreq_minload_qos_request_active(struct pm_qos_request *req); +void cpufreq_minload_qos_add_request(struct pm_qos_request *req, s32 value); +void cpufreq_minload_qos_update_request(struct pm_qos_request *req, + s32 new_value); +void cpufreq_minload_qos_remove_request(struct pm_qos_request *req); + #endif diff --git a/kernel/power/qos.c b/kernel/power/qos.c index db0bed2cae26..df2fdd962f35 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -671,3 +671,216 @@ int freq_qos_remove_notifier(struct freq_constraints *qos, return ret; } EXPORT_SYMBOL_GPL(freq_qos_remove_notifier); + +/* Definitions related to the cpufreq minimum load QoS. */ + +static struct pm_qos_constraints cpufreq_minload_constraints = { + .list = PLIST_HEAD_INIT(cpufreq_minload_constraints.list), + .target_value = CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE, + .default_value = CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE, + .no_constraint_value = CPUFREQ_GOV_QOS_MIN_LOAD_DEFAULT_VALUE, + .type = PM_QOS_MAX, +}; + +/** + * cpufreq_minload_qos_limit - Return current system-wide cpufreq + * minimum load QoS limit. + */ +s32 cpufreq_minload_qos_limit(void) +{ + return pm_qos_read_value(&cpufreq_minload_constraints); +} +EXPORT_SYMBOL_GPL(cpufreq_minload_qos_limit); + +/** + * cpufreq_minload_qos_request_active - Check the given PM QoS request. + * @req: PM QoS request to check. + * + * Return: 'true' if @req has been added to the cpufreq minimum load + * QoS list, 'false' otherwise. + */ +bool cpufreq_minload_qos_request_active(struct pm_qos_request *req) +{ + return req->qos == &cpufreq_minload_constraints; +} +EXPORT_SYMBOL_GPL(cpufreq_minload_qos_request_active); + +/** + * cpufreq_minload_qos_add_request - Add new cpufreq minimum load QoS request. + * @req: Pointer to a preallocated handle. + * @value: Requested constraint value. + * + * Use @value to initialize the request handle pointed to by @req, insert it as + * a new entry to the cpufreq minimum load QoS list and recompute the effective + * QoS constraint for that list. + * + * Callers need to save the handle for later use in updates and removal of the + * QoS request represented by it. + */ +void cpufreq_minload_qos_add_request(struct pm_qos_request *req, s32 value) +{ + if (!req) + return; + + if (cpufreq_minload_qos_request_active(req)) { + WARN(1, KERN_ERR "%s called for already added request\n", __func__); + return; + } + + trace_pm_qos_add_request(value); + + req->qos = &cpufreq_minload_constraints; + pm_qos_update_target(req->qos, &req->node, PM_QOS_ADD_REQ, value); +} +EXPORT_SYMBOL_GPL(cpufreq_minload_qos_add_request); + +/** + * cpufreq_minload_qos_update_request - Modify existing cpufreq minimum load + * QoS request. + * @req : QoS request to update. + * @new_value: New requested constraint value. + * + * Use @new_value to update the QoS request represented by @req in the cpufreq + * minimum load QoS list along with updating the effective constraint value for + * that list. + */ +void cpufreq_minload_qos_update_request(struct pm_qos_request *req, + s32 new_value) +{ + if (!req) + return; + + if (!cpufreq_minload_qos_request_active(req)) { + WARN(1, KERN_ERR "%s called for unknown object\n", __func__); + return; + } + + trace_pm_qos_update_request(new_value); + + if (new_value == req->node.prio) + return; + + pm_qos_update_target(req->qos, &req->node, PM_QOS_UPDATE_REQ, new_value); +} +EXPORT_SYMBOL_GPL(cpufreq_minload_qos_update_request); + +/** + * cpufreq_minload_qos_remove_request - Remove existing cpufreq minimum load QoS + * request. + * @req: QoS request to remove. + * + * Remove the cpufreq minimum load QoS request represented by @req from the + * cpufreq minimum load QoS list along with updating the effective constraint + * value for that list. + */ +void cpufreq_minload_qos_remove_request(struct pm_qos_request *req) +{ + if (!req) + return; + + if (!cpufreq_minload_qos_request_active(req)) { + WARN(1, KERN_ERR "%s called for unknown object\n", __func__); + return; + } + + trace_pm_qos_remove_request(PM_QOS_DEFAULT_VALUE); + + pm_qos_update_target(req->qos, &req->node, + PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); + memset(req, 0, sizeof(*req)); +} +EXPORT_SYMBOL_GPL(cpufreq_minload_qos_remove_request); + +/* User space interface to the cpufreq minimum load QoS via misc device. */ + +static int cpufreq_minload_qos_open(struct inode *inode, struct file *filp) +{ + struct pm_qos_request *req; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + cpufreq_minload_qos_add_request(req, PM_QOS_DEFAULT_VALUE); + filp->private_data = req; + + return 0; +} + +static int cpufreq_minload_qos_release(struct inode *inode, struct file *filp) +{ + struct pm_qos_request *req = filp->private_data; + + filp->private_data = NULL; + + cpufreq_minload_qos_remove_request(req); + kfree(req); + + return 0; +} + +static ssize_t cpufreq_minload_qos_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct pm_qos_request *req = filp->private_data; + unsigned long flags; + s32 value; + + if (!req || !cpufreq_minload_qos_request_active(req)) + return -EINVAL; + + spin_lock_irqsave(&pm_qos_lock, flags); + value = pm_qos_get_value(&cpufreq_minload_constraints); + spin_unlock_irqrestore(&pm_qos_lock, flags); + + return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32)); +} + +static ssize_t cpufreq_minload_qos_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *f_pos) +{ + s32 value; + + if (count == sizeof(s32)) { + if (copy_from_user(&value, buf, sizeof(s32))) + return -EFAULT; + } else { + int ret; + + ret = kstrtos32_from_user(buf, count, 16, &value); + if (ret) + return ret; + } + + cpufreq_minload_qos_update_request(filp->private_data, value); + + return count; +} + +static const struct file_operations cpufreq_minload_qos_fops = { + .write = cpufreq_minload_qos_write, + .read = cpufreq_minload_qos_read, + .open = cpufreq_minload_qos_open, + .release = cpufreq_minload_qos_release, + .llseek = noop_llseek, +}; + +static struct miscdevice cpufreq_minload_qos_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "cpufreq_minimum_load", + .fops = &cpufreq_minload_qos_fops, +}; + +static int __init cpufreq_minload_qos_init(void) +{ + int ret; + + ret = misc_register(&cpufreq_minload_qos_miscdev); + if (ret < 0) + pr_err("%s: %s setup failed\n", __func__, + cpufreq_minload_qos_miscdev.name); + + return ret; +} +late_initcall(cpufreq_minload_qos_init); -- 2.15.0