From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) (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 0F05828B7DB; Mon, 10 Nov 2025 17:10:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.176.79.56 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762794650; cv=none; b=k3byTsrG/xzmcSaeEe2ykftYAqCmRCGxCvxISjJhd/QrTq6FjkIwBY2p7djV9eP4nEVvGedrkc7rTL9Idu68fyJ0RGRQKfEVpnAM1T0vxX/IaJbXkPLCghrq3/O9Hs3UV0/yGJ8vf4NBahsWdzpEWDSUuf1pEXFMkpNDVU4/ls0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762794650; c=relaxed/simple; bh=Ye6ocu0lmBSHiBTs1d/lW5RA6u4Q8y6J4PsoIWQwW6c=; h=Date:From:To:CC:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CXZ4zycPEI8FxUbKE9KfcTw2mJMwZ0uxH4OG1JbRz3nGQDUfVeMWcxuM/mZyr6wp/lMztO+dCznstV6U2sC9S0VKrsZyUir0b7ZidyNrR71GPOwwcvXIK7sTZ+ffQIQhYdcqDuSM0bAmh4RACcDWxk+ufXAxTF/qV9mnhAVjVrg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=185.176.79.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTPS id 4d4x4h1wTRzHnGfG; Tue, 11 Nov 2025 01:10:28 +0800 (CST) Received: from dubpeml100005.china.huawei.com (unknown [7.214.146.113]) by mail.maildlp.com (Postfix) with ESMTPS id BA68B14033C; Tue, 11 Nov 2025 01:10:43 +0800 (CST) Received: from localhost (10.203.177.15) by dubpeml100005.china.huawei.com (7.214.146.113) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Mon, 10 Nov 2025 17:10:42 +0000 Date: Mon, 10 Nov 2025 17:10:41 +0000 From: Jonathan Cameron To: Ben Horgan CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , "Shaopeng Tan" Subject: Re: [PATCH 11/33] arm_mpam: Add the class and component structures for firmware described ris Message-ID: <20251110171041.00000a0d@huawei.com> In-Reply-To: <20251107123450.664001-12-ben.horgan@arm.com> References: <20251107123450.664001-1-ben.horgan@arm.com> <20251107123450.664001-12-ben.horgan@arm.com> X-Mailer: Claws Mail 4.3.0 (GTK 3.24.42; x86_64-w64-mingw32) Precedence: bulk X-Mailing-List: linux-acpi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-ClientProxiedBy: lhrpeml100012.china.huawei.com (7.191.174.184) To dubpeml100005.china.huawei.com (7.214.146.113) On Fri, 7 Nov 2025 12:34:28 +0000 Ben Horgan wrote: > From: James Morse > > An MSC is a container of resources, each identified by their RIS index. > Some RIS are described by firmware to provide their position in the system. > Others are discovered when the driver probes the hardware. > > To configure a resource it needs to be found by its class, e.g. 'L2'. > There are two kinds of grouping, a class is a set of components, which > are visible to user-space as there are likely to be multiple instances > of the L2 cache. (e.g. one per cluster or package) > > Add support for creating and destroying structures to allow a hierarchy > of resources to be created. > > CC: Ben Horgan Hi Ben, Remember to clear out CC'ing yourself. > Tested-by: Fenghua Yu > Tested-by: Shaopeng Tan > Tested-by: Peter Newman > Signed-off-by: James Morse > Signed-off-by: Ben Horgan > --- > Changes since v3: > Jonathan: > Code reordering. I'm guessing I may have sent things in a slightly less than ideal directly. Why can't we have ordering as follows (with no forwards declarations) mpam_class_alloc() mpam_class_destroy() //maybe other mpam_class stuff here mpam_component_alloc() mpam_component_destroy() - needs mpam_class_destroy() //maybe other mpam_component stuff here mpam_vmsc_alloc() mpam_vmsc_destroy() - needs mpam_component_destroy() //other mpam_vmsc here mpam_ris_create_locked() - needs all the destroys. mpam_ris_destroy() - needs mpam vmsc_destroy() I may well have missed a more complex dependency chain. Other than that, LGTM. Given any change in ordering can be trivially verified by building it and Gavin's comments seem simple to resolve. Reviewed-by: Jonathan Cameron > Comments. > --- > drivers/resctrl/mpam_devices.c | 393 +++++++++++++++++++++++++++++++- > drivers/resctrl/mpam_internal.h | 94 ++++++++ > include/linux/arm_mpam.h | 5 + > 3 files changed, 491 insertions(+), 1 deletion(-) > > diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c > index 6c6be133d73a..48a344d5cb43 100644 > --- a/drivers/resctrl/mpam_devices.c > +++ b/drivers/resctrl/mpam_devices.c > @@ -36,6 +36,384 @@ struct srcu_struct mpam_srcu; > */ > static atomic_t mpam_num_msc; > > +/* > + * An MSC is a physical container for controls and monitors, each identified by > + * their RIS index. These share a base-address, interrupts and some MMIO > + * registers. A vMSC is a virtual container for RIS in an MSC that control or > + * monitor the same thing. Members of a vMSC are all RIS in the same MSC, but > + * not all RIS in an MSC share a vMSC. > + * Components are a group of vMSC that control or monitor the same thing but > + * are from different MSC, so have different base-address, interrupts etc. > + * Classes are the set components of the same type. > + * > + * The features of a vMSC is the union of the RIS it contains. > + * The features of a Class and Component are the common subset of the vMSC > + * they contain. > + * > + * e.g. The system cache may have bandwidth controls on multiple interfaces, > + * for regulating traffic from devices independently of traffic from CPUs. > + * If these are two RIS in one MSC, they will be treated as controlling > + * different things, and will not share a vMSC/component/class. > + * > + * e.g. The L2 may have one MSC and two RIS, one for cache-controls another > + * for bandwidth. These two RIS are members of the same vMSC. > + * > + * e.g. The set of RIS that make up the L2 are grouped as a component. These > + * are sometimes termed slices. They should be configured the same, as if there > + * were only one. > + * > + * e.g. The SoC probably has more than one L2, each attached to a distinct set > + * of CPUs. All the L2 components are grouped as a class. > + * > + * When creating an MSC, struct mpam_msc is added to the all mpam_all_msc list, > + * then linked via struct mpam_ris to a vmsc, component and class. > + * The same MSC may exist under different class->component->vmsc paths, but the > + * RIS index will be unique. > + */ > +LIST_HEAD(mpam_classes); > + > +/* List of all objects that can be free()d after synchronise_srcu() */ > +static LLIST_HEAD(mpam_garbage); > + > +static inline void init_garbage(struct mpam_garbage *garbage) > +{ > + init_llist_node(&garbage->llist); > +} > + > +#define add_to_garbage(x) \ > +do { \ > + __typeof__(x) _x = (x); \ > + _x->garbage.to_free = _x; \ > + llist_add(&_x->garbage.llist, &mpam_garbage); \ > +} while (0) > + > +static void mpam_free_garbage(void) > +{ > + struct mpam_garbage *iter, *tmp; > + struct llist_node *to_free = llist_del_all(&mpam_garbage); > + > + if (!to_free) > + return; > + > + synchronize_srcu(&mpam_srcu); > + > + llist_for_each_entry_safe(iter, tmp, to_free, llist) { > + if (iter->pdev) > + devm_kfree(&iter->pdev->dev, iter->to_free); > + else > + kfree(iter->to_free); > + } > +} > + > +static struct mpam_vmsc * > +mpam_vmsc_alloc(struct mpam_component *comp, struct mpam_msc *msc) > +{ > + struct mpam_vmsc *vmsc; > + > + lockdep_assert_held(&mpam_list_lock); > + > + vmsc = kzalloc(sizeof(*vmsc), GFP_KERNEL); > + if (!vmsc) > + return ERR_PTR(-ENOMEM); > + init_garbage(&vmsc->garbage); > + > + INIT_LIST_HEAD_RCU(&vmsc->ris); > + INIT_LIST_HEAD_RCU(&vmsc->comp_list); > + vmsc->comp = comp; > + vmsc->msc = msc; > + > + list_add_rcu(&vmsc->comp_list, &comp->vmsc); > + > + return vmsc; > +} > + > +static void mpam_component_destroy(struct mpam_component *comp); > + > +static void mpam_vmsc_destroy(struct mpam_vmsc *vmsc) > +{ > + struct mpam_component *comp = vmsc->comp; > + > + lockdep_assert_held(&mpam_list_lock); > + > + list_del_rcu(&vmsc->comp_list); > + add_to_garbage(vmsc); > + > + if (list_empty(&comp->vmsc)) > + mpam_component_destroy(comp); > +} > + > +static struct mpam_vmsc * > +mpam_vmsc_find(struct mpam_component *comp, struct mpam_msc *msc) > +{ > + struct mpam_vmsc *vmsc; > + > + lockdep_assert_held(&mpam_list_lock); > + > + list_for_each_entry(vmsc, &comp->vmsc, comp_list) { > + if (vmsc->msc->id == msc->id) > + return vmsc; > + } > + > + return mpam_vmsc_alloc(comp, msc); > +} > + > +static struct mpam_component * > +mpam_component_alloc(struct mpam_class *class, int id) > +{ > + struct mpam_component *comp; > + > + lockdep_assert_held(&mpam_list_lock); > + > + comp = kzalloc(sizeof(*comp), GFP_KERNEL); > + if (!comp) > + return ERR_PTR(-ENOMEM); > + init_garbage(&comp->garbage); > + > + comp->comp_id = id; > + INIT_LIST_HEAD_RCU(&comp->vmsc); > + /* affinity is updated when ris are added */ > + INIT_LIST_HEAD_RCU(&comp->class_list); > + comp->class = class; > + > + list_add_rcu(&comp->class_list, &class->components); > + > + return comp; > +}