1 // SPDX-License-Identifier: GPL-2.0 2 /** 3 * PCI Endpoint *Controller* Address Space Management 4 * 5 * Copyright (C) 2017 Texas Instruments 6 * Author: Kishon Vijay Abraham I <kishon@ti.com> 7 */ 8 9 #include <linux/io.h> 10 #include <linux/module.h> 11 #include <linux/slab.h> 12 13 #include <linux/pci-epc.h> 14 15 /** 16 * pci_epc_mem_get_order() - determine the allocation order of a memory size 17 * @mem: address space of the endpoint controller 18 * @size: the size for which to get the order 19 * 20 * Reimplement get_order() for mem->page_size since the generic get_order 21 * always gets order with a constant PAGE_SIZE. 22 */ 23 static int pci_epc_mem_get_order(struct pci_epc_mem *mem, size_t size) 24 { 25 int order; 26 unsigned int page_shift = ilog2(mem->page_size); 27 28 size--; 29 size >>= page_shift; 30 #if BITS_PER_LONG == 32 31 order = fls(size); 32 #else 33 order = fls64(size); 34 #endif 35 return order; 36 } 37 38 /** 39 * __pci_epc_mem_init() - initialize the pci_epc_mem structure 40 * @epc: the EPC device that invoked pci_epc_mem_init 41 * @phys_base: the physical address of the base 42 * @size: the size of the address space 43 * @page_size: size of each page 44 * 45 * Invoke to initialize the pci_epc_mem structure used by the 46 * endpoint functions to allocate mapped PCI address. 47 */ 48 int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size, 49 size_t page_size) 50 { 51 int ret; 52 struct pci_epc_mem *mem; 53 unsigned long *bitmap; 54 unsigned int page_shift; 55 int pages; 56 int bitmap_size; 57 58 if (page_size < PAGE_SIZE) 59 page_size = PAGE_SIZE; 60 61 page_shift = ilog2(page_size); 62 pages = size >> page_shift; 63 bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); 64 65 mem = kzalloc(sizeof(*mem), GFP_KERNEL); 66 if (!mem) { 67 ret = -ENOMEM; 68 goto err; 69 } 70 71 bitmap = kzalloc(bitmap_size, GFP_KERNEL); 72 if (!bitmap) { 73 ret = -ENOMEM; 74 goto err_mem; 75 } 76 77 mem->bitmap = bitmap; 78 mem->phys_base = phys_base; 79 mem->page_size = page_size; 80 mem->pages = pages; 81 mem->size = size; 82 83 epc->mem = mem; 84 85 return 0; 86 87 err_mem: 88 kfree(mem); 89 90 err: 91 return ret; 92 } 93 EXPORT_SYMBOL_GPL(__pci_epc_mem_init); 94 95 /** 96 * pci_epc_mem_exit() - cleanup the pci_epc_mem structure 97 * @epc: the EPC device that invoked pci_epc_mem_exit 98 * 99 * Invoke to cleanup the pci_epc_mem structure allocated in 100 * pci_epc_mem_init(). 101 */ 102 void pci_epc_mem_exit(struct pci_epc *epc) 103 { 104 struct pci_epc_mem *mem = epc->mem; 105 106 epc->mem = NULL; 107 kfree(mem->bitmap); 108 kfree(mem); 109 } 110 EXPORT_SYMBOL_GPL(pci_epc_mem_exit); 111 112 /** 113 * pci_epc_mem_alloc_addr() - allocate memory address from EPC addr space 114 * @epc: the EPC device on which memory has to be allocated 115 * @phys_addr: populate the allocated physical address here 116 * @size: the size of the address space that has to be allocated 117 * 118 * Invoke to allocate memory address from the EPC address space. This 119 * is usually done to map the remote RC address into the local system. 120 */ 121 void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, 122 phys_addr_t *phys_addr, size_t size) 123 { 124 int pageno; 125 void __iomem *virt_addr; 126 struct pci_epc_mem *mem = epc->mem; 127 unsigned int page_shift = ilog2(mem->page_size); 128 int order; 129 130 size = ALIGN(size, mem->page_size); 131 order = pci_epc_mem_get_order(mem, size); 132 133 pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order); 134 if (pageno < 0) 135 return NULL; 136 137 *phys_addr = mem->phys_base + (pageno << page_shift); 138 virt_addr = ioremap(*phys_addr, size); 139 if (!virt_addr) 140 bitmap_release_region(mem->bitmap, pageno, order); 141 142 return virt_addr; 143 } 144 EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr); 145 146 /** 147 * pci_epc_mem_free_addr() - free the allocated memory address 148 * @epc: the EPC device on which memory was allocated 149 * @phys_addr: the allocated physical address 150 * @virt_addr: virtual address of the allocated mem space 151 * @size: the size of the allocated address space 152 * 153 * Invoke to free the memory allocated using pci_epc_mem_alloc_addr. 154 */ 155 void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr, 156 void __iomem *virt_addr, size_t size) 157 { 158 int pageno; 159 struct pci_epc_mem *mem = epc->mem; 160 unsigned int page_shift = ilog2(mem->page_size); 161 int order; 162 163 iounmap(virt_addr); 164 pageno = (phys_addr - mem->phys_base) >> page_shift; 165 size = ALIGN(size, mem->page_size); 166 order = pci_epc_mem_get_order(mem, size); 167 bitmap_release_region(mem->bitmap, pageno, order); 168 } 169 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr); 170 171 MODULE_DESCRIPTION("PCI EPC Address Space Management"); 172 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); 173 MODULE_LICENSE("GPL v2"); 174