aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/vfio/vfio_iommu_type1.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index c956b85264ae..3be1db3501cc 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -565,7 +565,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
565 mutex_lock(&iommu->lock); 565 mutex_lock(&iommu->lock);
566 566
567 /* Fail if notifier list is empty */ 567 /* Fail if notifier list is empty */
568 if ((!iommu->external_domain) || (!iommu->notifier.head)) { 568 if (!iommu->notifier.head) {
569 ret = -EINVAL; 569 ret = -EINVAL;
570 goto pin_done; 570 goto pin_done;
571 } 571 }
@@ -647,11 +647,6 @@ static int vfio_iommu_type1_unpin_pages(void *iommu_data,
647 647
648 mutex_lock(&iommu->lock); 648 mutex_lock(&iommu->lock);
649 649
650 if (!iommu->external_domain) {
651 mutex_unlock(&iommu->lock);
652 return -EINVAL;
653 }
654
655 do_accounting = !IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu); 650 do_accounting = !IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu);
656 for (i = 0; i < npage; i++) { 651 for (i = 0; i < npage; i++) {
657 struct vfio_dma *dma; 652 struct vfio_dma *dma;
@@ -1381,13 +1376,40 @@ static void vfio_iommu_detach_group(struct vfio_domain *domain,
1381 iommu_detach_group(domain->domain, group->iommu_group); 1376 iommu_detach_group(domain->domain, group->iommu_group);
1382} 1377}
1383 1378
1379static bool vfio_bus_is_mdev(struct bus_type *bus)
1380{
1381 struct bus_type *mdev_bus;
1382 bool ret = false;
1383
1384 mdev_bus = symbol_get(mdev_bus_type);
1385 if (mdev_bus) {
1386 ret = (bus == mdev_bus);
1387 symbol_put(mdev_bus_type);
1388 }
1389
1390 return ret;
1391}
1392
1393static int vfio_mdev_iommu_device(struct device *dev, void *data)
1394{
1395 struct device **old = data, *new;
1396
1397 new = vfio_mdev_get_iommu_device(dev);
1398 if (!new || (*old && *old != new))
1399 return -EINVAL;
1400
1401 *old = new;
1402
1403 return 0;
1404}
1405
1384static int vfio_iommu_type1_attach_group(void *iommu_data, 1406static int vfio_iommu_type1_attach_group(void *iommu_data,
1385 struct iommu_group *iommu_group) 1407 struct iommu_group *iommu_group)
1386{ 1408{
1387 struct vfio_iommu *iommu = iommu_data; 1409 struct vfio_iommu *iommu = iommu_data;
1388 struct vfio_group *group; 1410 struct vfio_group *group;
1389 struct vfio_domain *domain, *d; 1411 struct vfio_domain *domain, *d;
1390 struct bus_type *bus = NULL, *mdev_bus; 1412 struct bus_type *bus = NULL;
1391 int ret; 1413 int ret;
1392 bool resv_msi, msi_remap; 1414 bool resv_msi, msi_remap;
1393 phys_addr_t resv_msi_base; 1415 phys_addr_t resv_msi_base;
@@ -1422,23 +1444,30 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
1422 if (ret) 1444 if (ret)
1423 goto out_free; 1445 goto out_free;
1424 1446
1425 mdev_bus = symbol_get(mdev_bus_type); 1447 if (vfio_bus_is_mdev(bus)) {
1448 struct device *iommu_device = NULL;
1426 1449
1427 if (mdev_bus) { 1450 group->mdev_group = true;
1428 if ((bus == mdev_bus) && !iommu_present(bus)) { 1451
1429 symbol_put(mdev_bus_type); 1452 /* Determine the isolation type */
1453 ret = iommu_group_for_each_dev(iommu_group, &iommu_device,
1454 vfio_mdev_iommu_device);
1455 if (ret || !iommu_device) {
1430 if (!iommu->external_domain) { 1456 if (!iommu->external_domain) {
1431 INIT_LIST_HEAD(&domain->group_list); 1457 INIT_LIST_HEAD(&domain->group_list);
1432 iommu->external_domain = domain; 1458 iommu->external_domain = domain;
1433 } else 1459 } else {
1434 kfree(domain); 1460 kfree(domain);
1461 }
1435 1462
1436 list_add(&group->next, 1463 list_add(&group->next,
1437 &iommu->external_domain->group_list); 1464 &iommu->external_domain->group_list);
1438 mutex_unlock(&iommu->lock); 1465 mutex_unlock(&iommu->lock);
1466
1439 return 0; 1467 return 0;
1440 } 1468 }
1441 symbol_put(mdev_bus_type); 1469
1470 bus = iommu_device->bus;
1442 } 1471 }
1443 1472
1444 domain->domain = iommu_domain_alloc(bus); 1473 domain->domain = iommu_domain_alloc(bus);