diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-03 13:15:40 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-03 13:15:40 -0500 |
| commit | da4a22cba7cb2d922691214aed6b1977f04efaff (patch) | |
| tree | 89d3f02b13cd1eb280a33240878880f91066bac2 | |
| parent | 20ebc0073b0fb63ce4a27ca761418ecfdecaadb7 (diff) | |
| parent | e5beae16901795223d677f15aa2fe192976278ee (diff) | |
Merge branch 'io-mappings-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'io-mappings-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
io mapping: clean up #ifdefs
io mapping: improve documentation
i915: use io-mapping interfaces instead of a variety of mapping kludges
resources: add io-mapping functions to dynamically map large device apertures
x86: add iomap_atomic*()/iounmap_atomic() on 32-bit using fixmaps
| -rw-r--r-- | Documentation/io-mapping.txt | 82 | ||||
| -rw-r--r-- | arch/x86/Kconfig | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/fixmap.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/fixmap_32.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/highmem.h | 5 | ||||
| -rw-r--r-- | arch/x86/mm/Makefile | 2 | ||||
| -rw-r--r-- | arch/x86/mm/init_32.c | 3 | ||||
| -rw-r--r-- | arch/x86/mm/iomap_32.c | 59 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 174 | ||||
| -rw-r--r-- | include/asm-x86/iomap.h | 30 | ||||
| -rw-r--r-- | include/linux/io-mapping.h | 125 |
12 files changed, 390 insertions, 105 deletions
diff --git a/Documentation/io-mapping.txt b/Documentation/io-mapping.txt new file mode 100644 index 000000000000..473e43b2d588 --- /dev/null +++ b/Documentation/io-mapping.txt | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | The io_mapping functions in linux/io-mapping.h provide an abstraction for | ||
| 2 | efficiently mapping small regions of an I/O device to the CPU. The initial | ||
| 3 | usage is to support the large graphics aperture on 32-bit processors where | ||
| 4 | ioremap_wc cannot be used to statically map the entire aperture to the CPU | ||
| 5 | as it would consume too much of the kernel address space. | ||
| 6 | |||
| 7 | A mapping object is created during driver initialization using | ||
| 8 | |||
| 9 | struct io_mapping *io_mapping_create_wc(unsigned long base, | ||
| 10 | unsigned long size) | ||
| 11 | |||
| 12 | 'base' is the bus address of the region to be made | ||
| 13 | mappable, while 'size' indicates how large a mapping region to | ||
| 14 | enable. Both are in bytes. | ||
| 15 | |||
| 16 | This _wc variant provides a mapping which may only be used | ||
| 17 | with the io_mapping_map_atomic_wc or io_mapping_map_wc. | ||
| 18 | |||
| 19 | With this mapping object, individual pages can be mapped either atomically | ||
| 20 | or not, depending on the necessary scheduling environment. Of course, atomic | ||
| 21 | maps are more efficient: | ||
| 22 | |||
| 23 | void *io_mapping_map_atomic_wc(struct io_mapping *mapping, | ||
| 24 | unsigned long offset) | ||
| 25 | |||
| 26 | 'offset' is the offset within the defined mapping region. | ||
| 27 | Accessing addresses beyond the region specified in the | ||
| 28 | creation function yields undefined results. Using an offset | ||
| 29 | which is not page aligned yields an undefined result. The | ||
| 30 | return value points to a single page in CPU address space. | ||
| 31 | |||
| 32 | This _wc variant returns a write-combining map to the | ||
| 33 | page and may only be used with mappings created by | ||
| 34 | io_mapping_create_wc | ||
| 35 | |||
| 36 | Note that the task may not sleep while holding this page | ||
| 37 | mapped. | ||
| 38 | |||
| 39 | void io_mapping_unmap_atomic(void *vaddr) | ||
| 40 | |||
| 41 | 'vaddr' must be the the value returned by the last | ||
| 42 | io_mapping_map_atomic_wc call. This unmaps the specified | ||
| 43 | page and allows the task to sleep once again. | ||
| 44 | |||
| 45 | If you need to sleep while holding the lock, you can use the non-atomic | ||
| 46 | variant, although they may be significantly slower. | ||
| 47 | |||
| 48 | void *io_mapping_map_wc(struct io_mapping *mapping, | ||
| 49 | unsigned long offset) | ||
| 50 | |||
| 51 | This works like io_mapping_map_atomic_wc except it allows | ||
| 52 | the task to sleep while holding the page mapped. | ||
| 53 | |||
| 54 | void io_mapping_unmap(void *vaddr) | ||
| 55 | |||
| 56 | This works like io_mapping_unmap_atomic, except it is used | ||
| 57 | for pages mapped with io_mapping_map_wc. | ||
| 58 | |||
| 59 | At driver close time, the io_mapping object must be freed: | ||
| 60 | |||
| 61 | void io_mapping_free(struct io_mapping *mapping) | ||
| 62 | |||
| 63 | Current Implementation: | ||
| 64 | |||
| 65 | The initial implementation of these functions uses existing mapping | ||
| 66 | mechanisms and so provides only an abstraction layer and no new | ||
| 67 | functionality. | ||
| 68 | |||
| 69 | On 64-bit processors, io_mapping_create_wc calls ioremap_wc for the whole | ||
| 70 | range, creating a permanent kernel-visible mapping to the resource. The | ||
| 71 | map_atomic and map functions add the requested offset to the base of the | ||
| 72 | virtual address returned by ioremap_wc. | ||
| 73 | |||
| 74 | On 32-bit processors with HIGHMEM defined, io_mapping_map_atomic_wc uses | ||
| 75 | kmap_atomic_pfn to map the specified page in an atomic fashion; | ||
| 76 | kmap_atomic_pfn isn't really supposed to be used with device pages, but it | ||
| 77 | provides an efficient mapping for this usage. | ||
| 78 | |||
| 79 | On 32-bit processors without HIGHMEM defined, io_mapping_map_atomic_wc and | ||
| 80 | io_mapping_map_wc both use ioremap_wc, a terribly inefficient function which | ||
| 81 | performs an IPI to inform all processors about the new mapping. This results | ||
| 82 | in a significant performance penalty. | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6f20718d3156..e60c59b81bdd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -1894,6 +1894,10 @@ config SYSVIPC_COMPAT | |||
| 1894 | endmenu | 1894 | endmenu |
| 1895 | 1895 | ||
| 1896 | 1896 | ||
| 1897 | config HAVE_ATOMIC_IOMAP | ||
| 1898 | def_bool y | ||
| 1899 | depends on X86_32 | ||
| 1900 | |||
| 1897 | source "net/Kconfig" | 1901 | source "net/Kconfig" |
| 1898 | 1902 | ||
| 1899 | source "drivers/Kconfig" | 1903 | source "drivers/Kconfig" |
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 8668a94f850e..23696d44a0af 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
| @@ -9,6 +9,10 @@ | |||
| 9 | 9 | ||
| 10 | extern int fixmaps_set; | 10 | extern int fixmaps_set; |
| 11 | 11 | ||
| 12 | extern pte_t *kmap_pte; | ||
| 13 | extern pgprot_t kmap_prot; | ||
| 14 | extern pte_t *pkmap_page_table; | ||
| 15 | |||
| 12 | void __native_set_fixmap(enum fixed_addresses idx, pte_t pte); | 16 | void __native_set_fixmap(enum fixed_addresses idx, pte_t pte); |
| 13 | void native_set_fixmap(enum fixed_addresses idx, | 17 | void native_set_fixmap(enum fixed_addresses idx, |
| 14 | unsigned long phys, pgprot_t flags); | 18 | unsigned long phys, pgprot_t flags); |
diff --git a/arch/x86/include/asm/fixmap_32.h b/arch/x86/include/asm/fixmap_32.h index 09f29ab5c139..c7115c1d7217 100644 --- a/arch/x86/include/asm/fixmap_32.h +++ b/arch/x86/include/asm/fixmap_32.h | |||
| @@ -28,10 +28,8 @@ extern unsigned long __FIXADDR_TOP; | |||
| 28 | #include <asm/acpi.h> | 28 | #include <asm/acpi.h> |
| 29 | #include <asm/apicdef.h> | 29 | #include <asm/apicdef.h> |
| 30 | #include <asm/page.h> | 30 | #include <asm/page.h> |
| 31 | #ifdef CONFIG_HIGHMEM | ||
| 32 | #include <linux/threads.h> | 31 | #include <linux/threads.h> |
| 33 | #include <asm/kmap_types.h> | 32 | #include <asm/kmap_types.h> |
| 34 | #endif | ||
| 35 | 33 | ||
| 36 | /* | 34 | /* |
| 37 | * Here we define all the compile-time 'special' virtual | 35 | * Here we define all the compile-time 'special' virtual |
| @@ -75,10 +73,8 @@ enum fixed_addresses { | |||
| 75 | #ifdef CONFIG_X86_CYCLONE_TIMER | 73 | #ifdef CONFIG_X86_CYCLONE_TIMER |
| 76 | FIX_CYCLONE_TIMER, /*cyclone timer register*/ | 74 | FIX_CYCLONE_TIMER, /*cyclone timer register*/ |
| 77 | #endif | 75 | #endif |
| 78 | #ifdef CONFIG_HIGHMEM | ||
| 79 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ | 76 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ |
| 80 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, | 77 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, |
| 81 | #endif | ||
| 82 | #ifdef CONFIG_PCI_MMCONFIG | 78 | #ifdef CONFIG_PCI_MMCONFIG |
| 83 | FIX_PCIE_MCFG, | 79 | FIX_PCIE_MCFG, |
| 84 | #endif | 80 | #endif |
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h index a3b3b7c3027b..bf9276bea660 100644 --- a/arch/x86/include/asm/highmem.h +++ b/arch/x86/include/asm/highmem.h | |||
| @@ -25,14 +25,11 @@ | |||
| 25 | #include <asm/kmap_types.h> | 25 | #include <asm/kmap_types.h> |
| 26 | #include <asm/tlbflush.h> | 26 | #include <asm/tlbflush.h> |
| 27 | #include <asm/paravirt.h> | 27 | #include <asm/paravirt.h> |
| 28 | #include <asm/fixmap.h> | ||
| 28 | 29 | ||
| 29 | /* declarations for highmem.c */ | 30 | /* declarations for highmem.c */ |
| 30 | extern unsigned long highstart_pfn, highend_pfn; | 31 | extern unsigned long highstart_pfn, highend_pfn; |
| 31 | 32 | ||
| 32 | extern pte_t *kmap_pte; | ||
| 33 | extern pgprot_t kmap_prot; | ||
| 34 | extern pte_t *pkmap_page_table; | ||
| 35 | |||
| 36 | /* | 33 | /* |
| 37 | * Right now we initialize only a single pte table. It can be extended | 34 | * Right now we initialize only a single pte table. It can be extended |
| 38 | * easily, subsequent pte tables have to be allocated in one physical | 35 | * easily, subsequent pte tables have to be allocated in one physical |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 59f89b434b45..fea4565ff576 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ | 1 | obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ |
| 2 | pat.o pgtable.o gup.o | 2 | pat.o pgtable.o gup.o |
| 3 | 3 | ||
