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