1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
3 */
4 #include "iommufd_private.h"
5
_iommufd_object_alloc(struct iommufd_ctx * ictx,size_t size,enum iommufd_object_type type)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 */
iommufd_viommu_find_dev(struct iommufd_viommu * viommu,unsigned long vdev_id)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