| .. | .. |
|---|
| 20 | 20 | mappable, while 'size' indicates how large a mapping region to |
|---|
| 21 | 21 | enable. Both are in bytes. |
|---|
| 22 | 22 | |
|---|
| 23 | | -This _wc variant provides a mapping which may only be used with |
|---|
| 24 | | -io_mapping_map_local_wc() or io_mapping_map_wc(). |
|---|
| 23 | +This _wc variant provides a mapping which may only be used |
|---|
| 24 | +with the io_mapping_map_atomic_wc or io_mapping_map_wc. |
|---|
| 25 | 25 | |
|---|
| 26 | | -With this mapping object, individual pages can be mapped either temporarily |
|---|
| 27 | | -or long term, depending on the requirements. Of course, temporary maps are |
|---|
| 28 | | -more efficient. |
|---|
| 26 | +With this mapping object, individual pages can be mapped either atomically |
|---|
| 27 | +or not, depending on the necessary scheduling environment. Of course, atomic |
|---|
| 28 | +maps are more efficient:: |
|---|
| 29 | 29 | |
|---|
| 30 | | - void *io_mapping_map_local_wc(struct io_mapping *mapping, |
|---|
| 31 | | - unsigned long offset) |
|---|
| 30 | + void *io_mapping_map_atomic_wc(struct io_mapping *mapping, |
|---|
| 31 | + unsigned long offset) |
|---|
| 32 | 32 | |
|---|
| 33 | | -'offset' is the offset within the defined mapping region. Accessing |
|---|
| 34 | | -addresses beyond the region specified in the creation function yields |
|---|
| 35 | | -undefined results. Using an offset which is not page aligned yields an |
|---|
| 36 | | -undefined result. The return value points to a single page in CPU address |
|---|
| 37 | | -space. |
|---|
| 33 | +'offset' is the offset within the defined mapping region. |
|---|
| 34 | +Accessing addresses beyond the region specified in the |
|---|
| 35 | +creation function yields undefined results. Using an offset |
|---|
| 36 | +which is not page aligned yields an undefined result. The |
|---|
| 37 | +return value points to a single page in CPU address space. |
|---|
| 38 | 38 | |
|---|
| 39 | | -This _wc variant returns a write-combining map to the page and may only be |
|---|
| 40 | | -used with mappings created by io_mapping_create_wc() |
|---|
| 39 | +This _wc variant returns a write-combining map to the |
|---|
| 40 | +page and may only be used with mappings created by |
|---|
| 41 | +io_mapping_create_wc |
|---|
| 41 | 42 | |
|---|
| 42 | | -Temporary mappings are only valid in the context of the caller. The mapping |
|---|
| 43 | | -is not guaranteed to be globaly visible. |
|---|
| 43 | +Note that the task may not sleep while holding this page |
|---|
| 44 | +mapped. |
|---|
| 44 | 45 | |
|---|
| 45 | | -io_mapping_map_local_wc() has a side effect on X86 32bit as it disables |
|---|
| 46 | | -migration to make the mapping code work. No caller can rely on this side |
|---|
| 47 | | -effect. |
|---|
| 46 | +:: |
|---|
| 48 | 47 | |
|---|
| 49 | | -Nested mappings need to be undone in reverse order because the mapping |
|---|
| 50 | | -code uses a stack for keeping track of them:: |
|---|
| 48 | + void io_mapping_unmap_atomic(void *vaddr) |
|---|
| 51 | 49 | |
|---|
| 52 | | - addr1 = io_mapping_map_local_wc(map1, offset1); |
|---|
| 53 | | - addr2 = io_mapping_map_local_wc(map2, offset2); |
|---|
| 54 | | - ... |
|---|
| 55 | | - io_mapping_unmap_local(addr2); |
|---|
| 56 | | - io_mapping_unmap_local(addr1); |
|---|
| 50 | +'vaddr' must be the value returned by the last |
|---|
| 51 | +io_mapping_map_atomic_wc call. This unmaps the specified |
|---|
| 52 | +page and allows the task to sleep once again. |
|---|
| 57 | 53 | |
|---|
| 58 | | -The mappings are released with:: |
|---|
| 54 | +If you need to sleep while holding the lock, you can use the non-atomic |
|---|
| 55 | +variant, although they may be significantly slower. |
|---|
| 59 | 56 | |
|---|
| 60 | | - void io_mapping_unmap_local(void *vaddr) |
|---|
| 61 | | - |
|---|
| 62 | | -'vaddr' must be the value returned by the last io_mapping_map_local_wc() |
|---|
| 63 | | -call. This unmaps the specified mapping and undoes eventual side effects of |
|---|
| 64 | | -the mapping function. |
|---|
| 65 | | - |
|---|
| 66 | | -If you need to sleep while holding a mapping, you can use the regular |
|---|
| 67 | | -variant, although this may be significantly slower:: |
|---|
| 57 | +:: |
|---|
| 68 | 58 | |
|---|
| 69 | 59 | void *io_mapping_map_wc(struct io_mapping *mapping, |
|---|
| 70 | 60 | unsigned long offset) |
|---|
| 71 | 61 | |
|---|
| 72 | | -This works like io_mapping_map_local_wc() except it has no side effects and |
|---|
| 73 | | -the pointer is globaly visible. |
|---|
| 62 | +This works like io_mapping_map_atomic_wc except it allows |
|---|
| 63 | +the task to sleep while holding the page mapped. |
|---|
| 74 | 64 | |
|---|
| 75 | | -The mappings are released with:: |
|---|
| 65 | + |
|---|
| 66 | +:: |
|---|
| 76 | 67 | |
|---|
| 77 | 68 | void io_mapping_unmap(void *vaddr) |
|---|
| 78 | 69 | |
|---|
| 79 | | -Use for pages mapped with io_mapping_map_wc(). |
|---|
| 70 | +This works like io_mapping_unmap_atomic, except it is used |
|---|
| 71 | +for pages mapped with io_mapping_map_wc. |
|---|
| 80 | 72 | |
|---|
| 81 | 73 | At driver close time, the io_mapping object must be freed:: |
|---|
| 82 | 74 | |
|---|
| 83 | 75 | void io_mapping_free(struct io_mapping *mapping) |
|---|
| 76 | + |
|---|
| 77 | +Current Implementation |
|---|
| 78 | +====================== |
|---|
| 79 | + |
|---|
| 80 | +The initial implementation of these functions uses existing mapping |
|---|
| 81 | +mechanisms and so provides only an abstraction layer and no new |
|---|
| 82 | +functionality. |
|---|
| 83 | + |
|---|
| 84 | +On 64-bit processors, io_mapping_create_wc calls ioremap_wc for the whole |
|---|
| 85 | +range, creating a permanent kernel-visible mapping to the resource. The |
|---|
| 86 | +map_atomic and map functions add the requested offset to the base of the |
|---|
| 87 | +virtual address returned by ioremap_wc. |
|---|
| 88 | + |
|---|
| 89 | +On 32-bit processors with HIGHMEM defined, io_mapping_map_atomic_wc uses |
|---|
| 90 | +kmap_atomic_pfn to map the specified page in an atomic fashion; |
|---|
| 91 | +kmap_atomic_pfn isn't really supposed to be used with device pages, but it |
|---|
| 92 | +provides an efficient mapping for this usage. |
|---|
| 93 | + |
|---|
| 94 | +On 32-bit processors without HIGHMEM defined, io_mapping_map_atomic_wc and |
|---|
| 95 | +io_mapping_map_wc both use ioremap_wc, a terribly inefficient function which |
|---|
| 96 | +performs an IPI to inform all processors about the new mapping. This results |
|---|
| 97 | +in a significant performance penalty. |
|---|