forked from mirrors/linux
		
	io-mapping: Always create a struct to hold metadata about the io-mapping
Currently, we only allocate a structure to hold metadata if we need to allocate an ioremap for every access, such as on x86-32. However, it would be useful to store basic information about the io-mapping, such as its page protection, on all platforms. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: linux-mm@kvack.org Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20160819155428.1670-4-chris@chris-wilson.co.uk
This commit is contained in:
		
							parent
							
								
									8678fdaf39
								
							
						
					
					
						commit
						cafaf14a5d
					
				
					 1 changed files with 57 additions and 35 deletions
				
			
		|  | @ -31,16 +31,16 @@ | |||
|  * See Documentation/io-mapping.txt | ||||
|  */ | ||||
| 
 | ||||
| #ifdef CONFIG_HAVE_ATOMIC_IOMAP | ||||
| 
 | ||||
| #include <asm/iomap.h> | ||||
| 
 | ||||
| struct io_mapping { | ||||
| 	resource_size_t base; | ||||
| 	unsigned long size; | ||||
| 	pgprot_t prot; | ||||
| 	void __iomem *iomem; | ||||
| }; | ||||
| 
 | ||||
| #ifdef CONFIG_HAVE_ATOMIC_IOMAP | ||||
| 
 | ||||
| #include <asm/iomap.h> | ||||
| /*
 | ||||
|  * For small address space machines, mapping large objects | ||||
|  * into the kernel virtual space isn't practical. Where | ||||
|  | @ -49,34 +49,25 @@ struct io_mapping { | |||
|  */ | ||||
| 
 | ||||
| static inline struct io_mapping * | ||||
| io_mapping_create_wc(resource_size_t base, unsigned long size) | ||||
| io_mapping_init_wc(struct io_mapping *iomap, | ||||
| 		   resource_size_t base, | ||||
| 		   unsigned long size) | ||||
| { | ||||
| 	struct io_mapping *iomap; | ||||
| 	pgprot_t prot; | ||||
| 
 | ||||
| 	iomap = kmalloc(sizeof(*iomap), GFP_KERNEL); | ||||
| 	if (!iomap) | ||||
| 		goto out_err; | ||||
| 
 | ||||
| 	if (iomap_create_wc(base, size, &prot)) | ||||
| 		goto out_free; | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	iomap->base = base; | ||||
| 	iomap->size = size; | ||||
| 	iomap->prot = prot; | ||||
| 	return iomap; | ||||
| 
 | ||||
| out_free: | ||||
| 	kfree(iomap); | ||||
| out_err: | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| io_mapping_free(struct io_mapping *mapping) | ||||
| io_mapping_fini(struct io_mapping *mapping) | ||||
| { | ||||
| 	iomap_free(mapping->base, mapping->size); | ||||
| 	kfree(mapping); | ||||
| } | ||||
| 
 | ||||
| /* Atomic map/unmap */ | ||||
|  | @ -121,21 +112,40 @@ io_mapping_unmap(void __iomem *vaddr) | |||
| #else | ||||
| 
 | ||||
| #include <linux/uaccess.h> | ||||
| 
 | ||||
| /* this struct isn't actually defined anywhere */ | ||||
| struct io_mapping; | ||||
| #include <asm/pgtable_types.h> | ||||
| 
 | ||||
| /* Create the io_mapping object*/ | ||||
| static inline struct io_mapping * | ||||
| io_mapping_create_wc(resource_size_t base, unsigned long size) | ||||
| io_mapping_init_wc(struct io_mapping *iomap, | ||||
| 		   resource_size_t base, | ||||
| 		   unsigned long size) | ||||
| { | ||||
| 	return (struct io_mapping __force *) ioremap_wc(base, size); | ||||
| 	iomap->base = base; | ||||
| 	iomap->size = size; | ||||
| 	iomap->iomem = ioremap_wc(base, size); | ||||
| 	iomap->prot = pgprot_writecombine(PAGE_KERNEL_IO); | ||||
| 
 | ||||
| 	return iomap; | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| io_mapping_free(struct io_mapping *mapping) | ||||
| io_mapping_fini(struct io_mapping *mapping) | ||||
| { | ||||
| 	iounmap(mapping->iomem); | ||||
| } | ||||
| 
 | ||||
| /* Non-atomic map/unmap */ | ||||
| static inline void __iomem * | ||||
| io_mapping_map_wc(struct io_mapping *mapping, | ||||
| 		  unsigned long offset, | ||||
| 		  unsigned long size) | ||||
| { | ||||
| 	return mapping->iomem + offset; | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| io_mapping_unmap(void __iomem *vaddr) | ||||
| { | ||||
| 	iounmap((void __force __iomem *) mapping); | ||||
| } | ||||
| 
 | ||||
| /* Atomic map/unmap */ | ||||
|  | @ -145,30 +155,42 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping, | |||
| { | ||||
| 	preempt_disable(); | ||||
| 	pagefault_disable(); | ||||
| 	return ((char __force __iomem *) mapping) + offset; | ||||
| 	return io_mapping_map_wc(mapping, offset, PAGE_SIZE); | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| io_mapping_unmap_atomic(void __iomem *vaddr) | ||||
| { | ||||
| 	io_mapping_unmap(vaddr); | ||||
| 	pagefault_enable(); | ||||
| 	preempt_enable(); | ||||
| } | ||||
| 
 | ||||
| /* Non-atomic map/unmap */ | ||||
| static inline void __iomem * | ||||
| io_mapping_map_wc(struct io_mapping *mapping, | ||||
| 		  unsigned long offset, | ||||
| #endif /* HAVE_ATOMIC_IOMAP */ | ||||
| 
 | ||||
| static inline struct io_mapping * | ||||
| io_mapping_create_wc(resource_size_t base, | ||||
| 		     unsigned long size) | ||||
| { | ||||
| 	return ((char __force __iomem *) mapping) + offset; | ||||
| 	struct io_mapping *iomap; | ||||
| 
 | ||||
| 	iomap = kmalloc(sizeof(*iomap), GFP_KERNEL); | ||||
| 	if (!iomap) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if (!io_mapping_init_wc(iomap, base, size)) { | ||||
| 		kfree(iomap); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return iomap; | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| io_mapping_unmap(void __iomem *vaddr) | ||||
| io_mapping_free(struct io_mapping *iomap) | ||||
| { | ||||
| 	io_mapping_fini(iomap); | ||||
| 	kfree(iomap); | ||||
| } | ||||
| 
 | ||||
| #endif /* HAVE_ATOMIC_IOMAP */ | ||||
| 
 | ||||
| #endif /* _LINUX_IO_MAPPING_H */ | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Chris Wilson
						Chris Wilson