summaryrefslogtreecommitdiff
path: root/lib/ioctl_wrappers.c
diff options
context:
space:
mode:
authorAshutosh Dixit <ashutosh.dixit@intel.com>2021-03-15 15:53:56 -0700
committerAshutosh Dixit <ashutosh.dixit@intel.com>2021-03-17 15:24:36 -0700
commitad5eb02eb3f10a41d0f1feba7efc02db87cd06b8 (patch)
tree95ddc30b5588748c68f6f81f6f01ef6617fd258b /lib/ioctl_wrappers.c
parentb3eff02d5400944dd7b14896037bc9bbf362343e (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.c135
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)