.. | .. |
---|
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. |
---|