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 );
@@ -394,9 +407,14 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
394
407
for (i = 0 ; i < pagelistinfo -> num_pages ; i ++ )
395
408
put_page (pagelistinfo -> pages [i ]);
396
409
}
397
-
398
- dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
399
- pagelistinfo -> pagelist , pagelistinfo -> dma_addr );
410
+ if (pagelistinfo -> is_from_pool ) {
411
+ dma_pool_free (g_dma_pool , pagelistinfo -> pagelist ,
412
+ pagelistinfo -> dma_addr );
413
+ } else {
414
+ dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
415
+ pagelistinfo -> pagelist ,
416
+ pagelistinfo -> dma_addr );
417
+ }
400
418
}
401
419
402
420
/* There is a potential problem with partial cache lines (pages?)
@@ -416,6 +434,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
416
434
u32 * addrs ;
417
435
unsigned int num_pages , offset , i , k ;
418
436
int actual_pages ;
437
+ bool is_from_pool ;
419
438
size_t pagelist_size ;
420
439
struct scatterlist * scatterlist , * sg ;
421
440
int dma_buffers ;
@@ -433,10 +452,16 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
433
452
/* Allocate enough storage to hold the page pointers and the page
434
453
* list
435
454
*/
436
- pagelist = dma_zalloc_coherent (g_dev ,
437
- pagelist_size ,
438
- & dma_addr ,
439
- GFP_KERNEL );
455
+ if (pagelist_size > VCHIQ_DMA_POOL_SIZE ) {
456
+ pagelist = dma_zalloc_coherent (g_dev ,
457
+ pagelist_size ,
458
+ & dma_addr ,
459
+ GFP_KERNEL );
460
+ is_from_pool = false;
461
+ } else {
462
+ pagelist = dma_pool_zalloc (g_dma_pool , GFP_KERNEL , & dma_addr );
463
+ is_from_pool = true;
464
+ }
440
465
441
466
vchiq_log_trace (vchiq_arm_log_level , "%s - %pK" , __func__ , pagelist );
442
467
@@ -457,6 +482,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
457
482
pagelistinfo -> pagelist = pagelist ;
458
483
pagelistinfo -> pagelist_buffer_size = pagelist_size ;
459
484
pagelistinfo -> dma_addr = dma_addr ;
485
+ pagelistinfo -> is_from_pool = is_from_pool ;
460
486
pagelistinfo -> dma_dir = (type == PAGELIST_WRITE ) ?
461
487
DMA_TO_DEVICE : DMA_FROM_DEVICE ;
462
488
pagelistinfo -> num_pages = num_pages ;
0 commit comments