1*4882a593Smuzhiyun======================== 2*4882a593SmuzhiyunThe io_mapping functions 3*4882a593Smuzhiyun======================== 4*4882a593Smuzhiyun 5*4882a593SmuzhiyunAPI 6*4882a593Smuzhiyun=== 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunThe io_mapping functions in linux/io-mapping.h provide an abstraction for 9*4882a593Smuzhiyunefficiently mapping small regions of an I/O device to the CPU. The initial 10*4882a593Smuzhiyunusage is to support the large graphics aperture on 32-bit processors where 11*4882a593Smuzhiyunioremap_wc cannot be used to statically map the entire aperture to the CPU 12*4882a593Smuzhiyunas it would consume too much of the kernel address space. 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunA mapping object is created during driver initialization using:: 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun struct io_mapping *io_mapping_create_wc(unsigned long base, 17*4882a593Smuzhiyun unsigned long size) 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun'base' is the bus address of the region to be made 20*4882a593Smuzhiyunmappable, while 'size' indicates how large a mapping region to 21*4882a593Smuzhiyunenable. Both are in bytes. 22*4882a593Smuzhiyun 23*4882a593SmuzhiyunThis _wc variant provides a mapping which may only be used 24*4882a593Smuzhiyunwith the io_mapping_map_atomic_wc or io_mapping_map_wc. 25*4882a593Smuzhiyun 26*4882a593SmuzhiyunWith this mapping object, individual pages can be mapped either atomically 27*4882a593Smuzhiyunor not, depending on the necessary scheduling environment. Of course, atomic 28*4882a593Smuzhiyunmaps are more efficient:: 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun void *io_mapping_map_atomic_wc(struct io_mapping *mapping, 31*4882a593Smuzhiyun unsigned long offset) 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun'offset' is the offset within the defined mapping region. 34*4882a593SmuzhiyunAccessing addresses beyond the region specified in the 35*4882a593Smuzhiyuncreation function yields undefined results. Using an offset 36*4882a593Smuzhiyunwhich is not page aligned yields an undefined result. The 37*4882a593Smuzhiyunreturn value points to a single page in CPU address space. 38*4882a593Smuzhiyun 39*4882a593SmuzhiyunThis _wc variant returns a write-combining map to the 40*4882a593Smuzhiyunpage and may only be used with mappings created by 41*4882a593Smuzhiyunio_mapping_create_wc 42*4882a593Smuzhiyun 43*4882a593SmuzhiyunNote that the task may not sleep while holding this page 44*4882a593Smuzhiyunmapped. 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun:: 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun void io_mapping_unmap_atomic(void *vaddr) 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun'vaddr' must be the value returned by the last 51*4882a593Smuzhiyunio_mapping_map_atomic_wc call. This unmaps the specified 52*4882a593Smuzhiyunpage and allows the task to sleep once again. 53*4882a593Smuzhiyun 54*4882a593SmuzhiyunIf you need to sleep while holding the lock, you can use the non-atomic 55*4882a593Smuzhiyunvariant, although they may be significantly slower. 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun:: 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun void *io_mapping_map_wc(struct io_mapping *mapping, 60*4882a593Smuzhiyun unsigned long offset) 61*4882a593Smuzhiyun 62*4882a593SmuzhiyunThis works like io_mapping_map_atomic_wc except it allows 63*4882a593Smuzhiyunthe task to sleep while holding the page mapped. 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun:: 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun void io_mapping_unmap(void *vaddr) 69*4882a593Smuzhiyun 70*4882a593SmuzhiyunThis works like io_mapping_unmap_atomic, except it is used 71*4882a593Smuzhiyunfor pages mapped with io_mapping_map_wc. 72*4882a593Smuzhiyun 73*4882a593SmuzhiyunAt driver close time, the io_mapping object must be freed:: 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun void io_mapping_free(struct io_mapping *mapping) 76*4882a593Smuzhiyun 77*4882a593SmuzhiyunCurrent Implementation 78*4882a593Smuzhiyun====================== 79*4882a593Smuzhiyun 80*4882a593SmuzhiyunThe initial implementation of these functions uses existing mapping 81*4882a593Smuzhiyunmechanisms and so provides only an abstraction layer and no new 82*4882a593Smuzhiyunfunctionality. 83*4882a593Smuzhiyun 84*4882a593SmuzhiyunOn 64-bit processors, io_mapping_create_wc calls ioremap_wc for the whole 85*4882a593Smuzhiyunrange, creating a permanent kernel-visible mapping to the resource. The 86*4882a593Smuzhiyunmap_atomic and map functions add the requested offset to the base of the 87*4882a593Smuzhiyunvirtual address returned by ioremap_wc. 88*4882a593Smuzhiyun 89*4882a593SmuzhiyunOn 32-bit processors with HIGHMEM defined, io_mapping_map_atomic_wc uses 90*4882a593Smuzhiyunkmap_atomic_pfn to map the specified page in an atomic fashion; 91*4882a593Smuzhiyunkmap_atomic_pfn isn't really supposed to be used with device pages, but it 92*4882a593Smuzhiyunprovides an efficient mapping for this usage. 93*4882a593Smuzhiyun 94*4882a593SmuzhiyunOn 32-bit processors without HIGHMEM defined, io_mapping_map_atomic_wc and 95*4882a593Smuzhiyunio_mapping_map_wc both use ioremap_wc, a terribly inefficient function which 96*4882a593Smuzhiyunperforms an IPI to inform all processors about the new mapping. This results 97*4882a593Smuzhiyunin a significant performance penalty. 98