37
37
#include <linux/interrupt.h>
38
38
#include <linux/pagemap.h>
39
39
#include <linux/dma-mapping.h>
40
+ #include <linux/dmapool.h>
40
41
#include <linux/io.h>
41
42
#include <linux/platform_device.h>
42
43
#include <linux/uaccess.h>
60
61
#define BELL0 0x00
61
62
#define BELL2 0x08
62
63
64
+ #define VCHIQ_DMA_POOL_SIZE PAGE_SIZE
65
+
63
66
struct vchiq_2835_state {
64
67
int inited ;
65
68
VCHIQ_ARM_STATE_T arm_state ;
@@ -69,6 +72,7 @@ struct vchiq_pagelist_info {
69
72
PAGELIST_T * pagelist ;
70
73
size_t pagelist_buffer_size ;
71
74
dma_addr_t dma_addr ;
75
+ bool is_from_pool ;
72
76
enum dma_data_direction dma_dir ;
73
77
unsigned int num_pages ;
74
78
unsigned int pages_need_release ;
@@ -91,6 +95,7 @@ static void __iomem *g_regs;
91
95
* relevant Device Tree node.
92
96
*/
93
97
static unsigned int g_cache_line_size ;
98
+ static struct dma_pool * g_dma_pool ;
94
99
static unsigned int g_fragments_size ;
95
100
static char * g_fragments_base ;
96
101
static char * g_free_fragments ;
@@ -206,6 +211,14 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
206
211
}
207
212
208
213
g_dev = dev ;
214
+ g_dma_pool = dmam_pool_create ("vchiq_scatter_pool" , dev ,
215
+ VCHIQ_DMA_POOL_SIZE , g_cache_line_size ,
216
+ 0 );
217
+ if (!g_dma_pool ) {
218
+ dev_err (dev , "failed to create dma pool" );
219
+ return - ENOMEM ;
220
+ }
221
+
209
222
vchiq_log_info (vchiq_arm_log_level ,
210
223
"vchiq_init - done (slots %pK, phys %pad)" ,
211
224
vchiq_slot_zero , & slot_phys );
@@ -397,9 +410,14 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
397
410
for (i = 0 ; i < pagelistinfo -> num_pages ; i ++ )
398
411
put_page (pagelistinfo -> pages [i ]);
399
412
}
400
-
401
- dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
402
- pagelistinfo -> pagelist , pagelistinfo -> dma_addr );
413
+ if (pagelistinfo -> is_from_pool ) {
414
+ dma_pool_free (g_dma_pool , pagelistinfo -> pagelist ,
415
+ pagelistinfo -> dma_addr );
416
+ } else {
417
+ dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
418
+ pagelistinfo -> pagelist ,
419
+ pagelistinfo -> dma_addr );
420
+ }
403
421
}
404
422
405
423
/* There is a potential problem with partial cache lines (pages?)
@@ -419,6 +437,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
419
437
u32 * addrs ;
420
438
unsigned int num_pages , offset , i , k ;
421
439
int actual_pages ;
440
+ bool is_from_pool ;
422
441
size_t pagelist_size ;
423
442
struct scatterlist * scatterlist , * sg ;
424
443
int dma_buffers ;
@@ -445,10 +464,16 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
445
464
/* Allocate enough storage to hold the page pointers and the page
446
465
* list
447
466
*/
448
- pagelist = dma_zalloc_coherent (g_dev ,
449
- pagelist_size ,
450
- & dma_addr ,
451
- GFP_KERNEL );
467
+ if (pagelist_size > VCHIQ_DMA_POOL_SIZE ) {
468
+ pagelist = dma_zalloc_coherent (g_dev ,
469
+ pagelist_size ,
470
+ & dma_addr ,
471
+ GFP_KERNEL );
472
+ is_from_pool = false;
473
+ } else {
474
+ pagelist = dma_pool_zalloc (g_dma_pool , GFP_KERNEL , & dma_addr );
475
+ is_from_pool = true;
476
+ }
452
477
453
478
vchiq_log_trace (vchiq_arm_log_level , "%s - %pK" , __func__ , pagelist );
454
479
@@ -469,6 +494,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
469
494
pagelistinfo -> pagelist = pagelist ;
470
495
pagelistinfo -> pagelist_buffer_size = pagelist_size ;
471
496
pagelistinfo -> dma_addr = dma_addr ;
497
+ pagelistinfo -> is_from_pool = is_from_pool ;
472
498
pagelistinfo -> dma_dir = (type == PAGELIST_WRITE ) ?
473
499
DMA_TO_DEVICE : DMA_FROM_DEVICE ;
474
500
pagelistinfo -> num_pages = num_pages ;
0 commit comments