diff options
Diffstat (limited to 'drivers/iommu/iommufd')
| -rw-r--r-- | drivers/iommu/iommufd/device.c | 2 | ||||
| -rw-r--r-- | drivers/iommu/iommufd/eventq.c | 2 | ||||
| -rw-r--r-- | drivers/iommu/iommufd/pages.c | 3 | ||||
| -rw-r--r-- | drivers/iommu/iommufd/viommu.c | 22 |
4 files changed, 22 insertions, 7 deletions
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index 170a7005f0bc..2895e5370910 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -589,7 +589,7 @@ static int iommufd_hwpt_replace_device(struct iommufd_device *idev, if (rc) goto out_free_handle; - iommufd_auto_response_faults(hwpt, old_handle); + iommufd_auto_response_faults(old, old_handle); kfree(old_handle); return 0; diff --git a/drivers/iommu/iommufd/eventq.c b/drivers/iommu/iommufd/eventq.c index 5129e3bf5461..747dd5155121 100644 --- a/drivers/iommu/iommufd/eventq.c +++ b/drivers/iommu/iommufd/eventq.c @@ -484,6 +484,8 @@ int iommufd_fault_iopf_handler(struct iopf_group *group) hwpt = group->attach_handle->domain->iommufd_hwpt; fault = hwpt->fault; + iopf_group_dequeue(group); + spin_lock(&fault->common.lock); list_add_tail(&group->node, &fault->common.deliver); spin_unlock(&fault->common.lock); diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c index 03c8379bbc34..404f31d8f729 100644 --- a/drivers/iommu/iommufd/pages.c +++ b/drivers/iommu/iommufd/pages.c @@ -2451,6 +2451,9 @@ int iopt_area_add_access(struct iopt_area *area, unsigned long start_index, if ((flags & IOMMUFD_ACCESS_RW_WRITE) && !pages->writable) return -EPERM; + if (iopt_is_dmabuf(pages)) + return -EINVAL; + mutex_lock(&pages->mutex); access = iopt_pages_get_exact_access(pages, start_index, last_index); if (access) { diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c index 4081deda9b33..fc13cf4737ea 100644 --- a/drivers/iommu/iommufd/viommu.c +++ b/drivers/iommu/iommufd/viommu.c @@ -143,7 +143,7 @@ void iommufd_vdevice_destroy(struct iommufd_object *obj) int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd) { struct iommu_vdevice_alloc *cmd = ucmd->cmd; - struct iommufd_vdevice *vdev, *curr; + struct iommufd_vdevice *vdev; size_t vdev_size = sizeof(*vdev); struct iommufd_viommu *viommu; struct iommufd_device *idev; @@ -189,7 +189,7 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd) if (WARN_ON_ONCE(viommu->ops->vdevice_size < vdev_size || !viommu->ops->vdevice_init)) { rc = -EOPNOTSUPP; - goto out_put_idev; + goto out_unlock_igroup; } vdev_size = viommu->ops->vdevice_size; } @@ -218,18 +218,28 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd) */ idev->vdev = vdev; - curr = xa_cmpxchg(&viommu->vdevs, virt_id, NULL, vdev, GFP_KERNEL); - if (curr) { - rc = xa_err(curr) ?: -EEXIST; + /* + * Reserve the slot with a zero entry (reads back as NULL) until the + * vdevice_init() op accepts the vDEVICE. Only the xa_* helpers hide a + * reserved entry, so never use a raw xas_* iterator on this xarray. + */ + rc = xa_insert(&viommu->vdevs, virt_id, NULL, GFP_KERNEL); + if (rc) { + if (rc == -EBUSY) + rc = -EEXIST; goto out_abort; } if (viommu->ops && viommu->ops->vdevice_init) { rc = viommu->ops->vdevice_init(vdev); - if (rc) + if (rc) { + xa_release(&viommu->vdevs, virt_id); goto out_abort; + } } + xa_store(&viommu->vdevs, virt_id, vdev, GFP_KERNEL); + cmd->out_vdevice_id = vdev->obj.id; rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); if (rc) |
