]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/pci/endpoint/pci-epc-mem.c
2 * PCI Endpoint *Controller* Address Space Management
4 * Copyright (C) 2017 Texas Instruments
5 * Author: Kishon Vijay Abraham I <kishon@ti.com>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 of
9 * the License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/module.h>
22 #include <linux/slab.h>
24 #include <linux/pci-epc.h>
27 * pci_epc_mem_get_order() - determine the allocation order of a memory size
28 * @mem: address space of the endpoint controller
29 * @size: the size for which to get the order
31 * Reimplement get_order() for mem->page_size since the generic get_order
32 * always gets order with a constant PAGE_SIZE.
34 static int pci_epc_mem_get_order(struct pci_epc_mem
*mem
, size_t size
)
37 unsigned int page_shift
= ilog2(mem
->page_size
);
41 #if BITS_PER_LONG == 32
50 * __pci_epc_mem_init() - initialize the pci_epc_mem structure
51 * @epc: the EPC device that invoked pci_epc_mem_init
52 * @phys_base: the physical address of the base
53 * @size: the size of the address space
54 * @page_size: size of each page
56 * Invoke to initialize the pci_epc_mem structure used by the
57 * endpoint functions to allocate mapped PCI address.
59 int __pci_epc_mem_init(struct pci_epc
*epc
, phys_addr_t phys_base
, size_t size
,
63 struct pci_epc_mem
*mem
;
64 unsigned long *bitmap
;
65 unsigned int page_shift
;
69 if (page_size
< PAGE_SIZE
)
70 page_size
= PAGE_SIZE
;
72 page_shift
= ilog2(page_size
);
73 pages
= size
>> page_shift
;
74 bitmap_size
= BITS_TO_LONGS(pages
) * sizeof(long);
76 mem
= kzalloc(sizeof(*mem
), GFP_KERNEL
);
82 bitmap
= kzalloc(bitmap_size
, GFP_KERNEL
);
89 mem
->phys_base
= phys_base
;
90 mem
->page_size
= page_size
;
104 EXPORT_SYMBOL_GPL(__pci_epc_mem_init
);
107 * pci_epc_mem_exit() - cleanup the pci_epc_mem structure
108 * @epc: the EPC device that invoked pci_epc_mem_exit
110 * Invoke to cleanup the pci_epc_mem structure allocated in
111 * pci_epc_mem_init().
113 void pci_epc_mem_exit(struct pci_epc
*epc
)
115 struct pci_epc_mem
*mem
= epc
->mem
;
121 EXPORT_SYMBOL_GPL(pci_epc_mem_exit
);
124 * pci_epc_mem_alloc_addr() - allocate memory address from EPC addr space
125 * @epc: the EPC device on which memory has to be allocated
126 * @phys_addr: populate the allocated physical address here
127 * @size: the size of the address space that has to be allocated
129 * Invoke to allocate memory address from the EPC address space. This
130 * is usually done to map the remote RC address into the local system.
132 void __iomem
*pci_epc_mem_alloc_addr(struct pci_epc
*epc
,
133 phys_addr_t
*phys_addr
, size_t size
)
136 void __iomem
*virt_addr
;
137 struct pci_epc_mem
*mem
= epc
->mem
;
138 unsigned int page_shift
= ilog2(mem
->page_size
);
141 size
= ALIGN(size
, mem
->page_size
);
142 order
= pci_epc_mem_get_order(mem
, size
);
144 pageno
= bitmap_find_free_region(mem
->bitmap
, mem
->pages
, order
);
148 *phys_addr
= mem
->phys_base
+ (pageno
<< page_shift
);
149 virt_addr
= ioremap(*phys_addr
, size
);
151 bitmap_release_region(mem
->bitmap
, pageno
, order
);
155 EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr
);
158 * pci_epc_mem_free_addr() - free the allocated memory address
159 * @epc: the EPC device on which memory was allocated
160 * @phys_addr: the allocated physical address
161 * @virt_addr: virtual address of the allocated mem space
162 * @size: the size of the allocated address space
164 * Invoke to free the memory allocated using pci_epc_mem_alloc_addr.
166 void pci_epc_mem_free_addr(struct pci_epc
*epc
, phys_addr_t phys_addr
,
167 void __iomem
*virt_addr
, size_t size
)
170 struct pci_epc_mem
*mem
= epc
->mem
;
171 unsigned int page_shift
= ilog2(mem
->page_size
);
175 pageno
= (phys_addr
- mem
->phys_base
) >> page_shift
;
176 size
= ALIGN(size
, mem
->page_size
);
177 order
= pci_epc_mem_get_order(mem
, size
);
178 bitmap_release_region(mem
->bitmap
, pageno
, order
);
180 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr
);
182 MODULE_DESCRIPTION("PCI EPC Address Space Management");
183 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
184 MODULE_LICENSE("GPL v2");