2222#include <linux/platform_device.h>
2323#include <linux/compat.h>
2424#include <linux/dma-mapping.h>
25+ #include <linux/dmapool.h>
2526#include <linux/rcupdate.h>
2627#include <linux/delay.h>
2728#include <linux/slab.h>
5152
5253#define ARM_DS_ACTIVE BIT(2)
5354
55+ #define VCHIQ_DMA_POOL_SIZE PAGE_SIZE
56+
5457/* Override the default prefix, which would be vchiq_arm (from the filename) */
5558#undef MODULE_PARAM_PREFIX
5659#define MODULE_PARAM_PREFIX DEVICE_NAME "."
@@ -128,6 +131,7 @@ struct vchiq_pagelist_info {
128131 struct pagelist * pagelist ;
129132 size_t pagelist_buffer_size ;
130133 dma_addr_t dma_addr ;
134+ bool is_from_pool ;
131135 enum dma_data_direction dma_dir ;
132136 unsigned int num_pages ;
133137 unsigned int pages_need_release ;
@@ -148,6 +152,7 @@ static void __iomem *g_regs;
148152 * of 32.
149153 */
150154static unsigned int g_cache_line_size = 32 ;
155+ static struct dma_pool * g_dma_pool ;
151156static unsigned int g_use_36bit_addrs = 0 ;
152157static unsigned int g_fragments_size ;
153158static char * g_fragments_base ;
@@ -190,8 +195,13 @@ cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info
190195 if (pagelistinfo -> pages_need_release )
191196 unpin_user_pages (pagelistinfo -> pages , pagelistinfo -> num_pages );
192197
193- dma_free_coherent (instance -> state -> dev , pagelistinfo -> pagelist_buffer_size ,
194- pagelistinfo -> pagelist , pagelistinfo -> dma_addr );
198+ if (pagelistinfo -> is_from_pool ) {
199+ dma_pool_free (g_dma_pool , pagelistinfo -> pagelist ,
200+ pagelistinfo -> dma_addr );
201+ } else {
202+ dma_free_coherent (instance -> state -> dev , pagelistinfo -> pagelist_buffer_size ,
203+ pagelistinfo -> pagelist , pagelistinfo -> dma_addr );
204+ }
195205}
196206
197207static inline bool
@@ -226,6 +236,7 @@ create_pagelist(struct vchiq_instance *instance, char *buf, char __user *ubuf,
226236 u32 * addrs ;
227237 unsigned int num_pages , offset , i , k ;
228238 int actual_pages ;
239+ bool is_from_pool ;
229240 size_t pagelist_size ;
230241 struct scatterlist * scatterlist , * sg ;
231242 int dma_buffers ;
@@ -255,8 +266,14 @@ create_pagelist(struct vchiq_instance *instance, char *buf, char __user *ubuf,
255266 /* Allocate enough storage to hold the page pointers and the page
256267 * list
257268 */
258- pagelist = dma_alloc_coherent (instance -> state -> dev , pagelist_size , & dma_addr ,
259- GFP_KERNEL );
269+ if (pagelist_size > VCHIQ_DMA_POOL_SIZE ) {
270+ pagelist = dma_alloc_coherent (instance -> state -> dev , pagelist_size , & dma_addr ,
271+ GFP_KERNEL );
272+ is_from_pool = false;
273+ } else {
274+ pagelist = dma_pool_alloc (g_dma_pool , GFP_KERNEL , & dma_addr );
275+ is_from_pool = true;
276+ }
260277
261278 vchiq_log_trace (vchiq_arm_log_level , "%s - %pK" , __func__ , pagelist );
262279
@@ -277,6 +294,7 @@ create_pagelist(struct vchiq_instance *instance, char *buf, char __user *ubuf,
277294 pagelistinfo -> pagelist = pagelist ;
278295 pagelistinfo -> pagelist_buffer_size = pagelist_size ;
279296 pagelistinfo -> dma_addr = dma_addr ;
297+ pagelistinfo -> is_from_pool = is_from_pool ;
280298 pagelistinfo -> dma_dir = (type == PAGELIST_WRITE ) ?
281299 DMA_TO_DEVICE : DMA_FROM_DEVICE ;
282300 pagelistinfo -> num_pages = num_pages ;
@@ -617,6 +635,13 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state
617635 }
618636
619637 g_dma_dev = dma_dev ?: dev ;
638+ g_dma_pool = dmam_pool_create ("vchiq_scatter_pool" , dev ,
639+ VCHIQ_DMA_POOL_SIZE , g_cache_line_size ,
640+ 0 );
641+ if (!g_dma_pool ) {
642+ dev_err (dev , "failed to create dma pool" );
643+ return - ENOMEM ;
644+ }
620645
621646 vchiq_log_info (vchiq_arm_log_level , "vchiq_init - done (slots %pK, phys %pad)" ,
622647 vchiq_slot_zero , & slot_phys );
0 commit comments