浏览代码

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>
Eric Anholt 15 年之前
父节点
当前提交
c8e0f93a38
共有 2 个文件被更改,包括 16 次插入3 次删除
  1. 2 2
      drivers/gpu/drm/i915/i915_gem.c
  2. 14 1
      include/drm/drmP.h

+ 2 - 2
drivers/gpu/drm/i915/i915_gem.c

@@ -3563,8 +3563,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 		return -EINVAL;
 	}
 	/* Copy in the exec list from userland */
-	exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count);
-	object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count);
+	exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
+	object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
 	if (exec_list == NULL || object_list == NULL) {
 		DRM_ERROR("Failed to allocate exec or object list "
 			  "for %d buffers\n",

+ 14 - 1
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)