All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qinxin Xia <xiaqinxin@huawei.com>
To: <ben.horgan@arm.com>, <zhangzhanpeng.jasper@bytedance.com>,
	<joro@8bytes.org>, <palmer@dabbelt.com>, <tony.luck@intel.com>,
	<reinette.chatre@intel.com>, <tomasz.jeznach@linux.dev>,
	<zengheng4@huawei.com>, <fustini@kernel.org>,
	<cuiyunhui@bytedance.com>, <wangzhou1@hisilicon.com>,
	<xiaqinxin@huawei.com>
Cc: <will@kernel.org>, <robin.murphy@arm.com>, <pjw@kernel.org>,
	<aou@eecs.berkeley.edu>, <alex@ghiti.fr>, <Dave.Martin@arm.com>,
	<james.morse@arm.com>, <babu.moger@amd.com>, <corbet@lwn.net>,
	<shuah@kernel.org>, <jgg@ziepe.ca>, <kevin.tian@intel.com>,
	<yuanzhu@bytedance.com>, <iommu@lists.linux.dev>,
	<linuxarm@huawei.com>, <baolin.wang@linux.alibaba.com>
Subject: [RFC PATCH 1/5] iommu: Add per-device requestor QoS tagging and lookup helpers
Date: Tue, 1 Sep 2026 22:07:58 +0800	[thread overview]
Message-ID: <20260901140802.1215508-2-xiaqinxin@huawei.com> (raw)
In-Reply-To: <20260901140802.1215508-1-xiaqinxin@huawei.com>

Allow a device's DMA to be tagged with a QoS requestor ID so resctrl can
assign the device to a resource group.

Add helpers to program the requestor ID, track group membership changes,
and look up a device by name.

Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com>
---
 drivers/iommu/iommu.c | 113 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/iommu.h |  29 +++++++++++
 2 files changed, 142 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index cd1bca7ede9a..2f3739a755d6 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -43,6 +43,8 @@ static struct kset *iommu_group_kset;
 static DEFINE_IDA(iommu_group_ida);
 static DEFINE_IDA(iommu_global_pasid_ida);
 
+static const struct iommu_qos_device_ops *iommu_qos_dev_ops;
+
 static unsigned int iommu_def_domain_type __read_mostly;
 static bool iommu_dma_strict __read_mostly = IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_STRICT);
 static u32 iommu_cmd_line __read_mostly;
@@ -728,7 +730,10 @@ static void __iommu_group_free_device(struct iommu_group *group,
 				      struct group_device *grp_dev)
 {
 	struct device *dev = grp_dev->dev;
+	const struct iommu_qos_device_ops *qos_ops = READ_ONCE(iommu_qos_dev_ops);
 
+	if (qos_ops)
+		qos_ops->remove(dev);
 	sysfs_remove_link(group->devices_kobj, grp_dev->name);
 	sysfs_remove_link(&dev->kobj, "iommu_group");
 
@@ -1266,6 +1271,7 @@ static int iommu_create_device_direct_mappings(struct iommu_domain *domain,
 static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
 						     struct device *dev)
 {
+	const struct iommu_qos_device_ops *qos_ops;
 	int ret, i = 0;
 	struct group_device *device;
 
@@ -1304,6 +1310,9 @@ static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
 
 	trace_add_device_to_group(group->id, dev);
 
+	qos_ops = READ_ONCE(iommu_qos_dev_ops);
+	if (qos_ops)
+		qos_ops->add(dev);
 	dev_info(dev, "Adding to iommu group %d\n", group->id);
 
 	return device;
@@ -4222,6 +4231,110 @@ void pci_dev_reset_iommu_done(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_done);
 
+static struct iommu_group *iommu_group_kset_next_get(struct iommu_group *prev)
+{
+	struct iommu_group *group = NULL;
+	struct kobject *kobj;
+
+	if (!iommu_group_kset)
+		return NULL;
+
+	spin_lock(&iommu_group_kset->list_lock);
+	kobj = prev ? list_next_entry(&prev->kobj, entry) :
+		      list_first_entry_or_null(&iommu_group_kset->list,
+					       struct kobject, entry);
+	if (kobj) {
+		list_for_each_entry_from(kobj, &iommu_group_kset->list, entry) {
+			group = container_of(kobj, struct iommu_group, kobj);
+
+			/* Skip groups already on their way out (refcount 0). */
+			if (kobject_get_unless_zero(&group->kobj))
+				break;
+			group = NULL;
+		}
+	}
+	spin_unlock(&iommu_group_kset->list_lock);
+
+	return group;
+}
+
+struct device *iommu_group_find_device_by_name(const char *name)
+{
+	struct iommu_group *group, *next;
+	struct group_device *gdev;
+	struct device *dev = NULL;
+
+	if (!name)
+		return NULL;
+
+	for (group = iommu_group_kset_next_get(NULL); group; group = next) {
+		mutex_lock(&group->mutex);
+		for_each_group_device(group, gdev) {
+			if (!strcmp(gdev->name, name)) {
+				/*
+				 * Take a reference while still under
+				 * group->mutex: device removal also takes this
+				 * mutex before freeing the device, so the
+				 * pointer cannot vanish until we hold a
+				 * reference. The caller must put_device().
+				 */
+				dev = get_device(gdev->dev);
+				break;
+			}
+		}
+		mutex_unlock(&group->mutex);
+
+		next = dev ? NULL : iommu_group_kset_next_get(group);
+		kobject_put(&group->kobj);
+		if (dev)
+			break;
+	}
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(iommu_group_find_device_by_name);
+
+int iommu_set_dev_requestor_id(struct device *dev, u32 requestor_id, u8 pmg)
+{
+	const struct iommu_ops *ops;
+
+	if (!dev_has_iommu(dev))
+		return -EOPNOTSUPP;
+
+	ops = dev_iommu_ops(dev);
+	if (!ops->set_dev_requestor_id)
+		return -EOPNOTSUPP;
+
+	return ops->set_dev_requestor_id(dev, requestor_id, pmg);
+}
+EXPORT_SYMBOL_GPL(iommu_set_dev_requestor_id);
+
+void iommu_register_qos_device_ops(const struct iommu_qos_device_ops *ops)
+{
+	struct iommu_group *group, *next;
+	struct group_device *gdev;
+
+	/* Publish the ops first so newly probed devices see them. */
+	WRITE_ONCE(iommu_qos_dev_ops, ops);
+
+	/*
+	 * Registration happens late (e.g. from resctrl's fs_initcall), after
+	 * early IOMMU devices have already been added to their groups. Replay
+	 * the add() callback for every device that is currently on a group so
+	 * none are missed.
+	 */
+	for (group = iommu_group_kset_next_get(NULL); group; group = next) {
+		mutex_lock(&group->mutex);
+		for_each_group_device(group, gdev)
+			ops->add(gdev->dev);
+		mutex_unlock(&group->mutex);
+
+		next = iommu_group_kset_next_get(group);
+		kobject_put(&group->kobj);
+	}
+}
+EXPORT_SYMBOL_GPL(iommu_register_qos_device_ops);
+
 #if IS_ENABLED(CONFIG_IRQ_MSI_IOMMU)
 /**
  * iommu_dma_prepare_msi() - Map the MSI page in the IOMMU domain
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index ac43b8b93f14..20bb7f381064 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -340,6 +340,11 @@ struct iommu_pages_list {
 #define IOMMU_PAGES_LIST_INIT(name) \
 	((struct iommu_pages_list){ .pages = LIST_HEAD_INIT(name.pages) })
 
+struct iommu_qos_device_ops {
+	void (*add)(struct device *dev);
+	void (*remove)(struct device *dev);
+};
+
 #ifdef CONFIG_IOMMU_API
 
 /**
@@ -735,6 +740,9 @@ struct iommu_ops {
 			   struct iommu_domain *parent_domain,
 			   const struct iommu_user_data *user_data);
 
+	int (*set_dev_requestor_id)(struct device *dev, u32 requestor_id,
+				    u8 pmg);
+
 	const struct iommu_domain_ops *default_domain_ops;
 	struct module *owner;
 	struct iommu_domain *identity_domain;
@@ -1225,6 +1233,10 @@ void iommu_free_global_pasid(ioasid_t pasid);
 /* PCI device reset functions */
 int pci_dev_reset_iommu_prepare(struct pci_dev *pdev);
 void pci_dev_reset_iommu_done(struct pci_dev *pdev);
+
+struct device *iommu_group_find_device_by_name(const char *name);
+int iommu_set_dev_requestor_id(struct device *dev, u32 requestor_id, u8 pmg);
+void iommu_register_qos_device_ops(const struct iommu_qos_device_ops *ops);
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
@@ -1557,6 +1569,23 @@ static inline int pci_dev_reset_iommu_prepare(struct pci_dev *pdev)
 static inline void pci_dev_reset_iommu_done(struct pci_dev *pdev)
 {
 }
+
+static inline struct device *iommu_group_find_device_by_name(const char *name)
+{
+	return NULL;
+}
+
+static inline int iommu_set_dev_requestor_id(struct device *dev,
+					     u32 requestor_id, u8 pmg)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void
+iommu_register_qos_device_ops(const struct iommu_qos_device_ops *ops)
+{
+}
+
 #endif /* CONFIG_IOMMU_API */
 
 #ifdef CONFIG_IRQ_MSI_IOMMU
-- 
2.33.0


  reply	other threads:[~2026-09-01 14:08 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-01 14:07 [RFC PATCH 0/5] resctrl: Assign devices to resource groups via IOMMU DMA QoS tagging Qinxin Xia
2026-09-01 14:07 ` Qinxin Xia [this message]
2026-09-01 14:07 ` [RFC PATCH 2/5] arm_mpam: resctrl: Add arch query for device DMA QoS support Qinxin Xia
2026-09-01 14:08 ` [RFC PATCH 3/5] iommu/arm-smmu-v3: Support MPAM device DMA QoS tagging Qinxin Xia
2026-09-01 14:08 ` [RFC PATCH 4/5] fs/resctrl: Add device-to-group QoS tracking infrastructure Qinxin Xia
2026-09-01 14:08 ` [RFC PATCH 5/5] fs/resctrl: Add a "devices" file to assign devices to groups Qinxin Xia
2026-09-10 10:24   ` Ben Horgan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260901140802.1215508-2-xiaqinxin@huawei.com \
    --to=xiaqinxin@huawei.com \
    --cc=Dave.Martin@arm.com \
    --cc=alex@ghiti.fr \
    --cc=aou@eecs.berkeley.edu \
    --cc=babu.moger@amd.com \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=ben.horgan@arm.com \
    --cc=corbet@lwn.net \
    --cc=cuiyunhui@bytedance.com \
    --cc=fustini@kernel.org \
    --cc=iommu@lists.linux.dev \
    --cc=james.morse@arm.com \
    --cc=jgg@ziepe.ca \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=linuxarm@huawei.com \
    --cc=palmer@dabbelt.com \
    --cc=pjw@kernel.org \
    --cc=reinette.chatre@intel.com \
    --cc=robin.murphy@arm.com \
    --cc=shuah@kernel.org \
    --cc=tomasz.jeznach@linux.dev \
    --cc=tony.luck@intel.com \
    --cc=wangzhou1@hisilicon.com \
    --cc=will@kernel.org \
    --cc=yuanzhu@bytedance.com \
    --cc=zengheng4@huawei.com \
    --cc=zhangzhanpeng.jasper@bytedance.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.