xref: /linux/drivers/iommu/iommufd/driver.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
3  */
4 #include "iommufd_private.h"
5 
6 struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
7 					     size_t size,
8 					     enum iommufd_object_type type)
9 {
10 	struct iommufd_object *obj;
11 	int rc;
12 
13 	obj = kzalloc(size, GFP_KERNEL_ACCOUNT);
14 	if (!obj)
15 		return ERR_PTR(-ENOMEM);
16 	obj->type = type;
17 	/* Starts out bias'd by 1 until it is removed from the xarray */
18 	refcount_set(&obj->shortterm_users, 1);
19 	refcount_set(&obj->users, 1);
20 
21 	/*
22 	 * Reserve an ID in the xarray but do not publish the pointer yet since
23 	 * the caller hasn't initialized it yet. Once the pointer is published
24 	 * in the xarray and visible to other threads we can't reliably destroy
25 	 * it anymore, so the caller must complete all errorable operations
26 	 * before calling iommufd_object_finalize().
27 	 */
28 	rc = xa_alloc(&ictx->objects, &obj->id, XA_ZERO_ENTRY, xa_limit_31b,
29 		      GFP_KERNEL_ACCOUNT);
30 	if (rc)
31 		goto out_free;
32 	return obj;
33 out_free:
34 	kfree(obj);
35 	return ERR_PTR(rc);
36 }
37 EXPORT_SYMBOL_NS_GPL(_iommufd_object_alloc, IOMMUFD);
38 
39 /* Caller should xa_lock(&viommu->vdevs) to protect the return value */
40 struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
41 				       unsigned long vdev_id)
42 {
43 	struct iommufd_vdevice *vdev;
44 
45 	lockdep_assert_held(&viommu->vdevs.xa_lock);
46 
47 	vdev = xa_load(&viommu->vdevs, vdev_id);
48 	return vdev ? vdev->dev : NULL;
49 }
50 EXPORT_SYMBOL_NS_GPL(iommufd_viommu_find_dev, IOMMUFD);
51 
52 MODULE_DESCRIPTION("iommufd code shared with builtin modules");
53 MODULE_LICENSE("GPL");
54