18c2ecf20Sopenharmony_ci======================== 28c2ecf20Sopenharmony_ciThe io_mapping functions 38c2ecf20Sopenharmony_ci======================== 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ciAPI 68c2ecf20Sopenharmony_ci=== 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ciThe io_mapping functions in linux/io-mapping.h provide an abstraction for 98c2ecf20Sopenharmony_ciefficiently mapping small regions of an I/O device to the CPU. The initial 108c2ecf20Sopenharmony_ciusage is to support the large graphics aperture on 32-bit processors where 118c2ecf20Sopenharmony_ciioremap_wc cannot be used to statically map the entire aperture to the CPU 128c2ecf20Sopenharmony_cias it would consume too much of the kernel address space. 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciA mapping object is created during driver initialization using:: 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci struct io_mapping *io_mapping_create_wc(unsigned long base, 178c2ecf20Sopenharmony_ci unsigned long size) 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci'base' is the bus address of the region to be made 208c2ecf20Sopenharmony_cimappable, while 'size' indicates how large a mapping region to 218c2ecf20Sopenharmony_cienable. Both are in bytes. 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciThis _wc variant provides a mapping which may only be used 248c2ecf20Sopenharmony_ciwith the io_mapping_map_atomic_wc or io_mapping_map_wc. 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciWith this mapping object, individual pages can be mapped either atomically 278c2ecf20Sopenharmony_cior not, depending on the necessary scheduling environment. Of course, atomic 288c2ecf20Sopenharmony_cimaps are more efficient:: 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci void *io_mapping_map_atomic_wc(struct io_mapping *mapping, 318c2ecf20Sopenharmony_ci unsigned long offset) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci'offset' is the offset within the defined mapping region. 348c2ecf20Sopenharmony_ciAccessing addresses beyond the region specified in the 358c2ecf20Sopenharmony_cicreation function yields undefined results. Using an offset 368c2ecf20Sopenharmony_ciwhich is not page aligned yields an undefined result. The 378c2ecf20Sopenharmony_cireturn value points to a single page in CPU address space. 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciThis _wc variant returns a write-combining map to the 408c2ecf20Sopenharmony_cipage and may only be used with mappings created by 418c2ecf20Sopenharmony_ciio_mapping_create_wc 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciNote that the task may not sleep while holding this page 448c2ecf20Sopenharmony_cimapped. 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci:: 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci void io_mapping_unmap_atomic(void *vaddr) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci'vaddr' must be the value returned by the last 518c2ecf20Sopenharmony_ciio_mapping_map_atomic_wc call. This unmaps the specified 528c2ecf20Sopenharmony_cipage and allows the task to sleep once again. 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ciIf you need to sleep while holding the lock, you can use the non-atomic 558c2ecf20Sopenharmony_civariant, although they may be significantly slower. 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci:: 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci void *io_mapping_map_wc(struct io_mapping *mapping, 608c2ecf20Sopenharmony_ci unsigned long offset) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciThis works like io_mapping_map_atomic_wc except it allows 638c2ecf20Sopenharmony_cithe task to sleep while holding the page mapped. 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci:: 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci void io_mapping_unmap(void *vaddr) 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciThis works like io_mapping_unmap_atomic, except it is used 718c2ecf20Sopenharmony_cifor pages mapped with io_mapping_map_wc. 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciAt driver close time, the io_mapping object must be freed:: 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci void io_mapping_free(struct io_mapping *mapping) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ciCurrent Implementation 788c2ecf20Sopenharmony_ci====================== 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciThe initial implementation of these functions uses existing mapping 818c2ecf20Sopenharmony_cimechanisms and so provides only an abstraction layer and no new 828c2ecf20Sopenharmony_cifunctionality. 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ciOn 64-bit processors, io_mapping_create_wc calls ioremap_wc for the whole 858c2ecf20Sopenharmony_cirange, creating a permanent kernel-visible mapping to the resource. The 868c2ecf20Sopenharmony_cimap_atomic and map functions add the requested offset to the base of the 878c2ecf20Sopenharmony_civirtual address returned by ioremap_wc. 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ciOn 32-bit processors with HIGHMEM defined, io_mapping_map_atomic_wc uses 908c2ecf20Sopenharmony_cikmap_atomic_pfn to map the specified page in an atomic fashion; 918c2ecf20Sopenharmony_cikmap_atomic_pfn isn't really supposed to be used with device pages, but it 928c2ecf20Sopenharmony_ciprovides an efficient mapping for this usage. 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ciOn 32-bit processors without HIGHMEM defined, io_mapping_map_atomic_wc and 958c2ecf20Sopenharmony_ciio_mapping_map_wc both use ioremap_wc, a terribly inefficient function which 968c2ecf20Sopenharmony_ciperforms an IPI to inform all processors about the new mapping. This results 978c2ecf20Sopenharmony_ciin a significant performance penalty. 98