xref: /linux/drivers/iommu/iommufd/driver.c (revision cdd30ebb1b9f36159d66f088b61aee264e649d7a)
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