summaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2015-06-05 02:35:10 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-06-11 01:16:47 -0400
commitf87a88642e660edd8912ad39fe77848c6f9927a2 (patch)
tree728433c0ca8d3aa52fc4b75676131d2935e77bd6 /drivers/vfio
parent0eaf4defc7c44ed5dd33a03cab12a5f88c9b4b86 (diff)
vfio: powerpc/spapr/iommu/powernv/ioda2: Rework IOMMU ownership control
This adds tce_iommu_take_ownership() and tce_iommu_release_ownership which call in a loop iommu_take_ownership()/iommu_release_ownership() for every table on the group. As there is just one now, no change in behaviour is expected. At the moment the iommu_table struct has a set_bypass() which enables/ disables DMA bypass on IODA2 PHB. This is exposed to POWERPC IOMMU code which calls this callback when external IOMMU users such as VFIO are about to get over a PHB. The set_bypass() callback is not really an iommu_table function but IOMMU/PE function. This introduces a iommu_table_group_ops struct and adds take_ownership()/release_ownership() callbacks to it which are called when an external user takes/releases control over the IOMMU. This replaces set_bypass() with ownership callbacks as it is not necessarily just bypass enabling, it can be something else/more so let's give it more generic name. The callbacks is implemented for IODA2 only. Other platforms (P5IOC2, IODA1) will use the old iommu_take_ownership/iommu_release_ownership API. The following patches will replace iommu_take_ownership/ iommu_release_ownership calls in IODA2 with full IOMMU table release/ create. As we here and touching bypass control, this removes pnv_pci_ioda2_setup_bypass_pe() as it does not do much more compared to pnv_pci_ioda2_set_bypass. This moves tce_bypass_base initialization to pnv_pci_ioda2_setup_dma_pe. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> [aw: for the vfio related changes] Acked-by: Alex Williamson <alex.williamson@redhat.com> Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/vfio_iommu_spapr_tce.c70
1 files changed, 65 insertions, 5 deletions
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
index ffc634a75dba..9c720de46c33 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -486,6 +486,61 @@ static long tce_iommu_ioctl(void *iommu_data,
486 return -ENOTTY; 486 return -ENOTTY;
487} 487}
488 488
489static void tce_iommu_release_ownership(struct tce_container *container,
490 struct iommu_table_group *table_group)
491{
492 int i;
493
494 for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
495 struct iommu_table *tbl = table_group->tables[i];
496
497 if (!tbl)
498 continue;
499
500 tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);
501 if (tbl->it_map)
502 iommu_release_ownership(tbl);
503 }
504}
505
506static int tce_iommu_take_ownership(struct tce_container *container,
507 struct iommu_table_group *table_group)
508{
509 int i, j, rc = 0;
510
511 for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
512 struct iommu_table *tbl = table_group->tables[i];
513
514 if (!tbl || !tbl->it_map)
515 continue;
516
517 rc = iommu_take_ownership(tbl);
518 if (rc) {
519 for (j = 0; j < i; ++j)
520 iommu_release_ownership(
521 table_group->tables[j]);
522
523 return rc;
524 }
525 }
526
527 return 0;
528}
529
530static void tce_iommu_release_ownership_ddw(struct tce_container *container,
531 struct iommu_table_group *table_group)
532{
533 table_group->ops->release_ownership(table_group);
534}
535
536static long tce_iommu_take_ownership_ddw(struct tce_container *container,
537 struct iommu_table_group *table_group)
538{
539 table_group->ops->take_ownership(table_group);
540
541 return 0;
542}
543
489static int tce_iommu_attach_group(void *iommu_data, 544static int tce_iommu_attach_group(void *iommu_data,
490 struct iommu_group *iommu_group) 545 struct iommu_group *iommu_group)
491{ 546{
@@ -518,7 +573,12 @@ static int tce_iommu_attach_group(void *iommu_data,
518 goto unlock_exit; 573 goto unlock_exit;
519 } 574 }
520 575
521 ret = iommu_take_ownership(table_group->tables[0]); 576 if (!table_group->ops || !table_group->ops->take_ownership ||
577 !table_group->ops->release_ownership)
578 ret = tce_iommu_take_ownership(container, table_group);
579 else
580 ret = tce_iommu_take_ownership_ddw(container, table_group);
581
522 if (!ret) 582 if (!ret)
523 container->grp = iommu_group; 583 container->grp = iommu_group;
524 584
@@ -533,7 +593,6 @@ static void tce_iommu_detach_group(void *iommu_data,
533{ 593{
534 struct tce_container *container = iommu_data; 594 struct tce_container *container = iommu_data;
535 struct iommu_table_group *table_group; 595 struct iommu_table_group *table_group;
536 struct iommu_table *tbl;
537 596
538 mutex_lock(&container->lock); 597 mutex_lock(&container->lock);
539 if (iommu_group != container->grp) { 598 if (iommu_group != container->grp) {
@@ -556,9 +615,10 @@ static void tce_iommu_detach_group(void *iommu_data,
556 table_group = iommu_group_get_iommudata(iommu_group); 615 table_group = iommu_group_get_iommudata(iommu_group);
557 BUG_ON(!table_group); 616 BUG_ON(!table_group);
558 617
559 tbl = table_group->tables[0]; 618 if (!table_group->ops || !table_group->ops->release_ownership)
560 tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size); 619 tce_iommu_release_ownership(container, table_group);
561 iommu_release_ownership(tbl); 620 else
621 tce_iommu_release_ownership_ddw(container, table_group);
562 622
563unlock_exit: 623unlock_exit:
564 mutex_unlock(&container->lock); 624 mutex_unlock(&container->lock);