From nobody Tue Dec 2 00:25:40 2025 Received: from mail-lf1-f44.google.com (mail-lf1-f44.google.com [209.85.167.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C98E26CE3B for ; Tue, 25 Nov 2025 11:26:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764070020; cv=none; b=Z13pgJzsNX+hOipRtzgSLQd3axNAjp4rl99tX1JjtL8GZPug0+KWiknhR9syk57bC771PdaBBLN3aS6x2tKHa4oYJQAAFxZc2KQz/yM0tX1Z6cYeFAMlzV+9kQ5sEdBAXtPmxlFBld5s5zj2s5mhg1gsmMgcneQLPL9Ld58wpE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764070020; c=relaxed/simple; bh=36iGndTEM/3YoIZN6fKWhfnsw6ftPmJLUkt15edtXOk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LFBfwzYGTl0kylgkfAP1H1J3LGepMrR1d0c3A1Si3SEGvJhPT3QRGbbj1paWJPwVK1iKj8UEUFqSz3LWY5UAGBX/LMGkPkvCUw/wtK3Kq0WGchtAPZEcORUirLKlZ6IFIMDb9V69DCtHV9nAM1Bf6yziWNfhevqqtCyzqCGzRqM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=xxSqO1hu; arc=none smtp.client-ip=209.85.167.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="xxSqO1hu" Received: by mail-lf1-f44.google.com with SMTP id 2adb3069b0e04-5959b2f3fc9so5129193e87.2 for ; Tue, 25 Nov 2025 03:26:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764070016; x=1764674816; 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=FE45t6R4BBEDJliCvwSFl/kztT91PBe4qbzvkRlOVSY=; b=xxSqO1huq9U/U3KwH9GZJriZslv/CLFzWu7f8rUgkAx4FCXIzAbt2Fk+2D9HsSQfHy 8geAfVK2rjlXuGvNA5RJt/2dok1+fyP8AyR0f7FGgMBv5HmUqWnB5dWPRQHPoo3in3Te F6/LrjBZQDi4Vrehw7lFzqtXZ8LKQlXzL5fd0MP3f0zmJ8z4S2o3DH8zAk82OSqBfMjB vjVftziOtvVaF5pL8jq2tcP3RpIhkY3luXCF0c/nqmyNmRX2OOIozfx4Pa6a4vnBDJ4C oMNYop8nKe5QoaNItObZtnhBxVWNc7ragvr+z6g0ee2MKFDhhAQPB5Er84hd+AKiLDzl BeEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764070016; x=1764674816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FE45t6R4BBEDJliCvwSFl/kztT91PBe4qbzvkRlOVSY=; b=nRkj8zJt77UW3gX0jmlCwVR/dp6oBPNnpnw7xMd/nOCo8Oy+Yic6lgfh5xjSmS1u4C 81VHt/0PWyIpf+qzs9Yk8qTcENhK+Qqm6Ct2qLxIqGUgM3JLjVdywlFifLRTkGW89EXd H4Z/tmcaQDhb8/BLWJKrH4U872dBQ/MTXGD3OZPZMuxOcAiDiz4WGR1z64YlEvZDGqZk 5nYxaLpFn5tSerNBARoLe4CuF915tWBNMlZH2M5/7Tp4gLvRISyipC+CzxL7JwWx6L9s uo0bGWOZpj/QNX+AbhiryeoC9oWDD8E1MNFDWom06DvrkdLG1QSxx5oVNKY8EPN73vcK ezwg== X-Forwarded-Encrypted: i=1; AJvYcCU3PZ0f843U5ba07TZJ3AIxaH2Utd6RXd6DWxuvBrf8H6Vm1hxwh3BRotEy642QbTtIeHsTUby6n8cvfXM=@vger.kernel.org X-Gm-Message-State: AOJu0YyXzakaQXN82aCcHocbFsUzfSnXJd7Igs0iQ2xe4yGs88ZaYivH DK4gA6r70O//tgHWav9KKPfQGKUO9Lf1OFt2Ka4DH9QsYVfTDFbsO4OtFEJvuDq3QvQ= X-Gm-Gg: ASbGncsnGVx5d+aGdoy8dbfQ20oNdyMGSaxIhPCZyUJfEZ3VIcQiI3hwBYGIR3DQp1s ziOaT02znivO09dvVmJjKXobEk1jOYUuX13E8JVsTFSHOPk4lBOEigwqYTlUWzAOe1diX+wlgRG WXhWdHKEnTWTPjODJrCJB0OSDmuybQT4GIkAK6a0X8yP6FNwZ0DmGkOrVi/oobH+uwh4P/FGcst dqEQ1T+OTjVhgmMS47u2oti0OjukBrd5CrIHTiLwSnohGbsqa0N17P/+Ujozp6zfBnv0B058gtE dF0yrz2T+wbIZwQDL0JrKwxpW7PErlB4TaWLFgRhBoBtbu1rd76H9G1tCZpdzRSssW9MFLlf2c1 /CjnleKcu/oHDHlbQzfRn/kAEISgCwu8eSzJK9PODqZJ/hkRPAKz3WAX+nSLx0lbuOSmluXFTyb rif9SyPUEiAaTBbG6FdLzwFyYDRUDeDmrL3S/qYQbkKvVBz0zpgxc7wwIbIPfj X-Google-Smtp-Source: AGHT+IHQFhuvGIxrbLvzBOY3ImdRr5h5AdplkQMA/mpy30IgWDqDJmZVd9KXsBer5wdbinI8H9eOhQ== X-Received: by 2002:a05:6512:3341:b0:594:27dd:2700 with SMTP id 2adb3069b0e04-596a3ee51f6mr4340223e87.47.1764070016099; Tue, 25 Nov 2025 03:26:56 -0800 (PST) Received: from uffe-tuxpro14.. (h-178-174-189-39.A498.priv.bahnhof.se. [178.174.189.39]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5969db7563fsm4993526e87.2.2025.11.25.03.26.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Nov 2025 03:26:55 -0800 (PST) From: Ulf Hansson To: "Rafael J . Wysocki" , linux-pm@vger.kernel.org Cc: Vincent Guittot , Peter Zijlstra , Kevin Hilman , Pavel Machek , Len Brown , Daniel Lezcano , Maulik Shah , Prasad Sodagudi , Dhruva Gole , Deepti Jaggi , Ulf Hansson , linux-kernel@vger.kernel.org Subject: [PATCH v4 1/6] PM: QoS: Introduce a CPU system wakeup QoS limit Date: Tue, 25 Nov 2025 12:26:42 +0100 Message-ID: <20251125112650.329269-2-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251125112650.329269-1-ulf.hansson@linaro.org> References: <20251125112650.329269-1-ulf.hansson@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some platforms supports multiple low power states for CPUs that can be used when entering system-wide suspend. Currently we are always selecting the deepest possible state for the CPUs, which can break the system wakeup latency constraint that may be required for a use case. Let's take the first step towards addressing this problem, by introducing an interface for user space, that allows us to specify the CPU system wakeup QoS limit. Subsequent changes will start taking into account the new QoS limit. Reviewed-by: Dhruva Gole Reviewed-by: Kevin Hilman (TI) Tested-by: Kevin Hilman (TI) Signed-off-by: Ulf Hansson --- Changes in v4: - Added Kconfig help (Dhruva). - Added tags. Changes in v3: - Add Kconfig for the new interface (Rafael). - Updated commit message. Changes in v2: - Renamings to reflect the QoS are limited to CPUs. - Move code inside "CONFIG_CPU_IDLE". --- include/linux/pm_qos.h | 9 ++++ kernel/power/Kconfig | 11 +++++ kernel/power/qos.c | 106 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 4a69d4af3ff8..6cea4455f867 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -162,6 +162,15 @@ static inline void cpu_latency_qos_update_request(stru= ct pm_qos_request *req, static inline void cpu_latency_qos_remove_request(struct pm_qos_request *r= eq) {} #endif =20 +#ifdef CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP +s32 cpu_wakeup_latency_qos_limit(void); +#else +static inline s32 cpu_wakeup_latency_qos_limit(void) +{ + return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; +} +#endif + #ifdef CONFIG_PM enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask); enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask); diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 54a623680019..05337f437cca 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -202,6 +202,17 @@ config PM_WAKELOCKS_GC depends on PM_WAKELOCKS default y =20 +config PM_QOS_CPU_SYSTEM_WAKEUP + bool "User space interface for CPU system wakeup QoS" + depends on CPU_IDLE + help + Enable this to allow user space via the cpu_wakeup_latency file to + specify a CPU system wakeup latency limit. + + This may be particularly useful for platforms supporting multiple low + power states for CPUs during system-wide suspend and s2idle in + particular. + config PM bool "Device power management core functionality" help diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 4244b069442e..f7d8064e9adc 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -415,6 +415,105 @@ static struct miscdevice cpu_latency_qos_miscdev =3D { .fops =3D &cpu_latency_qos_fops, }; =20 +#ifdef CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP +/* The CPU system wakeup latency QoS. */ +static struct pm_qos_constraints cpu_wakeup_latency_constraints =3D { + .list =3D PLIST_HEAD_INIT(cpu_wakeup_latency_constraints.list), + .target_value =3D PM_QOS_RESUME_LATENCY_NO_CONSTRAINT, + .default_value =3D PM_QOS_RESUME_LATENCY_NO_CONSTRAINT, + .no_constraint_value =3D PM_QOS_RESUME_LATENCY_NO_CONSTRAINT, + .type =3D PM_QOS_MIN, +}; + +/** + * cpu_wakeup_latency_qos_limit - Current CPU system wakeup latency QoS li= mit. + * + * Returns the current CPU system wakeup latency QoS limit that may have b= een + * requested by user space. + */ +s32 cpu_wakeup_latency_qos_limit(void) +{ + return pm_qos_read_value(&cpu_wakeup_latency_constraints); +} + +static int cpu_wakeup_latency_qos_open(struct inode *inode, struct file *f= ilp) +{ + struct pm_qos_request *req; + + req =3D kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + req->qos =3D &cpu_wakeup_latency_constraints; + pm_qos_update_target(req->qos, &req->node, PM_QOS_ADD_REQ, + PM_QOS_RESUME_LATENCY_NO_CONSTRAINT); + filp->private_data =3D req; + + return 0; +} + +static int cpu_wakeup_latency_qos_release(struct inode *inode, + struct file *filp) +{ + struct pm_qos_request *req =3D filp->private_data; + + filp->private_data =3D NULL; + pm_qos_update_target(req->qos, &req->node, PM_QOS_REMOVE_REQ, + PM_QOS_RESUME_LATENCY_NO_CONSTRAINT); + kfree(req); + + return 0; +} + +static ssize_t cpu_wakeup_latency_qos_read(struct file *filp, char __user = *buf, + size_t count, loff_t *f_pos) +{ + s32 value =3D pm_qos_read_value(&cpu_wakeup_latency_constraints); + + return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32)); +} + +static ssize_t cpu_wakeup_latency_qos_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct pm_qos_request *req =3D filp->private_data; + s32 value; + + if (count =3D=3D sizeof(s32)) { + if (copy_from_user(&value, buf, sizeof(s32))) + return -EFAULT; + } else { + int ret; + + ret =3D kstrtos32_from_user(buf, count, 16, &value); + if (ret) + return ret; + } + + if (value < 0) + return -EINVAL; + + pm_qos_update_target(req->qos, &req->node, PM_QOS_UPDATE_REQ, value); + + return count; +} + +static const struct file_operations cpu_wakeup_latency_qos_fops =3D { + .open =3D cpu_wakeup_latency_qos_open, + .release =3D cpu_wakeup_latency_qos_release, + .read =3D cpu_wakeup_latency_qos_read, + .write =3D cpu_wakeup_latency_qos_write, + .llseek =3D noop_llseek, +}; + +static struct miscdevice cpu_wakeup_latency_qos_miscdev =3D { + .minor =3D MISC_DYNAMIC_MINOR, + .name =3D "cpu_wakeup_latency", + .fops =3D &cpu_wakeup_latency_qos_fops, +}; +#endif /* CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP */ + static int __init cpu_latency_qos_init(void) { int ret; @@ -424,6 +523,13 @@ static int __init cpu_latency_qos_init(void) pr_err("%s: %s setup failed\n", __func__, cpu_latency_qos_miscdev.name); =20 +#ifdef CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP + ret =3D misc_register(&cpu_wakeup_latency_qos_miscdev); + if (ret < 0) + pr_err("%s: %s setup failed\n", __func__, + cpu_wakeup_latency_qos_miscdev.name); +#endif + return ret; } late_initcall(cpu_latency_qos_init); --=20 2.43.0