mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-06 02:28:03 +02:00
intel-gem: Don't do the GTT-pwrite shortcut on tiled buffers.
These will be covered by the fence, while pread/pwrite are supposed to be CPU-perspective writes, with manual detiling done by the client.
This commit is contained in:
parent
a5d8f35f0f
commit
bddb952578
1 changed files with 85 additions and 25 deletions
|
|
@ -165,18 +165,12 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
#include "drm_compat.h"
|
||||
|
||||
/**
|
||||
* Writes data to the object referenced by handle.
|
||||
*
|
||||
* On error, the contents of the buffer that were to be modified are undefined.
|
||||
*/
|
||||
int
|
||||
i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
static int
|
||||
i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
|
||||
struct drm_i915_gem_pwrite *args,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_i915_gem_pwrite *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
ssize_t remain;
|
||||
loff_t offset;
|
||||
char __user *user_data;
|
||||
|
|
@ -186,18 +180,6 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
|||
unsigned long pfn;
|
||||
unsigned long unwritten;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
||||
if (obj == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/** Bounds check destination.
|
||||
*
|
||||
* XXX: This could use review for overflow issues...
|
||||
*/
|
||||
if (args->offset > obj->size || args->size > obj->size ||
|
||||
args->offset + args->size > obj->size)
|
||||
return -EFAULT;
|
||||
|
||||
user_data = (char __user *) (uintptr_t) args->data_ptr;
|
||||
remain = args->size;
|
||||
if (!access_ok(VERIFY_READ, user_data, remain))
|
||||
|
|
@ -207,7 +189,6 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
|||
mutex_lock(&dev->struct_mutex);
|
||||
ret = i915_gem_object_pin(obj, 0);
|
||||
if (ret) {
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -283,13 +264,92 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
fail:
|
||||
i915_gem_object_unpin (obj);
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
|
||||
struct drm_i915_gem_pwrite *args,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
int ret;
|
||||
loff_t offset;
|
||||
ssize_t written;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
ret = i915_gem_set_domain(obj, file_priv,
|
||||
I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
|
||||
if (ret) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
offset = args->offset;
|
||||
|
||||
written = vfs_write(obj->filp,
|
||||
(char __user *)(uintptr_t) args->data_ptr,
|
||||
args->size, &offset);
|
||||
if (written != args->size) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (written < 0)
|
||||
return written;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data to the object referenced by handle.
|
||||
*
|
||||
* On error, the contents of the buffer that were to be modified are undefined.
|
||||
*/
|
||||
int
|
||||
i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_i915_gem_pwrite *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
int ret = 0;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
||||
if (obj == NULL)
|
||||
return -EINVAL;
|
||||
obj_priv = obj->driver_private;
|
||||
|
||||
/** Bounds check destination.
|
||||
*
|
||||
* XXX: This could use review for overflow issues...
|
||||
*/
|
||||
if (args->offset > obj->size || args->size > obj->size ||
|
||||
args->offset + args->size > obj->size)
|
||||
return -EFAULT;
|
||||
|
||||
/* We can only do the GTT pwrite on untiled buffers, as otherwise
|
||||
* it would end up going through the fenced access, and we'll get
|
||||
* different detiling behavior between reading and writing.
|
||||
* pread/pwrite currently are reading and writing from the CPU
|
||||
* perspective, requiring manual detiling by the client.
|
||||
*/
|
||||
if (obj_priv->tiling_mode == I915_TILING_NONE)
|
||||
ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
|
||||
else
|
||||
ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
|
||||
|
||||
#if WATCH_PWRITE
|
||||
if (ret)
|
||||
DRM_INFO("pwrite failed %d\n", ret);
|
||||
#endif
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue