17d4f46c2SNicolin Chen // SPDX-License-Identifier: GPL-2.0-only
27d4f46c2SNicolin Chen /* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES
37d4f46c2SNicolin Chen */
47d4f46c2SNicolin Chen #include "iommufd_private.h"
57d4f46c2SNicolin Chen
_iommufd_object_alloc(struct iommufd_ctx * ictx,size_t size,enum iommufd_object_type type)67d4f46c2SNicolin Chen struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
77d4f46c2SNicolin Chen size_t size,
87d4f46c2SNicolin Chen enum iommufd_object_type type)
97d4f46c2SNicolin Chen {
107d4f46c2SNicolin Chen struct iommufd_object *obj;
117d4f46c2SNicolin Chen int rc;
127d4f46c2SNicolin Chen
137d4f46c2SNicolin Chen obj = kzalloc(size, GFP_KERNEL_ACCOUNT);
147d4f46c2SNicolin Chen if (!obj)
157d4f46c2SNicolin Chen return ERR_PTR(-ENOMEM);
167d4f46c2SNicolin Chen obj->type = type;
177d4f46c2SNicolin Chen /* Starts out bias'd by 1 until it is removed from the xarray */
187d4f46c2SNicolin Chen refcount_set(&obj->shortterm_users, 1);
197d4f46c2SNicolin Chen refcount_set(&obj->users, 1);
207d4f46c2SNicolin Chen
217d4f46c2SNicolin Chen /*
227d4f46c2SNicolin Chen * Reserve an ID in the xarray but do not publish the pointer yet since
237d4f46c2SNicolin Chen * the caller hasn't initialized it yet. Once the pointer is published
247d4f46c2SNicolin Chen * in the xarray and visible to other threads we can't reliably destroy
257d4f46c2SNicolin Chen * it anymore, so the caller must complete all errorable operations
267d4f46c2SNicolin Chen * before calling iommufd_object_finalize().
277d4f46c2SNicolin Chen */
287d4f46c2SNicolin Chen rc = xa_alloc(&ictx->objects, &obj->id, XA_ZERO_ENTRY, xa_limit_31b,
297d4f46c2SNicolin Chen GFP_KERNEL_ACCOUNT);
307d4f46c2SNicolin Chen if (rc)
317d4f46c2SNicolin Chen goto out_free;
327d4f46c2SNicolin Chen return obj;
337d4f46c2SNicolin Chen out_free:
347d4f46c2SNicolin Chen kfree(obj);
357d4f46c2SNicolin Chen return ERR_PTR(rc);
367d4f46c2SNicolin Chen }
37*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(_iommufd_object_alloc, "IOMMUFD");
387d4f46c2SNicolin Chen
39c747e679SNicolin Chen /* Caller should xa_lock(&viommu->vdevs) to protect the return value */
iommufd_viommu_find_dev(struct iommufd_viommu * viommu,unsigned long vdev_id)40c747e679SNicolin Chen struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
41c747e679SNicolin Chen unsigned long vdev_id)
42c747e679SNicolin Chen {
43c747e679SNicolin Chen struct iommufd_vdevice *vdev;
44c747e679SNicolin Chen
45c747e679SNicolin Chen lockdep_assert_held(&viommu->vdevs.xa_lock);
46c747e679SNicolin Chen
47c747e679SNicolin Chen vdev = xa_load(&viommu->vdevs, vdev_id);
48c747e679SNicolin Chen return vdev ? vdev->dev : NULL;
49c747e679SNicolin Chen }
50*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(iommufd_viommu_find_dev, "IOMMUFD");
51c747e679SNicolin Chen
527d4f46c2SNicolin Chen MODULE_DESCRIPTION("iommufd code shared with builtin modules");
537d4f46c2SNicolin Chen MODULE_LICENSE("GPL");
54