On Fri, 18 Mar 2022 14:27:35 -0300 Jason Gunthorpe <jgg@xxxxxxxxxx> wrote: > +/** > + * iommufd_bind_pci_device - Bind a physical device to an iommu fd > + * @fd: iommufd file descriptor. > + * @pdev: Pointer to a physical PCI device struct > + * @id: Output ID number to return to userspace for this device > + * > + * A successful bind establishes an ownership over the device and returns > + * struct iommufd_device pointer, otherwise returns error pointer. > + * > + * A driver using this API must set driver_managed_dma and must not touch > + * the device until this routine succeeds and establishes ownership. > + * > + * Binding a PCI device places the entire RID under iommufd control. > + * > + * The caller must undo this with iommufd_unbind_device() > + */ > +struct iommufd_device *iommufd_bind_pci_device(int fd, struct pci_dev *pdev, > + u32 *id) > +{ > + struct iommufd_device *idev; > + struct iommufd_ctx *ictx; > + struct iommu_group *group; > + int rc; > + > + ictx = iommufd_fget(fd); > + if (!ictx) > + return ERR_PTR(-EINVAL); > + > + group = iommu_group_get(&pdev->dev); > + if (!group) { > + rc = -ENODEV; > + goto out_file_put; > + } > + > + /* > + * FIXME: Use a device-centric iommu api and this won't work with > + * multi-device groups > + */ > + rc = iommu_group_claim_dma_owner(group, ictx->filp); > + if (rc) > + goto out_group_put; > + > + idev = iommufd_object_alloc(ictx, idev, IOMMUFD_OBJ_DEVICE); > + if (IS_ERR(idev)) { > + rc = PTR_ERR(idev); > + goto out_release_owner; > + } > + idev->ictx = ictx; > + idev->dev = &pdev->dev; > + /* The calling driver is a user until iommufd_unbind_device() */ > + refcount_inc(&idev->obj.users); > + /* group refcount moves into iommufd_device */ > + idev->group = group; > + > + /* > + * If the caller fails after this success it must call > + * iommufd_unbind_device() which is safe since we hold this refcount. > + * This also means the device is a leaf in the graph and no other object > + * can take a reference on it. > + */ > + iommufd_object_finalize(ictx, &idev->obj); > + *id = idev->obj.id; > + return idev; > + > +out_release_owner: > + iommu_group_release_dma_owner(group); > +out_group_put: > + iommu_group_put(group); > +out_file_put: > + fput(ictx->filp); > + return ERR_PTR(rc); > +} > +EXPORT_SYMBOL_GPL(iommufd_bind_pci_device); I'm stumped why this needs to be PCI specific. Anything beyond the RID comment? Please enlighten. Thanks, Alex