77#include <linux/mutex.h>
88#include <linux/pagemap.h>
99#include <linux/sched.h>
10+ #include <linux/vmalloc.h>
1011
1112#if defined(MODS_HAS_SET_DMA_MASK )
1213#include <linux/dma-mapping.h>
@@ -489,6 +490,17 @@ static struct MODS_DMA_MAP *find_dma_map(struct MODS_MEM_INFO *p_mem_info,
489490 return NULL ;
490491}
491492
493+ static void free_mem_info (struct mods_client * client ,
494+ struct MODS_MEM_INFO * p_mem_info )
495+ {
496+ if (unlikely (p_mem_info -> large_aux ))
497+ vfree (p_mem_info );
498+ else
499+ kfree (p_mem_info );
500+
501+ atomic_dec (& client -> num_allocs );
502+ }
503+
492504/* In order to map pages as UC or WC to the CPU, we need to change their
493505 * attributes by calling set_memory_uc()/set_memory_wc(), respectively.
494506 * On some CPUs this operation is extremely slow. In order to incur
@@ -1022,15 +1034,15 @@ static int unregister_and_free_alloc(struct mods_client *client,
10221034
10231035 pci_dev_put (p_mem_info -> dev );
10241036
1025- kfree ( p_mem_info );
1037+ free_mem_info ( client , p_mem_info );
10261038 } else {
10271039 /* Decrement client num_pages manually if not releasing chunks */
10281040 atomic_sub ((int )p_mem_info -> num_pages , & client -> num_pages );
10291041 mutex_lock (& mem_reservation_mtx );
10301042 list_add (& p_mem_info -> list , & avail_mem_reservations );
10311043 mutex_unlock (& mem_reservation_mtx );
1044+ atomic_dec (& client -> num_allocs ); /* Don't indicate a leak in this client */
10321045 }
1033- atomic_dec (& client -> num_allocs ); /* always decrement to avoid leak */
10341046 err = OK ;
10351047 } else {
10361048 cl_error ("failed to unregister allocation %p\n" , p_del_mem );
@@ -1287,11 +1299,13 @@ static inline u32 calc_mem_info_size(u32 num_chunks, u8 cache_type)
12871299
12881300static void init_mem_info (struct MODS_MEM_INFO * p_mem_info ,
12891301 u32 num_chunks ,
1290- u8 cache_type )
1302+ u8 cache_type ,
1303+ u32 alloc_size )
12911304{
12921305 p_mem_info -> sg = p_mem_info -> alloc_sg ;
12931306 p_mem_info -> num_chunks = num_chunks ;
12941307 p_mem_info -> cache_type = cache_type ;
1308+ p_mem_info -> large_aux = alloc_size >= MODS_LARGE_AUX_ALLOC_SIZE ;
12951309
12961310 p_mem_info -> wc_bitmap = (unsigned long * )
12971311 & p_mem_info -> alloc_sg [num_chunks ];
@@ -1310,7 +1324,12 @@ static struct MODS_MEM_INFO *alloc_mem_info(struct mods_client *client,
13101324
13111325 * alloc_size = calc_size ;
13121326
1313- p_mem_info = kzalloc (calc_size , GFP_KERNEL | __GFP_NORETRY );
1327+ if (likely (calc_size < MODS_LARGE_AUX_ALLOC_SIZE ))
1328+ p_mem_info = kzalloc (calc_size , GFP_KERNEL | __GFP_NORETRY );
1329+ else {
1330+ p_mem_info = vmalloc (calc_size );
1331+ memset (p_mem_info , 0 , calc_size );
1332+ }
13141333
13151334 if (likely (p_mem_info )) {
13161335 atomic_inc (& client -> num_allocs );
@@ -1341,21 +1360,17 @@ static struct MODS_MEM_INFO *optimize_chunks(struct mods_client *client,
13411360 }
13421361
13431362 if (num_chunks < p_mem_info -> num_chunks )
1344- p_new_mem_info = alloc_mem_info (client , num_chunks ,
1345- p_mem_info -> cache_type ,
1346- & alloc_size );
1363+ p_new_mem_info = alloc_mem_info (client , num_chunks , p_mem_info -> cache_type , & alloc_size );
13471364
13481365 if (p_new_mem_info ) {
13491366 const size_t copy_size =
13501367 calc_mem_info_size_no_bitmap (num_chunks );
13511368
13521369 memcpy (p_new_mem_info , p_mem_info , copy_size );
1353- init_mem_info (p_new_mem_info , num_chunks ,
1354- p_mem_info -> cache_type );
1370+ init_mem_info (p_new_mem_info , num_chunks , p_mem_info -> cache_type , alloc_size );
13551371 copy_wc_bitmap (p_new_mem_info , 0 , p_mem_info , num_chunks );
13561372
1357- kfree (p_mem_info );
1358- atomic_dec (& client -> num_allocs );
1373+ free_mem_info (client , p_mem_info );
13591374
13601375 p_mem_info = p_new_mem_info ;
13611376 }
@@ -1451,8 +1466,7 @@ int esc_mods_alloc_pages_2(struct mods_client *client,
14511466
14521467 cache_type = (u8 )(p -> flags & MODS_ALLOC_CACHE_MASK );
14531468
1454- p_mem_info = alloc_mem_info (client , num_chunks , cache_type ,
1455- & alloc_size );
1469+ p_mem_info = alloc_mem_info (client , num_chunks , cache_type , & alloc_size );
14561470
14571471 if (unlikely (!p_mem_info )) {
14581472 cl_error ("failed to allocate auxiliary 0x%x bytes for %u chunks to hold %u pages\n" ,
@@ -1461,7 +1475,7 @@ int esc_mods_alloc_pages_2(struct mods_client *client,
14611475 goto failed ;
14621476 }
14631477
1464- init_mem_info (p_mem_info , num_chunks , cache_type );
1478+ init_mem_info (p_mem_info , num_chunks , cache_type , alloc_size );
14651479
14661480 p_mem_info -> num_pages = num_pages ;
14671481 p_mem_info -> dma32 = (p -> flags & MODS_ALLOC_DMA32 ) ? true : false;
@@ -1561,8 +1575,7 @@ int esc_mods_alloc_pages_2(struct mods_client *client,
15611575 release_chunks (client , p_mem_info );
15621576 pci_dev_put (p_mem_info -> dev );
15631577
1564- kfree (p_mem_info );
1565- atomic_dec (& client -> num_allocs );
1578+ free_mem_info (client , p_mem_info );
15661579 }
15671580
15681581 LOG_EXT ();
@@ -1949,8 +1962,7 @@ int esc_mods_merge_pages(struct mods_client *client,
19491962 }
19501963 }
19511964
1952- p_mem_info = alloc_mem_info (client , num_chunks , cache_type ,
1953- & alloc_size );
1965+ p_mem_info = alloc_mem_info (client , num_chunks , cache_type , & alloc_size );
19541966
19551967 if (unlikely (!p_mem_info )) {
19561968 err = - ENOMEM ;
@@ -1974,8 +1986,7 @@ int esc_mods_merge_pages(struct mods_client *client,
19741986 calc_mem_info_size_no_bitmap (other_chunks );
19751987
19761988 memcpy (p_mem_info , p_other , copy_size );
1977- init_mem_info (p_mem_info , num_chunks ,
1978- p_other -> cache_type );
1989+ init_mem_info (p_mem_info , num_chunks , p_other -> cache_type , alloc_size );
19791990 p_mem_info -> num_chunks = other_chunks ;
19801991 copy_wc_bitmap (p_mem_info , 0 , p_other , other_chunks );
19811992
@@ -1995,8 +2006,7 @@ int esc_mods_merge_pages(struct mods_client *client,
19952006 p_mem_info -> num_pages += p_other -> num_pages ;
19962007 }
19972008
1998- kfree (p_other );
1999- atomic_dec (& client -> num_allocs );
2009+ free_mem_info (client , p_other );
20002010 }
20012011
20022012 cl_debug (DEBUG_MEM , "merge alloc %p: %u chunks, %u pages\n" ,
@@ -2918,7 +2928,7 @@ void mods_free_mem_reservations(void)
29182928
29192929 release_chunks (client , p_mem_info );
29202930 pci_dev_put (p_mem_info -> dev );
2921- kfree ( p_mem_info );
2931+ free_mem_info ( client , p_mem_info );
29222932
29232933 ++ num_freed ;
29242934 }
0 commit comments