From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2B5A424649; Mon, 6 Jul 2026 23:06:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783379191; cv=none; b=nn5zo/ypzgd7CZjoNz3bKdSEqlJjP23QuARs6eM4fr4Sekp5uV/LOMkrUkWSJ329OfkR4w0ZLNihm13NYWsaBu+DpOyDR2EyAIuicTzOcoXOxKZw3fyCxv22mWxF2wnTjFGgNmdRTCgvOLUA68w3qSO3RNntCRbYX4N+HcW0Glo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783379191; c=relaxed/simple; bh=/YrjRW7a+ARn8U8vHJRUv51UgcduMNXLoYKfvyKTiCc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JGYxDjQHkJxZac9J1yW+ctlFWiNlfz5xCOHPk6v4NJuYbJLg1B6XdViWstZ2duztsTmdmGE0Hbd5d/ztRgOldnhf2PIwCttt5S/KNIQ56Wx39TCqdo18PJxoVA3ovcfOi8i/GlBNXRJAPuEk3Hp61sIM2Fkq2rliXNqu/ecAkLE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hD6J88gb; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hD6J88gb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2E1911F00ACA; Mon, 6 Jul 2026 23:06:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1783379189; bh=1xx4pzASj9fdnVkNgPYzWRS5dUARTmrIszTMJb1iTAw=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=hD6J88gbWbx0gVs9OOUMw8i9LvpEvbbI+slwZXq+5UKGZerD49zPxw1L7g4Wpc4IA jqJcIKOokGu3U1YbCnswu7m9YzbzItH/lVdYcytlwXwQzyrXTFYA4edzs2JggrKTe+ JaFpZP8rl9EoXy8rWLQXYog1+pcUHnthYkB6eqfR1sGNLXq4RABomJHzvH5zI4Y7xa tN0HaCQDZuiW9kh+8qv+bZnBpakD1cpkpEf1wlfanytBHx46luUcPtAdKX2m63oyC9 iB8hPy2GAtnX/G/QVnM5SlxLbe+kXaaDX1WN3IJi5UfxXl3VdAuDyG3jStutMY5ip/ ZrNSaK9ohlL+Q== From: Drew Fustini Date: Mon, 06 Jul 2026 16:06:18 -0700 Subject: [PATCH v4 8/8] riscv_cbqri: Add CBQRI capacity allocation platform driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260706-dfustini-atl-sc-cbqri-dt-v4-8-e75c20201d64@kernel.org> References: <20260706-dfustini-atl-sc-cbqri-dt-v4-0-e75c20201d64@kernel.org> In-Reply-To: <20260706-dfustini-atl-sc-cbqri-dt-v4-0-e75c20201d64@kernel.org> To: Adrien Ricciardi , Alexandre Ghiti , Atish Kumar Patra , Atish Patra , Babu Moger , Ben Horgan , Borislav Petkov , Chen Pei , Conor Dooley , Conor Dooley , Dave Hansen , Dave Martin , Fenghua Yu , Gong Shuai , Gong Shuai , guo.wenjia23@zte.com.cn, James Morse , =?utf-8?q?Kornel_Dul=C4=99ba?= , Krzysztof Kozlowski , liu.qingtao2@zte.com.cn, Liu Zhiwei , Palmer Dabbelt , Paul Walmsley , Peter Newman , =?utf-8?q?Radim_Kr=C4=8Dm=C3=A1=C5=99?= , Reinette Chatre , Rob Herring , Samuel Holland , Sebastian Andrzej Siewior , Tony Luck , Vasudevan Srinivasan , Ved Shanbhogue , Weiwei Li , yunhui cui , Drew Fustini Cc: linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, x86@kernel.org, devicetree@vger.kernel.org, linux-rt-devel@lists.linux.dev, linux-doc@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7129; i=fustini@kernel.org; h=from:subject:message-id; bh=/YrjRW7a+ARn8U8vHJRUv51UgcduMNXLoYKfvyKTiCc=; b=owGbwMvMwCV2+43O4ZsaG3kYT6slMWT5mHz4x3389uqvz87sVd+nJs6+fVOwM2POdwb5G3frH C+vPZfb1FHKwiDGxSArpsiy6UPehSVeoV8XzH+xDWYOKxPIEAYuTgGYiEoRw/+AWR3zNiXtu7T4 rx371oVtDFVxXAerui7mlKvo+y6fI/eK4Q/n4j0RAQqFvBFZsu2t1ilmnFbfLLTSzixccLzNeTt 7OiMA X-Developer-Key: i=fustini@kernel.org; a=openpgp; fpr=1B6F948213EA489734F3997035D5CD577C1E6010 Add a device-tree platform driver, bound to the generic riscv,cbqri-capacity-controller compatible, that registers a CBQRI capacity controller as the resctrl cache-allocation resource for the cache it governs. The driver follows the node's riscv,cbqri-cache phandle to that cache, reads its level, and matches it against cacheinfo to get the resctrl domain id and the harts sharing the cache. It then hands the controller to riscv_cbqri_register_cc_dt() with the riscv,cbqri-rcid count from the node. Nothing is vendor-specific, and the DT "reg" is the CBQRI register block itself, so any SoC that describes a CBQRI capacity controller in device tree can reuse the driver unchanged. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Drew Fustini --- MAINTAINERS | 1 + drivers/resctrl/Kconfig | 12 ++++ drivers/resctrl/Makefile | 1 + drivers/resctrl/cbqri_capacity.c | 137 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5898fbcf4e2f..0b5d38b772e0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23347,6 +23347,7 @@ F: Documentation/devicetree/bindings/riscv/riscv,cbqri.yaml F: arch/riscv/include/asm/qos.h F: arch/riscv/include/asm/resctrl.h F: arch/riscv/kernel/qos.c +F: drivers/resctrl/cbqri_capacity.c F: drivers/resctrl/cbqri_devices.c F: drivers/resctrl/cbqri_internal.h F: drivers/resctrl/cbqri_resctrl.c diff --git a/drivers/resctrl/Kconfig b/drivers/resctrl/Kconfig index 68b4124df396..b7db6ff9d054 100644 --- a/drivers/resctrl/Kconfig +++ b/drivers/resctrl/Kconfig @@ -43,6 +43,18 @@ menuconfig RISCV_CBQRI if RISCV_CBQRI +config RISCV_CBQRI_CAPACITY + bool "RISC-V CBQRI cache capacity-allocation controller" + depends on OF + help + Enable driver for a RISC-V CBQRI capacity controller that + governs a CPU cache, matching the "riscv,cbqri-capacity-controller" + compatible. The controller's cache phandle gives the cache level and the + harts that share it, which the driver registers as a resctrl + cache-allocation resource. + + Say N unless your device tree describes a CBQRI capacity controller. + endif config RISCV_CBQRI_RESCTRL_FS diff --git a/drivers/resctrl/Makefile b/drivers/resctrl/Makefile index a7631712dba9..c8339113ef1f 100644 --- a/drivers/resctrl/Makefile +++ b/drivers/resctrl/Makefile @@ -7,3 +7,4 @@ ccflags-$(CONFIG_ARM64_MPAM_DRIVER_DEBUG) += -DDEBUG obj-$(CONFIG_RISCV_CBQRI) += cbqri.o cbqri-y += cbqri_devices.o cbqri-$(CONFIG_RISCV_CBQRI_RESCTRL_FS) += cbqri_resctrl.o +cbqri-$(CONFIG_RISCV_CBQRI_CAPACITY) += cbqri_capacity.o diff --git a/drivers/resctrl/cbqri_capacity.c b/drivers/resctrl/cbqri_capacity.c new file mode 100644 index 000000000000..ea88de02d407 --- /dev/null +++ b/drivers/resctrl/cbqri_capacity.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Platform driver for a RISC-V CBQRI capacity controller that backs a CPU + * cache. The controller is described in device tree by the generic + * "riscv,cbqri-capacity-controller" compatible together with a phandle to the + * cache node it governs. The driver hands it to the CBQRI core, which probes + * the capabilities register and exposes a controller that supports allocation + * as the resctrl cache allocation resource for that cache. + */ + +#define pr_fmt(fmt) "cbqri-capacity: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int cbqri_capacity_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cbqri_controller_info info = {}; + struct device_node *cache_np; + cpumask_var_t cpu_mask; + struct resource *res; + u32 rcid_count, cache_level; + int cache_id, cpu, ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + ret = of_property_read_u32(dev->of_node, "riscv,cbqri-rcid", &rcid_count); + if (ret) { + dev_err(dev, "missing riscv,cbqri-rcid\n"); + return ret; + } + + cache_np = of_parse_phandle(dev->of_node, "riscv,cbqri-cache", 0); + if (!cache_np) { + dev_err(dev, "missing riscv,cbqri-cache phandle\n"); + return -EINVAL; + } + + ret = of_property_read_u32(cache_np, "cache-level", &cache_level); + if (ret) { + dev_err(dev, "%pOF: missing cache-level\n", cache_np); + goto out_put; + } + + if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_put; + } + + /* + * Associate the controller with its cache instance via + * cacheinfo. The matching cache provides the cache id and the + * set of harts that share the cache. + * + * Taking the first leaf at the level is sufficient, because fw_token + * is keyed on the DT cache node, so sibling leaves of a split cache + * share it, and riscv,cbqri-cache must reference a unified shared + * cache (cache-unified), not a split private L1. + */ + cache_id = -1; + cpus_read_lock(); + for_each_online_cpu(cpu) { + struct cacheinfo *ci = get_cpu_cacheinfo_level(cpu, cache_level); + + if (ci && ci->fw_token == cache_np) { + cache_id = ci->id; + cpumask_copy(cpu_mask, &ci->shared_cpu_map); + break; + } + } + cpus_read_unlock(); + + if (cache_id < 0) { + dev_err(dev, "%pOF: no online hart reports an L%u cache for this node\n", + cache_np, cache_level); + ret = -ENODEV; + goto out_free; + } + + info.type = CBQRI_CONTROLLER_TYPE_CAPACITY; + info.addr = res->start; + info.size = resource_size(res); + info.rcid_count = rcid_count; + info.cache_id = cache_id; + + ret = riscv_cbqri_register_cc_dt(&info, cache_level, cpu_mask); + if (ret) { + dev_err(dev, "failed to register capacity controller: %d\n", ret); + goto out_free; + } + + dev_info(dev, "registered L%u capacity controller at %pa (cache_id=%d, rcid=%u)\n", + cache_level, &info.addr, cache_id, rcid_count); + +out_free: + free_cpumask_var(cpu_mask); +out_put: + of_node_put(cache_np); + return ret; +} + +static const struct of_device_id cbqri_capacity_of_match[] = { + { .compatible = "riscv,cbqri-capacity-controller" }, + {} +}; +MODULE_DEVICE_TABLE(of, cbqri_capacity_of_match); + +static struct platform_driver cbqri_capacity_driver = { + .probe = cbqri_capacity_probe, + .driver = { + .name = "cbqri-capacity", + .of_match_table = cbqri_capacity_of_match, + /* + * The controller is registered permanently into the + * CBQRI core for the life of the system. Block unbind + * so userspace cannot leave a dangling controller. + */ + .suppress_bind_attrs = true, + }, +}; + +/* + * Register at device_initcall so probe runs before the CBQRI core's + * late_initcall which walks the cbqri_controllers list. + */ +builtin_platform_driver(cbqri_capacity_driver); -- 2.43.0