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
|
@ -26,6 +26,7 @@
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/dmar.h>
|
#include <linux/dmar.h>
|
||||||
#include "iova.h"
|
#include "iova.h"
|
||||||
|
#include "intel-iommu.h"
|
||||||
|
|
||||||
#undef PREFIX
|
#undef PREFIX
|
||||||
#define PREFIX "DMAR:"
|
#define PREFIX "DMAR:"
|
||||||
|
|
|
@ -1088,7 +1088,7 @@ static void dmar_init_reserved_ranges(void)
|
||||||
int i;
|
int i;
|
||||||
u64 addr, size;
|
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 */
|
/* IOAPIC ranges shouldn't be accessed by DMA */
|
||||||
iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
|
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;
|
int adjust_width, agaw;
|
||||||
unsigned long sagaw;
|
unsigned long sagaw;
|
||||||
|
|
||||||
init_iova_domain(&domain->iovad);
|
init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
|
||||||
spin_lock_init(&domain->mapping_lock);
|
spin_lock_init(&domain->mapping_lock);
|
||||||
|
|
||||||
domain_reserve_special_ranges(domain);
|
domain_reserve_special_ranges(domain);
|
||||||
|
|
|
@ -23,9 +23,23 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/msi.h>
|
#include <linux/msi.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
#include "iova.h"
|
#include "iova.h"
|
||||||
#include <linux/io.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.
|
* Intel IOMMU register specification per version 1.0 public spec.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,19 +9,19 @@
|
||||||
#include "iova.h"
|
#include "iova.h"
|
||||||
|
|
||||||
void
|
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_alloc_lock);
|
||||||
spin_lock_init(&iovad->iova_rbtree_lock);
|
spin_lock_init(&iovad->iova_rbtree_lock);
|
||||||
iovad->rbroot = RB_ROOT;
|
iovad->rbroot = RB_ROOT;
|
||||||
iovad->cached32_node = NULL;
|
iovad->cached32_node = NULL;
|
||||||
|
iovad->dma_32bit_pfn = pfn_32bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rb_node *
|
static struct rb_node *
|
||||||
__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
|
__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))
|
(iovad->cached32_node == NULL))
|
||||||
return rb_last(&iovad->rbroot);
|
return rb_last(&iovad->rbroot);
|
||||||
else {
|
else {
|
||||||
|
@ -37,7 +37,7 @@ static void
|
||||||
__cached_rbnode_insert_update(struct iova_domain *iovad,
|
__cached_rbnode_insert_update(struct iova_domain *iovad,
|
||||||
unsigned long limit_pfn, struct iova *new)
|
unsigned long limit_pfn, struct iova *new)
|
||||||
{
|
{
|
||||||
if (limit_pfn != DMA_32BIT_PFN)
|
if (limit_pfn != iovad->dma_32bit_pfn)
|
||||||
return;
|
return;
|
||||||
iovad->cached32_node = &new->node;
|
iovad->cached32_node = &new->node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,22 +15,9 @@
|
||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
#include <linux/dma-mapping.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 */
|
/* IO virtual address start page frame number */
|
||||||
#define IOVA_START_PFN (1)
|
#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 */
|
/* iova structure */
|
||||||
struct iova {
|
struct iova {
|
||||||
struct rb_node node;
|
struct rb_node node;
|
||||||
|
@ -44,6 +31,7 @@ struct iova_domain {
|
||||||
spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
|
spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
|
||||||
struct rb_root rbroot; /* iova domain rbtree root */
|
struct rb_root rbroot; /* iova domain rbtree root */
|
||||||
struct rb_node *cached32_node; /* Save last alloced node */
|
struct rb_node *cached32_node; /* Save last alloced node */
|
||||||
|
unsigned long dma_32bit_pfn;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iova *alloc_iova_mem(void);
|
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,
|
struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
|
||||||
unsigned long pfn_hi);
|
unsigned long pfn_hi);
|
||||||
void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
|
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);
|
struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
|
||||||
void put_iova_domain(struct iova_domain *iovad);
|
void put_iova_domain(struct iova_domain *iovad);
|
||||||
|
|
||||||
|
|
Reference in New Issue