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