diff options
Diffstat (limited to 'arch/powerpc/include/asm/iommu.h')
| -rw-r--r-- | arch/powerpc/include/asm/iommu.h | 107 | 
1 files changed, 84 insertions, 23 deletions
diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index edfc9803ec9..42632c7a2a4 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -30,22 +30,19 @@  #include <asm/machdep.h>  #include <asm/types.h> -#define IOMMU_PAGE_SHIFT      12 -#define IOMMU_PAGE_SIZE       (ASM_CONST(1) << IOMMU_PAGE_SHIFT) -#define IOMMU_PAGE_MASK       (~((1 << IOMMU_PAGE_SHIFT) - 1)) -#define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE) +#define IOMMU_PAGE_SHIFT_4K      12 +#define IOMMU_PAGE_SIZE_4K       (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K) +#define IOMMU_PAGE_MASK_4K       (~((1 << IOMMU_PAGE_SHIFT_4K) - 1)) +#define IOMMU_PAGE_ALIGN_4K(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE_4K) + +#define IOMMU_PAGE_SIZE(tblptr) (ASM_CONST(1) << (tblptr)->it_page_shift) +#define IOMMU_PAGE_MASK(tblptr) (~((1 << (tblptr)->it_page_shift) - 1)) +#define IOMMU_PAGE_ALIGN(addr, tblptr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE(tblptr))  /* Boot time flags */  extern int iommu_is_off;  extern int iommu_force_on; -/* Pure 2^n version of get_order */ -static __inline__ __attribute_const__ int get_iommu_order(unsigned long size) -{ -	return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1; -} - -  /*   * IOMAP_MAX_ORDER defines the largest contiguous block   * of dma space we can get.  IOMAP_MAX_ORDER = 13 @@ -53,6 +50,16 @@ static __inline__ __attribute_const__ int get_iommu_order(unsigned long size)   */  #define IOMAP_MAX_ORDER		13 +#define IOMMU_POOL_HASHBITS	2 +#define IOMMU_NR_POOLS		(1 << IOMMU_POOL_HASHBITS) + +struct iommu_pool { +	unsigned long start; +	unsigned long end; +	unsigned long hint; +	spinlock_t lock; +} ____cacheline_aligned_in_smp; +  struct iommu_table {  	unsigned long  it_busno;     /* Bus number this table belongs to */  	unsigned long  it_size;      /* Size of iommu table in entries */ @@ -61,13 +68,26 @@ struct iommu_table {  	unsigned long  it_index;     /* which iommu table this is */  	unsigned long  it_type;      /* type: PCI or Virtual Bus */  	unsigned long  it_blocksize; /* Entries in each block (cacheline) */ -	unsigned long  it_hint;      /* Hint for next alloc */ -	unsigned long  it_largehint; /* Hint for large allocs */ -	unsigned long  it_halfpoint; /* Breaking point for small/large allocs */ -	spinlock_t     it_lock;      /* Protects it_map */ +	unsigned long  poolsize; +	unsigned long  nr_pools; +	struct iommu_pool large_pool; +	struct iommu_pool pools[IOMMU_NR_POOLS];  	unsigned long *it_map;       /* A simple allocation bitmap for now */ +	unsigned long  it_page_shift;/* table iommu page size */ +#ifdef CONFIG_IOMMU_API +	struct iommu_group *it_group; +#endif +	void (*set_bypass)(struct iommu_table *tbl, bool enable);  }; +/* Pure 2^n version of get_order */ +static inline __attribute_const__ +int get_iommu_order(unsigned long size, struct iommu_table *tbl) +{ +	return __ilog2((size - 1) >> tbl->it_page_shift) + 1; +} + +  struct scatterlist;  static inline void set_iommu_table_base(struct device *dev, void *base) @@ -88,6 +108,34 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);   */  extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,  					    int nid); +#ifdef CONFIG_IOMMU_API +extern void iommu_register_group(struct iommu_table *tbl, +				 int pci_domain_number, unsigned long pe_num); +extern int iommu_add_device(struct device *dev); +extern void iommu_del_device(struct device *dev); +#else +static inline void iommu_register_group(struct iommu_table *tbl, +					int pci_domain_number, +					unsigned long pe_num) +{ +} + +static inline int iommu_add_device(struct device *dev) +{ +	return 0; +} + +static inline void iommu_del_device(struct device *dev) +{ +} +#endif /* !CONFIG_IOMMU_API */ + +static inline void set_iommu_table_base_and_group(struct device *dev, +						  void *base) +{ +	set_iommu_table_base(dev, base); +	iommu_add_device(dev); +}  extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,  			struct scatterlist *sglist, int nelems, @@ -112,17 +160,9 @@ extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,  			     struct dma_attrs *attrs);  extern void iommu_init_early_pSeries(void); -extern void iommu_init_early_iSeries(void);  extern void iommu_init_early_dart(void);  extern void iommu_init_early_pasemi(void); -#ifdef CONFIG_PCI -extern void pci_iommu_init(void); -extern void pci_direct_iommu_init(void); -#else -static inline void pci_iommu_init(void) { } -#endif -  extern void alloc_dart_table(void);  #if defined(CONFIG_PPC64) && defined(CONFIG_PM)  static inline void iommu_save(void) @@ -138,5 +178,26 @@ static inline void iommu_restore(void)  }  #endif +/* The API to support IOMMU operations for VFIO */ +extern int iommu_tce_clear_param_check(struct iommu_table *tbl, +		unsigned long ioba, unsigned long tce_value, +		unsigned long npages); +extern int iommu_tce_put_param_check(struct iommu_table *tbl, +		unsigned long ioba, unsigned long tce); +extern int iommu_tce_build(struct iommu_table *tbl, unsigned long entry, +		unsigned long hwaddr, enum dma_data_direction direction); +extern unsigned long iommu_clear_tce(struct iommu_table *tbl, +		unsigned long entry); +extern int iommu_clear_tces_and_put_pages(struct iommu_table *tbl, +		unsigned long entry, unsigned long pages); +extern int iommu_put_tce_user_mode(struct iommu_table *tbl, +		unsigned long entry, unsigned long tce); + +extern void iommu_flush_tce(struct iommu_table *tbl); +extern int iommu_take_ownership(struct iommu_table *tbl); +extern void iommu_release_ownership(struct iommu_table *tbl); + +extern enum dma_data_direction iommu_tce_direction(unsigned long tce); +  #endif /* __KERNEL__ */  #endif /* _ASM_IOMMU_H */  | 
