diff options
author | Joerg Roedel <jroedel@suse.de> | 2015-04-01 08:58:49 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2015-04-02 07:31:07 -0400 |
commit | 71b390e9bec5121d25c45326ff0b0b96a143f9a8 (patch) | |
tree | caaec5e9629798ee60ad5ac13fa56415ff7cb62a /drivers/iommu/amd_iommu.c | |
parent | 3039ca1b1c37e61cc9239dbb3903db55141ecabd (diff) |
iommu/amd: Optimize iommu_unmap_page for new fetch_pte interface
Now that fetch_pte returns the page-size of the pte, this
function can be optimized a lot.
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/amd_iommu.c')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 32 |
1 files changed, 8 insertions, 24 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 24ef9e600289..c9ee444d8209 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -1428,8 +1428,8 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom, | |||
1428 | unsigned long bus_addr, | 1428 | unsigned long bus_addr, |
1429 | unsigned long page_size) | 1429 | unsigned long page_size) |
1430 | { | 1430 | { |
1431 | unsigned long long unmap_size, unmapped; | 1431 | unsigned long long unmapped; |
1432 | unsigned long pte_pgsize; | 1432 | unsigned long unmap_size; |
1433 | u64 *pte; | 1433 | u64 *pte; |
1434 | 1434 | ||
1435 | BUG_ON(!is_power_of_2(page_size)); | 1435 | BUG_ON(!is_power_of_2(page_size)); |
@@ -1438,28 +1438,12 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom, | |||
1438 | 1438 | ||
1439 | while (unmapped < page_size) { | 1439 | while (unmapped < page_size) { |
1440 | 1440 | ||
1441 | pte = fetch_pte(dom, bus_addr, &pte_pgsize); | 1441 | pte = fetch_pte(dom, bus_addr, &unmap_size); |
1442 | 1442 | ||
1443 | if (!pte) { | 1443 | if (pte) { |
1444 | /* | 1444 | int i, count; |
1445 | * No PTE for this address | 1445 | |
1446 | * move forward in 4kb steps | 1446 | count = PAGE_SIZE_PTE_COUNT(unmap_size); |
1447 | */ | ||
1448 | unmap_size = PAGE_SIZE; | ||
1449 | } else if (PM_PTE_LEVEL(*pte) == 0) { | ||
1450 | /* 4kb PTE found for this address */ | ||
1451 | unmap_size = PAGE_SIZE; | ||
1452 | *pte = 0ULL; | ||
1453 | } else { | ||
1454 | int count, i; | ||
1455 | |||
1456 | /* Large PTE found which maps this address */ | ||
1457 | unmap_size = PTE_PAGE_SIZE(*pte); | ||
1458 | |||
1459 | /* Only unmap from the first pte in the page */ | ||
1460 | if ((unmap_size - 1) & bus_addr) | ||
1461 | break; | ||
1462 | count = PAGE_SIZE_PTE_COUNT(unmap_size); | ||
1463 | for (i = 0; i < count; i++) | 1447 | for (i = 0; i < count; i++) |
1464 | pte[i] = 0ULL; | 1448 | pte[i] = 0ULL; |
1465 | } | 1449 | } |