diff options
author | Ashutosh Dixit <ashutosh.dixit@intel.com> | 2021-03-15 15:53:56 -0700 |
---|---|---|
committer | Ashutosh Dixit <ashutosh.dixit@intel.com> | 2021-03-17 15:24:36 -0700 |
commit | ad5eb02eb3f10a41d0f1feba7efc02db87cd06b8 (patch) | |
tree | 95ddc30b5588748c68f6f81f6f01ef6617fd258b /lib/ioctl_wrappers.c | |
parent | b3eff02d5400944dd7b14896037bc9bbf362343e (diff) |
lib/ioctl_wrappers: Keep IGT 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. This means IGT must handle
the absence of these ioctls. This patch does this by modifying
gem_read() and gem_write() 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.
Callers who must absolutely use the pread/pwrite ioctls (such as tests
which test these ioctls or must otherwise only use the pread/pwrite
ioctls) must use gem_require_pread_pwrite() to skip when these ioctls
are not available.
v1: Removed __gem_pread, gem_pread, __gem_pwrite and gem_pwrite
introduced previously since they are not necessary,
gem_require_pread_pwrite is sufficient
v2: Fix CI failures in gem_advise and gen9_exec_parse by introducing
gem_require_pread_pwrite
v3: Skip mmap for 0 length read/write's
v4: Remove redundant igt_assert's
v5: Re-run
v6: s/EOPNOTSUPP/-EOPNOTSUPP/
v7: Rebase on latest master, skip gem_exec_parallel@userptr with
gem_require_pread_pwrite
v8: Re-run
v9: Rebase
Acked-by: Dave Airlie <airlied@redhat.com>
Acked-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Zbigniew KempczyĆski <zbigniew.kempczynski@intel.com>
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Diffstat (limited to 'lib/ioctl_wrappers.c')
-rw-r--r-- | lib/ioctl_wrappers.c | 135 |
1 files changed, 129 insertions, 6 deletions
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c index 45415621..4440004c 100644 --- a/lib/ioctl_wrappers.c +++ b/lib/ioctl_wrappers.c @@ -56,6 +56,7 @@ #include "igt_debugfs.h" #include "igt_sysfs.h" #include "config.h" +#include "i915/gem_mman.h" #ifdef HAVE_VALGRIND #include <valgrind/valgrind.h> @@ -324,6 +325,70 @@ void gem_close(int fd, uint32_t handle) do_ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo); } +static bool is_cache_coherent(int fd, uint32_t handle) +{ + return gem_get_caching(fd, handle) != I915_CACHING_NONE; +} + +static void mmap_write(int fd, uint32_t handle, uint64_t offset, + const void *buf, uint64_t length) +{ + void *map = NULL; + + if (!length) + return; + + if (is_cache_coherent(fd, handle)) { + /* offset arg for mmap functions must be 0 */ + map = __gem_mmap__cpu_coherent(fd, handle, 0, offset + length, + PROT_READ | PROT_WRITE); + if (map) + gem_set_domain(fd, handle, + I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + } + + if (!map) { + map = __gem_mmap_offset__wc(fd, handle, 0, offset + length, + PROT_READ | PROT_WRITE); + if (!map) + map = gem_mmap__wc(fd, handle, 0, offset + length, + PROT_READ | PROT_WRITE); + gem_set_domain(fd, handle, + I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC); + } + + memcpy(map + offset, buf, length); + munmap(map, offset + length); +} + +static void mmap_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length) +{ + void *map = NULL; + + if (!length) + return; + + if (gem_has_llc(fd) || is_cache_coherent(fd, handle)) { + /* offset arg for mmap functions must be 0 */ + map = __gem_mmap__cpu_coherent(fd, handle, 0, + offset + length, PROT_READ); + if (map) + gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, 0); + } + + if (!map) { + map = __gem_mmap_offset__wc(fd, handle, 0, offset + length, + PROT_READ); + if (!map) + map = gem_mmap__wc(fd, handle, 0, offset + length, + PROT_READ); + gem_set_domain(fd, handle, I915_GEM_DOMAIN_WC, 0); + } + + memcpy(buf, map + offset, length); + munmap(map, offset + length); +} + int __gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint64_t length) { struct drm_i915_gem_pwrite gem_pwrite; @@ -349,12 +414,18 @@ int __gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint6 * @buf: pointer to the data to write into the buffer * @length: size of the subrange * - * This wraps the PWRITE ioctl, which is to upload a linear data to a subrange - * of a gem buffer object. + * Method to write to a gem object. Uses the PWRITE ioctl when it is + * available, else it uses mmap + memcpy to upload linear data to a + * subrange of a gem buffer object. */ void gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint64_t length) { - igt_assert_eq(__gem_write(fd, handle, offset, buf, length), 0); + int ret = __gem_write(fd, handle, offset, buf, length); + + igt_assert(ret == 0 || ret == -EOPNOTSUPP); + + if (ret == -EOPNOTSUPP) + mmap_write(fd, handle, offset, buf, length); } int __gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length) @@ -381,12 +452,64 @@ int __gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t len * @buf: pointer to the data to read into * @length: size of the subrange * - * This wraps the PREAD ioctl, which is to download a linear data to a subrange - * of a gem buffer object. + * Method to read from a gem object. Uses the PREAD ioctl when it is + * available, else it uses mmap + memcpy to download linear data from a + * subrange of a gem buffer object. */ void gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length) { - igt_assert_eq(__gem_read(fd, handle, offset, buf, length), 0); + int ret = __gem_read(fd, handle, offset, buf, length); + + igt_assert(ret == 0 || ret == -EOPNOTSUPP); + + if (ret == -EOPNOTSUPP) + mmap_read(fd, handle, offset, buf, length); +} + +/** + * gem_has_pwrite + * @fd: open i915 drm file descriptor + * + * Feature test macro to query whether pwrite ioctl is supported + */ +bool gem_has_pwrite(int fd) +{ + uint32_t handle = gem_create(fd, 4096); + int buf, ret; + + ret = __gem_write(fd, handle, 0, &buf, sizeof(buf)); + gem_close(fd, handle); + + return ret != -EOPNOTSUPP; +} + +/** + * gem_has_pread + * @fd: open i915 drm file descriptor + * + * Feature test macro to query whether pread ioctl is supported + */ +bool gem_has_pread(int fd) +{ + uint32_t handle = gem_create(fd, 4096); + int buf, ret; + + ret = __gem_read(fd, handle, 0, &buf, sizeof(buf)); + gem_close(fd, handle); + + return ret != -EOPNOTSUPP; +} + +/** + * gem_require_pread_pwrite + * @fd: open i915 drm file descriptor + * + * Feature test macro to query whether pread/pwrite ioctls are supported + * and skip if they are not + */ +void gem_require_pread_pwrite(int fd) +{ + igt_require(gem_has_pread(fd) && gem_has_pwrite(fd)); } int __gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write) |