1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
4 */
5 #include <linux/iommu.h>
6
7 #include "iommufd_private.h"
8
iommufd_hw_pagetable_destroy(struct iommufd_object * obj)9 void iommufd_hw_pagetable_destroy(struct iommufd_object *obj)
10 {
11 struct iommufd_hw_pagetable *hwpt =
12 container_of(obj, struct iommufd_hw_pagetable, obj);
13
14 WARN_ON(!list_empty(&hwpt->devices));
15
16 iommu_domain_free(hwpt->domain);
17 refcount_dec(&hwpt->ioas->obj.users);
18 mutex_destroy(&hwpt->devices_lock);
19 }
20
21 /**
22 * iommufd_hw_pagetable_alloc() - Get an iommu_domain for a device
23 * @ictx: iommufd context
24 * @ioas: IOAS to associate the domain with
25 * @dev: Device to get an iommu_domain for
26 *
27 * Allocate a new iommu_domain and return it as a hw_pagetable.
28 */
29 struct iommufd_hw_pagetable *
iommufd_hw_pagetable_alloc(struct iommufd_ctx * ictx,struct iommufd_ioas * ioas,struct device * dev)30 iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
31 struct device *dev)
32 {
33 struct iommufd_hw_pagetable *hwpt;
34 int rc;
35
36 hwpt = iommufd_object_alloc(ictx, hwpt, IOMMUFD_OBJ_HW_PAGETABLE);
37 if (IS_ERR(hwpt))
38 return hwpt;
39
40 hwpt->domain = iommu_domain_alloc(dev->bus);
41 if (!hwpt->domain) {
42 rc = -ENOMEM;
43 goto out_abort;
44 }
45
46 INIT_LIST_HEAD(&hwpt->devices);
47 INIT_LIST_HEAD(&hwpt->hwpt_item);
48 mutex_init(&hwpt->devices_lock);
49 /* Pairs with iommufd_hw_pagetable_destroy() */
50 refcount_inc(&ioas->obj.users);
51 hwpt->ioas = ioas;
52 return hwpt;
53
54 out_abort:
55 iommufd_object_abort(ictx, &hwpt->obj);
56 return ERR_PTR(rc);
57 }
58