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>
59
60
#define BELL0 0x00
60
61
#define BELL2 0x08
61
62
63
+ #define VCHIQ_DMA_POOL_SIZE PAGE_SIZE
64
+
62
65
struct vchiq_2835_state {
63
66
int inited ;
64
67
VCHIQ_ARM_STATE_T arm_state ;
@@ -68,6 +71,7 @@ struct vchiq_pagelist_info {
68
71
PAGELIST_T * pagelist ;
69
72
size_t pagelist_buffer_size ;
70
73
dma_addr_t dma_addr ;
74
+ bool is_from_pool ;
71
75
enum dma_data_direction dma_dir ;
72
76
unsigned int num_pages ;
73
77
unsigned int pages_need_release ;
@@ -88,6 +92,7 @@ static void __iomem *g_regs;
88
92
* of 32.
89
93
*/
90
94
static unsigned int g_cache_line_size = 32 ;
95
+ static struct dma_pool * g_dma_pool ;
91
96
static unsigned int g_fragments_size ;
92
97
static char * g_fragments_base ;
93
98
static char * g_free_fragments ;
@@ -194,6 +199,14 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
194
199
}
195
200
196
201
g_dev = dev ;
202
+ g_dma_pool = dmam_pool_create ("vchiq_scatter_pool" , dev ,
203
+ VCHIQ_DMA_POOL_SIZE , g_cache_line_size ,
204
+ 0 );
205
+ if (!g_dma_pool ) {
206
+ dev_err (dev , "failed to create dma pool" );
207
+ return - ENOMEM ;
208
+ }
209
+
197
210
vchiq_log_info (vchiq_arm_log_level ,
198
211
"vchiq_init - done (slots %pK, phys %pad)" ,
199
212
vchiq_slot_zero , & slot_phys );
@@ -382,9 +395,14 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo)
382
395
for (i = 0 ; i < pagelistinfo -> num_pages ; i ++ )
383
396
put_page (pagelistinfo -> pages [i ]);
384
397
}
385
-
386
- dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
387
- pagelistinfo -> pagelist , pagelistinfo -> dma_addr );
398
+ if (pagelistinfo -> is_from_pool ) {
399
+ dma_pool_free (g_dma_pool , pagelistinfo -> pagelist ,
400
+ pagelistinfo -> dma_addr );
401
+ } else {
402
+ dma_free_coherent (g_dev , pagelistinfo -> pagelist_buffer_size ,
403
+ pagelistinfo -> pagelist ,
404
+ pagelistinfo -> dma_addr );
405
+ }
388
406
}
389
407
390
408
/* There is a potential problem with partial cache lines (pages?)
@@ -404,6 +422,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
404
422
u32 * addrs ;
405
423
unsigned int num_pages , offset , i , k ;
406
424
int actual_pages ;
425
+ bool is_from_pool ;
407
426
size_t pagelist_size ;
408
427
struct scatterlist * scatterlist , * sg ;
409
428
int dma_buffers ;
@@ -421,10 +440,16 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
421
440
/* Allocate enough storage to hold the page pointers and the page
422
441
* list
423
442
*/
424
- pagelist = dma_zalloc_coherent (g_dev ,
425
- pagelist_size ,
426
- & dma_addr ,
427
- GFP_KERNEL );
443
+ if (pagelist_size > VCHIQ_DMA_POOL_SIZE ) {
444
+ pagelist = dma_zalloc_coherent (g_dev ,
445
+ pagelist_size ,
446
+ & dma_addr ,
447
+ GFP_KERNEL );
448
+ is_from_pool = false;
449
+ } else {
450
+ pagelist = dma_pool_zalloc (g_dma_pool , GFP_KERNEL , & dma_addr );
451
+ is_from_pool = true;
452
+ }
428
453
429
454
vchiq_log_trace (vchiq_arm_log_level , "%s - %pK" , __func__ , pagelist );
430
455
@@ -445,6 +470,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
445
470
pagelistinfo -> pagelist = pagelist ;
446
471
pagelistinfo -> pagelist_buffer_size = pagelist_size ;
447
472
pagelistinfo -> dma_addr = dma_addr ;
473
+ pagelistinfo -> is_from_pool = is_from_pool ;
448
474
pagelistinfo -> dma_dir = (type == PAGELIST_WRITE ) ?
449
475
DMA_TO_DEVICE : DMA_FROM_DEVICE ;
450
476
pagelistinfo -> num_pages = num_pages ;
0 commit comments