aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-11-21 21:49:37 -0500
committerEric Anholt <eric@anholt.net>2009-11-25 09:36:21 -0500
commitc8e0f93a381d1d76135e567f13a4418fce66fd95 (patch)
treeefa286f2e381d60b514c897cd148e5a824cce667
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>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c4
-rw-r--r--include/drm/drmP.h15
2 files changed, 16 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 2065b8f7e875..481c0ab888c8 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3563,8 +3563,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
3563 return -EINVAL; 3563 return -EINVAL;
3564 } 3564 }
3565 /* Copy in the exec list from userland */ 3565 /* Copy in the exec list from userland */
3566 exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count); 3566 exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
3567 object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count); 3567 object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
3568 if (exec_list == NULL || object_list == NULL) { 3568 if (exec_list == NULL || object_list == NULL) {
3569 DRM_ERROR("Failed to allocate exec or object list " 3569 DRM_ERROR("Failed to allocate exec or object list "
3570 "for %d buffers\n", 3570 "for %d buffers\n",
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index b0b36838ab11..1b807d0f6cdb 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)
1545 1545
1546static __inline__ void *drm_calloc_large(size_t nmemb, size_t size) 1546static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
1547{ 1547{
1548 if (size != 0 && nmemb > ULONG_MAX / size)
1549 return NULL;
1550
1548 if (size * nmemb <= PAGE_SIZE) 1551 if (size * nmemb <= PAGE_SIZE)
1549 return kcalloc(nmemb, size, GFP_KERNEL); 1552 return kcalloc(nmemb, size, GFP_KERNEL);
1550 1553
1554 return __vmalloc(size * nmemb,
1555 GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
1556}
1557
1558/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
1559static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
1560{
1551 if (size != 0 && nmemb > ULONG_MAX / size) 1561 if (size != 0 && nmemb > ULONG_MAX / size)
1552 return NULL; 1562 return NULL;
1553 1563
1564 if (size * nmemb <= PAGE_SIZE)
1565 return kmalloc(nmemb * size, GFP_KERNEL);
1566
1554 return __vmalloc(size * nmemb, 1567 return __vmalloc(size * nmemb,
1555 GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); 1568 GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
1556} 1569}
1557 1570
1558static __inline void drm_free_large(void *ptr) 1571static __inline void drm_free_large(void *ptr)