mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
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 <[email protected]> [aw: for the vfio related changes] Acked-by: Alex Williamson <[email protected]> Reviewed-by: Gavin Shan <[email protected]> Reviewed-by: David Gibson <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
This commit is contained in:
parent
0eaf4defc7
commit
f87a88642e
4 changed files with 103 additions and 33 deletions
|
|
@ -486,6 +486,61 @@ static long tce_iommu_ioctl(void *iommu_data,
|
|||
return -ENOTTY;
|
||||
}
|
||||
|
||||
static void tce_iommu_release_ownership(struct tce_container *container,
|
||||
struct iommu_table_group *table_group)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
|
||||
struct iommu_table *tbl = table_group->tables[i];
|
||||
|
||||
if (!tbl)
|
||||
continue;
|
||||
|
||||
tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);
|
||||
if (tbl->it_map)
|
||||
iommu_release_ownership(tbl);
|
||||
}
|
||||
}
|
||||
|
||||
static int tce_iommu_take_ownership(struct tce_container *container,
|
||||
struct iommu_table_group *table_group)
|
||||
{
|
||||
int i, j, rc = 0;
|
||||
|
||||
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
|
||||
struct iommu_table *tbl = table_group->tables[i];
|
||||
|
||||
if (!tbl || !tbl->it_map)
|
||||
continue;
|
||||
|
||||
rc = iommu_take_ownership(tbl);
|
||||
if (rc) {
|
||||
for (j = 0; j < i; ++j)
|
||||
iommu_release_ownership(
|
||||
table_group->tables[j]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tce_iommu_release_ownership_ddw(struct tce_container *container,
|
||||
struct iommu_table_group *table_group)
|
||||
{
|
||||
table_group->ops->release_ownership(table_group);
|
||||
}
|
||||
|
||||
static long tce_iommu_take_ownership_ddw(struct tce_container *container,
|
||||
struct iommu_table_group *table_group)
|
||||
{
|
||||
table_group->ops->take_ownership(table_group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tce_iommu_attach_group(void *iommu_data,
|
||||
struct iommu_group *iommu_group)
|
||||
{
|
||||
|
|
@ -518,7 +573,12 @@ static int tce_iommu_attach_group(void *iommu_data,
|
|||
goto unlock_exit;
|
||||
}
|
||||
|
||||
ret = iommu_take_ownership(table_group->tables[0]);
|
||||
if (!table_group->ops || !table_group->ops->take_ownership ||
|
||||
!table_group->ops->release_ownership)
|
||||
ret = tce_iommu_take_ownership(container, table_group);
|
||||
else
|
||||
ret = tce_iommu_take_ownership_ddw(container, table_group);
|
||||
|
||||
if (!ret)
|
||||
container->grp = iommu_group;
|
||||
|
||||
|
|
@ -533,7 +593,6 @@ static void tce_iommu_detach_group(void *iommu_data,
|
|||
{
|
||||
struct tce_container *container = iommu_data;
|
||||
struct iommu_table_group *table_group;
|
||||
struct iommu_table *tbl;
|
||||
|
||||
mutex_lock(&container->lock);
|
||||
if (iommu_group != container->grp) {
|
||||
|
|
@ -556,9 +615,10 @@ static void tce_iommu_detach_group(void *iommu_data,
|
|||
table_group = iommu_group_get_iommudata(iommu_group);
|
||||
BUG_ON(!table_group);
|
||||
|
||||
tbl = table_group->tables[0];
|
||||
tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);
|
||||
iommu_release_ownership(tbl);
|
||||
if (!table_group->ops || !table_group->ops->release_ownership)
|
||||
tce_iommu_release_ownership(container, table_group);
|
||||
else
|
||||
tce_iommu_release_ownership_ddw(container, table_group);
|
||||
|
||||
unlock_exit:
|
||||
mutex_unlock(&container->lock);
|
||||
|
|
|
|||
Loading…
Reference in a new issue