7
7
#include <linux/interrupt.h>
8
8
#include <linux/pagemap.h>
9
9
#include <linux/dma-mapping.h>
10
+ #include <linux/dmapool.h>
10
11
#include <linux/io.h>
11
12
#include <linux/platform_device.h>
12
13
#include <linux/uaccess.h>
31
32
32
33
#define ARM_DS_ACTIVE BIT(2)
33
34
35
+ #define VCHIQ_DMA_POOL_SIZE PAGE_SIZE
36
+
34
37
struct vchiq_2835_state {
35
38
int inited ;
36
39
struct vchiq_arm_state arm_state ;
@@ -40,6 +43,7 @@ struct vchiq_pagelist_info {
40
43
struct pagelist * pagelist ;
41
44
size_t pagelist_buffer_size ;
42
45
dma_addr_t dma_addr ;
46
+ bool is_from_pool ;
43
47
enum dma_data_direction dma_dir ;
44
48
unsigned int num_pages ;
45
49
unsigned int pages_need_release ;
@@ -60,6 +64,7 @@ static void __iomem *g_regs;
60
64
* of 32.
61
65
*/
62
66
static unsigned int g_cache_line_size = 32 ;
67
+ static struct dma_pool * g_dma_pool ;
63
68
static unsigned int g_use_36bit_addrs = 0 ;
64
69
static unsigned int g_fragments_size ;
65
70
static char * g_fragments_base ;
@@ -185,6 +190,13 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
185
190
186
191
g_dev = dev ;
187
192
g_dma_dev = dma_dev ?: dev ;
193
+ g_dma_pool = dmam_pool_create ("vchiq_scatter_pool" , dev ,
194
+ VCHIQ_DMA_POOL_SIZE , g_cache_line_size ,
195
+ 0 );
196
+ if (!g_dma_pool ) {
197
+ dev_err (dev , "failed to create dma pool" );
198
+ return - ENOMEM ;
199
+ }
188
200
189
201
vchiq_log_info (vchiq_arm_log_level ,
190
202
"vchiq_init - done (slots %pK, phys %pad)" ,
@@ -313,8 +325,14 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
313
325
if (pagelistinfo -> pages_need_release )
314
326
unpin_user_pages (pagelistinfo -> pages , pagelistinfo -> num_pages );
315
327
316
- dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
317
- pagelistinfo -> pagelist , pagelistinfo -> dma_addr );
328
+ if (pagelistinfo -> is_from_pool ) {
329
+ dma_pool_free (g_dma_pool , pagelistinfo -> pagelist ,
330
+ pagelistinfo -> dma_addr );
331
+ } else {
332
+ dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
333
+ pagelistinfo -> pagelist ,
334
+ pagelistinfo -> dma_addr );
335
+ }
318
336
}
319
337
320
338
/* There is a potential problem with partial cache lines (pages?)
@@ -335,6 +353,7 @@ create_pagelist(char *buf, char __user *ubuf,
335
353
u32 * addrs ;
336
354
unsigned int num_pages , offset , i , k ;
337
355
int actual_pages ;
356
+ bool is_from_pool ;
338
357
size_t pagelist_size ;
339
358
struct scatterlist * scatterlist , * sg ;
340
359
int dma_buffers ;
@@ -364,8 +383,16 @@ create_pagelist(char *buf, char __user *ubuf,
364
383
/* Allocate enough storage to hold the page pointers and the page
365
384
* list
366
385
*/
367
- pagelist = dma_alloc_coherent (g_dev , pagelist_size , & dma_addr ,
368
- GFP_KERNEL );
386
+ if (pagelist_size > VCHIQ_DMA_POOL_SIZE ) {
387
+ pagelist = dma_alloc_coherent (g_dev ,
388
+ pagelist_size ,
389
+ & dma_addr ,
390
+ GFP_KERNEL );
391
+ is_from_pool = false;
392
+ } else {
393
+ pagelist = dma_pool_alloc (g_dma_pool , GFP_KERNEL , & dma_addr );
394
+ is_from_pool = true;
395
+ }
369
396
370
397
vchiq_log_trace (vchiq_arm_log_level , "%s - %pK" , __func__ , pagelist );
371
398
@@ -386,6 +413,7 @@ create_pagelist(char *buf, char __user *ubuf,
386
413
pagelistinfo -> pagelist = pagelist ;
387
414
pagelistinfo -> pagelist_buffer_size = pagelist_size ;
388
415
pagelistinfo -> dma_addr = dma_addr ;
416
+ pagelistinfo -> is_from_pool = is_from_pool ;
389
417
pagelistinfo -> dma_dir = (type == PAGELIST_WRITE ) ?
390
418
DMA_TO_DEVICE : DMA_FROM_DEVICE ;
391
419
pagelistinfo -> num_pages = num_pages ;
0 commit comments