@@ -232,6 +232,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_EXEC_SOFTPIN:
value = 1;
break;
+ case I915_PARAM_CREATE_VERSION:
+ value = 2;
+ break;
default:
DRM_DEBUG("Unknown parameter %d\n", param->param);
return -EINVAL;
@@ -3383,7 +3383,7 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
int i915_gem_init_stolen(struct drm_device *dev);
void i915_gem_cleanup_stolen(struct drm_device *dev);
struct drm_i915_gem_object *
-i915_gem_object_create_stolen(struct drm_device *dev, u32 size);
+i915_gem_object_create_stolen(struct drm_device *dev, u64 size);
struct drm_i915_gem_object *
i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
u32 stolen_offset,
@@ -384,10 +384,36 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj)
kmem_cache_free(dev_priv->objects, obj);
}
+static struct drm_i915_gem_object *
+i915_gem_alloc_object_stolen(struct drm_device *dev, size_t size)
+{
+ struct drm_i915_gem_object *obj;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+ obj = i915_gem_object_create_stolen(dev, size);
+ if (!obj) {
+ mutex_unlock(&dev->struct_mutex);
+ return NULL;
+ }
+
+ /* Always clear fresh buffers before handing to userspace */
+ ret = i915_gem_object_clear(obj);
+ if (ret) {
+ drm_gem_object_unreference(&obj->base);
+ mutex_unlock(&dev->struct_mutex);
+ return NULL;
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+ return obj;
+}
+
static int
i915_gem_create(struct drm_file *file,
struct drm_device *dev,
uint64_t size,
+ uint64_t flags,
uint32_t *handle_p)
{
struct drm_i915_gem_object *obj;
@@ -398,8 +424,21 @@ i915_gem_create(struct drm_file *file,
if (size == 0)
return -EINVAL;
+ if (flags & __I915_CREATE_UNKNOWN_FLAGS)
+ return -EINVAL;
+
/* Allocate the new object */
- obj = i915_gem_alloc_object(dev, size);
+ switch (flags & I915_CREATE_PLACEMENT_MASK) {
+ case I915_CREATE_PLACEMENT_NORMAL:
+ obj = i915_gem_alloc_object(dev, size);
+ break;
+ case I915_CREATE_PLACEMENT_STOLEN:
+ obj = i915_gem_alloc_object_stolen(dev, size);
+ break;
+ default:
+ return -EINVAL;
+ }
+
if (obj == NULL)
return -ENOMEM;
@@ -422,7 +461,7 @@ i915_gem_dumb_create(struct drm_file *file,
args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64);
args->size = args->pitch * args->height;
return i915_gem_create(file, dev,
- args->size, &args->handle);
+ args->size, 0, &args->handle);
}
/**
@@ -435,7 +474,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_i915_gem_create *args = data;
return i915_gem_create(file, dev,
- args->size, &args->handle);
+ args->size, args->flags, &args->handle);
}
static inline int
@@ -595,7 +595,7 @@ cleanup:
}
struct drm_i915_gem_object *
-i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
+i915_gem_object_create_stolen(struct drm_device *dev, u64 size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj;
@@ -605,7 +605,7 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
if (!drm_mm_initialized(&dev_priv->mm.stolen))
return NULL;
- DRM_DEBUG_KMS("creating stolen object: size=%x\n", size);
+ DRM_DEBUG_KMS("creating stolen object: size=%llx\n", size);
if (size == 0)
return NULL;
@@ -357,6 +357,7 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_GPU_RESET 35
#define I915_PARAM_HAS_RESOURCE_STREAMER 36
#define I915_PARAM_HAS_EXEC_SOFTPIN 37
+#define I915_PARAM_CREATE_VERSION 38
typedef struct drm_i915_getparam {
__s32 param;
@@ -456,6 +457,46 @@ struct drm_i915_gem_create {
*/
__u32 handle;
__u32 pad;
+ /**
+ * Requested flags (currently used for placement
+ * (which memory domain))
+ *
+ * You can request that the object be created from special memory
+ * rather than regular system pages using this parameter. Such
+ * irregular objects may have certain restrictions (such as CPU
+ * access to a stolen object is verboten).
+ *
+ * This can be used in the future for other purposes too
+ * e.g. specifying tiling/caching/madvise
+ */
+ __u64 flags;
+#define I915_CREATE_PLACEMENT_NORMAL 0 /* standard swappable bo */
+/* Allocate the object from memory reserved for the igfx (stolen).
+ *
+ * Objects allocated from stolen are restricted in the API they can use,
+ * as direct CPU access to stolen memory is prohibited by the system.
+ * This means that you cannot use a regular CPU mmap (either using WB
+ * or with the WC extension). You can still use a GTT mmap, pwrite,
+ * pread and pass it around for use by execbuffer and between processes
+ * like normal.
+ *
+ * Stolen memory is a very limited resource and certain functions of the
+ * hardware can only work from within stolen memory. Userspace's
+ * allocations may be evicted from stolen and moved to normal memory as
+ * required. If the allocation is marked as purgeable (using madvise),
+ * the allocation will be dropped and further access to the object's
+ * backing storage will result in -EFAULT. Stolen objects will also be
+ * migrated to normal memory across suspend and resume, as the stolen
+ * memory is not preserved.
+ *
+ * Stolen memory is regarded as a resource placement hint, most suitable
+ * for medium-sized buffers that are only accessed by the GPU and can be
+ * discarded.
+ */
+#define I915_CREATE_PLACEMENT_STOLEN 1 /* Cannot use CPU mmaps */
+
+#define I915_CREATE_PLACEMENT_MASK 0xff
+#define __I915_CREATE_UNKNOWN_FLAGS ~I915_CREATE_PLACEMENT_MASK
};
struct drm_i915_gem_pread {