Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[cascardo/linux.git] / drivers / vfio / vfio_iommu_type1.c
index 0734fbe..4a9d666 100644 (file)
@@ -57,7 +57,8 @@ struct vfio_iommu {
        struct list_head        domain_list;
        struct mutex            lock;
        struct rb_root          dma_list;
-       bool v2;
+       bool                    v2;
+       bool                    nesting;
 };
 
 struct vfio_domain {
@@ -705,6 +706,15 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
                goto out_free;
        }
 
+       if (iommu->nesting) {
+               int attr = 1;
+
+               ret = iommu_domain_set_attr(domain->domain, DOMAIN_ATTR_NESTING,
+                                           &attr);
+               if (ret)
+                       goto out_domain;
+       }
+
        ret = iommu_attach_group(domain->domain, iommu_group);
        if (ret)
                goto out_domain;
@@ -713,14 +723,14 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
        list_add(&group->next, &domain->group_list);
 
        if (!allow_unsafe_interrupts &&
-           !iommu_domain_has_cap(domain->domain, IOMMU_CAP_INTR_REMAP)) {
+           !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
                pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
                       __func__);
                ret = -EPERM;
                goto out_detach;
        }
 
-       if (iommu_domain_has_cap(domain->domain, IOMMU_CAP_CACHE_COHERENCY))
+       if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY))
                domain->prot |= IOMMU_CACHE;
 
        /*
@@ -819,17 +829,26 @@ static void *vfio_iommu_type1_open(unsigned long arg)
 {
        struct vfio_iommu *iommu;
 
-       if (arg != VFIO_TYPE1_IOMMU && arg != VFIO_TYPE1v2_IOMMU)
-               return ERR_PTR(-EINVAL);
-
        iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
        if (!iommu)
                return ERR_PTR(-ENOMEM);
 
+       switch (arg) {
+       case VFIO_TYPE1_IOMMU:
+               break;
+       case VFIO_TYPE1_NESTING_IOMMU:
+               iommu->nesting = true;
+       case VFIO_TYPE1v2_IOMMU:
+               iommu->v2 = true;
+               break;
+       default:
+               kfree(iommu);
+               return ERR_PTR(-EINVAL);
+       }
+
        INIT_LIST_HEAD(&iommu->domain_list);
        iommu->dma_list = RB_ROOT;
        mutex_init(&iommu->lock);
-       iommu->v2 = (arg == VFIO_TYPE1v2_IOMMU);
 
        return iommu;
 }
@@ -885,6 +904,7 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
                switch (arg) {
                case VFIO_TYPE1_IOMMU:
                case VFIO_TYPE1v2_IOMMU:
+               case VFIO_TYPE1_NESTING_IOMMU:
                        return 1;
                case VFIO_DMA_CC_IOMMU:
                        if (!iommu)