Commit 8bda3092 authored by Joerg Roedel's avatar Joerg Roedel

amd-iommu: move page table allocation code to seperate function

This patch makes page table allocation usable for dma_ops code.
Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent c3239567
...@@ -55,7 +55,9 @@ struct iommu_cmd { ...@@ -55,7 +55,9 @@ struct iommu_cmd {
static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
struct unity_map_entry *e); struct unity_map_entry *e);
static struct dma_ops_domain *find_protection_domain(u16 devid); static struct dma_ops_domain *find_protection_domain(u16 devid);
static u64* alloc_pte(struct protection_domain *dom,
unsigned long address, u64
**pte_page, gfp_t gfp);
#ifdef CONFIG_AMD_IOMMU_STATS #ifdef CONFIG_AMD_IOMMU_STATS
...@@ -468,7 +470,7 @@ static int iommu_map_page(struct protection_domain *dom, ...@@ -468,7 +470,7 @@ static int iommu_map_page(struct protection_domain *dom,
unsigned long phys_addr, unsigned long phys_addr,
int prot) int prot)
{ {
u64 __pte, *pte, *page; u64 __pte, *pte;
bus_addr = PAGE_ALIGN(bus_addr); bus_addr = PAGE_ALIGN(bus_addr);
phys_addr = PAGE_ALIGN(phys_addr); phys_addr = PAGE_ALIGN(phys_addr);
...@@ -477,27 +479,7 @@ static int iommu_map_page(struct protection_domain *dom, ...@@ -477,27 +479,7 @@ static int iommu_map_page(struct protection_domain *dom,
if (bus_addr > IOMMU_MAP_SIZE_L3 || !(prot & IOMMU_PROT_MASK)) if (bus_addr > IOMMU_MAP_SIZE_L3 || !(prot & IOMMU_PROT_MASK))
return -EINVAL; return -EINVAL;
pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(bus_addr)]; pte = alloc_pte(dom, bus_addr, NULL, GFP_KERNEL);
if (!IOMMU_PTE_PRESENT(*pte)) {
page = (u64 *)get_zeroed_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
*pte = IOMMU_L2_PDE(virt_to_phys(page));
}
pte = IOMMU_PTE_PAGE(*pte);
pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
if (!IOMMU_PTE_PRESENT(*pte)) {
page = (u64 *)get_zeroed_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
*pte = IOMMU_L1_PDE(virt_to_phys(page));
}
pte = IOMMU_PTE_PAGE(*pte);
pte = &pte[IOMMU_PTE_L0_INDEX(bus_addr)];
if (IOMMU_PTE_PRESENT(*pte)) if (IOMMU_PTE_PRESENT(*pte))
return -EBUSY; return -EBUSY;
...@@ -1139,6 +1121,61 @@ static int get_device_resources(struct device *dev, ...@@ -1139,6 +1121,61 @@ static int get_device_resources(struct device *dev,
return 1; return 1;
} }
/*
* If the pte_page is not yet allocated this function is called
*/
static u64* alloc_pte(struct protection_domain *dom,
unsigned long address, u64 **pte_page, gfp_t gfp)
{
u64 *pte, *page;
pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(address)];
if (!IOMMU_PTE_PRESENT(*pte)) {
page = (u64 *)get_zeroed_page(gfp);
if (!page)
return NULL;
*pte = IOMMU_L2_PDE(virt_to_phys(page));
}
pte = IOMMU_PTE_PAGE(*pte);
pte = &pte[IOMMU_PTE_L1_INDEX(address)];
if (!IOMMU_PTE_PRESENT(*pte)) {
page = (u64 *)get_zeroed_page(gfp);
if (!page)
return NULL;
*pte = IOMMU_L1_PDE(virt_to_phys(page));
}
pte = IOMMU_PTE_PAGE(*pte);
if (pte_page)
*pte_page = pte;
pte = &pte[IOMMU_PTE_L0_INDEX(address)];
return pte;
}
/*
* This function fetches the PTE for a given address in the aperture
*/
static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
unsigned long address)
{
struct aperture_range *aperture = &dom->aperture;
u64 *pte, *pte_page;
pte = aperture->pte_pages[IOMMU_PTE_L1_INDEX(address)];
if (!pte) {
pte = alloc_pte(&dom->domain, address, &pte_page, GFP_ATOMIC);
aperture->pte_pages[IOMMU_PTE_L1_INDEX(address)] = pte_page;
}
return pte;
}
/* /*
* This is the generic map function. It maps one 4kb page at paddr to * This is the generic map function. It maps one 4kb page at paddr to
* the given address in the DMA address space for the domain. * the given address in the DMA address space for the domain.
...@@ -1155,8 +1192,7 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu, ...@@ -1155,8 +1192,7 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,
paddr &= PAGE_MASK; paddr &= PAGE_MASK;
pte = dom->aperture.pte_pages[IOMMU_PTE_L1_INDEX(address)]; pte = dma_ops_get_pte(dom, address);
pte += IOMMU_PTE_L0_INDEX(address);
__pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC; __pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment