summaryrefslogtreecommitdiffstats
path: root/include/drm
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-11-22 03:49:37 +0100
committerEric Anholt <eric@anholt.net>2009-11-25 06:36:21 -0800
commitc8e0f93a381d1d76135e567f13a4418fce66fd95 (patch)
treeefa286f2e381d60b514c897cd148e5a824cce667 /include/drm
parent5b8f0be0dce012d190a53d55240fe3fde6306476 (diff)
drm/i915: Replace a calloc followed by copying data over it with malloc.
Execbufs involve quite a bit of payload, to the extent that cache misses show up in the profiles here, and a suspicion that some of those cachelines may get evicted and then reloaded in the subsequent copy. This is still abstracted like drm_calloc_large since we want to check for size overflow, and because we want to choose between kmalloc and vmalloc on the fly. cairo's interface for malloc-with-calloc's-args was used as the model. Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'include/drm')
-rw-r--r--include/drm/drmP.h15
1 files changed, 14 insertions, 1 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index b0b36838ab1..1b807d0f6cd 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1545,14 +1545,27 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map)
static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
{
+ if (size != 0 && nmemb > ULONG_MAX / size)
+ return NULL;
+
if (size * nmemb <= PAGE_SIZE)
return kcalloc(nmemb, size, GFP_KERNEL);
+ return __vmalloc(size * nmemb,
+ GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+}
+
+/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
+static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
+{
if (size != 0 && nmemb > ULONG_MAX / size)
return NULL;
+ if (size * nmemb <= PAGE_SIZE)
+ return kmalloc(nmemb * size, GFP_KERNEL);
+
return __vmalloc(size * nmemb,
- GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+ GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
}
static __inline void drm_free_large(void *ptr)