diff options
author | Ashutosh Dixit <ashutosh.dixit@intel.com> | 2020-09-21 17:34:16 -0700 |
---|---|---|
committer | Ashutosh Dixit <ashutosh.dixit@intel.com> | 2021-03-22 15:22:31 -0700 |
commit | cd3681976c3bbefa08236be86551c11bd4599c88 (patch) | |
tree | 5fe9be01a413fcdec467c046ac02698d50a6d580 /intel | |
parent | 52f05d3d896480ee5431dcd444f53bb2a8e41cce (diff) | |
download | drm-cd3681976c3bbefa08236be86551c11bd4599c88.tar.gz |
intel: Keep libdrm working without pread/pwrite ioctls
The general direction at this time is to phase out pread/write ioctls and
not support them in future products. The ioctls have already been disabled
in i915 for future products. This means libdrm must handle the absence of
these ioctls. This patch does this by modifying drm_intel_gem_bo_subdata()
and drm_intel_gem_bo_get_subdata() to do the read/write using the
pread/pwrite ioctls first but when these ioctls are unavailable fall back
to doing the read/write using a combination of mmap and memcpy.
A similar solution was added to igt-gpu-tools in commit
ad5eb02eb3 ("lib/ioctl_wrappers: Keep IGT working without pread/pwrite
ioctls").
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Diffstat (limited to 'intel')
-rw-r--r-- | intel/intel_bufmgr_gem.c | 96 |
1 files changed, 92 insertions, 4 deletions
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index 023af61f..3c522eab 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -1732,6 +1732,82 @@ drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo) return drm_intel_gem_bo_unmap(bo); } +static bool is_cache_coherent(drm_intel_bo *bo) +{ + drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + struct drm_i915_gem_caching arg = {}; + + arg.handle = bo_gem->gem_handle; + if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_CACHING, &arg)) + assert(false); + return arg.caching != I915_CACHING_NONE; +} + +static void set_domain(drm_intel_bo *bo, uint32_t read, uint32_t write) +{ + drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + struct drm_i915_gem_set_domain arg = {}; + + arg.handle = bo_gem->gem_handle; + arg.read_domains = read; + arg.write_domain = write; + if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &arg)) + assert(false); +} + +static int mmap_write(drm_intel_bo *bo, unsigned long offset, + unsigned long length, const void *buf) +{ + void *map = NULL; + + if (!length) + return 0; + + if (is_cache_coherent(bo)) { + map = drm_intel_gem_bo_map__cpu(bo); + if (map) + set_domain(bo, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + } + if (!map) { + map = drm_intel_gem_bo_map__wc(bo); + if (map) + set_domain(bo, I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC); + } + + assert(map); + memcpy((char *)map + offset, buf, length); + drm_intel_gem_bo_unmap(bo); + return 0; +} + +static int mmap_read(drm_intel_bo *bo, unsigned long offset, + unsigned long length, void *buf) +{ + drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + void *map = NULL; + + if (!length) + return 0; + + if (bufmgr_gem->has_llc || is_cache_coherent(bo)) { + map = drm_intel_gem_bo_map__cpu(bo); + if (map) + set_domain(bo, I915_GEM_DOMAIN_CPU, 0); + } + if (!map) { + map = drm_intel_gem_bo_map__wc(bo); + if (map) + set_domain(bo, I915_GEM_DOMAIN_WC, 0); + } + + assert(map); + memcpy(buf, (char *)map + offset, length); + drm_intel_gem_bo_unmap(bo); + return 0; +} + static int drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset, unsigned long size, const void *data) @@ -1752,14 +1828,20 @@ drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset, ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite); - if (ret != 0) { + if (ret) ret = -errno; + + if (ret != 0 && ret != -EOPNOTSUPP) { DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n", __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, (int)size, strerror(errno)); + return ret; } - return ret; + if (ret == -EOPNOTSUPP) + mmap_write(bo, offset, size, data); + + return 0; } static int @@ -1807,14 +1889,20 @@ drm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PREAD, &pread); - if (ret != 0) { + if (ret) ret = -errno; + + if (ret != 0 && ret != -EOPNOTSUPP) { DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n", __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, (int)size, strerror(errno)); + return ret; } - return ret; + if (ret == -EOPNOTSUPP) + mmap_read(bo, offset, size, data); + + return 0; } /** Waits for all GPU rendering with the object to have completed. */ |