Merge tag 'ceph-for-4.13-rc8' of git://github.com/ceph/ceph-client
[linux/fpc-iii.git] / drivers / pci / endpoint / pci-epc-mem.c
blob3a94cc1caf22a6f38e3f7ada7ab702d73d9ab256
1 /**
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/>.
20 #include <linux/io.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
24 #include <linux/pci-epc.h>
26 /**
27 * pci_epc_mem_init() - initialize the pci_epc_mem structure
28 * @epc: the EPC device that invoked pci_epc_mem_init
29 * @phys_base: the physical address of the base
30 * @size: the size of the address space
32 * Invoke to initialize the pci_epc_mem structure used by the
33 * endpoint functions to allocate mapped PCI address.
35 int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
37 int ret;
38 struct pci_epc_mem *mem;
39 unsigned long *bitmap;
40 int pages = size >> PAGE_SHIFT;
41 int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
43 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
44 if (!mem) {
45 ret = -ENOMEM;
46 goto err;
49 bitmap = kzalloc(bitmap_size, GFP_KERNEL);
50 if (!bitmap) {
51 ret = -ENOMEM;
52 goto err_mem;
55 mem->bitmap = bitmap;
56 mem->phys_base = phys_base;
57 mem->pages = pages;
58 mem->size = size;
60 epc->mem = mem;
62 return 0;
64 err_mem:
65 kfree(mem);
67 err:
68 return ret;
70 EXPORT_SYMBOL_GPL(pci_epc_mem_init);
72 /**
73 * pci_epc_mem_exit() - cleanup the pci_epc_mem structure
74 * @epc: the EPC device that invoked pci_epc_mem_exit
76 * Invoke to cleanup the pci_epc_mem structure allocated in
77 * pci_epc_mem_init().
79 void pci_epc_mem_exit(struct pci_epc *epc)
81 struct pci_epc_mem *mem = epc->mem;
83 epc->mem = NULL;
84 kfree(mem->bitmap);
85 kfree(mem);
87 EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
89 /**
90 * pci_epc_mem_alloc_addr() - allocate memory address from EPC addr space
91 * @epc: the EPC device on which memory has to be allocated
92 * @phys_addr: populate the allocated physical address here
93 * @size: the size of the address space that has to be allocated
95 * Invoke to allocate memory address from the EPC address space. This
96 * is usually done to map the remote RC address into the local system.
98 void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
99 phys_addr_t *phys_addr, size_t size)
101 int pageno;
102 void __iomem *virt_addr;
103 struct pci_epc_mem *mem = epc->mem;
104 int order = get_order(size);
106 pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
107 if (pageno < 0)
108 return NULL;
110 *phys_addr = mem->phys_base + (pageno << PAGE_SHIFT);
111 virt_addr = ioremap(*phys_addr, size);
112 if (!virt_addr)
113 bitmap_release_region(mem->bitmap, pageno, order);
115 return virt_addr;
117 EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
120 * pci_epc_mem_free_addr() - free the allocated memory address
121 * @epc: the EPC device on which memory was allocated
122 * @phys_addr: the allocated physical address
123 * @virt_addr: virtual address of the allocated mem space
124 * @size: the size of the allocated address space
126 * Invoke to free the memory allocated using pci_epc_mem_alloc_addr.
128 void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
129 void __iomem *virt_addr, size_t size)
131 int pageno;
132 int order = get_order(size);
133 struct pci_epc_mem *mem = epc->mem;
135 iounmap(virt_addr);
136 pageno = (phys_addr - mem->phys_base) >> PAGE_SHIFT;
137 bitmap_release_region(mem->bitmap, pageno, order);
139 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
141 MODULE_DESCRIPTION("PCI EPC Address Space Management");
142 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
143 MODULE_LICENSE("GPL v2");