Messages in this thread |  | | From | yunhui cui <> | | Date | Tue, 5 May 2026 12:43:46 +0800 | | Subject | Re: [External] [PATCH RFC v3 04/11] RISC-V: QoS: add CBQRI hardware interface |
| |
Hi Drew,
On Wed, Apr 15, 2026 at 9:57 AM Drew Fustini <fustini@kernel.org> wrote: > > Add the CBQRI controller hardware interface layer. > > Define data structures representing CBQRI controller properties > (cbqri_controller) and hardware capabilities for capacity and bandwidth > controllers (riscv_cbqri_capacity_caps, riscv_cbqri_bandwidth_caps) in > include/linux/riscv_qos.h. > > Define MMIO register offsets, field masks, and internal wrapper structs > (cbqri_resctrl_res, cbqri_resctrl_dom, cbqri_config) in internal.h. > > Implement MMIO helpers for capacity block mask and bandwidth reservation, > alloc control operations for capacity and bandwidth controllers, and > probe functions to discover controller capabilities. A per-controller > spinlock serializes multi-step MMIO sequences. > > Co-developed-by: Adrien Ricciardi <aricciardi@baylibre.com> > Signed-off-by: Adrien Ricciardi <aricciardi@baylibre.com> > Signed-off-by: Drew Fustini <fustini@kernel.org> > --- > MAINTAINERS | 1 + > arch/riscv/kernel/qos/internal.h | 81 +++++++ > arch/riscv/kernel/qos/qos_resctrl.c | 432 ++++++++++++++++++++++++++++++++++++ > include/linux/riscv_qos.h | 76 +++++++ > 4 files changed, 590 insertions(+) > > diff --git a/MAINTAINERS b/MAINTAINERS > index b17f885411ba..6a66d7047c51 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -22785,6 +22785,7 @@ L: linux-riscv@lists.infradead.org > S: Supported > F: arch/riscv/include/asm/qos.h > F: arch/riscv/kernel/qos/ > +F: include/linux/riscv_qos.h > > RISC-V RPMI AND MPXY DRIVERS > M: Rahul Pathak <rahul@summations.net> > diff --git a/arch/riscv/kernel/qos/internal.h b/arch/riscv/kernel/qos/internal.h > new file mode 100644 > index 000000000000..edbcbd9471b1 > --- /dev/null > +++ b/arch/riscv/kernel/qos/internal.h > @@ -0,0 +1,81 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +#ifndef _ASM_RISCV_QOS_INTERNAL_H > +#define _ASM_RISCV_QOS_INTERNAL_H > + > +#include <linux/bitfield.h> > +#include <linux/resctrl.h> > +#include <linux/riscv_qos.h> > + > +#define RISCV_RESCTRL_EMPTY_CLOSID ((u32)~0) > + > +#define CBQRI_CC_CAPABILITIES_OFF 0 > +#define CBQRI_CC_MON_CTL_OFF 8 > +#define CBQRI_CC_MON_CTL_VAL_OFF 16 > +#define CBQRI_CC_ALLOC_CTL_OFF 24 > +#define CBQRI_CC_BLOCK_MASK_OFF 32 > + > +#define CBQRI_BC_CAPABILITIES_OFF 0 > +#define CBQRI_BC_MON_CTL_OFF 8 > +#define CBQRI_BC_MON_CTR_VAL_OFF 16 > +#define CBQRI_BC_ALLOC_CTL_OFF 24 > +#define CBQRI_BC_BW_ALLOC_OFF 32 > + > +#define CBQRI_CC_CAPABILITIES_VER_MINOR_MASK GENMASK(3, 0) > +#define CBQRI_CC_CAPABILITIES_VER_MAJOR_MASK GENMASK(7, 4) > + > +#define CBQRI_CC_CAPABILITIES_NCBLKS_MASK GENMASK(23, 8) > +#define CBQRI_CC_CAPABILITIES_FRCID_MASK GENMASK(24, 24) > + > +#define CBQRI_BC_CAPABILITIES_VER_MINOR_MASK GENMASK(3, 0) > +#define CBQRI_BC_CAPABILITIES_VER_MAJOR_MASK GENMASK(7, 4) > + > +#define CBQRI_BC_CAPABILITIES_NBWBLKS_MASK GENMASK(23, 8) > +#define CBQRI_BC_CAPABILITIES_MRBWB_MASK GENMASK_ULL(47, 32) > + > +#define CBQRI_CONTROL_REGISTERS_OP_MASK GENMASK(4, 0) > +#define CBQRI_CONTROL_REGISTERS_AT_MASK GENMASK(7, 5) > +#define CBQRI_CONTROL_REGISTERS_AT_DATA 0 > +#define CBQRI_CONTROL_REGISTERS_AT_CODE 1 > +#define CBQRI_CONTROL_REGISTERS_RCID_MASK GENMASK(19, 8) > +#define CBQRI_CONTROL_REGISTERS_STATUS_MASK GENMASK_ULL(38, 32) > +#define CBQRI_CONTROL_REGISTERS_BUSY_MASK GENMASK_ULL(39, 39) > +#define CBQRI_CONTROL_REGISTERS_RBWB_MASK GENMASK(15, 0) > + > +#define CBQRI_CC_MON_CTL_OP_CONFIG_EVENT 1 > +#define CBQRI_CC_MON_CTL_OP_READ_COUNTER 2 > +#define CBQRI_CC_MON_CTL_STATUS_SUCCESS 1 > + > +#define CBQRI_CC_ALLOC_CTL_OP_CONFIG_LIMIT 1 > +#define CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT 2 > +#define CBQRI_CC_ALLOC_CTL_OP_FLUSH_RCID 3 > +#define CBQRI_CC_ALLOC_CTL_STATUS_SUCCESS 1 > + > +#define CBQRI_BC_MON_CTL_OP_CONFIG_EVENT 1 > +#define CBQRI_BC_MON_CTL_OP_READ_COUNTER 2 > +#define CBQRI_BC_MON_CTL_STATUS_SUCCESS 1 > + > +#define CBQRI_BC_ALLOC_CTL_OP_CONFIG_LIMIT 1 > +#define CBQRI_BC_ALLOC_CTL_OP_READ_LIMIT 2 > +#define CBQRI_BC_ALLOC_CTL_STATUS_SUCCESS 1 > + > +int qos_resctrl_setup(void); > +int qos_resctrl_online_cpu(unsigned int cpu); > +int qos_resctrl_offline_cpu(unsigned int cpu); > + > +struct cbqri_resctrl_res { > + struct rdt_resource resctrl_res; > + u32 max_rcid; > + u32 max_mcid; > +}; > + > +struct cbqri_resctrl_dom { > + struct rdt_ctrl_domain resctrl_ctrl_dom; > + struct cbqri_controller *hw_ctrl; > +}; > + > +struct cbqri_config { > + u64 cbm; /* capacity block mask */ > + u64 rbwb; /* reserved bandwidth blocks */ > +}; > + > +#endif /* _ASM_RISCV_QOS_INTERNAL_H */ > diff --git a/arch/riscv/kernel/qos/qos_resctrl.c b/arch/riscv/kernel/qos/qos_resctrl.c > new file mode 100644 > index 000000000000..6d294f2f2504 > --- /dev/null > +++ b/arch/riscv/kernel/qos/qos_resctrl.c > @@ -0,0 +1,432 @@ > +// SPDX-License-Identifier: GPL-2.0-only > + > +#define pr_fmt(fmt) "qos: resctrl: " fmt > + > +#include <linux/err.h> > +#include <linux/io.h> > +#include <linux/io-64-nonatomic-lo-hi.h> > +#include <linux/iopoll.h> > +#include <linux/ioport.h> > +#include <linux/resctrl.h> > +#include <linux/riscv_qos.h> > +#include <linux/slab.h> > +#include <linux/types.h> > +#include <asm/csr.h> > +#include <asm/qos.h> > +#include "internal.h" > + > +static struct cbqri_resctrl_res cbqri_resctrl_resources[RDT_NUM_RESOURCES]; > + > +static bool exposed_alloc_capable; > +/* CDP (code data prioritization) on x86 is AT (access type) on RISC-V */ > +static bool exposed_cdp_l2_capable; > +static bool exposed_cdp_l3_capable; > +static bool is_cdp_l2_enabled; > +static bool is_cdp_l3_enabled; > + > +/* used by resctrl_arch_system_num_rmid_idx() */ > +static u32 max_rmid; > + > +LIST_HEAD(cbqri_controllers); > + > +static int cbqri_wait_busy_flag(struct cbqri_controller *ctrl, int reg_offset, > + u64 *regp); > + > +/* Set capacity block mask (cc_block_mask) */ > +static void cbqri_set_cbm(struct cbqri_controller *ctrl, u64 cbm) > +{ > + iowrite64(cbm, ctrl->base + CBQRI_CC_BLOCK_MASK_OFF); > +}
CBQRI capacity limits appear to include both cc_block_mask and cc_cunits, but only cc_block_mask seems to be modeled here. How is cc_cunits expected to be handled?
> + > +/* Set the Rbwb (reserved bandwidth blocks) field in bc_bw_alloc */ > +static void cbqri_set_rbwb(struct cbqri_controller *ctrl, u64 rbwb) > +{ > + u64 reg; > + > + reg = ioread64(ctrl->base + CBQRI_BC_BW_ALLOC_OFF); > + reg &= ~CBQRI_CONTROL_REGISTERS_RBWB_MASK; > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_RBWB_MASK, rbwb); > + iowrite64(reg, ctrl->base + CBQRI_BC_BW_ALLOC_OFF); > +} > + > +/* Get the Rbwb (reserved bandwidth blocks) field in bc_bw_alloc */ > +static u64 cbqri_get_rbwb(struct cbqri_controller *ctrl) > +{ > + u64 reg; > + > + reg = ioread64(ctrl->base + CBQRI_BC_BW_ALLOC_OFF); > + return FIELD_GET(CBQRI_CONTROL_REGISTERS_RBWB_MASK, reg); > +} > + > +static int cbqri_wait_busy_flag(struct cbqri_controller *ctrl, int reg_offset, > + u64 *regp) > +{ > + u64 reg; > + int ret; > + > + ret = readq_poll_timeout_atomic(ctrl->base + reg_offset, reg, > + !FIELD_GET(CBQRI_CONTROL_REGISTERS_BUSY_MASK, reg), > + 0, 1000); > + if (!ret && regp) > + *regp = reg; > + > + return ret; > +} > + > +/* Perform capacity allocation control operation on capacity controller */ > +static int cbqri_cc_alloc_op(struct cbqri_controller *ctrl, int operation, int rcid, > + enum resctrl_conf_type type) > +{ > + int reg_offset = CBQRI_CC_ALLOC_CTL_OFF; > + int status; > + u64 reg; > + > + reg = ioread64(ctrl->base + reg_offset); > + reg &= ~CBQRI_CONTROL_REGISTERS_OP_MASK; > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_OP_MASK, operation); > + reg &= ~CBQRI_CONTROL_REGISTERS_RCID_MASK; > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_RCID_MASK, rcid); > + > + /* CBQRI capacity AT is only supported on L2 and L3 caches for now */ > + if (ctrl->type == CBQRI_CONTROLLER_TYPE_CAPACITY && > + ((ctrl->cache.cache_level == 2 && is_cdp_l2_enabled) || > + (ctrl->cache.cache_level == 3 && is_cdp_l3_enabled))) { > + reg &= ~CBQRI_CONTROL_REGISTERS_AT_MASK; > + switch (type) { > + case CDP_CODE: > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_AT_MASK, > + CBQRI_CONTROL_REGISTERS_AT_CODE); > + break; > + case CDP_DATA: > + default: > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_AT_MASK, > + CBQRI_CONTROL_REGISTERS_AT_DATA); > + break; > + } > + } > + > + iowrite64(reg, ctrl->base + reg_offset); > + > + if (cbqri_wait_busy_flag(ctrl, reg_offset, ®) < 0) { > + pr_err("%s(): BUSY timeout when executing the operation\n", __func__); > + return -EIO; > + } > + > + status = FIELD_GET(CBQRI_CONTROL_REGISTERS_STATUS_MASK, reg); > + if (status != CBQRI_CC_ALLOC_CTL_STATUS_SUCCESS) { > + pr_err("%s(): operation %d failed: status=%d\n", __func__, operation, status); > + return -EIO; > + } > + > + return 0; > +} > + > +/* > + * Write a capacity block mask and verify the hardware accepted it by > + * reading back the value after a CONFIG_LIMIT + READ_LIMIT sequence. > + */ > +static int cbqri_apply_cache_config(struct cbqri_resctrl_dom *hw_dom, u32 closid, > + enum resctrl_conf_type type, struct cbqri_config *cfg) > +{ > + struct cbqri_controller *ctrl = hw_dom->hw_ctrl; > + int err = 0; > + u64 reg; > + > + spin_lock(&ctrl->lock); > + > + /* Set capacity block mask (cc_block_mask) */ > + cbqri_set_cbm(ctrl, cfg->cbm); > + > + /* Capacity config limit operation */ > + err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_CONFIG_LIMIT, closid, type); > + if (err < 0) { > + pr_err("%s(): operation failed: err = %d\n", __func__, err); > + goto out; > + } > + > + /* Clear cc_block_mask before read limit to verify op works */ > + cbqri_set_cbm(ctrl, 0); > + > + /* Perform a capacity read limit operation to verify blockmask */ > + err = cbqri_cc_alloc_op(ctrl, CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, closid, type); > + if (err < 0) { > + pr_err("%s(): operation failed: err = %d\n", __func__, err); > + goto out; > + } > + > + /* Read capacity blockmask to verify it matches the requested config */ > + reg = ioread64(ctrl->base + CBQRI_CC_BLOCK_MASK_OFF); > + if (reg != cfg->cbm) { > + pr_err("%s(): failed to verify allocation (reg:%llx != cbm:%llx)\n", > + __func__, reg, cfg->cbm); > + err = -EIO; > + } > + > +out: > + spin_unlock(&ctrl->lock); > + return err; > +} > + > +/* Perform bandwidth allocation control operation on bandwidth controller */ > +static int cbqri_bc_alloc_op(struct cbqri_controller *ctrl, int operation, int rcid) > +{ > + int reg_offset = CBQRI_BC_ALLOC_CTL_OFF; > + int status; > + u64 reg; > + > + reg = ioread64(ctrl->base + reg_offset); > + reg &= ~CBQRI_CONTROL_REGISTERS_OP_MASK; > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_OP_MASK, operation); > + reg &= ~CBQRI_CONTROL_REGISTERS_RCID_MASK; > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_RCID_MASK, rcid); > + iowrite64(reg, ctrl->base + reg_offset); > + > + if (cbqri_wait_busy_flag(ctrl, reg_offset, ®) < 0) { > + pr_err("%s(): BUSY timeout when executing the operation\n", __func__); > + return -EIO; > + } > + > + status = FIELD_GET(CBQRI_CONTROL_REGISTERS_STATUS_MASK, reg); > + if (status != CBQRI_BC_ALLOC_CTL_STATUS_SUCCESS) { > + pr_err("%s(): operation %d failed with status = %d\n", > + __func__, operation, status); > + return -EIO; > + } > + > + return 0; > +} > + > +/* > + * Write a bandwidth reservation and verify the hardware accepted it by > + * reading back the value after a CONFIG_LIMIT + READ_LIMIT sequence. > + */ > +static int cbqri_apply_bw_config(struct cbqri_resctrl_dom *hw_dom, u32 closid, > + enum resctrl_conf_type type, struct cbqri_config *cfg) > +{ > + struct cbqri_controller *ctrl = hw_dom->hw_ctrl; > + int ret = 0; > + u64 reg; > + > + spin_lock(&ctrl->lock); > + > + /* Set reserved bandwidth blocks */ > + cbqri_set_rbwb(ctrl, cfg->rbwb); > + > + /* Bandwidth config limit operation */ > + ret = cbqri_bc_alloc_op(ctrl, CBQRI_BC_ALLOC_CTL_OP_CONFIG_LIMIT, closid); > + if (ret < 0) { > + pr_err("%s(): operation failed: ret = %d\n", __func__, ret); > + goto out; > + } > + > + /* Clear rbwb before read limit to verify op works */ > + cbqri_set_rbwb(ctrl, 0); > + > + /* Bandwidth allocation read limit operation to verify */ > + ret = cbqri_bc_alloc_op(ctrl, CBQRI_BC_ALLOC_CTL_OP_READ_LIMIT, closid); > + if (ret < 0) > + goto out; > + > + /* Read bandwidth allocation to verify it matches the requested config */ > + reg = cbqri_get_rbwb(ctrl); > + if (reg != cfg->rbwb) { > + pr_err("%s(): failed to verify allocation (reg:%llx != rbwb:%llu)\n", > + __func__, reg, cfg->rbwb); > + ret = -EIO; > + } > + > +out: > + spin_unlock(&ctrl->lock); > + return ret; > +} > + > +static int cbqri_probe_feature(struct cbqri_controller *ctrl, int reg_offset, > + int operation, int *status, bool *access_type_supported) > +{ > + u64 reg, saved_reg; > + int at; > + > + /* Keep the initial register value to preserve the WPRI fields */ > + reg = ioread64(ctrl->base + reg_offset); > + saved_reg = reg; > + > + /* Execute the requested operation to find if the register is implemented */ > + reg &= ~CBQRI_CONTROL_REGISTERS_OP_MASK; > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_OP_MASK, operation); > + iowrite64(reg, ctrl->base + reg_offset); > + if (cbqri_wait_busy_flag(ctrl, reg_offset, ®) < 0) { > + pr_err("%s(): BUSY timeout when executing the operation\n", __func__); > + return -EIO; > + } > + > + /* Get the operation status */ > + *status = FIELD_GET(CBQRI_CONTROL_REGISTERS_STATUS_MASK, reg); > + > + /* > + * Check for the AT support if the register is implemented > + * (if not, the status value will remain 0) > + */ > + if (*status != 0) { > + /* Set the AT field to a valid value */ > + reg = saved_reg; > + reg &= ~CBQRI_CONTROL_REGISTERS_AT_MASK; > + reg |= FIELD_PREP(CBQRI_CONTROL_REGISTERS_AT_MASK, > + CBQRI_CONTROL_REGISTERS_AT_CODE); > + iowrite64(reg, ctrl->base + reg_offset); > + if (cbqri_wait_busy_flag(ctrl, reg_offset, ®) < 0) { > + pr_err("%s(): BUSY timeout when setting AT field\n", __func__); > + return -EIO; > + } > + > + /* > + * If the AT field value has been reset to zero, > + * then the AT support is not present > + */ > + at = FIELD_GET(CBQRI_CONTROL_REGISTERS_AT_MASK, reg); > + if (at == CBQRI_CONTROL_REGISTERS_AT_CODE) > + *access_type_supported = true; > + else > + *access_type_supported = false; > + } > + > + /* Restore the original register value */ > + iowrite64(saved_reg, ctrl->base + reg_offset); > + if (cbqri_wait_busy_flag(ctrl, reg_offset, NULL) < 0) { > + pr_err("%s(): BUSY timeout when restoring the original register value\n", __func__); > + return -EIO; > + } > + > + return 0; > +} > + > +static int cbqri_probe_cc(struct cbqri_controller *ctrl) > +{ > + int err, status; > + u64 reg; > + > + reg = ioread64(ctrl->base + CBQRI_CC_CAPABILITIES_OFF); > + if (reg == 0) > + return -ENODEV; > + > + ctrl->ver_minor = FIELD_GET(CBQRI_CC_CAPABILITIES_VER_MINOR_MASK, reg); > + ctrl->ver_major = FIELD_GET(CBQRI_CC_CAPABILITIES_VER_MAJOR_MASK, reg); > + ctrl->cc.supports_alloc_op_flush_rcid = > + FIELD_GET(CBQRI_CC_CAPABILITIES_FRCID_MASK, reg); > + ctrl->cc.ncblks = FIELD_GET(CBQRI_CC_CAPABILITIES_NCBLKS_MASK, reg); > + > + pr_debug("version=%d.%d ncblks=%d cache_level=%d\n", > + ctrl->ver_major, ctrl->ver_minor, > + ctrl->cc.ncblks, ctrl->cache.cache_level); > + > + /* Probe allocation features (monitoring not yet implemented) */ > + err = cbqri_probe_feature(ctrl, CBQRI_CC_ALLOC_CTL_OFF, > + CBQRI_CC_ALLOC_CTL_OP_READ_LIMIT, > + &status, &ctrl->cc.supports_alloc_at_code); > + if (err) > + return err; > + > + if (status == CBQRI_CC_ALLOC_CTL_STATUS_SUCCESS) { > + ctrl->alloc_capable = true; > + exposed_alloc_capable = true; > + } > + > + return 0; > +} > + > +static int cbqri_probe_bc(struct cbqri_controller *ctrl) > +{ > + int err, status; > + u64 reg; > + > + reg = ioread64(ctrl->base + CBQRI_BC_CAPABILITIES_OFF); > + if (reg == 0) > + return -ENODEV; > + > + ctrl->ver_minor = FIELD_GET(CBQRI_BC_CAPABILITIES_VER_MINOR_MASK, reg); > + ctrl->ver_major = FIELD_GET(CBQRI_BC_CAPABILITIES_VER_MAJOR_MASK, reg); > + ctrl->bc.nbwblks = FIELD_GET(CBQRI_BC_CAPABILITIES_NBWBLKS_MASK, reg); > + ctrl->bc.mrbwb = FIELD_GET(CBQRI_BC_CAPABILITIES_MRBWB_MASK, reg); > + > + if (!ctrl->bc.nbwblks) { > + pr_err("bandwidth controller has nbwblks=0\n"); > + return -EINVAL; > + } > + > + pr_debug("version=%d.%d nbwblks=%d mrbwb=%d\n", > + ctrl->ver_major, ctrl->ver_minor, > + ctrl->bc.nbwblks, ctrl->bc.mrbwb); > + > + /* Probe allocation features (monitoring not yet implemented) */ > + err = cbqri_probe_feature(ctrl, CBQRI_BC_ALLOC_CTL_OFF, > + CBQRI_BC_ALLOC_CTL_OP_READ_LIMIT, > + &status, &ctrl->bc.supports_alloc_at_code); > + if (err) > + return err; > + > + if (status == CBQRI_BC_ALLOC_CTL_STATUS_SUCCESS) { > + ctrl->alloc_capable = true; > + exposed_alloc_capable = true; > + } > + > + return 0; > +} > + > +static int cbqri_probe_controller(struct cbqri_controller *ctrl) > +{ > + int err; > + > + pr_debug("controller info: type=%d addr=%pa size=%pa max-rcid=%u max-mcid=%u\n", > + ctrl->type, &ctrl->addr, &ctrl->size, > + ctrl->rcid_count, ctrl->mcid_count); > + > + if (!ctrl->addr) { > + pr_warn("%s(): controller has invalid addr=0x0, skipping\n", __func__); > + return -EINVAL; > + } > + > + if (!request_mem_region(ctrl->addr, ctrl->size, "cbqri_controller")) { > + pr_err("%s(): request_mem_region failed for %pa\n", > + __func__, &ctrl->addr); > + return -EBUSY; > + } > + > + ctrl->base = ioremap(ctrl->addr, ctrl->size); > + if (!ctrl->base) { > + pr_err("%s(): ioremap failed for %pa\n", __func__, &ctrl->addr); > + err = -ENOMEM; > + goto err_release; > + } > + > + spin_lock_init(&ctrl->lock); > + > + switch (ctrl->type) { > + case CBQRI_CONTROLLER_TYPE_CAPACITY: > + err = cbqri_probe_cc(ctrl); > + break; > + case CBQRI_CONTROLLER_TYPE_BANDWIDTH: > + err = cbqri_probe_bc(ctrl); > + break; > + default: > + pr_err("unknown controller type %d\n", ctrl->type); > + err = -ENODEV; > + break; > + } > + > + if (err) > + goto err_iounmap; > + > + /* > + * max_rmid is used by resctrl_arch_system_num_rmid_idx() > + * Find the smallest mcid_count amongst all controllers. > + */ > + max_rmid = min(max_rmid, ctrl->mcid_count); > + > + return 0; > + > +err_iounmap: > + iounmap(ctrl->base); > + ctrl->base = NULL; > +err_release: > + release_mem_region(ctrl->addr, ctrl->size); > + return err; > +} > diff --git a/include/linux/riscv_qos.h b/include/linux/riscv_qos.h > new file mode 100644 > index 000000000000..0f3daae2e84f > --- /dev/null > +++ b/include/linux/riscv_qos.h > @@ -0,0 +1,76 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > + > +#ifndef __LINUX_RISCV_QOS_H > +#define __LINUX_RISCV_QOS_H > + > +#include <linux/spinlock.h> > +#include <linux/types.h> > + > +#include <asm/qos.h> > + > +enum cbqri_controller_type { > + CBQRI_CONTROLLER_TYPE_CAPACITY, > + CBQRI_CONTROLLER_TYPE_BANDWIDTH, > + CBQRI_CONTROLLER_TYPE_UNKNOWN > +}; > + > +/* Capacity Controller hardware capabilities */ > +struct riscv_cbqri_capacity_caps { > + u16 ncblks; /* number of capacity blocks */ > + > + bool supports_alloc_at_code; > + bool supports_alloc_op_flush_rcid; > +}; > + > +/* Bandwidth Controller hardware capabilities */ > +struct riscv_cbqri_bandwidth_caps { > + u16 nbwblks; /* number of bandwidth blocks */ > + u16 mrbwb; /* max reserved bw blocks */ > + > + bool supports_alloc_at_code; > +}; > + > +struct cbqri_controller { > + void __iomem *base; > + /* > + * Protects multi-step MMIO register sequences on this controller. > + * CBQRI operations (e.g. CONFIG_LIMIT, READ_LIMIT) require writing > + * an operation register, waiting for the busy flag to clear, then > + * reading back the result. These sequences must be atomic per > + * controller to prevent interleaving. > + */ > + spinlock_t lock; > + > + int ver_major; > + int ver_minor; > + > + struct riscv_cbqri_bandwidth_caps bc; > + struct riscv_cbqri_capacity_caps cc; > + > + bool alloc_capable; > + > + phys_addr_t addr; > + phys_addr_t size; > + enum cbqri_controller_type type; > + u32 rcid_count; > + u32 mcid_count; > + struct list_head list; > + > + struct cache_controller { > + u32 cache_level; > + u32 cache_size; /* in bytes */ > + struct cpumask cpu_mask; > + /* Unique Cache ID from the PPTT table's Cache Type Structure */ > + u32 cache_id; > + } cache; > + > + struct mem_controller { > + /* Proximity Domain from SRAT table Memory Affinity Controller */ > + u32 prox_dom; > + struct cpumask cpu_mask; > + } mem; > +}; > + > +extern struct list_head cbqri_controllers; > + > +#endif /* __LINUX_RISCV_QOS_H */ > > -- > 2.43.0 >
Thanks, Yunhui
|  |