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 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 * 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