1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * DMABUF System heap exporter for Rockchip
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2011 Google, Inc.
6*4882a593Smuzhiyun * Copyright (C) 2019, 2020 Linaro Ltd.
7*4882a593Smuzhiyun * Copyright (c) 2021, 2022 Rockchip Electronics Co. Ltd.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Portions based off of Andrew Davis' SRAM heap:
10*4882a593Smuzhiyun * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
11*4882a593Smuzhiyun * Andrew F. Davis <afd@ti.com>
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/dma-buf.h>
15*4882a593Smuzhiyun #include <linux/dma-mapping.h>
16*4882a593Smuzhiyun #include <linux/dma-heap.h>
17*4882a593Smuzhiyun #include <linux/err.h>
18*4882a593Smuzhiyun #include <linux/highmem.h>
19*4882a593Smuzhiyun #include <linux/mm.h>
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun #include <linux/scatterlist.h>
22*4882a593Smuzhiyun #include <linux/slab.h>
23*4882a593Smuzhiyun #include <linux/swiotlb.h>
24*4882a593Smuzhiyun #include <linux/vmalloc.h>
25*4882a593Smuzhiyun #include <linux/rockchip/rockchip_sip.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include "page_pool.h"
28*4882a593Smuzhiyun #include "deferred-free-helper.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static struct dma_heap *sys_heap;
31*4882a593Smuzhiyun static struct dma_heap *sys_dma32_heap;
32*4882a593Smuzhiyun static struct dma_heap *sys_uncached_heap;
33*4882a593Smuzhiyun static struct dma_heap *sys_uncached_dma32_heap;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* Default setting */
36*4882a593Smuzhiyun static u32 bank_bit_first = 12;
37*4882a593Smuzhiyun static u32 bank_bit_mask = 0x7;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun struct system_heap_buffer {
40*4882a593Smuzhiyun struct dma_heap *heap;
41*4882a593Smuzhiyun struct list_head attachments;
42*4882a593Smuzhiyun struct mutex lock;
43*4882a593Smuzhiyun unsigned long len;
44*4882a593Smuzhiyun struct sg_table sg_table;
45*4882a593Smuzhiyun int vmap_cnt;
46*4882a593Smuzhiyun void *vaddr;
47*4882a593Smuzhiyun struct deferred_freelist_item deferred_free;
48*4882a593Smuzhiyun struct dmabuf_page_pool **pools;
49*4882a593Smuzhiyun bool uncached;
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun struct dma_heap_attachment {
53*4882a593Smuzhiyun struct device *dev;
54*4882a593Smuzhiyun struct sg_table *table;
55*4882a593Smuzhiyun struct list_head list;
56*4882a593Smuzhiyun bool mapped;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun bool uncached;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO)
62*4882a593Smuzhiyun #define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
63*4882a593Smuzhiyun | __GFP_NORETRY) & ~__GFP_RECLAIM) \
64*4882a593Smuzhiyun | __GFP_COMP)
65*4882a593Smuzhiyun static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun * The selection of the orders used for allocation (1MB, 64K, 4K) is designed
68*4882a593Smuzhiyun * to match with the sizes often found in IOMMUs. Using order 4 pages instead
69*4882a593Smuzhiyun * of order 0 pages can significantly improve the performance of many IOMMUs
70*4882a593Smuzhiyun * by reducing TLB pressure and time spent updating page tables.
71*4882a593Smuzhiyun */
72*4882a593Smuzhiyun static unsigned int orders[] = {8, 4, 0};
73*4882a593Smuzhiyun #define NUM_ORDERS ARRAY_SIZE(orders)
74*4882a593Smuzhiyun struct dmabuf_page_pool *pools[NUM_ORDERS];
75*4882a593Smuzhiyun struct dmabuf_page_pool *dma32_pools[NUM_ORDERS];
76*4882a593Smuzhiyun
dup_sg_table(struct sg_table * table)77*4882a593Smuzhiyun static struct sg_table *dup_sg_table(struct sg_table *table)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun struct sg_table *new_table;
80*4882a593Smuzhiyun int ret, i;
81*4882a593Smuzhiyun struct scatterlist *sg, *new_sg;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun new_table = kzalloc(sizeof(*new_table), GFP_KERNEL);
84*4882a593Smuzhiyun if (!new_table)
85*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun ret = sg_alloc_table(new_table, table->orig_nents, GFP_KERNEL);
88*4882a593Smuzhiyun if (ret) {
89*4882a593Smuzhiyun kfree(new_table);
90*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun new_sg = new_table->sgl;
94*4882a593Smuzhiyun for_each_sgtable_sg(table, sg, i) {
95*4882a593Smuzhiyun sg_set_page(new_sg, sg_page(sg), sg->length, sg->offset);
96*4882a593Smuzhiyun new_sg = sg_next(new_sg);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun return new_table;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
system_heap_attach(struct dma_buf * dmabuf,struct dma_buf_attachment * attachment)102*4882a593Smuzhiyun static int system_heap_attach(struct dma_buf *dmabuf,
103*4882a593Smuzhiyun struct dma_buf_attachment *attachment)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
106*4882a593Smuzhiyun struct dma_heap_attachment *a;
107*4882a593Smuzhiyun struct sg_table *table;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun a = kzalloc(sizeof(*a), GFP_KERNEL);
110*4882a593Smuzhiyun if (!a)
111*4882a593Smuzhiyun return -ENOMEM;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun table = dup_sg_table(&buffer->sg_table);
114*4882a593Smuzhiyun if (IS_ERR(table)) {
115*4882a593Smuzhiyun kfree(a);
116*4882a593Smuzhiyun return -ENOMEM;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun a->table = table;
120*4882a593Smuzhiyun a->dev = attachment->dev;
121*4882a593Smuzhiyun INIT_LIST_HEAD(&a->list);
122*4882a593Smuzhiyun a->mapped = false;
123*4882a593Smuzhiyun a->uncached = buffer->uncached;
124*4882a593Smuzhiyun attachment->priv = a;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun mutex_lock(&buffer->lock);
127*4882a593Smuzhiyun list_add(&a->list, &buffer->attachments);
128*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun return 0;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
system_heap_detach(struct dma_buf * dmabuf,struct dma_buf_attachment * attachment)133*4882a593Smuzhiyun static void system_heap_detach(struct dma_buf *dmabuf,
134*4882a593Smuzhiyun struct dma_buf_attachment *attachment)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
137*4882a593Smuzhiyun struct dma_heap_attachment *a = attachment->priv;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun mutex_lock(&buffer->lock);
140*4882a593Smuzhiyun list_del(&a->list);
141*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun sg_free_table(a->table);
144*4882a593Smuzhiyun kfree(a->table);
145*4882a593Smuzhiyun kfree(a);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
system_heap_map_dma_buf(struct dma_buf_attachment * attachment,enum dma_data_direction direction)148*4882a593Smuzhiyun static struct sg_table *system_heap_map_dma_buf(struct dma_buf_attachment *attachment,
149*4882a593Smuzhiyun enum dma_data_direction direction)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun struct dma_heap_attachment *a = attachment->priv;
152*4882a593Smuzhiyun struct sg_table *table = a->table;
153*4882a593Smuzhiyun int attr = attachment->dma_map_attrs;
154*4882a593Smuzhiyun int ret;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun if (a->uncached)
157*4882a593Smuzhiyun attr |= DMA_ATTR_SKIP_CPU_SYNC;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun ret = dma_map_sgtable(attachment->dev, table, direction, attr);
160*4882a593Smuzhiyun if (ret)
161*4882a593Smuzhiyun return ERR_PTR(ret);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun a->mapped = true;
164*4882a593Smuzhiyun return table;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
system_heap_unmap_dma_buf(struct dma_buf_attachment * attachment,struct sg_table * table,enum dma_data_direction direction)167*4882a593Smuzhiyun static void system_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
168*4882a593Smuzhiyun struct sg_table *table,
169*4882a593Smuzhiyun enum dma_data_direction direction)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun struct dma_heap_attachment *a = attachment->priv;
172*4882a593Smuzhiyun int attr = attachment->dma_map_attrs;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (a->uncached)
175*4882a593Smuzhiyun attr |= DMA_ATTR_SKIP_CPU_SYNC;
176*4882a593Smuzhiyun a->mapped = false;
177*4882a593Smuzhiyun dma_unmap_sgtable(attachment->dev, table, direction, attr);
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
system_heap_dma_buf_begin_cpu_access(struct dma_buf * dmabuf,enum dma_data_direction direction)180*4882a593Smuzhiyun static int system_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
181*4882a593Smuzhiyun enum dma_data_direction direction)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
184*4882a593Smuzhiyun struct dma_heap_attachment *a;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun mutex_lock(&buffer->lock);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (buffer->vmap_cnt)
189*4882a593Smuzhiyun invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun if (!buffer->uncached) {
192*4882a593Smuzhiyun list_for_each_entry(a, &buffer->attachments, list) {
193*4882a593Smuzhiyun if (!a->mapped)
194*4882a593Smuzhiyun continue;
195*4882a593Smuzhiyun dma_sync_sgtable_for_cpu(a->dev, a->table, direction);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun return 0;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
system_heap_dma_buf_end_cpu_access(struct dma_buf * dmabuf,enum dma_data_direction direction)203*4882a593Smuzhiyun static int system_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
204*4882a593Smuzhiyun enum dma_data_direction direction)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
207*4882a593Smuzhiyun struct dma_heap_attachment *a;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun mutex_lock(&buffer->lock);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (buffer->vmap_cnt)
212*4882a593Smuzhiyun flush_kernel_vmap_range(buffer->vaddr, buffer->len);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun if (!buffer->uncached) {
215*4882a593Smuzhiyun list_for_each_entry(a, &buffer->attachments, list) {
216*4882a593Smuzhiyun if (!a->mapped)
217*4882a593Smuzhiyun continue;
218*4882a593Smuzhiyun dma_sync_sgtable_for_device(a->dev, a->table, direction);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun return 0;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
system_heap_sgl_sync_range(struct device * dev,struct sg_table * sgt,unsigned int offset,unsigned int length,enum dma_data_direction dir,bool for_cpu)226*4882a593Smuzhiyun static int system_heap_sgl_sync_range(struct device *dev,
227*4882a593Smuzhiyun struct sg_table *sgt,
228*4882a593Smuzhiyun unsigned int offset,
229*4882a593Smuzhiyun unsigned int length,
230*4882a593Smuzhiyun enum dma_data_direction dir,
231*4882a593Smuzhiyun bool for_cpu)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun struct scatterlist *sg;
234*4882a593Smuzhiyun unsigned int len = 0;
235*4882a593Smuzhiyun dma_addr_t sg_dma_addr;
236*4882a593Smuzhiyun int i;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun for_each_sgtable_sg(sgt, sg, i) {
239*4882a593Smuzhiyun unsigned int sg_offset, sg_left, size = 0;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun sg_dma_addr = sg_phys(sg);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun len += sg->length;
244*4882a593Smuzhiyun if (len <= offset)
245*4882a593Smuzhiyun continue;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun sg_left = len - offset;
248*4882a593Smuzhiyun sg_offset = sg->length - sg_left;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun size = (length < sg_left) ? length : sg_left;
251*4882a593Smuzhiyun if (for_cpu)
252*4882a593Smuzhiyun dma_sync_single_range_for_cpu(dev, sg_dma_addr,
253*4882a593Smuzhiyun sg_offset, size, dir);
254*4882a593Smuzhiyun else
255*4882a593Smuzhiyun dma_sync_single_range_for_device(dev, sg_dma_addr,
256*4882a593Smuzhiyun sg_offset, size, dir);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun offset += size;
259*4882a593Smuzhiyun length -= size;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (length == 0)
262*4882a593Smuzhiyun break;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun return 0;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun static int __maybe_unused
system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf * dmabuf,enum dma_data_direction direction,unsigned int offset,unsigned int len)269*4882a593Smuzhiyun system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf,
270*4882a593Smuzhiyun enum dma_data_direction direction,
271*4882a593Smuzhiyun unsigned int offset,
272*4882a593Smuzhiyun unsigned int len)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
275*4882a593Smuzhiyun struct dma_heap *heap = buffer->heap;
276*4882a593Smuzhiyun struct sg_table *table = &buffer->sg_table;
277*4882a593Smuzhiyun int ret;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (direction == DMA_TO_DEVICE)
280*4882a593Smuzhiyun return 0;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun mutex_lock(&buffer->lock);
283*4882a593Smuzhiyun if (buffer->vmap_cnt)
284*4882a593Smuzhiyun invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (buffer->uncached) {
287*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
288*4882a593Smuzhiyun return 0;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table,
292*4882a593Smuzhiyun offset, len, direction, true);
293*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun return ret;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun static int __maybe_unused
system_heap_dma_buf_end_cpu_access_partial(struct dma_buf * dmabuf,enum dma_data_direction direction,unsigned int offset,unsigned int len)299*4882a593Smuzhiyun system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf,
300*4882a593Smuzhiyun enum dma_data_direction direction,
301*4882a593Smuzhiyun unsigned int offset,
302*4882a593Smuzhiyun unsigned int len)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
305*4882a593Smuzhiyun struct dma_heap *heap = buffer->heap;
306*4882a593Smuzhiyun struct sg_table *table = &buffer->sg_table;
307*4882a593Smuzhiyun int ret;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun mutex_lock(&buffer->lock);
310*4882a593Smuzhiyun if (buffer->vmap_cnt)
311*4882a593Smuzhiyun flush_kernel_vmap_range(buffer->vaddr, buffer->len);
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun if (buffer->uncached) {
314*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
315*4882a593Smuzhiyun return 0;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table,
319*4882a593Smuzhiyun offset, len, direction, false);
320*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun return ret;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
system_heap_mmap(struct dma_buf * dmabuf,struct vm_area_struct * vma)325*4882a593Smuzhiyun static int system_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
328*4882a593Smuzhiyun struct sg_table *table = &buffer->sg_table;
329*4882a593Smuzhiyun unsigned long addr = vma->vm_start;
330*4882a593Smuzhiyun struct sg_page_iter piter;
331*4882a593Smuzhiyun int ret;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun if (buffer->uncached)
334*4882a593Smuzhiyun vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun for_each_sgtable_page(table, &piter, vma->vm_pgoff) {
337*4882a593Smuzhiyun struct page *page = sg_page_iter_page(&piter);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun ret = remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE,
340*4882a593Smuzhiyun vma->vm_page_prot);
341*4882a593Smuzhiyun if (ret)
342*4882a593Smuzhiyun return ret;
343*4882a593Smuzhiyun addr += PAGE_SIZE;
344*4882a593Smuzhiyun if (addr >= vma->vm_end)
345*4882a593Smuzhiyun return 0;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun return 0;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
system_heap_do_vmap(struct system_heap_buffer * buffer)350*4882a593Smuzhiyun static void *system_heap_do_vmap(struct system_heap_buffer *buffer)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun struct sg_table *table = &buffer->sg_table;
353*4882a593Smuzhiyun int npages = PAGE_ALIGN(buffer->len) / PAGE_SIZE;
354*4882a593Smuzhiyun struct page **pages = vmalloc(sizeof(struct page *) * npages);
355*4882a593Smuzhiyun struct page **tmp = pages;
356*4882a593Smuzhiyun struct sg_page_iter piter;
357*4882a593Smuzhiyun pgprot_t pgprot = PAGE_KERNEL;
358*4882a593Smuzhiyun void *vaddr;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun if (!pages)
361*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun if (buffer->uncached)
364*4882a593Smuzhiyun pgprot = pgprot_writecombine(PAGE_KERNEL);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun for_each_sgtable_page(table, &piter, 0) {
367*4882a593Smuzhiyun WARN_ON(tmp - pages >= npages);
368*4882a593Smuzhiyun *tmp++ = sg_page_iter_page(&piter);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun vaddr = vmap(pages, npages, VM_MAP, pgprot);
372*4882a593Smuzhiyun vfree(pages);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun if (!vaddr)
375*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return vaddr;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
system_heap_vmap(struct dma_buf * dmabuf)380*4882a593Smuzhiyun static void *system_heap_vmap(struct dma_buf *dmabuf)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
383*4882a593Smuzhiyun void *vaddr;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun mutex_lock(&buffer->lock);
386*4882a593Smuzhiyun if (buffer->vmap_cnt) {
387*4882a593Smuzhiyun buffer->vmap_cnt++;
388*4882a593Smuzhiyun vaddr = buffer->vaddr;
389*4882a593Smuzhiyun goto out;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun vaddr = system_heap_do_vmap(buffer);
393*4882a593Smuzhiyun if (IS_ERR(vaddr))
394*4882a593Smuzhiyun goto out;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun buffer->vaddr = vaddr;
397*4882a593Smuzhiyun buffer->vmap_cnt++;
398*4882a593Smuzhiyun out:
399*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun return vaddr;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
system_heap_vunmap(struct dma_buf * dmabuf,void * vaddr)404*4882a593Smuzhiyun static void system_heap_vunmap(struct dma_buf *dmabuf, void *vaddr)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun mutex_lock(&buffer->lock);
409*4882a593Smuzhiyun if (!--buffer->vmap_cnt) {
410*4882a593Smuzhiyun vunmap(buffer->vaddr);
411*4882a593Smuzhiyun buffer->vaddr = NULL;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun mutex_unlock(&buffer->lock);
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
system_heap_zero_buffer(struct system_heap_buffer * buffer)416*4882a593Smuzhiyun static int system_heap_zero_buffer(struct system_heap_buffer *buffer)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun struct sg_table *sgt = &buffer->sg_table;
419*4882a593Smuzhiyun struct sg_page_iter piter;
420*4882a593Smuzhiyun struct page *p;
421*4882a593Smuzhiyun void *vaddr;
422*4882a593Smuzhiyun int ret = 0;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun for_each_sgtable_page(sgt, &piter, 0) {
425*4882a593Smuzhiyun p = sg_page_iter_page(&piter);
426*4882a593Smuzhiyun vaddr = kmap_atomic(p);
427*4882a593Smuzhiyun memset(vaddr, 0, PAGE_SIZE);
428*4882a593Smuzhiyun kunmap_atomic(vaddr);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun return ret;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
system_heap_buf_free(struct deferred_freelist_item * item,enum df_reason reason)434*4882a593Smuzhiyun static void system_heap_buf_free(struct deferred_freelist_item *item,
435*4882a593Smuzhiyun enum df_reason reason)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun struct system_heap_buffer *buffer;
438*4882a593Smuzhiyun struct sg_table *table;
439*4882a593Smuzhiyun struct scatterlist *sg;
440*4882a593Smuzhiyun int i, j;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun buffer = container_of(item, struct system_heap_buffer, deferred_free);
443*4882a593Smuzhiyun /* Zero the buffer pages before adding back to the pool */
444*4882a593Smuzhiyun if (reason == DF_NORMAL)
445*4882a593Smuzhiyun if (system_heap_zero_buffer(buffer))
446*4882a593Smuzhiyun reason = DF_UNDER_PRESSURE; // On failure, just free
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun table = &buffer->sg_table;
449*4882a593Smuzhiyun for_each_sgtable_sg(table, sg, i) {
450*4882a593Smuzhiyun struct page *page = sg_page(sg);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if (reason == DF_UNDER_PRESSURE) {
453*4882a593Smuzhiyun __free_pages(page, compound_order(page));
454*4882a593Smuzhiyun } else {
455*4882a593Smuzhiyun for (j = 0; j < NUM_ORDERS; j++) {
456*4882a593Smuzhiyun if (compound_order(page) == orders[j])
457*4882a593Smuzhiyun break;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun dmabuf_page_pool_free(buffer->pools[j], page);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun sg_free_table(table);
463*4882a593Smuzhiyun kfree(buffer);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
system_heap_dma_buf_release(struct dma_buf * dmabuf)466*4882a593Smuzhiyun static void system_heap_dma_buf_release(struct dma_buf *dmabuf)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun struct system_heap_buffer *buffer = dmabuf->priv;
469*4882a593Smuzhiyun int npages = PAGE_ALIGN(buffer->len) / PAGE_SIZE;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun deferred_free(&buffer->deferred_free, system_heap_buf_free, npages);
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun static const struct dma_buf_ops system_heap_buf_ops = {
475*4882a593Smuzhiyun .attach = system_heap_attach,
476*4882a593Smuzhiyun .detach = system_heap_detach,
477*4882a593Smuzhiyun .map_dma_buf = system_heap_map_dma_buf,
478*4882a593Smuzhiyun .unmap_dma_buf = system_heap_unmap_dma_buf,
479*4882a593Smuzhiyun .begin_cpu_access = system_heap_dma_buf_begin_cpu_access,
480*4882a593Smuzhiyun .end_cpu_access = system_heap_dma_buf_end_cpu_access,
481*4882a593Smuzhiyun #ifdef CONFIG_DMABUF_PARTIAL
482*4882a593Smuzhiyun .begin_cpu_access_partial = system_heap_dma_buf_begin_cpu_access_partial,
483*4882a593Smuzhiyun .end_cpu_access_partial = system_heap_dma_buf_end_cpu_access_partial,
484*4882a593Smuzhiyun #endif
485*4882a593Smuzhiyun .mmap = system_heap_mmap,
486*4882a593Smuzhiyun .vmap = system_heap_vmap,
487*4882a593Smuzhiyun .vunmap = system_heap_vunmap,
488*4882a593Smuzhiyun .release = system_heap_dma_buf_release,
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun
system_heap_alloc_largest_available(struct dma_heap * heap,struct dmabuf_page_pool ** pool,unsigned long size,unsigned int max_order)491*4882a593Smuzhiyun static struct page *system_heap_alloc_largest_available(struct dma_heap *heap,
492*4882a593Smuzhiyun struct dmabuf_page_pool **pool,
493*4882a593Smuzhiyun unsigned long size,
494*4882a593Smuzhiyun unsigned int max_order)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun struct page *page;
497*4882a593Smuzhiyun int i;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun for (i = 0; i < NUM_ORDERS; i++) {
500*4882a593Smuzhiyun if (size < (PAGE_SIZE << orders[i]))
501*4882a593Smuzhiyun continue;
502*4882a593Smuzhiyun if (max_order < orders[i])
503*4882a593Smuzhiyun continue;
504*4882a593Smuzhiyun page = dmabuf_page_pool_alloc(pool[i]);
505*4882a593Smuzhiyun if (!page)
506*4882a593Smuzhiyun continue;
507*4882a593Smuzhiyun return page;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun return NULL;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
system_heap_do_allocate(struct dma_heap * heap,unsigned long len,unsigned long fd_flags,unsigned long heap_flags,bool uncached)512*4882a593Smuzhiyun static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap,
513*4882a593Smuzhiyun unsigned long len,
514*4882a593Smuzhiyun unsigned long fd_flags,
515*4882a593Smuzhiyun unsigned long heap_flags,
516*4882a593Smuzhiyun bool uncached)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun struct system_heap_buffer *buffer;
519*4882a593Smuzhiyun DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
520*4882a593Smuzhiyun unsigned long size_remaining = len;
521*4882a593Smuzhiyun unsigned int max_order = orders[0];
522*4882a593Smuzhiyun struct dma_buf *dmabuf;
523*4882a593Smuzhiyun struct sg_table *table;
524*4882a593Smuzhiyun struct scatterlist *sg;
525*4882a593Smuzhiyun struct list_head pages;
526*4882a593Smuzhiyun struct page *page, *tmp_page;
527*4882a593Smuzhiyun int i, ret = -ENOMEM;
528*4882a593Smuzhiyun struct list_head lists[8];
529*4882a593Smuzhiyun unsigned int block_index[8] = {0};
530*4882a593Smuzhiyun unsigned int block_1M = 0;
531*4882a593Smuzhiyun unsigned int block_64K = 0;
532*4882a593Smuzhiyun unsigned int maximum;
533*4882a593Smuzhiyun int j;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
536*4882a593Smuzhiyun if (!buffer)
537*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun INIT_LIST_HEAD(&buffer->attachments);
540*4882a593Smuzhiyun mutex_init(&buffer->lock);
541*4882a593Smuzhiyun buffer->heap = heap;
542*4882a593Smuzhiyun buffer->len = len;
543*4882a593Smuzhiyun buffer->uncached = uncached;
544*4882a593Smuzhiyun buffer->pools = strstr(dma_heap_get_name(heap), "dma32") ? dma32_pools : pools;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun INIT_LIST_HEAD(&pages);
547*4882a593Smuzhiyun for (i = 0; i < 8; i++)
548*4882a593Smuzhiyun INIT_LIST_HEAD(&lists[i]);
549*4882a593Smuzhiyun i = 0;
550*4882a593Smuzhiyun while (size_remaining > 0) {
551*4882a593Smuzhiyun /*
552*4882a593Smuzhiyun * Avoid trying to allocate memory if the process
553*4882a593Smuzhiyun * has been killed by SIGKILL
554*4882a593Smuzhiyun */
555*4882a593Smuzhiyun if (fatal_signal_pending(current))
556*4882a593Smuzhiyun goto free_buffer;
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun page = system_heap_alloc_largest_available(heap, buffer->pools,
559*4882a593Smuzhiyun size_remaining,
560*4882a593Smuzhiyun max_order);
561*4882a593Smuzhiyun if (!page)
562*4882a593Smuzhiyun goto free_buffer;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun size_remaining -= page_size(page);
565*4882a593Smuzhiyun max_order = compound_order(page);
566*4882a593Smuzhiyun if (max_order) {
567*4882a593Smuzhiyun if (max_order == 8)
568*4882a593Smuzhiyun block_1M++;
569*4882a593Smuzhiyun if (max_order == 4)
570*4882a593Smuzhiyun block_64K++;
571*4882a593Smuzhiyun list_add_tail(&page->lru, &pages);
572*4882a593Smuzhiyun } else {
573*4882a593Smuzhiyun dma_addr_t phys = page_to_phys(page);
574*4882a593Smuzhiyun unsigned int bit_index = ((phys >> bank_bit_first) & bank_bit_mask) & 0x7;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun list_add_tail(&page->lru, &lists[bit_index]);
577*4882a593Smuzhiyun block_index[bit_index]++;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun i++;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun table = &buffer->sg_table;
583*4882a593Smuzhiyun if (sg_alloc_table(table, i, GFP_KERNEL))
584*4882a593Smuzhiyun goto free_buffer;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun maximum = block_index[0];
587*4882a593Smuzhiyun for (i = 1; i < 8; i++)
588*4882a593Smuzhiyun maximum = max(maximum, block_index[i]);
589*4882a593Smuzhiyun sg = table->sgl;
590*4882a593Smuzhiyun list_for_each_entry_safe(page, tmp_page, &pages, lru) {
591*4882a593Smuzhiyun sg_set_page(sg, page, page_size(page), 0);
592*4882a593Smuzhiyun sg = sg_next(sg);
593*4882a593Smuzhiyun list_del(&page->lru);
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun for (i = 0; i < maximum; i++) {
596*4882a593Smuzhiyun for (j = 0; j < 8; j++) {
597*4882a593Smuzhiyun if (!list_empty(&lists[j])) {
598*4882a593Smuzhiyun page = list_first_entry(&lists[j], struct page, lru);
599*4882a593Smuzhiyun sg_set_page(sg, page, PAGE_SIZE, 0);
600*4882a593Smuzhiyun sg = sg_next(sg);
601*4882a593Smuzhiyun list_del(&page->lru);
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun /* create the dmabuf */
607*4882a593Smuzhiyun exp_info.exp_name = dma_heap_get_name(heap);
608*4882a593Smuzhiyun exp_info.ops = &system_heap_buf_ops;
609*4882a593Smuzhiyun exp_info.size = buffer->len;
610*4882a593Smuzhiyun exp_info.flags = fd_flags;
611*4882a593Smuzhiyun exp_info.priv = buffer;
612*4882a593Smuzhiyun dmabuf = dma_buf_export(&exp_info);
613*4882a593Smuzhiyun if (IS_ERR(dmabuf)) {
614*4882a593Smuzhiyun ret = PTR_ERR(dmabuf);
615*4882a593Smuzhiyun goto free_pages;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun /*
619*4882a593Smuzhiyun * For uncached buffers, we need to initially flush cpu cache, since
620*4882a593Smuzhiyun * the __GFP_ZERO on the allocation means the zeroing was done by the
621*4882a593Smuzhiyun * cpu and thus it is likely cached. Map (and implicitly flush) and
622*4882a593Smuzhiyun * unmap it now so we don't get corruption later on.
623*4882a593Smuzhiyun */
624*4882a593Smuzhiyun if (buffer->uncached) {
625*4882a593Smuzhiyun dma_map_sgtable(dma_heap_get_dev(heap), table, DMA_BIDIRECTIONAL, 0);
626*4882a593Smuzhiyun dma_unmap_sgtable(dma_heap_get_dev(heap), table, DMA_BIDIRECTIONAL, 0);
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun return dmabuf;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun free_pages:
632*4882a593Smuzhiyun for_each_sgtable_sg(table, sg, i) {
633*4882a593Smuzhiyun struct page *p = sg_page(sg);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun __free_pages(p, compound_order(p));
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun sg_free_table(table);
638*4882a593Smuzhiyun free_buffer:
639*4882a593Smuzhiyun list_for_each_entry_safe(page, tmp_page, &pages, lru)
640*4882a593Smuzhiyun __free_pages(page, compound_order(page));
641*4882a593Smuzhiyun for (i = 0; i < 8; i++) {
642*4882a593Smuzhiyun list_for_each_entry_safe(page, tmp_page, &lists[i], lru)
643*4882a593Smuzhiyun __free_pages(page, compound_order(page));
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun kfree(buffer);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun return ERR_PTR(ret);
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
system_heap_allocate(struct dma_heap * heap,unsigned long len,unsigned long fd_flags,unsigned long heap_flags)650*4882a593Smuzhiyun static struct dma_buf *system_heap_allocate(struct dma_heap *heap,
651*4882a593Smuzhiyun unsigned long len,
652*4882a593Smuzhiyun unsigned long fd_flags,
653*4882a593Smuzhiyun unsigned long heap_flags)
654*4882a593Smuzhiyun {
655*4882a593Smuzhiyun return system_heap_do_allocate(heap, len, fd_flags, heap_flags, false);
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun
system_get_pool_size(struct dma_heap * heap)658*4882a593Smuzhiyun static long system_get_pool_size(struct dma_heap *heap)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun int i;
661*4882a593Smuzhiyun long num_pages = 0;
662*4882a593Smuzhiyun struct dmabuf_page_pool **pool;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun pool = strstr(dma_heap_get_name(heap), "dma32") ? dma32_pools : pools;
665*4882a593Smuzhiyun for (i = 0; i < NUM_ORDERS; i++, pool++) {
666*4882a593Smuzhiyun num_pages += ((*pool)->count[POOL_LOWPAGE] +
667*4882a593Smuzhiyun (*pool)->count[POOL_HIGHPAGE]) << (*pool)->order;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun return num_pages << PAGE_SHIFT;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun static const struct dma_heap_ops system_heap_ops = {
674*4882a593Smuzhiyun .allocate = system_heap_allocate,
675*4882a593Smuzhiyun .get_pool_size = system_get_pool_size,
676*4882a593Smuzhiyun };
677*4882a593Smuzhiyun
system_uncached_heap_allocate(struct dma_heap * heap,unsigned long len,unsigned long fd_flags,unsigned long heap_flags)678*4882a593Smuzhiyun static struct dma_buf *system_uncached_heap_allocate(struct dma_heap *heap,
679*4882a593Smuzhiyun unsigned long len,
680*4882a593Smuzhiyun unsigned long fd_flags,
681*4882a593Smuzhiyun unsigned long heap_flags)
682*4882a593Smuzhiyun {
683*4882a593Smuzhiyun return system_heap_do_allocate(heap, len, fd_flags, heap_flags, true);
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun /* Dummy function to be used until we can call coerce_mask_and_coherent */
system_uncached_heap_not_initialized(struct dma_heap * heap,unsigned long len,unsigned long fd_flags,unsigned long heap_flags)687*4882a593Smuzhiyun static struct dma_buf *system_uncached_heap_not_initialized(struct dma_heap *heap,
688*4882a593Smuzhiyun unsigned long len,
689*4882a593Smuzhiyun unsigned long fd_flags,
690*4882a593Smuzhiyun unsigned long heap_flags)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun return ERR_PTR(-EBUSY);
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun static struct dma_heap_ops system_uncached_heap_ops = {
696*4882a593Smuzhiyun /* After system_heap_create is complete, we will swap this */
697*4882a593Smuzhiyun .allocate = system_uncached_heap_not_initialized,
698*4882a593Smuzhiyun };
699*4882a593Smuzhiyun
set_heap_dev_dma(struct device * heap_dev)700*4882a593Smuzhiyun static int set_heap_dev_dma(struct device *heap_dev)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun int err = 0;
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun if (!heap_dev)
705*4882a593Smuzhiyun return -EINVAL;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun dma_coerce_mask_and_coherent(heap_dev, DMA_BIT_MASK(64));
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun if (!heap_dev->dma_parms) {
710*4882a593Smuzhiyun heap_dev->dma_parms = devm_kzalloc(heap_dev,
711*4882a593Smuzhiyun sizeof(*heap_dev->dma_parms),
712*4882a593Smuzhiyun GFP_KERNEL);
713*4882a593Smuzhiyun if (!heap_dev->dma_parms)
714*4882a593Smuzhiyun return -ENOMEM;
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun err = dma_set_max_seg_size(heap_dev, (unsigned int)DMA_BIT_MASK(64));
717*4882a593Smuzhiyun if (err) {
718*4882a593Smuzhiyun devm_kfree(heap_dev, heap_dev->dma_parms);
719*4882a593Smuzhiyun dev_err(heap_dev, "Failed to set DMA segment size, err:%d\n", err);
720*4882a593Smuzhiyun return err;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun return 0;
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun
system_heap_create(void)727*4882a593Smuzhiyun static int system_heap_create(void)
728*4882a593Smuzhiyun {
729*4882a593Smuzhiyun struct dma_heap_export_info exp_info;
730*4882a593Smuzhiyun int i, err = 0;
731*4882a593Smuzhiyun struct dram_addrmap_info *ddr_map_info;
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun /*
734*4882a593Smuzhiyun * Since swiotlb has memory size limitation, this will calculate
735*4882a593Smuzhiyun * the maximum size locally.
736*4882a593Smuzhiyun *
737*4882a593Smuzhiyun * Once swiotlb_max_segment() return not '0', means that the totalram size
738*4882a593Smuzhiyun * is larger than 4GiB and swiotlb is not force mode, in this case, system
739*4882a593Smuzhiyun * heap should limit largest allocation.
740*4882a593Smuzhiyun *
741*4882a593Smuzhiyun * FIX: fix the orders[] as a workaround.
742*4882a593Smuzhiyun */
743*4882a593Smuzhiyun if (swiotlb_max_segment()) {
744*4882a593Smuzhiyun unsigned int max_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE;
745*4882a593Smuzhiyun int max_order = MAX_ORDER;
746*4882a593Smuzhiyun int i;
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun max_size = max_t(unsigned int, max_size, PAGE_SIZE) >> PAGE_SHIFT;
749*4882a593Smuzhiyun max_order = min(max_order, ilog2(max_size));
750*4882a593Smuzhiyun for (i = 0; i < NUM_ORDERS; i++) {
751*4882a593Smuzhiyun if (max_order < orders[i])
752*4882a593Smuzhiyun orders[i] = max_order;
753*4882a593Smuzhiyun pr_info("system_heap: orders[%d] = %u\n", i, orders[i]);
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun for (i = 0; i < NUM_ORDERS; i++) {
758*4882a593Smuzhiyun pools[i] = dmabuf_page_pool_create(order_flags[i], orders[i]);
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun if (!pools[i]) {
761*4882a593Smuzhiyun int j;
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun pr_err("%s: page pool creation failed!\n", __func__);
764*4882a593Smuzhiyun for (j = 0; j < i; j++)
765*4882a593Smuzhiyun dmabuf_page_pool_destroy(pools[j]);
766*4882a593Smuzhiyun return -ENOMEM;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun for (i = 0; i < NUM_ORDERS; i++) {
771*4882a593Smuzhiyun dma32_pools[i] = dmabuf_page_pool_create(order_flags[i] | GFP_DMA32, orders[i]);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (!dma32_pools[i]) {
774*4882a593Smuzhiyun int j;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun pr_err("%s: page dma32 pool creation failed!\n", __func__);
777*4882a593Smuzhiyun for (j = 0; j < i; j++)
778*4882a593Smuzhiyun dmabuf_page_pool_destroy(dma32_pools[j]);
779*4882a593Smuzhiyun goto err_dma32_pool;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun exp_info.name = "system";
784*4882a593Smuzhiyun exp_info.ops = &system_heap_ops;
785*4882a593Smuzhiyun exp_info.priv = NULL;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun sys_heap = dma_heap_add(&exp_info);
788*4882a593Smuzhiyun if (IS_ERR(sys_heap))
789*4882a593Smuzhiyun return PTR_ERR(sys_heap);
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun exp_info.name = "system-dma32";
792*4882a593Smuzhiyun exp_info.ops = &system_heap_ops;
793*4882a593Smuzhiyun exp_info.priv = NULL;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun sys_dma32_heap = dma_heap_add(&exp_info);
796*4882a593Smuzhiyun if (IS_ERR(sys_dma32_heap))
797*4882a593Smuzhiyun return PTR_ERR(sys_dma32_heap);
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun exp_info.name = "system-uncached";
800*4882a593Smuzhiyun exp_info.ops = &system_uncached_heap_ops;
801*4882a593Smuzhiyun exp_info.priv = NULL;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun sys_uncached_heap = dma_heap_add(&exp_info);
804*4882a593Smuzhiyun if (IS_ERR(sys_uncached_heap))
805*4882a593Smuzhiyun return PTR_ERR(sys_uncached_heap);
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun err = set_heap_dev_dma(dma_heap_get_dev(sys_uncached_heap));
808*4882a593Smuzhiyun if (err)
809*4882a593Smuzhiyun return err;
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun exp_info.name = "system-uncached-dma32";
812*4882a593Smuzhiyun exp_info.ops = &system_uncached_heap_ops;
813*4882a593Smuzhiyun exp_info.priv = NULL;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun sys_uncached_dma32_heap = dma_heap_add(&exp_info);
816*4882a593Smuzhiyun if (IS_ERR(sys_uncached_dma32_heap))
817*4882a593Smuzhiyun return PTR_ERR(sys_uncached_dma32_heap);
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun err = set_heap_dev_dma(dma_heap_get_dev(sys_uncached_dma32_heap));
820*4882a593Smuzhiyun if (err)
821*4882a593Smuzhiyun return err;
822*4882a593Smuzhiyun dma_coerce_mask_and_coherent(dma_heap_get_dev(sys_uncached_dma32_heap), DMA_BIT_MASK(32));
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun mb(); /* make sure we only set allocate after dma_mask is set */
825*4882a593Smuzhiyun system_uncached_heap_ops.allocate = system_uncached_heap_allocate;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun ddr_map_info = sip_smc_get_dram_map();
828*4882a593Smuzhiyun if (ddr_map_info) {
829*4882a593Smuzhiyun bank_bit_first = ddr_map_info->bank_bit_first;
830*4882a593Smuzhiyun bank_bit_mask = ddr_map_info->bank_bit_mask;
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun return 0;
834*4882a593Smuzhiyun err_dma32_pool:
835*4882a593Smuzhiyun for (i = 0; i < NUM_ORDERS; i++)
836*4882a593Smuzhiyun dmabuf_page_pool_destroy(pools[i]);
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun return -ENOMEM;
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun module_init(system_heap_create);
841*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
842