Genericizing iova.[ch]
I would like to potentially move the sparc64 IOMMU code over to using the nice new drivers/pci/iova.[ch] code for free area management.. In order to do that we have to detach the IOMMU page size assumptions which only really need to exist in the intel-iommu.[ch] code. This patch attempts to implement that. [akpm@linux-foundation.org: build fix] Signed-off-by: David S. Miller <davem@davemloft.net> Acked-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b1ed88b47f
commit
f661197e0a
5 changed files with 23 additions and 20 deletions
|
@ -26,6 +26,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/dmar.h>
|
||||
#include "iova.h"
|
||||
#include "intel-iommu.h"
|
||||
|
||||
#undef PREFIX
|
||||
#define PREFIX "DMAR:"
|
||||
|
|
|
@ -1088,7 +1088,7 @@ static void dmar_init_reserved_ranges(void)
|
|||
int i;
|
||||
u64 addr, size;
|
||||
|
||||
init_iova_domain(&reserved_iova_list);
|
||||
init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
|
||||
|
||||
/* IOAPIC ranges shouldn't be accessed by DMA */
|
||||
iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
|
||||
|
@ -1142,7 +1142,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
|
|||
int adjust_width, agaw;
|
||||
unsigned long sagaw;
|
||||
|
||||
init_iova_domain(&domain->iovad);
|
||||
init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
|
||||
spin_lock_init(&domain->mapping_lock);
|
||||
|
||||
domain_reserve_special_ranges(domain);
|
||||
|
|
|
@ -23,9 +23,23 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include "iova.h"
|
||||
#include <linux/io.h>
|
||||
|
||||
/*
|
||||
* We need a fixed PAGE_SIZE of 4K irrespective of
|
||||
* arch PAGE_SIZE for IOMMU page tables.
|
||||
*/
|
||||
#define PAGE_SHIFT_4K (12)
|
||||
#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
|
||||
#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
|
||||
#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
|
||||
|
||||
#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K)
|
||||
#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK)
|
||||
#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK)
|
||||
|
||||
/*
|
||||
* Intel IOMMU register specification per version 1.0 public spec.
|
||||
*/
|
||||
|
|
|
@ -9,19 +9,19 @@
|
|||
#include "iova.h"
|
||||
|
||||
void
|
||||
init_iova_domain(struct iova_domain *iovad)
|
||||
init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
|
||||
{
|
||||
spin_lock_init(&iovad->iova_alloc_lock);
|
||||
spin_lock_init(&iovad->iova_rbtree_lock);
|
||||
iovad->rbroot = RB_ROOT;
|
||||
iovad->cached32_node = NULL;
|
||||
|
||||
iovad->dma_32bit_pfn = pfn_32bit;
|
||||
}
|
||||
|
||||
static struct rb_node *
|
||||
__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
|
||||
{
|
||||
if ((*limit_pfn != DMA_32BIT_PFN) ||
|
||||
if ((*limit_pfn != iovad->dma_32bit_pfn) ||
|
||||
(iovad->cached32_node == NULL))
|
||||
return rb_last(&iovad->rbroot);
|
||||
else {
|
||||
|
@ -37,7 +37,7 @@ static void
|
|||
__cached_rbnode_insert_update(struct iova_domain *iovad,
|
||||
unsigned long limit_pfn, struct iova *new)
|
||||
{
|
||||
if (limit_pfn != DMA_32BIT_PFN)
|
||||
if (limit_pfn != iovad->dma_32bit_pfn)
|
||||
return;
|
||||
iovad->cached32_node = &new->node;
|
||||
}
|
||||
|
|
|
@ -15,22 +15,9 @@
|
|||
#include <linux/rbtree.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
/*
|
||||
* We need a fixed PAGE_SIZE of 4K irrespective of
|
||||
* arch PAGE_SIZE for IOMMU page tables.
|
||||
*/
|
||||
#define PAGE_SHIFT_4K (12)
|
||||
#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
|
||||
#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
|
||||
#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
|
||||
|
||||
/* IO virtual address start page frame number */
|
||||
#define IOVA_START_PFN (1)
|
||||
|
||||
#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K)
|
||||
#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK)
|
||||
#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK)
|
||||
|
||||
/* iova structure */
|
||||
struct iova {
|
||||
struct rb_node node;
|
||||
|
@ -44,6 +31,7 @@ struct iova_domain {
|
|||
spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
|
||||
struct rb_root rbroot; /* iova domain rbtree root */
|
||||
struct rb_node *cached32_node; /* Save last alloced node */
|
||||
unsigned long dma_32bit_pfn;
|
||||
};
|
||||
|
||||
struct iova *alloc_iova_mem(void);
|
||||
|
@ -56,7 +44,7 @@ struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
|
|||
struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
|
||||
unsigned long pfn_hi);
|
||||
void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
|
||||
void init_iova_domain(struct iova_domain *iovad);
|
||||
void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit);
|
||||
struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
|
||||
void put_iova_domain(struct iova_domain *iovad);
|
||||
|
||||
|
|
Loading…
Reference in a new issue