diff options
author | Zhao Qiang <qiang.zhao@freescale.com> | 2015-11-29 21:48:54 -0500 |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2015-12-22 18:10:18 -0500 |
commit | 0e6e01ff694ee222acc5a9184211678473c948e3 (patch) | |
tree | b3c1809b02b0b8accf5b7b8ca82c632842799e7a | |
parent | b26981c8f743d3cb64a6907eb1f5c6c4ba6ca672 (diff) |
CPM/QE: use genalloc to manage CPM/QE muram
Use genalloc to manage CPM/QE muram instead of rheap.
Signed-off-by: Zhao Qiang <qiang.zhao@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
-rw-r--r-- | arch/powerpc/include/asm/cpm.h | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/Kconfig | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/cpm_common.c | 126 | ||||
-rw-r--r-- | lib/genalloc.c | 2 |
4 files changed, 94 insertions, 41 deletions
diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index 4398a6cdcf53..46e86b50abf3 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __CPM_H | 2 | #define __CPM_H |
3 | 3 | ||
4 | #include <linux/compiler.h> | 4 | #include <linux/compiler.h> |
5 | #include <linux/genalloc.h> | ||
5 | #include <linux/types.h> | 6 | #include <linux/types.h> |
6 | #include <linux/errno.h> | 7 | #include <linux/errno.h> |
7 | #include <linux/of.h> | 8 | #include <linux/of.h> |
@@ -161,6 +162,8 @@ int cpm_muram_init(void); | |||
161 | unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); | 162 | unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); |
162 | int cpm_muram_free(unsigned long offset); | 163 | int cpm_muram_free(unsigned long offset); |
163 | unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); | 164 | unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); |
165 | unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo, | ||
166 | void *data); | ||
164 | void __iomem *cpm_muram_addr(unsigned long offset); | 167 | void __iomem *cpm_muram_addr(unsigned long offset); |
165 | unsigned long cpm_muram_offset(void __iomem *addr); | 168 | unsigned long cpm_muram_offset(void __iomem *addr); |
166 | dma_addr_t cpm_muram_dma(void __iomem *addr); | 169 | dma_addr_t cpm_muram_dma(void __iomem *addr); |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index b7f9c408bf24..57069eb8f093 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -275,7 +275,7 @@ config TAU_AVERAGE | |||
275 | config QUICC_ENGINE | 275 | config QUICC_ENGINE |
276 | bool "Freescale QUICC Engine (QE) Support" | 276 | bool "Freescale QUICC Engine (QE) Support" |
277 | depends on FSL_SOC && PPC32 | 277 | depends on FSL_SOC && PPC32 |
278 | select PPC_LIB_RHEAP | 278 | select GENERIC_ALLOCATOR |
279 | select CRC32 | 279 | select CRC32 |
280 | help | 280 | help |
281 | The QUICC Engine (QE) is a new generation of communications | 281 | The QUICC Engine (QE) is a new generation of communications |
@@ -295,7 +295,6 @@ config CPM2 | |||
295 | bool "Enable support for the CPM2 (Communications Processor Module)" | 295 | bool "Enable support for the CPM2 (Communications Processor Module)" |
296 | depends on (FSL_SOC_BOOKE && PPC32) || 8260 | 296 | depends on (FSL_SOC_BOOKE && PPC32) || 8260 |
297 | select CPM | 297 | select CPM |
298 | select PPC_LIB_RHEAP | ||
299 | select PPC_PCI_CHOICE | 298 | select PPC_PCI_CHOICE |
300 | select ARCH_REQUIRE_GPIOLIB | 299 | select ARCH_REQUIRE_GPIOLIB |
301 | help | 300 | help |
@@ -325,6 +324,7 @@ config FSL_ULI1575 | |||
325 | 324 | ||
326 | config CPM | 325 | config CPM |
327 | bool | 326 | bool |
327 | select GENERIC_ALLOCATOR | ||
328 | 328 | ||
329 | config OF_RTC | 329 | config OF_RTC |
330 | bool | 330 | bool |
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index e00a5ee58fd7..fcc83cd9cc2f 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * published by the Free Software Foundation. | 17 | * published by the Free Software Foundation. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/genalloc.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
22 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
@@ -27,7 +28,6 @@ | |||
27 | 28 | ||
28 | #include <asm/udbg.h> | 29 | #include <asm/udbg.h> |
29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
30 | #include <asm/rheap.h> | ||
31 | #include <asm/cpm.h> | 31 | #include <asm/cpm.h> |
32 | 32 | ||
33 | #include <mm/mmu_decl.h> | 33 | #include <mm/mmu_decl.h> |
@@ -65,14 +65,22 @@ void __init udbg_init_cpm(void) | |||
65 | } | 65 | } |
66 | #endif | 66 | #endif |
67 | 67 | ||
68 | static struct gen_pool *muram_pool; | ||
68 | static spinlock_t cpm_muram_lock; | 69 | static spinlock_t cpm_muram_lock; |
69 | static rh_block_t cpm_boot_muram_rh_block[16]; | ||
70 | static rh_info_t cpm_muram_info; | ||
71 | static u8 __iomem *muram_vbase; | 70 | static u8 __iomem *muram_vbase; |
72 | static phys_addr_t muram_pbase; | 71 | static phys_addr_t muram_pbase; |
73 | 72 | ||
74 | /* Max address size we deal with */ | 73 | struct muram_block { |
74 | struct list_head head; | ||
75 | unsigned long start; | ||
76 | int size; | ||
77 | }; | ||
78 | |||
79 | static LIST_HEAD(muram_block_list); | ||
80 | |||
81 | /* max address size we deal with */ | ||
75 | #define OF_MAX_ADDR_CELLS 4 | 82 | #define OF_MAX_ADDR_CELLS 4 |
83 | #define GENPOOL_OFFSET (4096 * 8) | ||
76 | 84 | ||
77 | int cpm_muram_init(void) | 85 | int cpm_muram_init(void) |
78 | { | 86 | { |
@@ -87,50 +95,51 @@ int cpm_muram_init(void) | |||
87 | return 0; | 95 | return 0; |
88 | 96 | ||
89 | spin_lock_init(&cpm_muram_lock); | 97 | spin_lock_init(&cpm_muram_lock); |
90 | /* initialize the info header */ | ||
91 | rh_init(&cpm_muram_info, 1, | ||
92 | sizeof(cpm_boot_muram_rh_block) / | ||
93 | sizeof(cpm_boot_muram_rh_block[0]), | ||
94 | cpm_boot_muram_rh_block); | ||
95 | |||
96 | np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data"); | 98 | np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data"); |
97 | if (!np) { | 99 | if (!np) { |
98 | /* try legacy bindings */ | 100 | /* try legacy bindings */ |
99 | np = of_find_node_by_name(NULL, "data-only"); | 101 | np = of_find_node_by_name(NULL, "data-only"); |
100 | if (!np) { | 102 | if (!np) { |
101 | printk(KERN_ERR "Cannot find CPM muram data node"); | 103 | pr_err("Cannot find CPM muram data node"); |
102 | ret = -ENODEV; | 104 | ret = -ENODEV; |
103 | goto out; | 105 | goto out_muram; |
104 | } | 106 | } |
105 | } | 107 | } |
106 | 108 | ||
109 | muram_pool = gen_pool_create(0, -1); | ||
107 | muram_pbase = of_translate_address(np, zero); | 110 | muram_pbase = of_translate_address(np, zero); |
108 | if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) { | 111 | if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) { |
109 | printk(KERN_ERR "Cannot translate zero through CPM muram node"); | 112 | pr_err("Cannot translate zero through CPM muram node"); |
110 | ret = -ENODEV; | 113 | ret = -ENODEV; |
111 | goto out; | 114 | goto out_pool; |
112 | } | 115 | } |
113 | 116 | ||
114 | while (of_address_to_resource(np, i++, &r) == 0) { | 117 | while (of_address_to_resource(np, i++, &r) == 0) { |
115 | if (r.end > max) | 118 | if (r.end > max) |
116 | max = r.end; | 119 | max = r.end; |
117 | 120 | ret = gen_pool_add(muram_pool, r.start - muram_pbase + | |
118 | rh_attach_region(&cpm_muram_info, r.start - muram_pbase, | 121 | GENPOOL_OFFSET, resource_size(&r), -1); |
119 | resource_size(&r)); | 122 | if (ret) { |
123 | pr_err("QE: couldn't add muram to pool!\n"); | ||
124 | goto out_pool; | ||
125 | } | ||
120 | } | 126 | } |
121 | 127 | ||
122 | muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1); | 128 | muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1); |
123 | if (!muram_vbase) { | 129 | if (!muram_vbase) { |
124 | printk(KERN_ERR "Cannot map CPM muram"); | 130 | pr_err("Cannot map QE muram"); |
125 | ret = -ENOMEM; | 131 | ret = -ENOMEM; |
132 | goto out_pool; | ||
126 | } | 133 | } |
127 | 134 | goto out_muram; | |
128 | out: | 135 | out_pool: |
136 | gen_pool_destroy(muram_pool); | ||
137 | out_muram: | ||
129 | of_node_put(np); | 138 | of_node_put(np); |
130 | return ret; | 139 | return ret; |
131 | } | 140 | } |
132 | 141 | ||
133 | /** | 142 | /* |
134 | * cpm_muram_alloc - allocate the requested size worth of multi-user ram | 143 | * cpm_muram_alloc - allocate the requested size worth of multi-user ram |
135 | * @size: number of bytes to allocate | 144 | * @size: number of bytes to allocate |
136 | * @align: requested alignment, in bytes | 145 | * @align: requested alignment, in bytes |
@@ -143,14 +152,13 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align) | |||
143 | { | 152 | { |
144 | unsigned long start; | 153 | unsigned long start; |
145 | unsigned long flags; | 154 | unsigned long flags; |
155 | struct genpool_data_align muram_pool_data; | ||
146 | 156 | ||
147 | spin_lock_irqsave(&cpm_muram_lock, flags); | 157 | spin_lock_irqsave(&cpm_muram_lock, flags); |
148 | cpm_muram_info.alignment = align; | 158 | muram_pool_data.align = align; |
149 | start = rh_alloc(&cpm_muram_info, size, "commproc"); | 159 | start = cpm_muram_alloc_common(size, gen_pool_first_fit_align, |
150 | if (!IS_ERR_VALUE(start)) | 160 | &muram_pool_data); |
151 | memset_io(cpm_muram_addr(start), 0, size); | ||
152 | spin_unlock_irqrestore(&cpm_muram_lock, flags); | 161 | spin_unlock_irqrestore(&cpm_muram_lock, flags); |
153 | |||
154 | return start; | 162 | return start; |
155 | } | 163 | } |
156 | EXPORT_SYMBOL(cpm_muram_alloc); | 164 | EXPORT_SYMBOL(cpm_muram_alloc); |
@@ -161,23 +169,31 @@ EXPORT_SYMBOL(cpm_muram_alloc); | |||
161 | */ | 169 | */ |
162 | int cpm_muram_free(unsigned long offset) | 170 | int cpm_muram_free(unsigned long offset) |
163 | { | 171 | { |
164 | int ret; | ||
165 | unsigned long flags; | 172 | unsigned long flags; |
173 | int size; | ||
174 | struct muram_block *tmp; | ||
166 | 175 | ||
176 | size = 0; | ||
167 | spin_lock_irqsave(&cpm_muram_lock, flags); | 177 | spin_lock_irqsave(&cpm_muram_lock, flags); |
168 | ret = rh_free(&cpm_muram_info, offset); | 178 | list_for_each_entry(tmp, &muram_block_list, head) { |
179 | if (tmp->start == offset) { | ||
180 | size = tmp->size; | ||
181 | list_del(&tmp->head); | ||
182 | kfree(tmp); | ||
183 | break; | ||
184 | } | ||
185 | } | ||
186 | gen_pool_free(muram_pool, offset + GENPOOL_OFFSET, size); | ||
169 | spin_unlock_irqrestore(&cpm_muram_lock, flags); | 187 | spin_unlock_irqrestore(&cpm_muram_lock, flags); |
170 | 188 | return size; | |
171 | return ret; | ||
172 | } | 189 | } |
173 | EXPORT_SYMBOL(cpm_muram_free); | 190 | EXPORT_SYMBOL(cpm_muram_free); |
174 | 191 | ||
175 | /** | 192 | /* |
176 | * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram | 193 | * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram |
177 | * @offset: the offset into the muram area to reserve | 194 | * @offset: offset of allocation start address |
178 | * @size: the number of bytes to reserve | 195 | * @size: number of bytes to allocate |
179 | * | 196 | * This function returns an offset into the muram area |
180 | * This function returns "start" on success, -ENOMEM on failure. | ||
181 | * Use cpm_dpram_addr() to get the virtual address of the area. | 197 | * Use cpm_dpram_addr() to get the virtual address of the area. |
182 | * Use cpm_muram_free() to free the allocation. | 198 | * Use cpm_muram_free() to free the allocation. |
183 | */ | 199 | */ |
@@ -185,16 +201,50 @@ unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) | |||
185 | { | 201 | { |
186 | unsigned long start; | 202 | unsigned long start; |
187 | unsigned long flags; | 203 | unsigned long flags; |
204 | struct genpool_data_fixed muram_pool_data_fixed; | ||
188 | 205 | ||
189 | spin_lock_irqsave(&cpm_muram_lock, flags); | 206 | spin_lock_irqsave(&cpm_muram_lock, flags); |
190 | cpm_muram_info.alignment = 1; | 207 | muram_pool_data_fixed.offset = offset + GENPOOL_OFFSET; |
191 | start = rh_alloc_fixed(&cpm_muram_info, offset, size, "commproc"); | 208 | start = cpm_muram_alloc_common(size, gen_pool_fixed_alloc, |
209 | &muram_pool_data_fixed); | ||
192 | spin_unlock_irqrestore(&cpm_muram_lock, flags); | 210 | spin_unlock_irqrestore(&cpm_muram_lock, flags); |
193 | |||
194 | return start; | 211 | return start; |
195 | } | 212 | } |
196 | EXPORT_SYMBOL(cpm_muram_alloc_fixed); | 213 | EXPORT_SYMBOL(cpm_muram_alloc_fixed); |
197 | 214 | ||
215 | /* | ||
216 | * cpm_muram_alloc_common - cpm_muram_alloc common code | ||
217 | * @size: number of bytes to allocate | ||
218 | * @algo: algorithm for alloc. | ||
219 | * @data: data for genalloc's algorithm. | ||
220 | * | ||
221 | * This function returns an offset into the muram area. | ||
222 | */ | ||
223 | unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo, | ||
224 | void *data) | ||
225 | { | ||
226 | struct muram_block *entry; | ||
227 | unsigned long start; | ||
228 | |||
229 | start = gen_pool_alloc_algo(muram_pool, size, algo, data); | ||
230 | if (!start) | ||
231 | goto out2; | ||
232 | start = start - GENPOOL_OFFSET; | ||
233 | memset_io(cpm_muram_addr(start), 0, size); | ||
234 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
235 | if (!entry) | ||
236 | goto out1; | ||
237 | entry->start = start; | ||
238 | entry->size = size; | ||
239 | list_add(&entry->head, &muram_block_list); | ||
240 | |||
241 | return start; | ||
242 | out1: | ||
243 | gen_pool_free(muram_pool, start, size); | ||
244 | out2: | ||
245 | return (unsigned long)-ENOMEM; | ||
246 | } | ||
247 | |||
198 | /** | 248 | /** |
199 | * cpm_muram_addr - turn a muram offset into a virtual address | 249 | * cpm_muram_addr - turn a muram offset into a virtual address |
200 | * @offset: muram offset to convert | 250 | * @offset: muram offset to convert |
diff --git a/lib/genalloc.c b/lib/genalloc.c index 5ec83cd93284..0a1139644d32 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c | |||
@@ -576,7 +576,7 @@ unsigned long gen_pool_fixed_alloc(unsigned long *map, unsigned long size, | |||
576 | fixed_data = data; | 576 | fixed_data = data; |
577 | order = pool->min_alloc_order; | 577 | order = pool->min_alloc_order; |
578 | offset_bit = fixed_data->offset >> order; | 578 | offset_bit = fixed_data->offset >> order; |
579 | if (WARN_ON(fixed_data->offset & (1UL << order - 1))) | 579 | if (WARN_ON(fixed_data->offset & ((1UL << order) - 1))) |
580 | return size; | 580 | return size; |
581 | 581 | ||
582 | start_bit = bitmap_find_next_zero_area(map, size, | 582 | start_bit = bitmap_find_next_zero_area(map, size, |