diff options
author | Greg Hartman <ghartman@google.com> | 2019-07-11 17:40:40 -0700 |
---|---|---|
committer | Greg Hartman <ghartman@google.com> | 2019-07-11 17:43:12 -0700 |
commit | b13cae464cd3de87e42dbeb8257ea0ef41cfe282 (patch) | |
tree | 1a7d1b407c04e79fde0f04607e2bb3bddc6c6799 | |
parent | 1edaa80c2112b8a78deaf549ec282c7187dbf840 (diff) | |
parent | 681e860638e5fc6eed856bda1f6a087473afc793 (diff) | |
download | libdrm-pie-gsi.tar.gz |
Merge aosp/master into aosp/pie-gsipie-gsi
BUG: 123765087
BUG: 123764798 (Milestone)
BUG: 77276633 (OKR)
Test: Builds
Change-Id: Id8c2e6140ac987f8dd1c0f189559459bbb51dbc3
268 files changed, 14251 insertions, 7778 deletions
diff --git a/.editorconfig b/.editorconfig index 893b7be0..29b4f393 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,3 +17,7 @@ indent_style = tab [*.m4] indent_style = space indent_size = 2 + +[{meson.build,meson_options.txt}] +indent_style = space +indent_size = 2 @@ -1,6 +1,3 @@ -bsd-core/*/@ -bsd-core/*/machine -*~ *.1 *.3 *.5 @@ -17,17 +14,22 @@ bsd-core/*/machine *.o.cmd *.sw? *.trs +*~ +.*check* +.*install* .depend .deps .libs .tmp_versions -.*check* -.*install* +/_build* +/build* Makefile Makefile.in TAGS aclocal.m4 autom4te.cache +bsd-core/*/@ +bsd-core/*/machine build-aux bus_if.h compile @@ -47,21 +49,22 @@ drm_pciids.h export_syms i915.kld install-sh -libdrm/config.h.in libdrm.pc +libdrm/config.h.in +libdrm_amdgpu.pc +libdrm_etnaviv.pc +libdrm_exynos.pc +libdrm_freedreno.pc libdrm_intel.pc libdrm_nouveau.pc -libdrm_radeon.pc libdrm_omap.pc -libdrm_exynos.pc -libdrm_freedreno.pc -libdrm_amdgpu.pc +libdrm_radeon.pc libdrm_vc4.pc -libdrm_etnaviv.pc libkms.pc libtool ltmain.sh mach64.kld +man/*.3 man/.man_fixup mga.kld missing @@ -74,35 +77,34 @@ savage.kld sis.kld stamp-h1 tdfx.kld -via.kld -tests/auth tests/amdgpu/amdgpu_test +tests/auth tests/dristat tests/drmdevice tests/drmsl tests/drmstat +tests/etnaviv/etnaviv_2d_test +tests/etnaviv/etnaviv_bo_cache_test +tests/etnaviv/etnaviv_cmd_stream_test +tests/exynos/exynos_fimg2d_event +tests/exynos/exynos_fimg2d_perf +tests/exynos/exynos_fimg2d_test tests/getclient tests/getstats tests/getversion tests/hash +tests/kms/kms-steal-crtc +tests/kms/kms-universal-planes +tests/kmstest/kmstest tests/lock -tests/openclose -tests/random -tests/setversion -tests/updatedraw tests/modeprint/modeprint tests/modetest/modetest tests/name_from_fd +tests/openclose tests/proptest/proptest -tests/kms/kms-steal-crtc -tests/kms/kms-universal-planes -tests/kmstest/kmstest -tests/vbltest/vbltest tests/radeon/radeon_ttm -tests/exynos/exynos_fimg2d_event -tests/exynos/exynos_fimg2d_perf -tests/exynos/exynos_fimg2d_test -tests/etnaviv/etnaviv_2d_test -tests/etnaviv/etnaviv_cmd_stream_test -tests/etnaviv/etnaviv_bo_cache_test -man/*.3 +tests/random +tests/setversion +tests/updatedraw +tests/vbltest/vbltest +via.kld diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..a0edfdff --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,159 @@ +.artifacts-meson: &artifacts-meson + when: always + paths: + - _build/meson-logs + +.artifacts-autotools: &artifacts-autotools + when: always + paths: + - _build/*.log + - _build/*/*.log + - _build/*/*/*.log + +.meson-build: &meson-build + - meson _build + -D amdgpu=true + -D cairo-tests=true + -D etnaviv=true + -D exynos=true + -D freedreno=true + -D freedreno-kgsl=true + -D intel=true + -D libkms=true + -D man-pages=true + -D nouveau=true + -D omap=true + -D radeon=true + -D tegra=true + -D udev=true + -D valgrind=true + -D vc4=true + -D vmwgfx=true + - ninja -C _build + - ninja -C _build test + +.autotools-build: &autotools-build + - mkdir _build + - cd _build + - ../autogen.sh + --enable-udev + --enable-libkms + --enable-intel + --enable-radeon + --enable-amdgpu + --enable-nouveau + --enable-vmwgfx + --enable-omap-experimental-api + --enable-exynos-experimental-api + --enable-freedreno + --enable-freedreno-kgsl + --enable-tegra-experimental-api + --enable-vc4 + --enable-etnaviv-experimental-api + - make + - make check + +latest-meson: + stage: build + image: base/archlinux:latest + before_script: + - pacman -Syu --noconfirm --needed + base-devel + meson + libpciaccess + libxslt docbook-xsl + valgrind + libatomic_ops + cairo cunit + script: *meson-build + +latest-autotools: + stage: build + image: base/archlinux:latest + artifacts: *artifacts-autotools + before_script: + - pacman -Syu --noconfirm --needed + base-devel + libpciaccess + libxslt docbook-xsl + valgrind + libatomic_ops + cairo cunit + xorg-util-macros + git # autogen.sh depends on git + script: *autotools-build + +oldest-meson: + stage: build + image: debian:stable + artifacts: *artifacts-meson + before_script: + - printf > /etc/dpkg/dpkg.cfg.d/99-exclude-cruft "%s\n" + 'path-exclude=/usr/share/doc/*' + 'path-exclude=/usr/share/man/*' + - printf > /usr/sbin/policy-rc.d "%s\n" + '#!/bin/sh' + 'exit 101' + - chmod +x /usr/sbin/policy-rc.d + - apt-get update + - apt-get -y --no-install-recommends install + build-essential + pkg-config + xsltproc + libxslt1-dev docbook-xsl + valgrind + libatomic-ops-dev + libcairo2-dev libcunit1-dev + ninja-build + python3 python3-pip + wget + # We need `--no-check-certificate` here because Debian's CA list is + # too old to know about LetsEncrypt's CA, so it refuses to connect + # to FreeDesktop.org + - LIBPCIACCESS_VERSION=libpciaccess-0.10 && + wget --no-check-certificate https://xorg.freedesktop.org/releases/individual/lib/$LIBPCIACCESS_VERSION.tar.bz2 && + tar -jxvf $LIBPCIACCESS_VERSION.tar.bz2 && + (cd $LIBPCIACCESS_VERSION && ./configure --prefix=$HOME/prefix && make install) + - pip3 install wheel setuptools + - pip3 install meson==0.43 + - export PKG_CONFIG_PATH=$HOME/prefix/lib/pkgconfig:$HOME/prefix/share/pkgconfig + - export LD_LIBRARY_PATH="$HOME/prefix/lib:$LD_LIBRARY_PATH" + script: *meson-build + +oldest-autotools: + stage: build + image: debian:stable + artifacts: *artifacts-autotools + before_script: + - printf > /etc/dpkg/dpkg.cfg.d/99-exclude-cruft "%s\n" + 'path-exclude=/usr/share/doc/*' + 'path-exclude=/usr/share/man/*' + - printf > /usr/sbin/policy-rc.d "%s\n" + '#!/bin/sh' + 'exit 101' + - chmod +x /usr/sbin/policy-rc.d + - apt-get update + - apt-get -y --no-install-recommends install + build-essential + automake + autoconf + libtool + pkg-config + xsltproc + libxslt1-dev docbook-xsl + valgrind + libatomic-ops-dev + libcairo2-dev libcunit1-dev + wget + xutils-dev + git # autogen.sh depends on git + # We need `--no-check-certificate` here because Debian's CA list is + # too old to know about LetsEncrypt's CA, so it refuses to connect + # to FreeDesktop.org + - LIBPCIACCESS_VERSION=libpciaccess-0.10 && + wget --no-check-certificate https://xorg.freedesktop.org/releases/individual/lib/$LIBPCIACCESS_VERSION.tar.bz2 && + tar -jxvf $LIBPCIACCESS_VERSION.tar.bz2 && + (cd $LIBPCIACCESS_VERSION && ./configure --prefix=$HOME/prefix && make install) + - export PKG_CONFIG_PATH=$HOME/prefix/lib/pkgconfig:$HOME/prefix/share/pkgconfig + - export LD_LIBRARY_PATH="$HOME/prefix/lib:$LD_LIBRARY_PATH" + script: *autotools-build @@ -54,7 +54,7 @@ cc_library { "libdrm_sources", ], - export_include_dirs: ["include/drm"], + export_include_dirs: ["include/drm", "android"], cflags: [ "-Wno-enum-conversion", diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 00000000..96f1e4fb --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,105 @@ +Contributing to libdrm +====================== + +Submitting Patches +------------------ + +Patches should be sent to dri-devel@lists.freedesktop.org, using git +send-email. For patches only touching driver specific code one of the driver +mailing lists (like amd-gfx@lists.freedesktop.org) is also appropriate. See git +documentation for help: + +http://git-scm.com/documentation + +Since dri-devel is a very busy mailing list please use --subject-prefix="PATCH +libdrm" to make it easier to find libdrm patches. This is best done by running + + git config --local format.subjectprefix "PATCH libdrm" + +The first line of a commit message should contain a prefix indicating what part +is affected by the patch followed by one sentence that describes the change. For +examples: + + amdgpu: Use uint32_t i in amdgpu_find_bo_by_cpu_mapping + +The body of the commit message should describe what the patch changes and why, +and also note any particular side effects. For a recommended reading on +writing commit messages, see: + +http://who-t.blogspot.de/2009/12/on-commit-messages.html + +Your patches should also include a Signed-off-by line with your name and email +address. If you're not the patch's original author, you should also gather +S-o-b's by them (and/or whomever gave the patch to you.) The significance of +this is that it certifies that you created the patch, that it was created under +an appropriate open source license, or provided to you under those terms. This +lets us indicate a chain of responsibility for the copyright status of the code. +For more details: + +https://developercertificate.org/ + +We won't reject patches that lack S-o-b, but it is strongly recommended. + +Review and Merging +------------------ + +Patches should have at least one positive review (Reviewed-by: tag) or +indication of approval (Acked-by: tag) before merging. For any code shared +between drivers this is mandatory. + +Please note that kernel/userspace API header files have special rules, see +include/drm/README. + +Coding style in the project loosely follows the CodingStyle of the linux kernel: + +https://www.kernel.org/doc/html/latest/process/coding-style.html?highlight=coding%20style + +Commit Rights +------------- + +Commit rights will be granted to anyone who requests them and fulfills the +below criteria: + +- Submitted a few (5-10 as a rule of thumb) non-trivial (not just simple + spelling fixes and whitespace adjustment) patches that have been merged + already. Since libdrm is just a glue library between the kernel and userspace + drivers, merged patches to those components also count towards the commit + criteria. + +- Are actively participating on discussions about their work (on the mailing + list or IRC). This should not be interpreted as a requirement to review other + peoples patches but just make sure that patch submission isn't one-way + communication. Cross-review is still highly encouraged. + +- Will be regularly contributing further patches. This includes regular + contributors to other parts of the open source graphics stack who only + do the oddball rare patch within libdrm itself. + +- Agrees to use their commit rights in accordance with the documented merge + criteria, tools, and processes. + +To apply for commit rights ("Developer" role in gitlab) send a mail to +dri-devel@lists.freedesktop.org and please ping the maintainers if your request +is stuck. + +Committers are encouraged to request their commit rights get removed when they +no longer contribute to the project. Commit rights will be reinstated when they +come back to the project. + +Maintainers and committers should encourage contributors to request commit +rights, as especially junior contributors tend to underestimate their skills. + +Code of Conduct +--------------- + +Please be aware the fd.o Code of Conduct also applies to libdrm: + +https://www.freedesktop.org/wiki/CodeOfConduct/ + +See the gitlab project owners for contact details of the libdrm maintainers. + +Abuse of commit rights, like engaging in commit fights or willfully pushing +patches that violate the documented merge criteria, will also be handled through +the Code of Conduct enforcement process. + +Happy hacking! diff --git a/Makefile.am b/Makefile.am index 2bf644be..730de1f2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -96,10 +96,6 @@ MAN_SUBDIR = man endif endif -if HAVE_ROCKCHIP -ROCKCHIP_SUBDIR = rockchip -endif - SUBDIRS = \ . \ $(LIBKMS_SUBDIR) \ @@ -113,9 +109,9 @@ SUBDIRS = \ $(TEGRA_SUBDIR) \ $(VC4_SUBDIR) \ $(ETNAVIV_SUBDIR) \ + data \ tests \ - $(MAN_SUBDIR) \ - $(ROCKCHIP_SUBDIR) + $(MAN_SUBDIR) libdrm_la_LTLIBRARIES = libdrm.la libdrm_ladir = $(libdir) @@ -125,6 +121,7 @@ libdrm_la_LIBADD = @CLOCK_LIB@ -lm libdrm_la_CPPFLAGS = -I$(top_srcdir)/include/drm AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ $(VALGRIND_CFLAGS) libdrm_la_SOURCES = $(LIBDRM_FILES) @@ -139,7 +136,37 @@ if HAVE_VMWGFX klibdrminclude_HEADERS += $(LIBDRM_INCLUDE_VMWGFX_H_FILES) endif -EXTRA_DIST = include/drm/README +EXTRA_DIST = \ + include/drm/README \ + amdgpu/meson.build \ + data/meson.build \ + etnaviv/meson.build \ + exynos/meson.build \ + freedreno/meson.build \ + intel/meson.build \ + libkms/meson.build \ + man/meson.build \ + nouveau/meson.build \ + omap/meson.build \ + radeon/meson.build \ + tegra/meson.build \ + tests/amdgpu/meson.build \ + tests/etnaviv/meson.build \ + tests/exynos/meson.build \ + tests/kms/meson.build \ + tests/kmstest/meson.build \ + tests/meson.build \ + tests/modeprint/meson.build \ + tests/modetest/meson.build \ + tests/nouveau/meson.build \ + tests/proptest/meson.build \ + tests/radeon/meson.build \ + tests/tegra/meson.build \ + tests/util/meson.build \ + tests/vbltest/meson.build \ + vc4/meson.build \ + meson.build \ + meson_options.txt copy-headers : cp -r $(kernel_source)/include/uapi/drm/*.h $(top_srcdir)/include/drm/ diff --git a/Makefile.sources b/Makefile.sources index 10aa1d0f..55290fe9 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -25,6 +25,7 @@ LIBDRM_INCLUDE_H_FILES := \ include/drm/i915_drm.h \ include/drm/mach64_drm.h \ include/drm/mga_drm.h \ + include/drm/msm_drm.h \ include/drm/nouveau_drm.h \ include/drm/qxl_drm.h \ include/drm/r128_drm.h \ @@ -37,5 +38,8 @@ LIBDRM_INCLUDE_H_FILES := \ include/drm/via_drm.h \ include/drm/virtgpu_drm.h +LIBDRM_INCLUDE_ANDROID_H_FILES := \ + android/gralloc_handle.h + LIBDRM_INCLUDE_VMWGFX_H_FILES := \ include/drm/vmwgfx_drm.h @@ -0,0 +1,5 @@ +# Default code reviewers picked from top 3 or more developers. +# Please update this list if you find better candidates. +adelva@google.com +john.stultz@linaro.org +seanpaul@google.com diff --git a/README b/README deleted file mode 100644 index 26cab9d3..00000000 --- a/README +++ /dev/null @@ -1,41 +0,0 @@ -libdrm - userspace library for drm - -This is libdrm, a userspace library for accessing the DRM, direct -rendering manager, on Linux, BSD and other operating systems that -support the ioctl interface. The library provides wrapper functions -for the ioctls to avoid exposing the kernel interface directly, and -for chipsets with drm memory manager, support for tracking relocations -and buffers. libdrm is a low-level library, typically used by -graphics drivers such as the Mesa DRI drivers, the X drivers, libva -and similar projects. New functionality in the kernel DRM drivers -typically requires a new libdrm, but a new libdrm will always work -with an older kernel. - - -Compiling ---------- - -libdrm is a standard autotools package and follows the normal -configure, build and install steps. The first step is to configure -the package, which is done by running the configure shell script: - - ./configure - -By default, libdrm will install into the /usr/local/ prefix. If you -want to install this DRM to replace your system copy, pass ---prefix=/usr and --exec-prefix=/ to configure. If you are building -libdrm from a git checkout, you first need to run the autogen.sh -script. You can pass any options to autogen.sh that you would other -wise pass to configure, or you can just re-run configure with the -options you need once autogen.sh finishes. - -Next step is to build libdrm: - - make - -and once make finishes successfully, install the package using - - make install - -If you are installing into a system location, you will need to be root -to perform the install step. diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..e47cb241 --- /dev/null +++ b/README.rst @@ -0,0 +1,61 @@ +libdrm - userspace library for drm +---------------------------------- + +This is libdrm, a userspace library for accessing the DRM, direct rendering +manager, on Linux, BSD and other operating systems that support the ioctl +interface. +The library provides wrapper functions for the ioctls to avoid exposing the +kernel interface directly, and for chipsets with drm memory manager, support +for tracking relocations and buffers. +New functionality in the kernel DRM drivers typically requires a new libdrm, +but a new libdrm will always work with an older kernel. + +libdrm is a low-level library, typically used by graphics drivers such as +the Mesa drivers, the X drivers, libva and similar projects. + + +Compiling +--------- + +libdrm has two build systems, a legacy autotools build system, and a newer +meson build system. The meson build system is much faster, and offers a +slightly different interface, but otherwise provides an equivalent feature set. + +To use it: + + meson builddir/ + +By default this will install into /usr/local, you can change your prefix +with --prefix=/usr (or `meson configure builddir/ -Dprefix=/usr` after +the initial meson setup). + +Then use ninja to build and install: + + ninja -C builddir/ install + +If you are installing into a system location you will need to run install +separately, and as root. + + +Alternatively you can invoke autotools configure: + + ./configure + +By default, libdrm will install into the /usr/local/ prefix. If you +want to install this DRM to replace your system copy, pass +--prefix=/usr and --exec-prefix=/ to configure. If you are building +libdrm from a git checkout, you first need to run the autogen.sh +script. You can pass any options to autogen.sh that you would other +wise pass to configure, or you can just re-run configure with the +options you need once autogen.sh finishes. + +Next step is to build libdrm: + + make + +and once make finishes successfully, install the package using + + make install + +If you are installing into a system location, you will need to be root +to perform the install step. @@ -9,9 +9,9 @@ However, this is up to whoever is driving the feature in question. Follow these steps to release a new version of libdrm: - 1) Bump the version number in configure.ac. We seem to have settled - for 2.4.x as the versioning scheme for libdrm, so just bump the - micro version. + 1) Bump the version number in configure.ac and meson.build. We seem + to have settled for 2.4.x as the versioning scheme for libdrm, so + just bump the micro version. 2) Run autoconf and then re-run ./configure so the build system picks up the new version number. diff --git a/amdgpu/.editorconfig b/amdgpu/.editorconfig new file mode 100644 index 00000000..426273fd --- /dev/null +++ b/amdgpu/.editorconfig @@ -0,0 +1,13 @@ +# To use this config with your editor, follow the instructions at: +# http://editorconfig.org + +[*] +charset = utf-8 +indent_style = tab +indent_size = 8 +tab_width = 8 +insert_final_newline = true + +[meson.build] +indent_style = space +indent_size = 2 diff --git a/amdgpu/Android.bp b/amdgpu/Android.bp index a63b6174..976f03e9 100644 --- a/amdgpu/Android.bp +++ b/amdgpu/Android.bp @@ -2,6 +2,11 @@ build = ["Android.sources.bp"] cc_library_shared { name: "libdrm_amdgpu", + + cflags: [ + "-DAMDGPU_ASIC_ID_TABLE=\"/vendor/etc/hwdata/amdgpu.ids\"" + ], + defaults: [ "libdrm_defaults", "libdrm_amdgpu_sources", diff --git a/amdgpu/Android.sources.bp b/amdgpu/Android.sources.bp index 62b8f054..be85283d 100644 --- a/amdgpu/Android.sources.bp +++ b/amdgpu/Android.sources.bp @@ -3,12 +3,13 @@ cc_defaults { name: "libdrm_amdgpu_sources", srcs: [ + "amdgpu_asic_id.c", "amdgpu_bo.c", "amdgpu_cs.c", "amdgpu_device.c", "amdgpu_gpu_info.c", "amdgpu_vamgr.c", - "util_hash.c", - "util_hash_table.c", + "amdgpu_vm.c", + "handle_table.c", ], } diff --git a/amdgpu/Makefile.am b/amdgpu/Makefile.am index cf7bc1ba..ef8ab057 100644 --- a/amdgpu/Makefile.am +++ b/amdgpu/Makefile.am @@ -26,16 +26,21 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ -I$(top_srcdir)/include/drm +libdrmdatadir = @libdrmdatadir@ +AM_CPPFLAGS = -DAMDGPU_ASIC_ID_TABLE=\"${libdrmdatadir}/amdgpu.ids\" + libdrm_amdgpu_la_LTLIBRARIES = libdrm_amdgpu.la libdrm_amdgpu_ladir = $(libdir) libdrm_amdgpu_la_LDFLAGS = -version-number 1:0:0 -no-undefined libdrm_amdgpu_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ libdrm_amdgpu_la_SOURCES = $(LIBDRM_AMDGPU_FILES) +amdgpu_asic_id.lo: $(top_srcdir)/data/amdgpu.ids libdrm_amdgpuincludedir = ${includedir}/libdrm libdrm_amdgpuinclude_HEADERS = $(LIBDRM_AMDGPU_H_FILES) @@ -43,5 +48,6 @@ libdrm_amdgpuinclude_HEADERS = $(LIBDRM_AMDGPU_H_FILES) pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_amdgpu.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = amdgpu-symbol-check EXTRA_DIST = $(TESTS) diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources index 487b9e0a..d6df324a 100644 --- a/amdgpu/Makefile.sources +++ b/amdgpu/Makefile.sources @@ -1,15 +1,14 @@ LIBDRM_AMDGPU_FILES := \ - amdgpu_asic_id.h \ + amdgpu_asic_id.c \ amdgpu_bo.c \ amdgpu_cs.c \ amdgpu_device.c \ amdgpu_gpu_info.c \ amdgpu_internal.h \ amdgpu_vamgr.c \ - util_hash.c \ - util_hash.h \ - util_hash_table.c \ - util_hash_table.h + amdgpu_vm.c \ + handle_table.c \ + handle_table.h LIBDRM_AMDGPU_H_FILES := \ amdgpu.h diff --git a/amdgpu/amdgpu-symbol-check b/amdgpu/amdgpu-symbol-check index 87f4fd2c..96a44b40 100755 --- a/amdgpu/amdgpu-symbol-check +++ b/amdgpu/amdgpu-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.am/libdrm_amdgpuinclude_HEADERS -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_amdgpu.so} | awk '{print $3}' | while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_amdgpu.so} | awk '{print $3}' | while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata @@ -16,25 +18,48 @@ amdgpu_bo_cpu_unmap amdgpu_bo_export amdgpu_bo_free amdgpu_bo_import +amdgpu_bo_inc_ref +amdgpu_bo_list_create_raw +amdgpu_bo_list_destroy_raw amdgpu_bo_list_create amdgpu_bo_list_destroy amdgpu_bo_list_update amdgpu_bo_query_info amdgpu_bo_set_metadata amdgpu_bo_va_op +amdgpu_bo_va_op_raw amdgpu_bo_wait_for_idle amdgpu_create_bo_from_user_mem +amdgpu_cs_chunk_fence_info_to_data +amdgpu_cs_chunk_fence_to_dep amdgpu_cs_create_semaphore +amdgpu_cs_create_syncobj +amdgpu_cs_create_syncobj2 amdgpu_cs_ctx_create +amdgpu_cs_ctx_create2 amdgpu_cs_ctx_free amdgpu_cs_destroy_semaphore +amdgpu_cs_destroy_syncobj +amdgpu_cs_export_syncobj +amdgpu_cs_fence_to_handle +amdgpu_cs_import_syncobj amdgpu_cs_query_fence_status amdgpu_cs_query_reset_state +amdgpu_query_sw_info amdgpu_cs_signal_semaphore amdgpu_cs_submit +amdgpu_cs_submit_raw +amdgpu_cs_submit_raw2 +amdgpu_cs_syncobj_export_sync_file +amdgpu_cs_syncobj_import_sync_file +amdgpu_cs_syncobj_reset +amdgpu_cs_syncobj_signal +amdgpu_cs_syncobj_wait +amdgpu_cs_wait_fences amdgpu_cs_wait_semaphore amdgpu_device_deinitialize amdgpu_device_initialize +amdgpu_find_bo_by_cpu_mapping amdgpu_get_marketing_name amdgpu_query_buffer_size_alignment amdgpu_query_crtc_from_id @@ -45,10 +70,13 @@ amdgpu_query_heap_info amdgpu_query_hw_ip_count amdgpu_query_hw_ip_info amdgpu_query_info +amdgpu_query_sensor_info amdgpu_read_mm_registers amdgpu_va_range_alloc amdgpu_va_range_free amdgpu_va_range_query +amdgpu_vm_reserve_vmid +amdgpu_vm_unreserve_vmid EOF done) diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h index 7b26a04c..d6de3b8d 100644 --- a/amdgpu/amdgpu.h +++ b/amdgpu/amdgpu.h @@ -37,7 +37,12 @@ #include <stdint.h> #include <stdbool.h> +#ifdef __cplusplus +extern "C" { +#endif + struct drm_amdgpu_info_hw_ip; +struct drm_amdgpu_bo_list_entry; /*--------------------------------------------------------------------------*/ /* --------------------------- Defines ------------------------------------ */ @@ -80,7 +85,12 @@ enum amdgpu_bo_handle_type { amdgpu_bo_handle_type_kms = 1, /** DMA-buf fd handle */ - amdgpu_bo_handle_type_dma_buf_fd = 2 + amdgpu_bo_handle_type_dma_buf_fd = 2, + + /** KMS handle, but re-importing as a DMABUF handle through + * drmPrimeHandleToFD is forbidden. (Glamor does that) + */ + amdgpu_bo_handle_type_kms_noimport = 3, }; /** Define known types of GPU VM VA ranges */ @@ -90,6 +100,10 @@ enum amdgpu_gpu_va_range amdgpu_gpu_va_range_general = 0 }; +enum amdgpu_sw_info { + amdgpu_sw_info_address32_hi = 0, +}; + /*--------------------------------------------------------------------------*/ /* -------------------------- Datatypes ----------------------------------- */ /*--------------------------------------------------------------------------*/ @@ -665,6 +679,29 @@ int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev, amdgpu_bo_handle *buf_handle); /** + * Validate if the user memory comes from BO + * + * \param dev - [in] Device handle. See #amdgpu_device_initialize() + * \param cpu - [in] CPU address of user allocated memory which we + * want to map to GPU address space (make GPU accessible) + * (This address must be correctly aligned). + * \param size - [in] Size of allocation (must be correctly aligned) + * \param buf_handle - [out] Buffer handle for the userptr memory + * if the user memory is not from BO, the buf_handle will be NULL. + * \param offset_in_bo - [out] offset in this BO for this user memory + * + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_find_bo_by_cpu_mapping(amdgpu_device_handle dev, + void *cpu, + uint64_t size, + amdgpu_bo_handle *buf_handle, + uint64_t *offset_in_bo); + +/** * Free previosuly allocated memory * * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() @@ -685,7 +722,17 @@ int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev, int amdgpu_bo_free(amdgpu_bo_handle buf_handle); /** - * Request CPU access to GPU accessible memory + * Increase the reference count of a buffer object + * + * \param bo - \c [in] Buffer object handle to increase the reference count + * + * \sa amdgpu_bo_alloc(), amdgpu_bo_free() + * +*/ +void amdgpu_bo_inc_ref(amdgpu_bo_handle bo); + +/** + * Request CPU access to GPU accessable memory * * \param buf_handle - \c [in] Buffer handle * \param cpu - \c [out] CPU address to be used for access @@ -733,6 +780,37 @@ int amdgpu_bo_wait_for_idle(amdgpu_bo_handle buf_handle, * * \param dev - \c [in] Device handle. * See #amdgpu_device_initialize() + * \param number_of_buffers - \c [in] Number of BOs in the list + * \param buffers - \c [in] List of BO handles + * \param result - \c [out] Created BO list handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + * \sa amdgpu_bo_list_destroy_raw(), amdgpu_cs_submit_raw2() +*/ +int amdgpu_bo_list_create_raw(amdgpu_device_handle dev, + uint32_t number_of_buffers, + struct drm_amdgpu_bo_list_entry *buffers, + uint32_t *result); + +/** + * Destroys a BO list handle. + * + * \param bo_list - \c [in] BO list handle. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + * \sa amdgpu_bo_list_create_raw(), amdgpu_cs_submit_raw2() +*/ +int amdgpu_bo_list_destroy_raw(amdgpu_device_handle dev, uint32_t bo_list); + +/** + * Creates a BO list handle for command submission. + * + * \param dev - \c [in] Device handle. + * See #amdgpu_device_initialize() * \param number_of_resources - \c [in] Number of BOs in the list * \param resources - \c [in] List of BO handles * \param resource_prios - \c [in] Optional priority for each handle @@ -794,8 +872,9 @@ int amdgpu_bo_list_update(amdgpu_bo_list_handle handle, * context will always be executed in order (first come, first serve). * * - * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() - * \param context - \c [out] GPU Context handle + * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() + * \param priority - \c [in] Context creation flags. See AMDGPU_CTX_PRIORITY_* + * \param context - \c [out] GPU Context handle * * \return 0 on success\n * <0 - Negative POSIX Error code @@ -803,6 +882,18 @@ int amdgpu_bo_list_update(amdgpu_bo_list_handle handle, * \sa amdgpu_cs_ctx_free() * */ +int amdgpu_cs_ctx_create2(amdgpu_device_handle dev, + uint32_t priority, + amdgpu_context_handle *context); +/** + * Create GPU execution Context + * + * Refer to amdgpu_cs_ctx_create2 for full documentation. This call + * is missing the priority parameter. + * + * \sa amdgpu_cs_ctx_create2() + * +*/ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, amdgpu_context_handle *context); @@ -907,6 +998,29 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, uint64_t flags, uint32_t *expired); +/** + * Wait for multiple fences + * + * \param fences - \c [in] The fence array to wait + * \param fence_count - \c [in] The fence count + * \param wait_all - \c [in] If true, wait all fences to be signaled, + * otherwise, wait at least one fence + * \param timeout_ns - \c [in] The timeout to wait, in nanoseconds + * \param status - \c [out] '1' for signaled, '0' for timeout + * \param first - \c [out] the index of the first signaled fence from @fences + * + * \return 0 on success + * <0 - Negative POSIX Error code + * + * \note Currently it supports only one amdgpu_device. All fences come from + * the same amdgpu_device with the same fd. +*/ +int amdgpu_cs_wait_fences(struct amdgpu_cs_fence *fences, + uint32_t fence_count, + bool wait_all, + uint64_t timeout_ns, + uint32_t *status, uint32_t *first); + /* * Query / Info API * @@ -1046,6 +1160,23 @@ int amdgpu_query_info(amdgpu_device_handle dev, unsigned info_id, unsigned size, void *value); /** + * Query hardware or driver information. + * + * The return size is query-specific and depends on the "info_id" parameter. + * No more than "size" bytes is returned. + * + * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() + * \param info - \c [in] amdgpu_sw_info_* + * \param value - \c [out] Pointer to the return value. + * + * \return 0 on success\n + * <0 - Negative POSIX error code + * +*/ +int amdgpu_query_sw_info(amdgpu_device_handle dev, enum amdgpu_sw_info info, + void *value); + +/** * Query information about GDS * * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() @@ -1059,6 +1190,24 @@ int amdgpu_query_gds_info(amdgpu_device_handle dev, struct amdgpu_gds_resource_info *gds_info); /** + * Query information about sensor. + * + * The return size is query-specific and depends on the "sensor_type" + * parameter. No more than "size" bytes is returned. + * + * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() + * \param sensor_type - \c [in] AMDGPU_INFO_SENSOR_* + * \param size - \c [in] Size of the returned value. + * \param value - \c [out] Pointer to the return value. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_query_sensor_info(amdgpu_device_handle dev, unsigned sensor_type, + unsigned size, void *value); + +/** * Read a set of consecutive memory-mapped registers. * Not all registers are allowed to be read by userspace. * @@ -1083,6 +1232,7 @@ int amdgpu_read_mm_registers(amdgpu_device_handle dev, unsigned dword_offset, * Flag to request VA address range in the 32bit address space */ #define AMDGPU_VA_RANGE_32_BIT 0x1 +#define AMDGPU_VA_RANGE_HIGH 0x2 /** * Allocate virtual address range @@ -1186,6 +1336,34 @@ int amdgpu_bo_va_op(amdgpu_bo_handle bo, uint32_t ops); /** + * VA mapping/unmapping for a buffer object or PRT region. + * + * This is not a simple drop-in extension for amdgpu_bo_va_op; instead, all + * parameters are treated "raw", i.e. size is not automatically aligned, and + * all flags must be specified explicitly. + * + * \param dev - \c [in] device handle + * \param bo - \c [in] BO handle (may be NULL) + * \param offset - \c [in] Start offset to map + * \param size - \c [in] Size to map + * \param addr - \c [in] Start virtual address. + * \param flags - \c [in] Supported flags for mapping/unmapping + * \param ops - \c [in] AMDGPU_VA_OP_MAP or AMDGPU_VA_OP_UNMAP + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ + +int amdgpu_bo_va_op_raw(amdgpu_device_handle dev, + amdgpu_bo_handle bo, + uint64_t offset, + uint64_t size, + uint64_t addr, + uint64_t flags, + uint32_t ops); + +/** * create semaphore * * \param sem - \c [out] semaphore handle @@ -1255,4 +1433,238 @@ int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem); */ const char *amdgpu_get_marketing_name(amdgpu_device_handle dev); +/** + * Create kernel sync object + * + * \param dev - \c [in] device handle + * \param flags - \c [in] flags that affect creation + * \param syncobj - \c [out] sync object handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_create_syncobj2(amdgpu_device_handle dev, + uint32_t flags, + uint32_t *syncobj); + +/** + * Create kernel sync object + * + * \param dev - \c [in] device handle + * \param syncobj - \c [out] sync object handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_create_syncobj(amdgpu_device_handle dev, + uint32_t *syncobj); +/** + * Destroy kernel sync object + * + * \param dev - \c [in] device handle + * \param syncobj - \c [in] sync object handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev, + uint32_t syncobj); + +/** + * Reset kernel sync objects to unsignalled state. + * + * \param dev - \c [in] device handle + * \param syncobjs - \c [in] array of sync object handles + * \param syncobj_count - \c [in] number of handles in syncobjs + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_syncobj_reset(amdgpu_device_handle dev, + const uint32_t *syncobjs, uint32_t syncobj_count); + +/** + * Signal kernel sync objects. + * + * \param dev - \c [in] device handle + * \param syncobjs - \c [in] array of sync object handles + * \param syncobj_count - \c [in] number of handles in syncobjs + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_syncobj_signal(amdgpu_device_handle dev, + const uint32_t *syncobjs, uint32_t syncobj_count); + +/** + * Wait for one or all sync objects to signal. + * + * \param dev - \c [in] self-explanatory + * \param handles - \c [in] array of sync object handles + * \param num_handles - \c [in] self-explanatory + * \param timeout_nsec - \c [in] self-explanatory + * \param flags - \c [in] a bitmask of DRM_SYNCOBJ_WAIT_FLAGS_* + * \param first_signaled - \c [in] self-explanatory + * + * \return 0 on success\n + * -ETIME - Timeout + * <0 - Negative POSIX Error code + * + */ +int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev, + uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); + +/** + * Export kernel sync object to shareable fd. + * + * \param dev - \c [in] device handle + * \param syncobj - \c [in] sync object handle + * \param shared_fd - \c [out] shared file descriptor. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_export_syncobj(amdgpu_device_handle dev, + uint32_t syncobj, + int *shared_fd); +/** + * Import kernel sync object from shareable fd. + * + * \param dev - \c [in] device handle + * \param shared_fd - \c [in] shared file descriptor. + * \param syncobj - \c [out] sync object handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_cs_import_syncobj(amdgpu_device_handle dev, + int shared_fd, + uint32_t *syncobj); + +/** + * Export kernel sync object to a sync_file. + * + * \param dev - \c [in] device handle + * \param syncobj - \c [in] sync object handle + * \param sync_file_fd - \c [out] sync_file file descriptor. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + */ +int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int *sync_file_fd); + +/** + * Import kernel sync object from a sync_file. + * + * \param dev - \c [in] device handle + * \param syncobj - \c [in] sync object handle + * \param sync_file_fd - \c [in] sync_file file descriptor. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + */ +int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int sync_file_fd); + +/** + * Export an amdgpu fence as a handle (syncobj or fd). + * + * \param what AMDGPU_FENCE_TO_HANDLE_GET_{SYNCOBJ, FD} + * \param out_handle returned handle + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + */ +int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev, + struct amdgpu_cs_fence *fence, + uint32_t what, + uint32_t *out_handle); + +/** + * Submit raw command submission to kernel + * + * \param dev - \c [in] device handle + * \param context - \c [in] context handle for context id + * \param bo_list_handle - \c [in] request bo list handle (0 for none) + * \param num_chunks - \c [in] number of CS chunks to submit + * \param chunks - \c [in] array of CS chunks + * \param seq_no - \c [out] output sequence number for submission. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + */ +struct drm_amdgpu_cs_chunk; +struct drm_amdgpu_cs_chunk_dep; +struct drm_amdgpu_cs_chunk_data; + +int amdgpu_cs_submit_raw(amdgpu_device_handle dev, + amdgpu_context_handle context, + amdgpu_bo_list_handle bo_list_handle, + int num_chunks, + struct drm_amdgpu_cs_chunk *chunks, + uint64_t *seq_no); + +/** + * Submit raw command submission to the kernel with a raw BO list handle. + * + * \param dev - \c [in] device handle + * \param context - \c [in] context handle for context id + * \param bo_list_handle - \c [in] raw bo list handle (0 for none) + * \param num_chunks - \c [in] number of CS chunks to submit + * \param chunks - \c [in] array of CS chunks + * \param seq_no - \c [out] output sequence number for submission. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * + * \sa amdgpu_bo_list_create_raw(), amdgpu_bo_list_destroy_raw() + */ +int amdgpu_cs_submit_raw2(amdgpu_device_handle dev, + amdgpu_context_handle context, + uint32_t bo_list_handle, + int num_chunks, + struct drm_amdgpu_cs_chunk *chunks, + uint64_t *seq_no); + +void amdgpu_cs_chunk_fence_to_dep(struct amdgpu_cs_fence *fence, + struct drm_amdgpu_cs_chunk_dep *dep); +void amdgpu_cs_chunk_fence_info_to_data(struct amdgpu_cs_fence_info *fence_info, + struct drm_amdgpu_cs_chunk_data *data); + +/** + * Reserve VMID + * \param context - \c [in] GPU Context + * \param flags - \c [in] TBD + * + * \return 0 on success otherwise POSIX Error code +*/ +int amdgpu_vm_reserve_vmid(amdgpu_device_handle dev, uint32_t flags); + +/** + * Free reserved VMID + * \param context - \c [in] GPU Context + * \param flags - \c [in] TBD + * + * \return 0 on success otherwise POSIX Error code +*/ +int amdgpu_vm_unreserve_vmid(amdgpu_device_handle dev, uint32_t flags); + +#ifdef __cplusplus +} +#endif #endif /* #ifdef _AMDGPU_H_ */ diff --git a/amdgpu/amdgpu_asic_id.c b/amdgpu/amdgpu_asic_id.c new file mode 100644 index 00000000..a5007ffc --- /dev/null +++ b/amdgpu/amdgpu_asic_id.c @@ -0,0 +1,161 @@ +/* + * Copyright © 2017 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include "xf86drm.h" +#include "amdgpu_drm.h" +#include "amdgpu_internal.h" + +static int parse_one_line(struct amdgpu_device *dev, const char *line) +{ + char *buf, *saveptr; + char *s_did; + uint32_t did; + char *s_rid; + uint32_t rid; + char *s_name; + char *endptr; + int r = -EINVAL; + + /* ignore empty line and commented line */ + if (strlen(line) == 0 || line[0] == '#') + return -EAGAIN; + + buf = strdup(line); + if (!buf) + return -ENOMEM; + + /* device id */ + s_did = strtok_r(buf, ",", &saveptr); + if (!s_did) + goto out; + + did = strtol(s_did, &endptr, 16); + if (*endptr) + goto out; + + if (did != dev->info.asic_id) { + r = -EAGAIN; + goto out; + } + + /* revision id */ + s_rid = strtok_r(NULL, ",", &saveptr); + if (!s_rid) + goto out; + + rid = strtol(s_rid, &endptr, 16); + if (*endptr) + goto out; + + if (rid != dev->info.pci_rev_id) { + r = -EAGAIN; + goto out; + } + + /* marketing name */ + s_name = strtok_r(NULL, ",", &saveptr); + if (!s_name) + goto out; + + /* trim leading whitespaces or tabs */ + while (isblank(*s_name)) + s_name++; + if (strlen(s_name) == 0) + goto out; + + dev->marketing_name = strdup(s_name); + if (dev->marketing_name) + r = 0; + else + r = -ENOMEM; + +out: + free(buf); + + return r; +} + +void amdgpu_parse_asic_ids(struct amdgpu_device *dev) +{ + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t n; + int line_num = 1; + int r = 0; + + fp = fopen(AMDGPU_ASIC_ID_TABLE, "r"); + if (!fp) { + fprintf(stderr, "%s: %s\n", AMDGPU_ASIC_ID_TABLE, + strerror(errno)); + return; + } + + /* 1st valid line is file version */ + while ((n = getline(&line, &len, fp)) != -1) { + /* trim trailing newline */ + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + + /* ignore empty line and commented line */ + if (strlen(line) == 0 || line[0] == '#') { + line_num++; + continue; + } + + drmMsg("%s version: %s\n", AMDGPU_ASIC_ID_TABLE, line); + break; + } + + while ((n = getline(&line, &len, fp)) != -1) { + /* trim trailing newline */ + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + + r = parse_one_line(dev, line); + if (r != -EAGAIN) + break; + + line_num++; + } + + if (r == -EINVAL) { + fprintf(stderr, "Invalid format: %s: line %d: %s\n", + AMDGPU_ASIC_ID_TABLE, line_num, line); + } else if (r && r != -EAGAIN) { + fprintf(stderr, "%s: Cannot parse ASIC IDs: %s\n", + __func__, strerror(-r)); + } + + free(line); + fclose(fp); +} diff --git a/amdgpu/amdgpu_asic_id.h b/amdgpu/amdgpu_asic_id.h deleted file mode 100644 index 3e7d736b..00000000 --- a/amdgpu/amdgpu_asic_id.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright © 2016 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef __AMDGPU_ASIC_ID_H__ -#define __AMDGPU_ASIC_ID_H__ - -static struct amdgpu_asic_id_table_t { - uint32_t did; - uint32_t rid; - const char *marketing_name; -} const amdgpu_asic_id_table [] = { - {0x6600, 0x0, "AMD Radeon HD 8600/8700M"}, - {0x6600, 0x81, "AMD Radeon R7 M370"}, - {0x6601, 0x0, "AMD Radeon HD 8500M/8700M"}, - {0x6604, 0x0, "AMD Radeon R7 M265 Series"}, - {0x6604, 0x81, "AMD Radeon R7 M350"}, - {0x6605, 0x0, "AMD Radeon R7 M260 Series"}, - {0x6605, 0x81, "AMD Radeon R7 M340"}, - {0x6606, 0x0, "AMD Radeon HD 8790M"}, - {0x6607, 0x0, "AMD Radeon HD8530M"}, - {0x6608, 0x0, "AMD FirePro W2100"}, - {0x6610, 0x0, "AMD Radeon HD 8600 Series"}, - {0x6610, 0x81, "AMD Radeon R7 350"}, - {0x6610, 0x83, "AMD Radeon R5 340"}, - {0x6611, 0x0, "AMD Radeon HD 8500 Series"}, - {0x6613, 0x0, "AMD Radeon HD 8500 series"}, - {0x6617, 0xC7, "AMD Radeon R7 240 Series"}, - {0x6640, 0x0, "AMD Radeon HD 8950"}, - {0x6640, 0x80, "AMD Radeon R9 M380"}, - {0x6646, 0x0, "AMD Radeon R9 M280X"}, - {0x6646, 0x80, "AMD Radeon R9 M470X"}, - {0x6647, 0x0, "AMD Radeon R9 M270X"}, - {0x6647, 0x80, "AMD Radeon R9 M380"}, - {0x6649, 0x0, "AMD FirePro W5100"}, - {0x6658, 0x0, "AMD Radeon R7 200 Series"}, - {0x665C, 0x0, "AMD Radeon HD 7700 Series"}, - {0x665D, 0x0, "AMD Radeon R7 200 Series"}, - {0x665F, 0x81, "AMD Radeon R7 300 Series"}, - {0x6660, 0x0, "AMD Radeon HD 8600M Series"}, - {0x6660, 0x81, "AMD Radeon R5 M335"}, - {0x6660, 0x83, "AMD Radeon R5 M330"}, - {0x6663, 0x0, "AMD Radeon HD 8500M Series"}, - {0x6663, 0x83, "AMD Radeon R5 M320"}, - {0x6664, 0x0, "AMD Radeon R5 M200 Series"}, - {0x6665, 0x0, "AMD Radeon R5 M200 Series"}, - {0x6665, 0x83, "AMD Radeon R5 M320"}, - {0x6667, 0x0, "AMD Radeon R5 M200 Series"}, - {0x666F, 0x0, "AMD Radeon HD 8500M"}, - {0x6780, 0x0, "ATI FirePro V (FireGL V) Graphics Adapter"}, - {0x678A, 0x0, "ATI FirePro V (FireGL V) Graphics Adapter"}, - {0x6798, 0x0, "AMD Radeon HD 7900 Series"}, - {0x679A, 0x0, "AMD Radeon HD 7900 Series"}, - {0x679B, 0x0, "AMD Radeon HD 7900 Series"}, - {0x679E, 0x0, "AMD Radeon HD 7800 Series"}, - {0x67A0, 0x0, "HAWAII XTGL (67A0)"}, - {0x67A1, 0x0, "HAWAII GL40 (67A1)"}, - {0x67B0, 0x0, "AMD Radeon R9 200 Series"}, - {0x67B0, 0x80, "AMD Radeon R9 390 Series"}, - {0x67B1, 0x0, "AMD Radeon R9 200 Series"}, - {0x67B1, 0x80, "AMD Radeon R9 390 Series"}, - {0x67B9, 0x0, "AMD Radeon R9 200 Series"}, - {0x67DF, 0xC4, "AMD Radeon RX 480 Graphics"}, - {0x67DF, 0xC5, "AMD Radeon RX 470 Graphics"}, - {0x67DF, 0xC7, "AMD Radeon RX 480 Graphics"}, - {0x67DF, 0xCF, "AMD Radeon RX 470 Graphics"}, - {0x67C4, 0x00, "AMD Radeon Pro WX 7100 Graphics"}, - {0x67C7, 0x00, "AMD Radeon Pro WX 5100 Graphics"}, - {0x67C0, 0x00, "AMD Radeon Pro WX 7100 Graphics"}, - {0x67E0, 0x00, "AMD Radeon Pro WX Series Graphics"}, - {0x67E3, 0x00, "AMD Radeon Pro WX 4100 Graphics"}, - {0x67E8, 0x00, "AMD Radeon Pro WX Series Graphics"}, - {0x67E8, 0x01, "AMD Radeon Pro WX Series Graphics"}, - {0x67E8, 0x80, "AMD Radeon E9260 Graphics"}, - {0x67EB, 0x00, "AMD Radeon Pro WX Series Graphics"}, - {0x67EF, 0xC0, "AMD Radeon RX Graphics"}, - {0x67EF, 0xC1, "AMD Radeon RX 460 Graphics"}, - {0x67EF, 0xC5, "AMD Radeon RX 460 Graphics"}, - {0x67EF, 0xC7, "AMD Radeon RX Graphics"}, - {0x67EF, 0xCF, "AMD Radeon RX 460 Graphics"}, - {0x67EF, 0xEF, "AMD Radeon RX Graphics"}, - {0x67FF, 0xC0, "AMD Radeon RX Graphics"}, - {0x67FF, 0xC1, "AMD Radeon RX Graphics"}, - {0x6800, 0x0, "AMD Radeon HD 7970M"}, - {0x6801, 0x0, "AMD Radeon(TM) HD8970M"}, - {0x6808, 0x0, "ATI FirePro V(FireGL V) Graphics Adapter"}, - {0x6809, 0x0, "ATI FirePro V(FireGL V) Graphics Adapter"}, - {0x6810, 0x0, "AMD Radeon(TM) HD 8800 Series"}, - {0x6810, 0x81, "AMD Radeon R7 370 Series"}, - {0x6811, 0x0, "AMD Radeon(TM) HD8800 Series"}, - {0x6811, 0x81, "AMD Radeon R7 300 Series"}, - {0x6818, 0x0, "AMD Radeon HD 7800 Series"}, - {0x6819, 0x0, "AMD Radeon HD 7800 Series"}, - {0x6820, 0x0, "AMD Radeon HD 8800M Series"}, - {0x6820, 0x81, "AMD Radeon R9 M375"}, - {0x6820, 0x83, "AMD Radeon R9 M375X"}, - {0x6821, 0x0, "AMD Radeon HD 8800M Series"}, - {0x6821, 0x87, "AMD Radeon R7 M380"}, - {0x6821, 0x83, "AMD Radeon R9 M370X"}, - {0x6822, 0x0, "AMD Radeon E8860"}, - {0x6823, 0x0, "AMD Radeon HD 8800M Series"}, - {0x6825, 0x0, "AMD Radeon HD 7800M Series"}, - {0x6827, 0x0, "AMD Radeon HD 7800M Series"}, - {0x6828, 0x0, "ATI FirePro V(FireGL V) Graphics Adapter"}, - {0x682B, 0x0, "AMD Radeon HD 8800M Series"}, - {0x682B, 0x87, "AMD Radeon R9 M360"}, - {0x682C, 0x0, "AMD FirePro W4100"}, - {0x682D, 0x0, "AMD Radeon HD 7700M Series"}, - {0x682F, 0x0, "AMD Radeon HD 7700M Series"}, - {0x6835, 0x0, "AMD Radeon R7 Series / HD 9000 Series"}, - {0x6837, 0x0, "AMD Radeon HD7700 Series"}, - {0x683D, 0x0, "AMD Radeon HD 7700 Series"}, - {0x683F, 0x0, "AMD Radeon HD 7700 Series"}, - {0x6900, 0x0, "AMD Radeon R7 M260"}, - {0x6900, 0x81, "AMD Radeon R7 M360"}, - {0x6900, 0x83, "AMD Radeon R7 M340"}, - {0x6901, 0x0, "AMD Radeon R5 M255"}, - {0x6907, 0x0, "AMD Radeon R5 M255"}, - {0x6907, 0x87, "AMD Radeon R5 M315"}, - {0x6920, 0x0, "AMD Radeon R9 M395X"}, - {0x6920, 0x1, "AMD Radeon R9 M390X"}, - {0x6921, 0x0, "AMD Radeon R9 M295X"}, - {0x6929, 0x0, "AMD FirePro S7150"}, - {0x692B, 0x0, "AMD FirePro W7100"}, - {0x6938, 0x0, "AMD Radeon R9 200 Series"}, - {0x6938, 0xF0, "AMD Radeon R9 200 Series"}, - {0x6938, 0xF1, "AMD Radeon R9 380 Series"}, - {0x6939, 0xF0, "AMD Radeon R9 200 Series"}, - {0x6939, 0x0, "AMD Radeon R9 200 Series"}, - {0x6939, 0xF1, "AMD Radeon R9 380 Series"}, - {0x7300, 0xC8, "AMD Radeon R9 Fury Series"}, - {0x7300, 0xCB, "AMD Radeon R9 Fury Series"}, - {0x7300, 0xCA, "AMD Radeon R9 Fury Series"}, - {0x9874, 0xC4, "AMD Radeon R7 Graphics"}, - {0x9874, 0xC5, "AMD Radeon R6 Graphics"}, - {0x9874, 0xC6, "AMD Radeon R6 Graphics"}, - {0x9874, 0xC7, "AMD Radeon R5 Graphics"}, - {0x9874, 0x81, "AMD Radeon R6 Graphics"}, - {0x9874, 0x87, "AMD Radeon R5 Graphics"}, - {0x9874, 0x85, "AMD Radeon R6 Graphics"}, - {0x9874, 0x84, "AMD Radeon R7 Graphics"}, - - {0x0000, 0x0, "\0"}, -}; -#endif diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c index d30fd1e7..32ee358f 100644 --- a/amdgpu/amdgpu_bo.c +++ b/amdgpu/amdgpu_bo.c @@ -22,10 +22,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <stdio.h> #include <stdint.h> @@ -41,7 +37,6 @@ #include "xf86drm.h" #include "amdgpu_drm.h" #include "amdgpu_internal.h" -#include "util_hash_table.h" #include "util_math.h" static void amdgpu_close_kms_handle(amdgpu_device_handle dev, @@ -53,41 +48,12 @@ static void amdgpu_close_kms_handle(amdgpu_device_handle dev, drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &args); } -drm_private void amdgpu_bo_free_internal(amdgpu_bo_handle bo) -{ - /* Remove the buffer from the hash tables. */ - pthread_mutex_lock(&bo->dev->bo_table_mutex); - util_hash_table_remove(bo->dev->bo_handles, - (void*)(uintptr_t)bo->handle); - if (bo->flink_name) { - util_hash_table_remove(bo->dev->bo_flink_names, - (void*)(uintptr_t)bo->flink_name); - } - pthread_mutex_unlock(&bo->dev->bo_table_mutex); - - /* Release CPU access. */ - if (bo->cpu_map_count > 0) { - bo->cpu_map_count = 1; - amdgpu_bo_cpu_unmap(bo); - } - - amdgpu_close_kms_handle(bo->dev, bo->handle); - pthread_mutex_destroy(&bo->cpu_access_mutex); - free(bo); -} - -int amdgpu_bo_alloc(amdgpu_device_handle dev, - struct amdgpu_bo_alloc_request *alloc_buffer, - amdgpu_bo_handle *buf_handle) +static int amdgpu_bo_create(amdgpu_device_handle dev, + uint64_t size, + uint32_t handle, + amdgpu_bo_handle *buf_handle) { struct amdgpu_bo *bo; - union drm_amdgpu_gem_create args; - unsigned heap = alloc_buffer->preferred_heap; - int r = 0; - - /* It's an error if the heap is not specified */ - if (!(heap & (AMDGPU_GEM_DOMAIN_GTT | AMDGPU_GEM_DOMAIN_VRAM))) - return -EINVAL; bo = calloc(1, sizeof(struct amdgpu_bo)); if (!bo) @@ -95,34 +61,54 @@ int amdgpu_bo_alloc(amdgpu_device_handle dev, atomic_set(&bo->refcount, 1); bo->dev = dev; - bo->alloc_size = alloc_buffer->alloc_size; + bo->alloc_size = size; + bo->handle = handle; + pthread_mutex_init(&bo->cpu_access_mutex, NULL); + + *buf_handle = bo; + return 0; +} + +drm_public int amdgpu_bo_alloc(amdgpu_device_handle dev, + struct amdgpu_bo_alloc_request *alloc_buffer, + amdgpu_bo_handle *buf_handle) +{ + union drm_amdgpu_gem_create args; + int r; memset(&args, 0, sizeof(args)); args.in.bo_size = alloc_buffer->alloc_size; args.in.alignment = alloc_buffer->phys_alignment; /* Set the placement. */ - args.in.domains = heap; + args.in.domains = alloc_buffer->preferred_heap; args.in.domain_flags = alloc_buffer->flags; /* Allocate the buffer with the preferred heap. */ r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_CREATE, &args, sizeof(args)); + if (r) + goto out; + + r = amdgpu_bo_create(dev, alloc_buffer->alloc_size, args.out.handle, + buf_handle); if (r) { - free(bo); - return r; + amdgpu_close_kms_handle(dev, args.out.handle); + goto out; } - bo->handle = args.out.handle; - - pthread_mutex_init(&bo->cpu_access_mutex, NULL); - - *buf_handle = bo; - return 0; + pthread_mutex_lock(&dev->bo_table_mutex); + r = handle_table_insert(&dev->bo_handles, (*buf_handle)->handle, + *buf_handle); + pthread_mutex_unlock(&dev->bo_table_mutex); + if (r) + amdgpu_bo_free(*buf_handle); +out: + return r; } -int amdgpu_bo_set_metadata(amdgpu_bo_handle bo, - struct amdgpu_bo_metadata *info) +drm_public int amdgpu_bo_set_metadata(amdgpu_bo_handle bo, + struct amdgpu_bo_metadata *info) { struct drm_amdgpu_gem_metadata args = {}; @@ -144,8 +130,8 @@ int amdgpu_bo_set_metadata(amdgpu_bo_handle bo, &args, sizeof(args)); } -int amdgpu_bo_query_info(amdgpu_bo_handle bo, - struct amdgpu_bo_info *info) +drm_public int amdgpu_bo_query_info(amdgpu_bo_handle bo, + struct amdgpu_bo_info *info) { struct drm_amdgpu_gem_metadata metadata = {}; struct drm_amdgpu_gem_create_in bo_info = {}; @@ -195,14 +181,6 @@ int amdgpu_bo_query_info(amdgpu_bo_handle bo, return 0; } -static void amdgpu_add_handle_to_table(amdgpu_bo_handle bo) -{ - pthread_mutex_lock(&bo->dev->bo_table_mutex); - util_hash_table_set(bo->dev->bo_handles, - (void*)(uintptr_t)bo->handle, bo); - pthread_mutex_unlock(&bo->dev->bo_table_mutex); -} - static int amdgpu_bo_export_flink(amdgpu_bo_handle bo) { struct drm_gem_flink flink; @@ -243,17 +221,15 @@ static int amdgpu_bo_export_flink(amdgpu_bo_handle bo) } pthread_mutex_lock(&bo->dev->bo_table_mutex); - util_hash_table_set(bo->dev->bo_flink_names, - (void*)(uintptr_t)bo->flink_name, - bo); + r = handle_table_insert(&bo->dev->bo_flink_names, bo->flink_name, bo); pthread_mutex_unlock(&bo->dev->bo_table_mutex); - return 0; + return r; } -int amdgpu_bo_export(amdgpu_bo_handle bo, - enum amdgpu_bo_handle_type type, - uint32_t *shared_handle) +drm_public int amdgpu_bo_export(amdgpu_bo_handle bo, + enum amdgpu_bo_handle_type type, + uint32_t *shared_handle) { int r; @@ -267,26 +243,29 @@ int amdgpu_bo_export(amdgpu_bo_handle bo, return 0; case amdgpu_bo_handle_type_kms: - amdgpu_add_handle_to_table(bo); + case amdgpu_bo_handle_type_kms_noimport: *shared_handle = bo->handle; return 0; case amdgpu_bo_handle_type_dma_buf_fd: - amdgpu_add_handle_to_table(bo); - return drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC, - (int*)shared_handle); + return drmPrimeHandleToFD(bo->dev->fd, bo->handle, + DRM_CLOEXEC | DRM_RDWR, + (int*)shared_handle); } return -EINVAL; } -int amdgpu_bo_import(amdgpu_device_handle dev, - enum amdgpu_bo_handle_type type, - uint32_t shared_handle, +drm_public int amdgpu_bo_import(amdgpu_device_handle dev, + enum amdgpu_bo_handle_type type, + uint32_t shared_handle, struct amdgpu_bo_import_result *output) { struct drm_gem_open open_arg = {}; + struct drm_gem_close close_arg = {}; struct amdgpu_bo *bo = NULL; - int r; + uint32_t handle = 0, flink_name = 0; + uint64_t alloc_size = 0; + int r = 0; int dma_fd; uint64_t dma_buf_size = 0; @@ -296,21 +275,18 @@ int amdgpu_bo_import(amdgpu_device_handle dev, /* Convert a DMA buf handle to a KMS handle now. */ if (type == amdgpu_bo_handle_type_dma_buf_fd) { - uint32_t handle; off_t size; /* Get a KMS handle. */ r = drmPrimeFDToHandle(dev->fd, shared_handle, &handle); - if (r) { - return r; - } + if (r) + goto unlock; /* Query the buffer size. */ size = lseek(shared_handle, 0, SEEK_END); if (size == (off_t)-1) { - pthread_mutex_unlock(&dev->bo_table_mutex); - amdgpu_close_kms_handle(dev, handle); - return -errno; + r = -errno; + goto free_bo_handle; } lseek(shared_handle, 0, SEEK_SET); @@ -321,110 +297,148 @@ int amdgpu_bo_import(amdgpu_device_handle dev, /* If we have already created a buffer with this handle, find it. */ switch (type) { case amdgpu_bo_handle_type_gem_flink_name: - bo = util_hash_table_get(dev->bo_flink_names, - (void*)(uintptr_t)shared_handle); + bo = handle_table_lookup(&dev->bo_flink_names, shared_handle); break; case amdgpu_bo_handle_type_dma_buf_fd: - bo = util_hash_table_get(dev->bo_handles, - (void*)(uintptr_t)shared_handle); + bo = handle_table_lookup(&dev->bo_handles, shared_handle); break; case amdgpu_bo_handle_type_kms: + case amdgpu_bo_handle_type_kms_noimport: /* Importing a KMS handle in not allowed. */ - pthread_mutex_unlock(&dev->bo_table_mutex); - return -EPERM; + r = -EPERM; + goto unlock; default: - pthread_mutex_unlock(&dev->bo_table_mutex); - return -EINVAL; + r = -EINVAL; + goto unlock; } if (bo) { - pthread_mutex_unlock(&dev->bo_table_mutex); - /* The buffer already exists, just bump the refcount. */ atomic_inc(&bo->refcount); + pthread_mutex_unlock(&dev->bo_table_mutex); output->buf_handle = bo; output->alloc_size = bo->alloc_size; return 0; } - bo = calloc(1, sizeof(struct amdgpu_bo)); - if (!bo) { - pthread_mutex_unlock(&dev->bo_table_mutex); - if (type == amdgpu_bo_handle_type_dma_buf_fd) { - amdgpu_close_kms_handle(dev, shared_handle); - } - return -ENOMEM; - } - /* Open the handle. */ switch (type) { case amdgpu_bo_handle_type_gem_flink_name: open_arg.name = shared_handle; r = drmIoctl(dev->flink_fd, DRM_IOCTL_GEM_OPEN, &open_arg); - if (r) { - free(bo); - pthread_mutex_unlock(&dev->bo_table_mutex); - return r; - } + if (r) + goto unlock; - bo->handle = open_arg.handle; + flink_name = shared_handle; + handle = open_arg.handle; + alloc_size = open_arg.size; if (dev->flink_fd != dev->fd) { - r = drmPrimeHandleToFD(dev->flink_fd, bo->handle, DRM_CLOEXEC, &dma_fd); - if (r) { - free(bo); - pthread_mutex_unlock(&dev->bo_table_mutex); - return r; - } - r = drmPrimeFDToHandle(dev->fd, dma_fd, &bo->handle ); - + r = drmPrimeHandleToFD(dev->flink_fd, handle, + DRM_CLOEXEC, &dma_fd); + if (r) + goto free_bo_handle; + r = drmPrimeFDToHandle(dev->fd, dma_fd, &handle); close(dma_fd); - - if (r) { - free(bo); - pthread_mutex_unlock(&dev->bo_table_mutex); - return r; - } + if (r) + goto free_bo_handle; + close_arg.handle = open_arg.handle; + r = drmIoctl(dev->flink_fd, DRM_IOCTL_GEM_CLOSE, + &close_arg); + if (r) + goto free_bo_handle; } - bo->flink_name = shared_handle; - bo->alloc_size = open_arg.size; - util_hash_table_set(dev->bo_flink_names, - (void*)(uintptr_t)bo->flink_name, bo); break; case amdgpu_bo_handle_type_dma_buf_fd: - bo->handle = shared_handle; - bo->alloc_size = dma_buf_size; + handle = shared_handle; + alloc_size = dma_buf_size; break; case amdgpu_bo_handle_type_kms: + case amdgpu_bo_handle_type_kms_noimport: assert(0); /* unreachable */ } /* Initialize it. */ - atomic_set(&bo->refcount, 1); - bo->dev = dev; - pthread_mutex_init(&bo->cpu_access_mutex, NULL); + r = amdgpu_bo_create(dev, alloc_size, handle, &bo); + if (r) + goto free_bo_handle; - util_hash_table_set(dev->bo_handles, (void*)(uintptr_t)bo->handle, bo); - pthread_mutex_unlock(&dev->bo_table_mutex); + r = handle_table_insert(&dev->bo_handles, bo->handle, bo); + if (r) + goto free_bo_handle; + if (flink_name) { + bo->flink_name = flink_name; + r = handle_table_insert(&dev->bo_flink_names, flink_name, + bo); + if (r) + goto remove_handle; + + } output->buf_handle = bo; output->alloc_size = bo->alloc_size; + pthread_mutex_unlock(&dev->bo_table_mutex); return 0; + +remove_handle: + handle_table_remove(&dev->bo_handles, bo->handle); +free_bo_handle: + if (flink_name && !close_arg.handle && open_arg.handle) { + close_arg.handle = open_arg.handle; + drmIoctl(dev->flink_fd, DRM_IOCTL_GEM_CLOSE, &close_arg); + } + if (bo) + amdgpu_bo_free(bo); + else + amdgpu_close_kms_handle(dev, handle); +unlock: + pthread_mutex_unlock(&dev->bo_table_mutex); + return r; } -int amdgpu_bo_free(amdgpu_bo_handle buf_handle) +drm_public int amdgpu_bo_free(amdgpu_bo_handle buf_handle) { - /* Just drop the reference. */ - amdgpu_bo_reference(&buf_handle, NULL); + struct amdgpu_device *dev; + struct amdgpu_bo *bo = buf_handle; + + assert(bo != NULL); + dev = bo->dev; + pthread_mutex_lock(&dev->bo_table_mutex); + + if (update_references(&bo->refcount, NULL)) { + /* Remove the buffer from the hash tables. */ + handle_table_remove(&dev->bo_handles, bo->handle); + + if (bo->flink_name) + handle_table_remove(&dev->bo_flink_names, + bo->flink_name); + + /* Release CPU access. */ + if (bo->cpu_map_count > 0) { + bo->cpu_map_count = 1; + amdgpu_bo_cpu_unmap(bo); + } + + amdgpu_close_kms_handle(dev, bo->handle); + pthread_mutex_destroy(&bo->cpu_access_mutex); + free(bo); + } + + pthread_mutex_unlock(&dev->bo_table_mutex); return 0; } -int amdgpu_bo_cpu_map(amdgpu_bo_handle bo, void **cpu) +drm_public void amdgpu_bo_inc_ref(amdgpu_bo_handle bo) +{ + atomic_inc(&bo->refcount); +} + +drm_public int amdgpu_bo_cpu_map(amdgpu_bo_handle bo, void **cpu) { union drm_amdgpu_gem_mmap args; void *ptr; @@ -472,7 +486,7 @@ int amdgpu_bo_cpu_map(amdgpu_bo_handle bo, void **cpu) return 0; } -int amdgpu_bo_cpu_unmap(amdgpu_bo_handle bo) +drm_public int amdgpu_bo_cpu_unmap(amdgpu_bo_handle bo) { int r; @@ -498,7 +512,7 @@ int amdgpu_bo_cpu_unmap(amdgpu_bo_handle bo) return r; } -int amdgpu_query_buffer_size_alignment(amdgpu_device_handle dev, +drm_public int amdgpu_query_buffer_size_alignment(amdgpu_device_handle dev, struct amdgpu_buffer_size_alignments *info) { info->size_local = dev->dev_info.pte_fragment_size; @@ -506,8 +520,8 @@ int amdgpu_query_buffer_size_alignment(amdgpu_device_handle dev, return 0; } -int amdgpu_bo_wait_for_idle(amdgpu_bo_handle bo, - uint64_t timeout_ns, +drm_public int amdgpu_bo_wait_for_idle(amdgpu_bo_handle bo, + uint64_t timeout_ns, bool *busy) { union drm_amdgpu_gem_wait_idle args; @@ -529,13 +543,54 @@ int amdgpu_bo_wait_for_idle(amdgpu_bo_handle bo, } } -int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev, - void *cpu, - uint64_t size, - amdgpu_bo_handle *buf_handle) +drm_public int amdgpu_find_bo_by_cpu_mapping(amdgpu_device_handle dev, + void *cpu, + uint64_t size, + amdgpu_bo_handle *buf_handle, + uint64_t *offset_in_bo) { - int r; struct amdgpu_bo *bo; + uint32_t i; + int r = 0; + + if (cpu == NULL || size == 0) + return -EINVAL; + + /* + * Workaround for a buggy application which tries to import previously + * exposed CPU pointers. If we find a real world use case we should + * improve that by asking the kernel for the right handle. + */ + pthread_mutex_lock(&dev->bo_table_mutex); + for (i = 0; i < dev->bo_handles.max_key; i++) { + bo = handle_table_lookup(&dev->bo_handles, i); + if (!bo || !bo->cpu_ptr || size > bo->alloc_size) + continue; + if (cpu >= bo->cpu_ptr && + cpu < (void*)((uintptr_t)bo->cpu_ptr + bo->alloc_size)) + break; + } + + if (i < dev->bo_handles.max_key) { + atomic_inc(&bo->refcount); + *buf_handle = bo; + *offset_in_bo = (uintptr_t)cpu - (uintptr_t)bo->cpu_ptr; + } else { + *buf_handle = NULL; + *offset_in_bo = 0; + r = -ENXIO; + } + pthread_mutex_unlock(&dev->bo_table_mutex); + + return r; +} + +drm_public int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev, + void *cpu, + uint64_t size, + amdgpu_bo_handle *buf_handle) +{ + int r; struct drm_amdgpu_gem_userptr args; args.addr = (uintptr_t)cpu; @@ -545,27 +600,63 @@ int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev, r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_USERPTR, &args, sizeof(args)); if (r) - return r; + goto out; - bo = calloc(1, sizeof(struct amdgpu_bo)); - if (!bo) - return -ENOMEM; + r = amdgpu_bo_create(dev, size, args.handle, buf_handle); + if (r) { + amdgpu_close_kms_handle(dev, args.handle); + goto out; + } - atomic_set(&bo->refcount, 1); - bo->dev = dev; - bo->alloc_size = size; - bo->handle = args.handle; + pthread_mutex_lock(&dev->bo_table_mutex); + r = handle_table_insert(&dev->bo_handles, (*buf_handle)->handle, + *buf_handle); + pthread_mutex_unlock(&dev->bo_table_mutex); + if (r) + amdgpu_bo_free(*buf_handle); +out: + return r; +} - *buf_handle = bo; +drm_public int amdgpu_bo_list_create_raw(amdgpu_device_handle dev, + uint32_t number_of_buffers, + struct drm_amdgpu_bo_list_entry *buffers, + uint32_t *result) +{ + union drm_amdgpu_bo_list args; + int r; + + memset(&args, 0, sizeof(args)); + args.in.operation = AMDGPU_BO_LIST_OP_CREATE; + args.in.bo_number = number_of_buffers; + args.in.bo_info_size = sizeof(struct drm_amdgpu_bo_list_entry); + args.in.bo_info_ptr = (uint64_t)(uintptr_t)buffers; + r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_BO_LIST, + &args, sizeof(args)); + if (!r) + *result = args.out.list_handle; return r; } -int amdgpu_bo_list_create(amdgpu_device_handle dev, - uint32_t number_of_resources, - amdgpu_bo_handle *resources, - uint8_t *resource_prios, - amdgpu_bo_list_handle *result) +drm_public int amdgpu_bo_list_destroy_raw(amdgpu_device_handle dev, + uint32_t bo_list) +{ + union drm_amdgpu_bo_list args; + + memset(&args, 0, sizeof(args)); + args.in.operation = AMDGPU_BO_LIST_OP_DESTROY; + args.in.list_handle = bo_list; + + return drmCommandWriteRead(dev->fd, DRM_AMDGPU_BO_LIST, + &args, sizeof(args)); +} + +drm_public int amdgpu_bo_list_create(amdgpu_device_handle dev, + uint32_t number_of_resources, + amdgpu_bo_handle *resources, + uint8_t *resource_prios, + amdgpu_bo_list_handle *result) { struct drm_amdgpu_bo_list_entry *list; union drm_amdgpu_bo_list args; @@ -616,7 +707,7 @@ int amdgpu_bo_list_create(amdgpu_device_handle dev, return 0; } -int amdgpu_bo_list_destroy(amdgpu_bo_list_handle list) +drm_public int amdgpu_bo_list_destroy(amdgpu_bo_list_handle list) { union drm_amdgpu_bo_list args; int r; @@ -634,10 +725,10 @@ int amdgpu_bo_list_destroy(amdgpu_bo_list_handle list) return r; } -int amdgpu_bo_list_update(amdgpu_bo_list_handle handle, - uint32_t number_of_resources, - amdgpu_bo_handle *resources, - uint8_t *resource_prios) +drm_public int amdgpu_bo_list_update(amdgpu_bo_list_handle handle, + uint32_t number_of_resources, + amdgpu_bo_handle *resources, + uint8_t *resource_prios) { struct drm_amdgpu_bo_list_entry *list; union drm_amdgpu_bo_list args; @@ -652,7 +743,7 @@ int amdgpu_bo_list_update(amdgpu_bo_list_handle handle, return -EINVAL; list = malloc(number_of_resources * sizeof(struct drm_amdgpu_bo_list_entry)); - if (list == NULL) + if (!list) return -ENOMEM; args.in.operation = AMDGPU_BO_LIST_OP_UPDATE; @@ -675,29 +766,45 @@ int amdgpu_bo_list_update(amdgpu_bo_list_handle handle, return r; } -int amdgpu_bo_va_op(amdgpu_bo_handle bo, - uint64_t offset, - uint64_t size, - uint64_t addr, - uint64_t flags, - uint32_t ops) +drm_public int amdgpu_bo_va_op(amdgpu_bo_handle bo, + uint64_t offset, + uint64_t size, + uint64_t addr, + uint64_t flags, + uint32_t ops) { amdgpu_device_handle dev = bo->dev; + + size = ALIGN(size, getpagesize()); + + return amdgpu_bo_va_op_raw(dev, bo, offset, size, addr, + AMDGPU_VM_PAGE_READABLE | + AMDGPU_VM_PAGE_WRITEABLE | + AMDGPU_VM_PAGE_EXECUTABLE, ops); +} + +drm_public int amdgpu_bo_va_op_raw(amdgpu_device_handle dev, + amdgpu_bo_handle bo, + uint64_t offset, + uint64_t size, + uint64_t addr, + uint64_t flags, + uint32_t ops) +{ struct drm_amdgpu_gem_va va; int r; - if (ops != AMDGPU_VA_OP_MAP && ops != AMDGPU_VA_OP_UNMAP) + if (ops != AMDGPU_VA_OP_MAP && ops != AMDGPU_VA_OP_UNMAP && + ops != AMDGPU_VA_OP_REPLACE && ops != AMDGPU_VA_OP_CLEAR) return -EINVAL; memset(&va, 0, sizeof(va)); - va.handle = bo->handle; + va.handle = bo ? bo->handle : 0; va.operation = ops; - va.flags = AMDGPU_VM_PAGE_READABLE | - AMDGPU_VM_PAGE_WRITEABLE | - AMDGPU_VM_PAGE_EXECUTABLE; + va.flags = flags; va.va_address = addr; va.offset_in_bo = offset; - va.map_size = ALIGN(size, getpagesize()); + va.map_size = size; r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_VA, &va, sizeof(va)); diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c index fb5b3a8c..ba158f2a 100644 --- a/amdgpu/amdgpu_cs.c +++ b/amdgpu/amdgpu_cs.c @@ -21,10 +21,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -46,26 +42,26 @@ static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem); /** * Create command submission context * - * \param dev - \c [in] amdgpu device handle - * \param context - \c [out] amdgpu context handle + * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() + * \param priority - \c [in] Context creation flags. See AMDGPU_CTX_PRIORITY_* + * \param context - \c [out] GPU Context handle * * \return 0 on success otherwise POSIX Error code */ -int amdgpu_cs_ctx_create(amdgpu_device_handle dev, - amdgpu_context_handle *context) +drm_public int amdgpu_cs_ctx_create2(amdgpu_device_handle dev, + uint32_t priority, + amdgpu_context_handle *context) { struct amdgpu_context *gpu_context; union drm_amdgpu_ctx args; int i, j, k; int r; - if (NULL == dev) - return -EINVAL; - if (NULL == context) + if (!dev || !context) return -EINVAL; gpu_context = calloc(1, sizeof(struct amdgpu_context)); - if (NULL == gpu_context) + if (!gpu_context) return -ENOMEM; gpu_context->dev = dev; @@ -77,6 +73,8 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev, /* Create the context */ memset(&args, 0, sizeof(args)); args.in.op = AMDGPU_CTX_OP_ALLOC_CTX; + args.in.priority = priority; + r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CTX, &args, sizeof(args)); if (r) goto error; @@ -96,6 +94,12 @@ error: return r; } +drm_public int amdgpu_cs_ctx_create(amdgpu_device_handle dev, + amdgpu_context_handle *context) +{ + return amdgpu_cs_ctx_create2(dev, AMDGPU_CTX_PRIORITY_NORMAL, context); +} + /** * Release command submission context * @@ -104,13 +108,13 @@ error: * * \return 0 on success otherwise POSIX Error code */ -int amdgpu_cs_ctx_free(amdgpu_context_handle context) +drm_public int amdgpu_cs_ctx_free(amdgpu_context_handle context) { union drm_amdgpu_ctx args; int i, j, k; int r; - if (NULL == context) + if (!context) return -EINVAL; pthread_mutex_destroy(&context->sequence_mutex); @@ -138,8 +142,8 @@ int amdgpu_cs_ctx_free(amdgpu_context_handle context) return r; } -int amdgpu_cs_query_reset_state(amdgpu_context_handle context, - uint32_t *state, uint32_t *hangs) +drm_public int amdgpu_cs_query_reset_state(amdgpu_context_handle context, + uint32_t *state, uint32_t *hangs) { union drm_amdgpu_ctx args; int r; @@ -188,8 +192,6 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context, return -EINVAL; if (ibs_request->ring >= AMDGPU_CS_MAX_RINGS) return -EINVAL; - if (ibs_request->number_of_ibs > AMDGPU_CS_MAX_IBS_PER_SUBMIT) - return -EINVAL; if (ibs_request->number_of_ibs == 0) { ibs_request->seq_no = AMDGPU_NULL_SUBMIT_SEQ; return 0; @@ -322,17 +324,15 @@ error_unlock: return r; } -int amdgpu_cs_submit(amdgpu_context_handle context, - uint64_t flags, - struct amdgpu_cs_request *ibs_request, - uint32_t number_of_requests) +drm_public int amdgpu_cs_submit(amdgpu_context_handle context, + uint64_t flags, + struct amdgpu_cs_request *ibs_request, + uint32_t number_of_requests) { uint32_t i; int r; - if (NULL == context) - return -EINVAL; - if (NULL == ibs_request) + if (!context || !ibs_request) return -EINVAL; r = 0; @@ -408,19 +408,15 @@ static int amdgpu_ioctl_wait_cs(amdgpu_context_handle context, return 0; } -int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, - uint64_t timeout_ns, - uint64_t flags, - uint32_t *expired) +drm_public int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, + uint64_t timeout_ns, + uint64_t flags, + uint32_t *expired) { bool busy = true; int r; - if (NULL == fence) - return -EINVAL; - if (NULL == expired) - return -EINVAL; - if (NULL == fence->context) + if (!fence || !expired || !fence->context) return -EINVAL; if (fence->ip_type >= AMDGPU_HW_IP_NUM) return -EINVAL; @@ -443,15 +439,83 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, return r; } -int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem) +static int amdgpu_ioctl_wait_fences(struct amdgpu_cs_fence *fences, + uint32_t fence_count, + bool wait_all, + uint64_t timeout_ns, + uint32_t *status, + uint32_t *first) +{ + struct drm_amdgpu_fence *drm_fences; + amdgpu_device_handle dev = fences[0].context->dev; + union drm_amdgpu_wait_fences args; + int r; + uint32_t i; + + drm_fences = alloca(sizeof(struct drm_amdgpu_fence) * fence_count); + for (i = 0; i < fence_count; i++) { + drm_fences[i].ctx_id = fences[i].context->id; + drm_fences[i].ip_type = fences[i].ip_type; + drm_fences[i].ip_instance = fences[i].ip_instance; + drm_fences[i].ring = fences[i].ring; + drm_fences[i].seq_no = fences[i].fence; + } + + memset(&args, 0, sizeof(args)); + args.in.fences = (uint64_t)(uintptr_t)drm_fences; + args.in.fence_count = fence_count; + args.in.wait_all = wait_all; + args.in.timeout_ns = amdgpu_cs_calculate_timeout(timeout_ns); + + r = drmIoctl(dev->fd, DRM_IOCTL_AMDGPU_WAIT_FENCES, &args); + if (r) + return -errno; + + *status = args.out.status; + + if (first) + *first = args.out.first_signaled; + + return 0; +} + +drm_public int amdgpu_cs_wait_fences(struct amdgpu_cs_fence *fences, + uint32_t fence_count, + bool wait_all, + uint64_t timeout_ns, + uint32_t *status, + uint32_t *first) +{ + uint32_t i; + + /* Sanity check */ + if (!fences || !status || !fence_count) + return -EINVAL; + + for (i = 0; i < fence_count; i++) { + if (NULL == fences[i].context) + return -EINVAL; + if (fences[i].ip_type >= AMDGPU_HW_IP_NUM) + return -EINVAL; + if (fences[i].ring >= AMDGPU_CS_MAX_RINGS) + return -EINVAL; + } + + *status = 0; + + return amdgpu_ioctl_wait_fences(fences, fence_count, wait_all, + timeout_ns, status, first); +} + +drm_public int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem) { struct amdgpu_semaphore *gpu_semaphore; - if (NULL == sem) + if (!sem) return -EINVAL; gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore)); - if (NULL == gpu_semaphore) + if (!gpu_semaphore) return -ENOMEM; atomic_set(&gpu_semaphore->refcount, 1); @@ -460,20 +524,18 @@ int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem) return 0; } -int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, - uint32_t ip_type, +drm_public int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, uint32_t ip_instance, uint32_t ring, amdgpu_semaphore_handle sem) { - if (NULL == ctx) + if (!ctx || !sem) return -EINVAL; if (ip_type >= AMDGPU_HW_IP_NUM) return -EINVAL; if (ring >= AMDGPU_CS_MAX_RINGS) return -EINVAL; - if (NULL == sem) - return -EINVAL; /* sem has been signaled */ if (sem->signal_fence.context) return -EINVAL; @@ -488,22 +550,20 @@ int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, return 0; } -int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, - uint32_t ip_type, +drm_public int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, + uint32_t ip_type, uint32_t ip_instance, uint32_t ring, amdgpu_semaphore_handle sem) { - if (NULL == ctx) + if (!ctx || !sem) return -EINVAL; if (ip_type >= AMDGPU_HW_IP_NUM) return -EINVAL; if (ring >= AMDGPU_CS_MAX_RINGS) return -EINVAL; - if (NULL == sem) - return -EINVAL; /* must signal first */ - if (NULL == sem->signal_fence.context) + if (!sem->signal_fence.context) return -EINVAL; pthread_mutex_lock(&ctx->sequence_mutex); @@ -514,12 +574,10 @@ int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem) { - if (NULL == sem) - return -EINVAL; - if (NULL == sem->signal_fence.context) + if (!sem || !sem->signal_fence.context) return -EINVAL; - sem->signal_fence.context = NULL;; + sem->signal_fence.context = NULL; sem->signal_fence.ip_type = 0; sem->signal_fence.ip_instance = 0; sem->signal_fence.ring = 0; @@ -530,7 +588,7 @@ static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem) static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem) { - if (NULL == sem) + if (!sem) return -EINVAL; if (update_references(&sem->refcount, NULL)) @@ -538,7 +596,204 @@ static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem) return 0; } -int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem) +drm_public int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem) { return amdgpu_cs_unreference_sem(sem); } + +drm_public int amdgpu_cs_create_syncobj2(amdgpu_device_handle dev, + uint32_t flags, + uint32_t *handle) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjCreate(dev->fd, flags, handle); +} + +drm_public int amdgpu_cs_create_syncobj(amdgpu_device_handle dev, + uint32_t *handle) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjCreate(dev->fd, 0, handle); +} + +drm_public int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev, + uint32_t handle) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjDestroy(dev->fd, handle); +} + +drm_public int amdgpu_cs_syncobj_reset(amdgpu_device_handle dev, + const uint32_t *syncobjs, + uint32_t syncobj_count) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjReset(dev->fd, syncobjs, syncobj_count); +} + +drm_public int amdgpu_cs_syncobj_signal(amdgpu_device_handle dev, + const uint32_t *syncobjs, + uint32_t syncobj_count) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjSignal(dev->fd, syncobjs, syncobj_count); +} + +drm_public int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev, + uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjWait(dev->fd, handles, num_handles, timeout_nsec, + flags, first_signaled); +} + +drm_public int amdgpu_cs_export_syncobj(amdgpu_device_handle dev, + uint32_t handle, + int *shared_fd) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjHandleToFD(dev->fd, handle, shared_fd); +} + +drm_public int amdgpu_cs_import_syncobj(amdgpu_device_handle dev, + int shared_fd, + uint32_t *handle) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjFDToHandle(dev->fd, shared_fd, handle); +} + +drm_public int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int *sync_file_fd) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjExportSyncFile(dev->fd, syncobj, sync_file_fd); +} + +drm_public int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev, + uint32_t syncobj, + int sync_file_fd) +{ + if (NULL == dev) + return -EINVAL; + + return drmSyncobjImportSyncFile(dev->fd, syncobj, sync_file_fd); +} + +drm_public int amdgpu_cs_submit_raw(amdgpu_device_handle dev, + amdgpu_context_handle context, + amdgpu_bo_list_handle bo_list_handle, + int num_chunks, + struct drm_amdgpu_cs_chunk *chunks, + uint64_t *seq_no) +{ + union drm_amdgpu_cs cs; + uint64_t *chunk_array; + int i, r; + if (num_chunks == 0) + return -EINVAL; + + memset(&cs, 0, sizeof(cs)); + chunk_array = alloca(sizeof(uint64_t) * num_chunks); + for (i = 0; i < num_chunks; i++) + chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i]; + cs.in.chunks = (uint64_t)(uintptr_t)chunk_array; + cs.in.ctx_id = context->id; + cs.in.bo_list_handle = bo_list_handle ? bo_list_handle->handle : 0; + cs.in.num_chunks = num_chunks; + r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CS, + &cs, sizeof(cs)); + if (r) + return r; + + if (seq_no) + *seq_no = cs.out.handle; + return 0; +} + +drm_public int amdgpu_cs_submit_raw2(amdgpu_device_handle dev, + amdgpu_context_handle context, + uint32_t bo_list_handle, + int num_chunks, + struct drm_amdgpu_cs_chunk *chunks, + uint64_t *seq_no) +{ + union drm_amdgpu_cs cs; + uint64_t *chunk_array; + int i, r; + + memset(&cs, 0, sizeof(cs)); + chunk_array = alloca(sizeof(uint64_t) * num_chunks); + for (i = 0; i < num_chunks; i++) + chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i]; + cs.in.chunks = (uint64_t)(uintptr_t)chunk_array; + cs.in.ctx_id = context->id; + cs.in.bo_list_handle = bo_list_handle; + cs.in.num_chunks = num_chunks; + r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CS, + &cs, sizeof(cs)); + if (!r && seq_no) + *seq_no = cs.out.handle; + return r; +} + +drm_public void amdgpu_cs_chunk_fence_info_to_data(struct amdgpu_cs_fence_info *fence_info, + struct drm_amdgpu_cs_chunk_data *data) +{ + data->fence_data.handle = fence_info->handle->handle; + data->fence_data.offset = fence_info->offset * sizeof(uint64_t); +} + +drm_public void amdgpu_cs_chunk_fence_to_dep(struct amdgpu_cs_fence *fence, + struct drm_amdgpu_cs_chunk_dep *dep) +{ + dep->ip_type = fence->ip_type; + dep->ip_instance = fence->ip_instance; + dep->ring = fence->ring; + dep->ctx_id = fence->context->id; + dep->handle = fence->fence; +} + +drm_public int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev, + struct amdgpu_cs_fence *fence, + uint32_t what, + uint32_t *out_handle) +{ + union drm_amdgpu_fence_to_handle fth; + int r; + + memset(&fth, 0, sizeof(fth)); + fth.in.fence.ctx_id = fence->context->id; + fth.in.fence.ip_type = fence->ip_type; + fth.in.fence.ip_instance = fence->ip_instance; + fth.in.fence.ring = fence->ring; + fth.in.fence.seq_no = fence->fence; + fth.in.what = what; + + r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_FENCE_TO_HANDLE, + &fth, sizeof(fth)); + if (r == 0) + *out_handle = fth.out.handle; + return r; +} diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c index f4ede031..362494b1 100644 --- a/amdgpu/amdgpu_device.c +++ b/amdgpu/amdgpu_device.c @@ -28,62 +28,26 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <sys/stat.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <fcntl.h> #include "xf86drm.h" #include "amdgpu_drm.h" #include "amdgpu_internal.h" -#include "util_hash_table.h" #include "util_math.h" -#include "amdgpu_asic_id.h" #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) -#define UINT_TO_PTR(x) ((void *)((intptr_t)(x))) static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER; -static struct util_hash_table *fd_tab; - -static unsigned handle_hash(void *key) -{ - return PTR_TO_UINT(key); -} - -static int handle_compare(void *key1, void *key2) -{ - return PTR_TO_UINT(key1) != PTR_TO_UINT(key2); -} - -static unsigned fd_hash(void *key) -{ - int fd = PTR_TO_UINT(key); - char *name = drmGetPrimaryDeviceNameFromFd(fd); - unsigned result = 0; - char *c; - - if (name == NULL) - return 0; - - for (c = name; *c; ++c) - result += *c; - - free(name); - - return result; -} +static amdgpu_device_handle fd_list; -static int fd_compare(void *key1, void *key2) +static int fd_compare(int fd1, int fd2) { - int fd1 = PTR_TO_UINT(key1); - int fd2 = PTR_TO_UINT(key2); char *name1 = drmGetPrimaryDeviceNameFromFd(fd1); char *name2 = drmGetPrimaryDeviceNameFromFd(fd2); int result; @@ -131,17 +95,26 @@ static int amdgpu_get_auth(int fd, int *auth) static void amdgpu_device_free_internal(amdgpu_device_handle dev) { - amdgpu_vamgr_deinit(dev->vamgr); - free(dev->vamgr); - amdgpu_vamgr_deinit(dev->vamgr_32); - free(dev->vamgr_32); - util_hash_table_destroy(dev->bo_flink_names); - util_hash_table_destroy(dev->bo_handles); - pthread_mutex_destroy(&dev->bo_table_mutex); - util_hash_table_remove(fd_tab, UINT_TO_PTR(dev->fd)); + amdgpu_device_handle *node = &fd_list; + + pthread_mutex_lock(&fd_mutex); + while (*node != dev && (*node)->next) + node = &(*node)->next; + *node = (*node)->next; + pthread_mutex_unlock(&fd_mutex); + close(dev->fd); if ((dev->flink_fd >= 0) && (dev->fd != dev->flink_fd)) close(dev->flink_fd); + + amdgpu_vamgr_deinit(&dev->vamgr_32); + amdgpu_vamgr_deinit(&dev->vamgr); + amdgpu_vamgr_deinit(&dev->vamgr_high_32); + amdgpu_vamgr_deinit(&dev->vamgr_high); + handle_table_fini(&dev->bo_handles); + handle_table_fini(&dev->bo_flink_names); + pthread_mutex_destroy(&dev->bo_table_mutex); + free(dev->marketing_name); free(dev); } @@ -160,17 +133,17 @@ static void amdgpu_device_free_internal(amdgpu_device_handle dev) * // incremented. dst is freed if its reference counter is 0. */ static void amdgpu_device_reference(struct amdgpu_device **dst, - struct amdgpu_device *src) + struct amdgpu_device *src) { if (update_references(&(*dst)->refcount, &src->refcount)) amdgpu_device_free_internal(*dst); *dst = src; } -int amdgpu_device_initialize(int fd, - uint32_t *major_version, - uint32_t *minor_version, - amdgpu_device_handle *device_handle) +drm_public int amdgpu_device_initialize(int fd, + uint32_t *major_version, + uint32_t *minor_version, + amdgpu_device_handle *device_handle) { struct amdgpu_device *dev; drmVersionPtr version; @@ -183,22 +156,28 @@ int amdgpu_device_initialize(int fd, *device_handle = NULL; pthread_mutex_lock(&fd_mutex); - if (!fd_tab) - fd_tab = util_hash_table_create(fd_hash, fd_compare); r = amdgpu_get_auth(fd, &flag_auth); if (r) { + fprintf(stderr, "%s: amdgpu_get_auth (1) failed (%i)\n", + __func__, r); pthread_mutex_unlock(&fd_mutex); return r; } - dev = util_hash_table_get(fd_tab, UINT_TO_PTR(fd)); + + for (dev = fd_list; dev; dev = dev->next) + if (fd_compare(dev->fd, fd) == 0) + break; + if (dev) { r = amdgpu_get_auth(dev->fd, &flag_authexist); if (r) { + fprintf(stderr, "%s: amdgpu_get_auth (2) failed (%i)\n", + __func__, r); pthread_mutex_unlock(&fd_mutex); return r; } if ((flag_auth) && (!flag_authexist)) { - dev->flink_fd = dup(fd); + dev->flink_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); } *major_version = dev->major_version; *minor_version = dev->minor_version; @@ -209,6 +188,7 @@ int amdgpu_device_initialize(int fd, dev = calloc(1, sizeof(struct amdgpu_device)); if (!dev) { + fprintf(stderr, "%s: calloc failed\n", __func__); pthread_mutex_unlock(&fd_mutex); return -ENOMEM; } @@ -231,66 +211,66 @@ int amdgpu_device_initialize(int fd, goto cleanup; } - dev->fd = dup(fd); + dev->fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); dev->flink_fd = dev->fd; dev->major_version = version->version_major; dev->minor_version = version->version_minor; drmFreeVersion(version); - dev->bo_flink_names = util_hash_table_create(handle_hash, - handle_compare); - dev->bo_handles = util_hash_table_create(handle_hash, handle_compare); pthread_mutex_init(&dev->bo_table_mutex, NULL); /* Check if acceleration is working. */ r = amdgpu_query_info(dev, AMDGPU_INFO_ACCEL_WORKING, 4, &accel_working); - if (r) + if (r) { + fprintf(stderr, "%s: amdgpu_query_info(ACCEL_WORKING) failed (%i)\n", + __func__, r); goto cleanup; + } if (!accel_working) { + fprintf(stderr, "%s: AMDGPU_INFO_ACCEL_WORKING = 0\n", __func__); r = -EBADF; goto cleanup; } r = amdgpu_query_gpu_info_init(dev); - if (r) + if (r) { + fprintf(stderr, "%s: amdgpu_query_gpu_info_init failed\n", __func__); goto cleanup; + } - dev->vamgr = calloc(1, sizeof(struct amdgpu_bo_va_mgr)); - if (dev->vamgr == NULL) - goto cleanup; + start = dev->dev_info.virtual_address_offset; + max = MIN2(dev->dev_info.virtual_address_max, 0x100000000ULL); + amdgpu_vamgr_init(&dev->vamgr_32, start, max, + dev->dev_info.virtual_address_alignment); + + start = max; + max = MAX2(dev->dev_info.virtual_address_max, 0x100000000ULL); + amdgpu_vamgr_init(&dev->vamgr, start, max, + dev->dev_info.virtual_address_alignment); - amdgpu_vamgr_init(dev->vamgr, dev->dev_info.virtual_address_offset, - dev->dev_info.virtual_address_max, + start = dev->dev_info.high_va_offset; + max = MIN2(dev->dev_info.high_va_max, (start & ~0xffffffffULL) + + 0x100000000ULL); + amdgpu_vamgr_init(&dev->vamgr_high_32, start, max, dev->dev_info.virtual_address_alignment); - max = MIN2(dev->dev_info.virtual_address_max, 0xffffffff); - start = amdgpu_vamgr_find_va(dev->vamgr, - max - dev->dev_info.virtual_address_offset, - dev->dev_info.virtual_address_alignment, 0); - if (start > 0xffffffff) - goto free_va; /* shouldn't get here */ - - dev->vamgr_32 = calloc(1, sizeof(struct amdgpu_bo_va_mgr)); - if (dev->vamgr_32 == NULL) - goto free_va; - amdgpu_vamgr_init(dev->vamgr_32, start, max, + start = max; + max = MAX2(dev->dev_info.high_va_max, (start & ~0xffffffffULL) + + 0x100000000ULL); + amdgpu_vamgr_init(&dev->vamgr_high, start, max, dev->dev_info.virtual_address_alignment); + amdgpu_parse_asic_ids(dev); + *major_version = dev->major_version; *minor_version = dev->minor_version; *device_handle = dev; - util_hash_table_set(fd_tab, UINT_TO_PTR(dev->fd), dev); + dev->next = fd_list; + fd_list = dev; pthread_mutex_unlock(&fd_mutex); return 0; -free_va: - r = -ENOMEM; - amdgpu_vamgr_free_va(dev->vamgr, start, - max - dev->dev_info.virtual_address_offset); - amdgpu_vamgr_deinit(dev->vamgr); - free(dev->vamgr); - cleanup: if (dev->fd >= 0) close(dev->fd); @@ -299,22 +279,30 @@ cleanup: return r; } -int amdgpu_device_deinitialize(amdgpu_device_handle dev) +drm_public int amdgpu_device_deinitialize(amdgpu_device_handle dev) { amdgpu_device_reference(&dev, NULL); return 0; } -const char *amdgpu_get_marketing_name(amdgpu_device_handle dev) +drm_public const char *amdgpu_get_marketing_name(amdgpu_device_handle dev) { - const struct amdgpu_asic_id_table_t *t = amdgpu_asic_id_table; + return dev->marketing_name; +} - while (t->did) { - if ((t->did == dev->info.asic_id) && - (t->rid == dev->info.pci_rev_id)) - return t->marketing_name; - t++; +drm_public int amdgpu_query_sw_info(amdgpu_device_handle dev, + enum amdgpu_sw_info info, + void *value) +{ + uint32_t *val32 = (uint32_t*)value; + + switch (info) { + case amdgpu_sw_info_address32_hi: + if (dev->vamgr_high_32.va_max) + *val32 = (dev->vamgr_high_32.va_max - 1) >> 32; + else + *val32 = (dev->vamgr_32.va_max - 1) >> 32; + return 0; } - - return NULL; + return -EINVAL; } diff --git a/amdgpu/amdgpu_gpu_info.c b/amdgpu/amdgpu_gpu_info.c index 66c7e0e1..777087f2 100644 --- a/amdgpu/amdgpu_gpu_info.c +++ b/amdgpu/amdgpu_gpu_info.c @@ -22,10 +22,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <string.h> @@ -34,8 +30,8 @@ #include "amdgpu_internal.h" #include "xf86drm.h" -int amdgpu_query_info(amdgpu_device_handle dev, unsigned info_id, - unsigned size, void *value) +drm_public int amdgpu_query_info(amdgpu_device_handle dev, unsigned info_id, + unsigned size, void *value) { struct drm_amdgpu_info request; @@ -48,8 +44,8 @@ int amdgpu_query_info(amdgpu_device_handle dev, unsigned info_id, sizeof(struct drm_amdgpu_info)); } -int amdgpu_query_crtc_from_id(amdgpu_device_handle dev, unsigned id, - int32_t *result) +drm_public int amdgpu_query_crtc_from_id(amdgpu_device_handle dev, unsigned id, + int32_t *result) { struct drm_amdgpu_info request; @@ -63,9 +59,9 @@ int amdgpu_query_crtc_from_id(amdgpu_device_handle dev, unsigned id, sizeof(struct drm_amdgpu_info)); } -int amdgpu_read_mm_registers(amdgpu_device_handle dev, unsigned dword_offset, - unsigned count, uint32_t instance, uint32_t flags, - uint32_t *values) +drm_public int amdgpu_read_mm_registers(amdgpu_device_handle dev, + unsigned dword_offset, unsigned count, uint32_t instance, + uint32_t flags, uint32_t *values) { struct drm_amdgpu_info request; @@ -82,8 +78,9 @@ int amdgpu_read_mm_registers(amdgpu_device_handle dev, unsigned dword_offset, sizeof(struct drm_amdgpu_info)); } -int amdgpu_query_hw_ip_count(amdgpu_device_handle dev, unsigned type, - uint32_t *count) +drm_public int amdgpu_query_hw_ip_count(amdgpu_device_handle dev, + unsigned type, + uint32_t *count) { struct drm_amdgpu_info request; @@ -97,9 +94,9 @@ int amdgpu_query_hw_ip_count(amdgpu_device_handle dev, unsigned type, sizeof(struct drm_amdgpu_info)); } -int amdgpu_query_hw_ip_info(amdgpu_device_handle dev, unsigned type, - unsigned ip_instance, - struct drm_amdgpu_info_hw_ip *info) +drm_public int amdgpu_query_hw_ip_info(amdgpu_device_handle dev, unsigned type, + unsigned ip_instance, + struct drm_amdgpu_info_hw_ip *info) { struct drm_amdgpu_info request; @@ -114,9 +111,9 @@ int amdgpu_query_hw_ip_info(amdgpu_device_handle dev, unsigned type, sizeof(struct drm_amdgpu_info)); } -int amdgpu_query_firmware_version(amdgpu_device_handle dev, unsigned fw_type, - unsigned ip_instance, unsigned index, - uint32_t *version, uint32_t *feature) +drm_public int amdgpu_query_firmware_version(amdgpu_device_handle dev, + unsigned fw_type, unsigned ip_instance, unsigned index, + uint32_t *version, uint32_t *feature) { struct drm_amdgpu_info request; struct drm_amdgpu_info_firmware firmware = {}; @@ -169,53 +166,57 @@ drm_private int amdgpu_query_gpu_info_init(amdgpu_device_handle dev) dev->info.vce_harvest_config = dev->dev_info.vce_harvest_config; dev->info.pci_rev_id = dev->dev_info.pci_rev; - for (i = 0; i < (int)dev->info.num_shader_engines; i++) { - unsigned instance = (i << AMDGPU_INFO_MMR_SE_INDEX_SHIFT) | - (AMDGPU_INFO_MMR_SH_INDEX_MASK << - AMDGPU_INFO_MMR_SH_INDEX_SHIFT); + if (dev->info.family_id < AMDGPU_FAMILY_AI) { + for (i = 0; i < (int)dev->info.num_shader_engines; i++) { + unsigned instance = (i << AMDGPU_INFO_MMR_SE_INDEX_SHIFT) | + (AMDGPU_INFO_MMR_SH_INDEX_MASK << + AMDGPU_INFO_MMR_SH_INDEX_SHIFT); - r = amdgpu_read_mm_registers(dev, 0x263d, 1, instance, 0, - &dev->info.backend_disable[i]); - if (r) - return r; - /* extract bitfield CC_RB_BACKEND_DISABLE.BACKEND_DISABLE */ - dev->info.backend_disable[i] = - (dev->info.backend_disable[i] >> 16) & 0xff; - - r = amdgpu_read_mm_registers(dev, 0xa0d4, 1, instance, 0, - &dev->info.pa_sc_raster_cfg[i]); - if (r) - return r; + r = amdgpu_read_mm_registers(dev, 0x263d, 1, instance, 0, + &dev->info.backend_disable[i]); + if (r) + return r; + /* extract bitfield CC_RB_BACKEND_DISABLE.BACKEND_DISABLE */ + dev->info.backend_disable[i] = + (dev->info.backend_disable[i] >> 16) & 0xff; - if (dev->info.family_id >= AMDGPU_FAMILY_CI) { - r = amdgpu_read_mm_registers(dev, 0xa0d5, 1, instance, 0, - &dev->info.pa_sc_raster_cfg1[i]); + r = amdgpu_read_mm_registers(dev, 0xa0d4, 1, instance, 0, + &dev->info.pa_sc_raster_cfg[i]); if (r) return r; + + if (dev->info.family_id >= AMDGPU_FAMILY_CI) { + r = amdgpu_read_mm_registers(dev, 0xa0d5, 1, instance, 0, + &dev->info.pa_sc_raster_cfg1[i]); + if (r) + return r; + } } } - r = amdgpu_read_mm_registers(dev, 0x2644, 32, 0xffffffff, 0, - dev->info.gb_tile_mode); + r = amdgpu_read_mm_registers(dev, 0x263e, 1, 0xffffffff, 0, + &dev->info.gb_addr_cfg); if (r) return r; - if (dev->info.family_id >= AMDGPU_FAMILY_CI) { - r = amdgpu_read_mm_registers(dev, 0x2664, 16, 0xffffffff, 0, - dev->info.gb_macro_tile_mode); + if (dev->info.family_id < AMDGPU_FAMILY_AI) { + r = amdgpu_read_mm_registers(dev, 0x2644, 32, 0xffffffff, 0, + dev->info.gb_tile_mode); if (r) return r; - } - r = amdgpu_read_mm_registers(dev, 0x263e, 1, 0xffffffff, 0, - &dev->info.gb_addr_cfg); - if (r) - return r; + if (dev->info.family_id >= AMDGPU_FAMILY_CI) { + r = amdgpu_read_mm_registers(dev, 0x2664, 16, 0xffffffff, 0, + dev->info.gb_macro_tile_mode); + if (r) + return r; + } - r = amdgpu_read_mm_registers(dev, 0x9d8, 1, 0xffffffff, 0, - &dev->info.mc_arb_ramcfg); - if (r) - return r; + r = amdgpu_read_mm_registers(dev, 0x9d8, 1, 0xffffffff, 0, + &dev->info.mc_arb_ramcfg); + if (r) + return r; + } dev->info.cu_active_number = dev->dev_info.cu_active_number; dev->info.cu_ao_mask = dev->dev_info.cu_ao_mask; @@ -227,21 +228,22 @@ drm_private int amdgpu_query_gpu_info_init(amdgpu_device_handle dev) return 0; } -int amdgpu_query_gpu_info(amdgpu_device_handle dev, - struct amdgpu_gpu_info *info) +drm_public int amdgpu_query_gpu_info(amdgpu_device_handle dev, + struct amdgpu_gpu_info *info) { - if ((dev == NULL) || (info == NULL)) + if (!dev || !info) return -EINVAL; + /* Get ASIC info*/ *info = dev->info; return 0; } -int amdgpu_query_heap_info(amdgpu_device_handle dev, - uint32_t heap, - uint32_t flags, - struct amdgpu_heap_info *info) +drm_public int amdgpu_query_heap_info(amdgpu_device_handle dev, + uint32_t heap, + uint32_t flags, + struct amdgpu_heap_info *info) { struct drm_amdgpu_info_vram_gtt vram_gtt_info = {}; int r; @@ -290,13 +292,13 @@ int amdgpu_query_heap_info(amdgpu_device_handle dev, return 0; } -int amdgpu_query_gds_info(amdgpu_device_handle dev, - struct amdgpu_gds_resource_info *gds_info) +drm_public int amdgpu_query_gds_info(amdgpu_device_handle dev, + struct amdgpu_gds_resource_info *gds_info) { struct drm_amdgpu_info_gds gds_config = {}; int r; - if (gds_info == NULL) + if (!gds_info) return -EINVAL; r = amdgpu_query_info(dev, AMDGPU_INFO_GDS_CONFIG, @@ -314,3 +316,18 @@ int amdgpu_query_gds_info(amdgpu_device_handle dev, return 0; } + +drm_public int amdgpu_query_sensor_info(amdgpu_device_handle dev, unsigned sensor_type, + unsigned size, void *value) +{ + struct drm_amdgpu_info request; + + memset(&request, 0, sizeof(request)); + request.return_pointer = (uintptr_t)value; + request.return_size = size; + request.query = AMDGPU_INFO_SENSOR; + request.sensor_info.type = sensor_type; + + return drmCommandWrite(dev->fd, DRM_AMDGPU_INFO, &request, + sizeof(struct drm_amdgpu_info)); +} diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h index 4f039b68..a340abbd 100644 --- a/amdgpu/amdgpu_internal.h +++ b/amdgpu/amdgpu_internal.h @@ -25,10 +25,6 @@ #ifndef _AMDGPU_INTERNAL_H_ #define _AMDGPU_INTERNAL_H_ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <assert.h> #include <pthread.h> @@ -36,6 +32,7 @@ #include "xf86atomic.h" #include "amdgpu.h" #include "util_double_list.h" +#include "handle_table.h" #define AMDGPU_CS_MAX_RINGS 8 /* do not use below macro if b is not power of 2 aligned value */ @@ -53,8 +50,6 @@ struct amdgpu_bo_va_hole { }; struct amdgpu_bo_va_mgr { - /* the start virtual address */ - uint64_t va_offset; uint64_t va_max; struct list_head va_holes; pthread_mutex_t bo_va_mutex; @@ -71,23 +66,29 @@ struct amdgpu_va { struct amdgpu_device { atomic_t refcount; + struct amdgpu_device *next; int fd; int flink_fd; unsigned major_version; unsigned minor_version; + char *marketing_name; /** List of buffer handles. Protected by bo_table_mutex. */ - struct util_hash_table *bo_handles; + struct handle_table bo_handles; /** List of buffer GEM flink names. Protected by bo_table_mutex. */ - struct util_hash_table *bo_flink_names; + struct handle_table bo_flink_names; /** This protects all hash tables. */ pthread_mutex_t bo_table_mutex; struct drm_amdgpu_info_device dev_info; struct amdgpu_gpu_info info; - /** The global VA manager for the whole virtual address space */ - struct amdgpu_bo_va_mgr *vamgr; + /** The VA manager for the lower virtual address space */ + struct amdgpu_bo_va_mgr vamgr; /** The VA manager for the 32bit address space */ - struct amdgpu_bo_va_mgr *vamgr_32; + struct amdgpu_bo_va_mgr vamgr_32; + /** The VA manager for the high virtual address space */ + struct amdgpu_bo_va_mgr vamgr_high; + /** The VA manager for the 32bit high address space */ + struct amdgpu_bo_va_mgr vamgr_high_32; }; struct amdgpu_bo { @@ -135,19 +136,12 @@ struct amdgpu_semaphore { * Functions. */ -drm_private void amdgpu_bo_free_internal(amdgpu_bo_handle bo); - drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, uint64_t max, uint64_t alignment); drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr); -drm_private uint64_t -amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, - uint64_t alignment, uint64_t base_required); - -drm_private void -amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size); +drm_private void amdgpu_parse_asic_ids(struct amdgpu_device *dev); drm_private int amdgpu_query_gpu_info_init(amdgpu_device_handle dev); @@ -179,26 +173,4 @@ static inline bool update_references(atomic_t *dst, atomic_t *src) return false; } -/** - * Assignment between two amdgpu_bo pointers with reference counting. - * - * Usage: - * struct amdgpu_bo *dst = ... , *src = ...; - * - * dst = src; - * // No reference counting. Only use this when you need to move - * // a reference from one pointer to another. - * - * amdgpu_bo_reference(&dst, src); - * // Reference counters are updated. dst is decremented and src is - * // incremented. dst is freed if its reference counter is 0. - */ -static inline void amdgpu_bo_reference(struct amdgpu_bo **dst, - struct amdgpu_bo *src) -{ - if (update_references(&(*dst)->refcount, &src->refcount)) - amdgpu_bo_free_internal(*dst); - *dst = src; -} - #endif diff --git a/amdgpu/amdgpu_vamgr.c b/amdgpu/amdgpu_vamgr.c index 8a707cbc..d25d4216 100644 --- a/amdgpu/amdgpu_vamgr.c +++ b/amdgpu/amdgpu_vamgr.c @@ -21,10 +21,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <string.h> #include <errno.h> @@ -33,26 +29,34 @@ #include "amdgpu_internal.h" #include "util_math.h" -int amdgpu_va_range_query(amdgpu_device_handle dev, - enum amdgpu_gpu_va_range type, uint64_t *start, uint64_t *end) +drm_public int amdgpu_va_range_query(amdgpu_device_handle dev, + enum amdgpu_gpu_va_range type, + uint64_t *start, uint64_t *end) { - if (type == amdgpu_gpu_va_range_general) { - *start = dev->dev_info.virtual_address_offset; - *end = dev->dev_info.virtual_address_max; - return 0; - } - return -EINVAL; + if (type != amdgpu_gpu_va_range_general) + return -EINVAL; + + *start = dev->dev_info.virtual_address_offset; + *end = dev->dev_info.virtual_address_max; + return 0; } drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, - uint64_t max, uint64_t alignment) + uint64_t max, uint64_t alignment) { - mgr->va_offset = start; + struct amdgpu_bo_va_hole *n; + mgr->va_max = max; mgr->va_alignment = alignment; list_inithead(&mgr->va_holes); pthread_mutex_init(&mgr->bo_va_mutex, NULL); + pthread_mutex_lock(&mgr->bo_va_mutex); + n = calloc(1, sizeof(struct amdgpu_bo_va_hole)); + n->size = mgr->va_max - start; + n->offset = start; + list_add(&n->list, &mgr->va_holes); + pthread_mutex_unlock(&mgr->bo_va_mutex); } drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) @@ -65,13 +69,14 @@ drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) pthread_mutex_destroy(&mgr->bo_va_mutex); } -drm_private uint64_t +static drm_private uint64_t amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, uint64_t alignment, uint64_t base_required) { struct amdgpu_bo_va_hole *hole, *n; uint64_t offset = 0, waste = 0; + alignment = MAX2(alignment, mgr->va_alignment); size = ALIGN(size, mgr->va_alignment); @@ -79,12 +84,10 @@ amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, return AMDGPU_INVALID_VA_ADDRESS; pthread_mutex_lock(&mgr->bo_va_mutex); - /* TODO: using more appropriate way to track the holes */ - /* first look for a hole */ - LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) { + LIST_FOR_EACH_ENTRY_SAFE_REV(hole, n, &mgr->va_holes, list) { if (base_required) { - if(hole->offset > base_required || - (hole->offset + hole->size) < (base_required + size)) + if (hole->offset > base_required || + (hole->offset + hole->size) < (base_required + size)) continue; waste = base_required - hole->offset; offset = base_required; @@ -123,41 +126,14 @@ amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, } } - if (base_required) { - if (base_required < mgr->va_offset) { - pthread_mutex_unlock(&mgr->bo_va_mutex); - return AMDGPU_INVALID_VA_ADDRESS; - } - offset = mgr->va_offset; - waste = base_required - mgr->va_offset; - } else { - offset = mgr->va_offset; - waste = offset % alignment; - waste = waste ? alignment - waste : 0; - } - - if (offset + waste + size > mgr->va_max) { - pthread_mutex_unlock(&mgr->bo_va_mutex); - return AMDGPU_INVALID_VA_ADDRESS; - } - - if (waste) { - n = calloc(1, sizeof(struct amdgpu_bo_va_hole)); - n->size = waste; - n->offset = offset; - list_add(&n->list, &mgr->va_holes); - } - - offset += waste; - mgr->va_offset += size + waste; pthread_mutex_unlock(&mgr->bo_va_mutex); - return offset; + return AMDGPU_INVALID_VA_ADDRESS; } -drm_private void +static drm_private void amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size) { - struct amdgpu_bo_va_hole *hole; + struct amdgpu_bo_va_hole *hole, *next; if (va == AMDGPU_INVALID_VA_ADDRESS) return; @@ -165,80 +141,77 @@ amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size) size = ALIGN(size, mgr->va_alignment); pthread_mutex_lock(&mgr->bo_va_mutex); - if ((va + size) == mgr->va_offset) { - mgr->va_offset = va; - /* Delete uppermost hole if it reaches the new top */ - if (!LIST_IS_EMPTY(&mgr->va_holes)) { - hole = container_of(mgr->va_holes.next, hole, list); - if ((hole->offset + hole->size) == va) { - mgr->va_offset = hole->offset; + hole = container_of(&mgr->va_holes, hole, list); + LIST_FOR_EACH_ENTRY(next, &mgr->va_holes, list) { + if (next->offset < va) + break; + hole = next; + } + + if (&hole->list != &mgr->va_holes) { + /* Grow upper hole if it's adjacent */ + if (hole->offset == (va + size)) { + hole->offset = va; + hole->size += size; + /* Merge lower hole if it's adjacent */ + if (next != hole && + &next->list != &mgr->va_holes && + (next->offset + next->size) == va) { + next->size += hole->size; list_del(&hole->list); free(hole); } - } - } else { - struct amdgpu_bo_va_hole *next; - - hole = container_of(&mgr->va_holes, hole, list); - LIST_FOR_EACH_ENTRY(next, &mgr->va_holes, list) { - if (next->offset < va) - break; - hole = next; - } - - if (&hole->list != &mgr->va_holes) { - /* Grow upper hole if it's adjacent */ - if (hole->offset == (va + size)) { - hole->offset = va; - hole->size += size; - /* Merge lower hole if it's adjacent */ - if (next != hole - && &next->list != &mgr->va_holes - && (next->offset + next->size) == va) { - next->size += hole->size; - list_del(&hole->list); - free(hole); - } - goto out; - } - } - - /* Grow lower hole if it's adjacent */ - if (next != hole && &next->list != &mgr->va_holes && - (next->offset + next->size) == va) { - next->size += size; goto out; } + } - /* FIXME on allocation failure we just lose virtual address space - * maybe print a warning - */ - next = calloc(1, sizeof(struct amdgpu_bo_va_hole)); - if (next) { - next->size = size; - next->offset = va; - list_add(&next->list, &hole->list); - } + /* Grow lower hole if it's adjacent */ + if (next != hole && &next->list != &mgr->va_holes && + (next->offset + next->size) == va) { + next->size += size; + goto out; + } + + /* FIXME on allocation failure we just lose virtual address space + * maybe print a warning + */ + next = calloc(1, sizeof(struct amdgpu_bo_va_hole)); + if (next) { + next->size = size; + next->offset = va; + list_add(&next->list, &hole->list); } + out: pthread_mutex_unlock(&mgr->bo_va_mutex); } -int amdgpu_va_range_alloc(amdgpu_device_handle dev, - enum amdgpu_gpu_va_range va_range_type, - uint64_t size, - uint64_t va_base_alignment, - uint64_t va_base_required, - uint64_t *va_base_allocated, - amdgpu_va_handle *va_range_handle, - uint64_t flags) +drm_public int amdgpu_va_range_alloc(amdgpu_device_handle dev, + enum amdgpu_gpu_va_range va_range_type, + uint64_t size, + uint64_t va_base_alignment, + uint64_t va_base_required, + uint64_t *va_base_allocated, + amdgpu_va_handle *va_range_handle, + uint64_t flags) { struct amdgpu_bo_va_mgr *vamgr; - if (flags & AMDGPU_VA_RANGE_32_BIT) - vamgr = dev->vamgr_32; - else - vamgr = dev->vamgr; + /* Clear the flag when the high VA manager is not initialized */ + if (flags & AMDGPU_VA_RANGE_HIGH && !dev->vamgr_high_32.va_max) + flags &= ~AMDGPU_VA_RANGE_HIGH; + + if (flags & AMDGPU_VA_RANGE_HIGH) { + if (flags & AMDGPU_VA_RANGE_32_BIT) + vamgr = &dev->vamgr_high_32; + else + vamgr = &dev->vamgr_high; + } else { + if (flags & AMDGPU_VA_RANGE_32_BIT) + vamgr = &dev->vamgr_32; + else + vamgr = &dev->vamgr; + } va_base_alignment = MAX2(va_base_alignment, vamgr->va_alignment); size = ALIGN(size, vamgr->va_alignment); @@ -249,7 +222,10 @@ int amdgpu_va_range_alloc(amdgpu_device_handle dev, if (!(flags & AMDGPU_VA_RANGE_32_BIT) && (*va_base_allocated == AMDGPU_INVALID_VA_ADDRESS)) { /* fallback to 32bit address */ - vamgr = dev->vamgr_32; + if (flags & AMDGPU_VA_RANGE_HIGH) + vamgr = &dev->vamgr_high_32; + else + vamgr = &dev->vamgr_32; *va_base_allocated = amdgpu_vamgr_find_va(vamgr, size, va_base_alignment, va_base_required); } @@ -274,7 +250,7 @@ int amdgpu_va_range_alloc(amdgpu_device_handle dev, return 0; } -int amdgpu_va_range_free(amdgpu_va_handle va_range_handle) +drm_public int amdgpu_va_range_free(amdgpu_va_handle va_range_handle) { if(!va_range_handle || !va_range_handle->address) return 0; diff --git a/amdgpu/amdgpu_vm.c b/amdgpu/amdgpu_vm.c new file mode 100644 index 00000000..7e6e28f0 --- /dev/null +++ b/amdgpu/amdgpu_vm.c @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "amdgpu.h" +#include "amdgpu_drm.h" +#include "xf86drm.h" +#include "amdgpu_internal.h" + +drm_public int amdgpu_vm_reserve_vmid(amdgpu_device_handle dev, uint32_t flags) +{ + union drm_amdgpu_vm vm; + + vm.in.op = AMDGPU_VM_OP_RESERVE_VMID; + vm.in.flags = flags; + + return drmCommandWriteRead(dev->fd, DRM_AMDGPU_VM, + &vm, sizeof(vm)); +} + +drm_public int amdgpu_vm_unreserve_vmid(amdgpu_device_handle dev, + uint32_t flags) +{ + union drm_amdgpu_vm vm; + + vm.in.op = AMDGPU_VM_OP_UNRESERVE_VMID; + vm.in.flags = flags; + + return drmCommandWriteRead(dev->fd, DRM_AMDGPU_VM, + &vm, sizeof(vm)); +} diff --git a/amdgpu/handle_table.c b/amdgpu/handle_table.c new file mode 100644 index 00000000..4fdd29d3 --- /dev/null +++ b/amdgpu/handle_table.c @@ -0,0 +1,72 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include "handle_table.h" +#include "util_math.h" + +drm_private int handle_table_insert(struct handle_table *table, uint32_t key, + void *value) +{ + if (key >= table->max_key) { + uint32_t alignment = sysconf(_SC_PAGESIZE) / sizeof(void*); + uint32_t max_key = ALIGN(key + 1, alignment); + void **values; + + values = realloc(table->values, max_key * sizeof(void *)); + if (!values) + return -ENOMEM; + + memset(values + table->max_key, 0, (max_key - table->max_key) * + sizeof(void *)); + + table->max_key = max_key; + table->values = values; + } + table->values[key] = value; + return 0; +} + +drm_private void handle_table_remove(struct handle_table *table, uint32_t key) +{ + if (key < table->max_key) + table->values[key] = NULL; +} + +drm_private void *handle_table_lookup(struct handle_table *table, uint32_t key) +{ + if (key < table->max_key) + return table->values[key]; + else + return NULL; +} + +drm_private void handle_table_fini(struct handle_table *table) +{ + free(table->values); + table->max_key = 0; + table->values = NULL; +} diff --git a/amdgpu/handle_table.h b/amdgpu/handle_table.h new file mode 100644 index 00000000..461193f6 --- /dev/null +++ b/amdgpu/handle_table.h @@ -0,0 +1,41 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _HANDLE_TABLE_H_ +#define _HANDLE_TABLE_H_ + +#include <stdint.h> +#include "libdrm_macros.h" + +struct handle_table { + uint32_t max_key; + void **values; +}; + +drm_private int handle_table_insert(struct handle_table *table, uint32_t key, + void *value); +drm_private void handle_table_remove(struct handle_table *table, uint32_t key); +drm_private void *handle_table_lookup(struct handle_table *table, uint32_t key); +drm_private void handle_table_fini(struct handle_table *table); + +#endif /* _HANDLE_TABLE_H_ */ diff --git a/amdgpu/meson.build b/amdgpu/meson.build new file mode 100644 index 00000000..7c8ccc7e --- /dev/null +++ b/amdgpu/meson.build @@ -0,0 +1,65 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +datadir_amdgpu = join_paths(get_option('prefix'), get_option('datadir'), 'libdrm') + +libdrm_amdgpu = shared_library( + 'drm_amdgpu', + [ + files( + 'amdgpu_asic_id.c', 'amdgpu_bo.c', 'amdgpu_cs.c', 'amdgpu_device.c', + 'amdgpu_gpu_info.c', 'amdgpu_vamgr.c', 'amdgpu_vm.c', 'handle_table.c', + ), + config_file, + ], + c_args : [ + libdrm_c_args, + '-DAMDGPU_ASIC_ID_TABLE="@0@"'.format(join_paths(datadir_amdgpu, 'amdgpu.ids')), + ], + include_directories : [inc_root, inc_drm], + link_with : libdrm, + dependencies : [dep_pthread_stubs, dep_atomic_ops], + version : '1.0.0', + install : true, +) + +install_headers('amdgpu.h', subdir : 'libdrm') + +pkg.generate( + name : 'libdrm_amdgpu', + libraries : libdrm_amdgpu, + subdirs : ['.', 'libdrm'], + version : meson.project_version(), + requires_private : 'libdrm', + description : 'Userspace interface to kernel DRM services for amdgpu', +) + +ext_libdrm_amdgpu = declare_dependency( + link_with : [libdrm, libdrm_amdgpu], + include_directories : [inc_drm, include_directories('.')], +) + +test( + 'amdgpu-symbol-check', + prog_bash, + env : env_test, + args : [files('amdgpu-symbol-check'), libdrm_amdgpu] +) diff --git a/amdgpu/util_hash.c b/amdgpu/util_hash.c deleted file mode 100644 index 87cb671b..00000000 --- a/amdgpu/util_hash.c +++ /dev/null @@ -1,387 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - /* - * Authors: - * Zack Rusin <zackr@vmware.com> - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "util_hash.h" - -#include <stdlib.h> -#include <assert.h> - -#define MAX(a, b) ((a > b) ? (a) : (b)) - -static const int MinNumBits = 4; - -static const unsigned char prime_deltas[] = { - 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, - 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 -}; - -static int primeForNumBits(int numBits) -{ - return (1 << numBits) + prime_deltas[numBits]; -} - -/* Returns the smallest integer n such that - primeForNumBits(n) >= hint. -*/ -static int countBits(int hint) -{ - int numBits = 0; - int bits = hint; - - while (bits > 1) { - bits >>= 1; - numBits++; - } - - if (numBits >= (int)sizeof(prime_deltas)) { - numBits = sizeof(prime_deltas) - 1; - } else if (primeForNumBits(numBits) < hint) { - ++numBits; - } - return numBits; -} - -struct util_node { - struct util_node *next; - unsigned key; - void *value; -}; - -struct util_hash_data { - struct util_node *fakeNext; - struct util_node **buckets; - int size; - int nodeSize; - short userNumBits; - short numBits; - int numBuckets; -}; - -struct util_hash { - union { - struct util_hash_data *d; - struct util_node *e; - } data; -}; - -static void *util_data_allocate_node(struct util_hash_data *hash) -{ - return malloc(hash->nodeSize); -} - -static void util_free_node(struct util_node *node) -{ - free(node); -} - -static struct util_node * -util_hash_create_node(struct util_hash *hash, - unsigned akey, void *avalue, - struct util_node **anextNode) -{ - struct util_node *node = util_data_allocate_node(hash->data.d); - - if (!node) - return NULL; - - node->key = akey; - node->value = avalue; - - node->next = (struct util_node*)(*anextNode); - *anextNode = node; - ++hash->data.d->size; - return node; -} - -static void util_data_rehash(struct util_hash_data *hash, int hint) -{ - if (hint < 0) { - hint = countBits(-hint); - if (hint < MinNumBits) - hint = MinNumBits; - hash->userNumBits = (short)hint; - while (primeForNumBits(hint) < (hash->size >> 1)) - ++hint; - } else if (hint < MinNumBits) { - hint = MinNumBits; - } - - if (hash->numBits != hint) { - struct util_node *e = (struct util_node *)(hash); - struct util_node **oldBuckets = hash->buckets; - int oldNumBuckets = hash->numBuckets; - int i = 0; - - hash->numBits = (short)hint; - hash->numBuckets = primeForNumBits(hint); - hash->buckets = malloc(sizeof(struct util_node*) * hash->numBuckets); - for (i = 0; i < hash->numBuckets; ++i) - hash->buckets[i] = e; - - for (i = 0; i < oldNumBuckets; ++i) { - struct util_node *firstNode = oldBuckets[i]; - while (firstNode != e) { - unsigned h = firstNode->key; - struct util_node *lastNode = firstNode; - struct util_node *afterLastNode; - struct util_node **beforeFirstNode; - - while (lastNode->next != e && lastNode->next->key == h) - lastNode = lastNode->next; - - afterLastNode = lastNode->next; - beforeFirstNode = &hash->buckets[h % hash->numBuckets]; - while (*beforeFirstNode != e) - beforeFirstNode = &(*beforeFirstNode)->next; - lastNode->next = *beforeFirstNode; - *beforeFirstNode = firstNode; - firstNode = afterLastNode; - } - } - free(oldBuckets); - } -} - -static void util_data_might_grow(struct util_hash_data *hash) -{ - if (hash->size >= hash->numBuckets) - util_data_rehash(hash, hash->numBits + 1); -} - -static void util_data_has_shrunk(struct util_hash_data *hash) -{ - if (hash->size <= (hash->numBuckets >> 3) && - hash->numBits > hash->userNumBits) { - int max = MAX(hash->numBits-2, hash->userNumBits); - util_data_rehash(hash, max); - } -} - -static struct util_node *util_data_first_node(struct util_hash_data *hash) -{ - struct util_node *e = (struct util_node *)(hash); - struct util_node **bucket = hash->buckets; - int n = hash->numBuckets; - while (n--) { - if (*bucket != e) - return *bucket; - ++bucket; - } - return e; -} - -static struct util_node **util_hash_find_node(struct util_hash *hash, unsigned akey) -{ - struct util_node **node; - - if (hash->data.d->numBuckets) { - node = (struct util_node **)(&hash->data.d->buckets[akey % hash->data.d->numBuckets]); - assert(*node == hash->data.e || (*node)->next); - while (*node != hash->data.e && (*node)->key != akey) - node = &(*node)->next; - } else { - node = (struct util_node **)((const struct util_node * const *)(&hash->data.e)); - } - return node; -} - -drm_private struct util_hash_iter -util_hash_insert(struct util_hash *hash, unsigned key, void *data) -{ - util_data_might_grow(hash->data.d); - - { - struct util_node **nextNode = util_hash_find_node(hash, key); - struct util_node *node = util_hash_create_node(hash, key, data, nextNode); - if (!node) { - struct util_hash_iter null_iter = {hash, 0}; - return null_iter; - } - - { - struct util_hash_iter iter = {hash, node}; - return iter; - } - } -} - -drm_private struct util_hash *util_hash_create(void) -{ - struct util_hash *hash = malloc(sizeof(struct util_hash)); - if (!hash) - return NULL; - - hash->data.d = malloc(sizeof(struct util_hash_data)); - if (!hash->data.d) { - free(hash); - return NULL; - } - - hash->data.d->fakeNext = 0; - hash->data.d->buckets = 0; - hash->data.d->size = 0; - hash->data.d->nodeSize = sizeof(struct util_node); - hash->data.d->userNumBits = (short)MinNumBits; - hash->data.d->numBits = 0; - hash->data.d->numBuckets = 0; - - return hash; -} - -drm_private void util_hash_delete(struct util_hash *hash) -{ - struct util_node *e_for_x = (struct util_node *)(hash->data.d); - struct util_node **bucket = (struct util_node **)(hash->data.d->buckets); - int n = hash->data.d->numBuckets; - while (n--) { - struct util_node *cur = *bucket++; - while (cur != e_for_x) { - struct util_node *next = cur->next; - util_free_node(cur); - cur = next; - } - } - free(hash->data.d->buckets); - free(hash->data.d); - free(hash); -} - -drm_private struct util_hash_iter -util_hash_find(struct util_hash *hash, unsigned key) -{ - struct util_node **nextNode = util_hash_find_node(hash, key); - struct util_hash_iter iter = {hash, *nextNode}; - return iter; -} - -drm_private unsigned util_hash_iter_key(struct util_hash_iter iter) -{ - if (!iter.node || iter.hash->data.e == iter.node) - return 0; - return iter.node->key; -} - -drm_private void *util_hash_iter_data(struct util_hash_iter iter) -{ - if (!iter.node || iter.hash->data.e == iter.node) - return 0; - return iter.node->value; -} - -static struct util_node *util_hash_data_next(struct util_node *node) -{ - union { - struct util_node *next; - struct util_node *e; - struct util_hash_data *d; - } a; - int start; - struct util_node **bucket; - int n; - - a.next = node->next; - if (!a.next) { - /* iterating beyond the last element */ - return 0; - } - if (a.next->next) - return a.next; - - start = (node->key % a.d->numBuckets) + 1; - bucket = a.d->buckets + start; - n = a.d->numBuckets - start; - while (n--) { - if (*bucket != a.e) - return *bucket; - ++bucket; - } - return a.e; -} - -drm_private struct util_hash_iter -util_hash_iter_next(struct util_hash_iter iter) -{ - struct util_hash_iter next = {iter.hash, util_hash_data_next(iter.node)}; - return next; -} - -drm_private int util_hash_iter_is_null(struct util_hash_iter iter) -{ - if (!iter.node || iter.node == iter.hash->data.e) - return 1; - return 0; -} - -drm_private void *util_hash_take(struct util_hash *hash, unsigned akey) -{ - struct util_node **node = util_hash_find_node(hash, akey); - if (*node != hash->data.e) { - void *t = (*node)->value; - struct util_node *next = (*node)->next; - util_free_node(*node); - *node = next; - --hash->data.d->size; - util_data_has_shrunk(hash->data.d); - return t; - } - return 0; -} - -drm_private struct util_hash_iter util_hash_first_node(struct util_hash *hash) -{ - struct util_hash_iter iter = {hash, util_data_first_node(hash->data.d)}; - return iter; -} - -drm_private struct util_hash_iter -util_hash_erase(struct util_hash *hash, struct util_hash_iter iter) -{ - struct util_hash_iter ret = iter; - struct util_node *node = iter.node; - struct util_node **node_ptr; - - if (node == hash->data.e) - return iter; - - ret = util_hash_iter_next(ret); - node_ptr = (struct util_node**)(&hash->data.d->buckets[node->key % hash->data.d->numBuckets]); - while (*node_ptr != node) - node_ptr = &(*node_ptr)->next; - *node_ptr = node->next; - util_free_node(node); - --hash->data.d->size; - return ret; -} diff --git a/amdgpu/util_hash.h b/amdgpu/util_hash.h deleted file mode 100644 index 01a4779b..00000000 --- a/amdgpu/util_hash.h +++ /dev/null @@ -1,107 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Hash implementation. - * - * This file provides a hash implementation that is capable of dealing - * with collisions. It stores colliding entries in linked list. All - * functions operating on the hash return an iterator. The iterator - * itself points to the collision list. If there wasn't any collision - * the list will have just one entry, otherwise client code should - * iterate over the entries to find the exact entry among ones that - * had the same key (e.g. memcmp could be used on the data to check - * that) - * - * @author Zack Rusin <zackr@vmware.com> - */ - -#ifndef UTIL_HASH_H -#define UTIL_HASH_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdbool.h> - -#include "libdrm_macros.h" - -struct util_hash; -struct util_node; - -struct util_hash_iter { - struct util_hash *hash; - struct util_node *node; -}; - - -drm_private struct util_hash *util_hash_create(void); -drm_private void util_hash_delete(struct util_hash *hash); - - -/** - * Adds a data with the given key to the hash. If entry with the given - * key is already in the hash, this current entry is instered before it - * in the collision list. - * Function returns iterator pointing to the inserted item in the hash. - */ -drm_private struct util_hash_iter -util_hash_insert(struct util_hash *hash, unsigned key, void *data); - -/** - * Removes the item pointed to by the current iterator from the hash. - * Note that the data itself is not erased and if it was a malloc'ed pointer - * it will have to be freed after calling this function by the callee. - * Function returns iterator pointing to the item after the removed one in - * the hash. - */ -drm_private struct util_hash_iter -util_hash_erase(struct util_hash *hash, struct util_hash_iter iter); - -drm_private void *util_hash_take(struct util_hash *hash, unsigned key); - - -drm_private struct util_hash_iter util_hash_first_node(struct util_hash *hash); - -/** - * Return an iterator pointing to the first entry in the collision list. - */ -drm_private struct util_hash_iter -util_hash_find(struct util_hash *hash, unsigned key); - - -drm_private int util_hash_iter_is_null(struct util_hash_iter iter); -drm_private unsigned util_hash_iter_key(struct util_hash_iter iter); -drm_private void *util_hash_iter_data(struct util_hash_iter iter); - - -drm_private struct util_hash_iter -util_hash_iter_next(struct util_hash_iter iter); - -#endif diff --git a/amdgpu/util_hash_table.c b/amdgpu/util_hash_table.c deleted file mode 100644 index fa7f6eab..00000000 --- a/amdgpu/util_hash_table.c +++ /dev/null @@ -1,262 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * General purpose hash table implementation. - * - * Just uses the util_hash for now, but it might be better switch to a linear - * probing hash table implementation at some point -- as it is said they have - * better lookup and cache performance and it appears to be possible to write - * a lock-free implementation of such hash tables . - * - * @author José Fonseca <jfonseca@vmware.com> - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "util_hash_table.h" -#include "util_hash.h" - -#include <stdlib.h> -#include <assert.h> - -struct util_hash_table -{ - struct util_hash *head; - - /** Hash function */ - unsigned (*make_hash)(void *key); - - /** Compare two keys */ - int (*compare)(void *key1, void *key2); -}; - -struct util_hash_table_item -{ - void *key; - void *value; -}; - - -static struct util_hash_table_item * -util_hash_table_item(struct util_hash_iter iter) -{ - return (struct util_hash_table_item *)util_hash_iter_data(iter); -} - -drm_private struct util_hash_table * -util_hash_table_create(unsigned (*hash)(void *key), - int (*compare)(void *key1, void *key2)) -{ - struct util_hash_table *ht; - - ht = malloc(sizeof(struct util_hash_table)); - if(!ht) - return NULL; - - ht->head = util_hash_create(); - if(!ht->head) { - free(ht); - return NULL; - } - - ht->make_hash = hash; - ht->compare = compare; - - return ht; -} - -static struct util_hash_iter -util_hash_table_find_iter(struct util_hash_table *ht, - void *key, unsigned key_hash) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - iter = util_hash_find(ht->head, key_hash); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - if (!ht->compare(item->key, key)) - break; - iter = util_hash_iter_next(iter); - } - - return iter; -} - -static struct util_hash_table_item * -util_hash_table_find_item(struct util_hash_table *ht, - void *key, unsigned key_hash) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - iter = util_hash_find(ht->head, key_hash); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - if (!ht->compare(item->key, key)) - return item; - iter = util_hash_iter_next(iter); - } - - return NULL; -} - -drm_private void -util_hash_table_set(struct util_hash_table *ht, void *key, void *value) -{ - unsigned key_hash; - struct util_hash_table_item *item; - struct util_hash_iter iter; - - assert(ht); - if (!ht) - return; - - key_hash = ht->make_hash(key); - - item = util_hash_table_find_item(ht, key, key_hash); - if(item) { - /* TODO: key/value destruction? */ - item->value = value; - return; - } - - item = malloc(sizeof(struct util_hash_table_item)); - if(!item) - return; - - item->key = key; - item->value = value; - - iter = util_hash_insert(ht->head, key_hash, item); - if(util_hash_iter_is_null(iter)) { - free(item); - return; - } -} - -drm_private void *util_hash_table_get(struct util_hash_table *ht, void *key) -{ - unsigned key_hash; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return NULL; - - key_hash = ht->make_hash(key); - - item = util_hash_table_find_item(ht, key, key_hash); - if(!item) - return NULL; - - return item->value; -} - -drm_private void util_hash_table_remove(struct util_hash_table *ht, void *key) -{ - unsigned key_hash; - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - key_hash = ht->make_hash(key); - - iter = util_hash_table_find_iter(ht, key, key_hash); - if(util_hash_iter_is_null(iter)) - return; - - item = util_hash_table_item(iter); - assert(item); - free(item); - - util_hash_erase(ht->head, iter); -} - -drm_private void util_hash_table_clear(struct util_hash_table *ht) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - iter = util_hash_first_node(ht->head); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_take(ht->head, util_hash_iter_key(iter)); - free(item); - iter = util_hash_first_node(ht->head); - } -} - -drm_private void util_hash_table_foreach(struct util_hash_table *ht, - void (*callback)(void *key, void *value, void *data), - void *data) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - iter = util_hash_first_node(ht->head); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - callback(item->key, item->value, data); - iter = util_hash_iter_next(iter); - } -} - -drm_private void util_hash_table_destroy(struct util_hash_table *ht) -{ - struct util_hash_iter iter; - struct util_hash_table_item *item; - - assert(ht); - if (!ht) - return; - - iter = util_hash_first_node(ht->head); - while (!util_hash_iter_is_null(iter)) { - item = (struct util_hash_table_item *)util_hash_iter_data(iter); - free(item); - iter = util_hash_iter_next(iter); - } - - util_hash_delete(ht->head); - free(ht); -} diff --git a/amdgpu/util_hash_table.h b/amdgpu/util_hash_table.h deleted file mode 100644 index e0001289..00000000 --- a/amdgpu/util_hash_table.h +++ /dev/null @@ -1,73 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * General purpose hash table. - * - * @author José Fonseca <jfonseca@vmware.com> - */ - -#ifndef U_HASH_TABLE_H_ -#define U_HASH_TABLE_H_ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "libdrm_macros.h" - -/** - * Generic purpose hash table. - */ -struct util_hash_table; - -/** - * Create an hash table. - * - * @param hash hash function - * @param compare should return 0 for two equal keys. - */ -drm_private struct util_hash_table * -util_hash_table_create(unsigned (*hash)(void *key), - int (*compare)(void *key1, void *key2)); - -drm_private void -util_hash_table_set(struct util_hash_table *ht, void *key, void *value); - -drm_private void *util_hash_table_get(struct util_hash_table *ht, void *key); - -drm_private void util_hash_table_remove(struct util_hash_table *ht, void *key); - -drm_private void util_hash_table_clear(struct util_hash_table *ht); - -drm_private void util_hash_table_foreach(struct util_hash_table *ht, - void (*callback)(void *key, void *value, void *data), - void *data); - -drm_private void util_hash_table_destroy(struct util_hash_table *ht); - -#endif /* U_HASH_TABLE_H_ */ diff --git a/android/gralloc_handle.h b/android/gralloc_handle.h new file mode 100644 index 00000000..d3d975ee --- /dev/null +++ b/android/gralloc_handle.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com> + * Copyright (C) 2010-2011 LunarG Inc. + * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org> + * Copyright (C) 2018 Collabora, Robert Foss <robert.foss@collabora.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __ANDROID_GRALLOC_HANDLE_H__ +#define __ANDROID_GRALLOC_HANDLE_H__ + +#include <cutils/native_handle.h> +#include <stdint.h> + +/* support users of drm_gralloc/gbm_gralloc */ +#define gralloc_gbm_handle_t gralloc_handle_t +#define gralloc_drm_handle_t gralloc_handle_t + +struct gralloc_handle_t { + native_handle_t base; + + /* dma-buf file descriptor + * Must be located first since, native_handle_t is allocated + * using native_handle_create(), which allocates space for + * sizeof(native_handle_t) + sizeof(int) * (numFds + numInts) + * numFds = GRALLOC_HANDLE_NUM_FDS + * numInts = GRALLOC_HANDLE_NUM_INTS + * Where numFds represents the number of FDs and + * numInts represents the space needed for the + * remainder of this struct. + * And the FDs are expected to be found first following + * native_handle_t. + */ + int prime_fd; + + /* api variables */ + uint32_t magic; /* differentiate between allocator impls */ + uint32_t version; /* api version */ + + uint32_t width; /* width of buffer in pixels */ + uint32_t height; /* height of buffer in pixels */ + uint32_t format; /* pixel format (Android) */ + uint32_t usage; /* android libhardware usage flags */ + + uint32_t stride; /* the stride in bytes */ + int data_owner; /* owner of data (for validation) */ + uint64_t modifier __attribute__((aligned(8))); /* buffer modifiers */ + + union { + void *data; /* pointer to struct gralloc_gbm_bo_t */ + uint64_t reserved; + } __attribute__((aligned(8))); +}; + +#define GRALLOC_HANDLE_VERSION 4 +#define GRALLOC_HANDLE_MAGIC 0x60585350 +#define GRALLOC_HANDLE_NUM_FDS 1 +#define GRALLOC_HANDLE_NUM_INTS ( \ + ((sizeof(struct gralloc_handle_t) - sizeof(native_handle_t))/sizeof(int)) \ + - GRALLOC_HANDLE_NUM_FDS) + +static inline struct gralloc_handle_t *gralloc_handle(buffer_handle_t handle) +{ + return (struct gralloc_handle_t *)handle; +} + +/** + * Create a buffer handle. + */ +static inline native_handle_t *gralloc_handle_create(int32_t width, + int32_t height, + int32_t hal_format, + int32_t usage) +{ + struct gralloc_handle_t *handle; + native_handle_t *nhandle = native_handle_create(GRALLOC_HANDLE_NUM_FDS, + GRALLOC_HANDLE_NUM_INTS); + + if (!nhandle) + return NULL; + + handle = gralloc_handle(nhandle); + handle->magic = GRALLOC_HANDLE_MAGIC; + handle->version = GRALLOC_HANDLE_VERSION; + handle->width = width; + handle->height = height; + handle->format = hal_format; + handle->usage = usage; + handle->prime_fd = -1; + + return nhandle; +} + +#endif @@ -6,15 +6,15 @@ test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd "$srcdir" -autoreconf --force --verbose --install || exit 1 -cd "$ORIGDIR" || exit $? - -git config --local --get format.subjectPrefix || +git config --local --get format.subjectPrefix >/dev/null || git config --local format.subjectPrefix "PATCH libdrm" 2>/dev/null -git config --local --get sendemail.to || +git config --local --get sendemail.to >/dev/null || git config --local sendemail.to "dri-devel@lists.freedesktop.org" 2>/dev/null +autoreconf --force --verbose --install || exit 1 +cd "$ORIGDIR" || exit $? + if test -z "$NOCONFIGURE"; then "$srcdir"/configure "$@" fi diff --git a/configure.ac b/configure.ac index 1da9d86b..7e7c8d38 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ([2.63]) AC_INIT([libdrm], - [2.4.75], + [2.4.97], [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI], [libdrm]) @@ -28,6 +28,7 @@ AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) +PKG_PROG_PKG_CONFIG # Require xorg-macros minimum of 1.12 for XORG_WITH_XSLTPROC m4_ifndef([XORG_MACROS_VERSION], @@ -44,6 +45,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) # Check for programs AC_PROG_CC AC_PROG_CC_C99 +AC_PROG_NM if test "x$ac_cv_prog_cc_c99" = xno; then AC_MSG_ERROR([Building libdrm requires C99 enabled compiler]) @@ -53,20 +55,39 @@ AC_USE_SYSTEM_EXTENSIONS AC_SYS_LARGEFILE AC_FUNC_ALLOCA +save_CFLAGS="$CFLAGS" +export CFLAGS="$CFLAGS -Werror" AC_HEADER_MAJOR +CFLAGS="$save_CFLAGS" + AC_CHECK_HEADERS([sys/sysctl.h sys/select.h]) # Initialize libtool LT_PREREQ([2.2]) LT_INIT([disable-static]) - - -AC_SUBST(PTHREADSTUBS_CFLAGS) -AC_SUBST(PTHREADSTUBS_LIBS) +dnl pthread-stubs is mandatory on some BSD platforms, due to the nature of the +dnl project. Even then there's a notable issue as described in the project README +case "$host_os" in +linux* | cygwin* | darwin* | solaris* | *-gnu* | gnu* | openbsd*) + pthread_stubs_possible="no" + ;; +* ) + pthread_stubs_possible="yes" + ;; +esac + +if test "x$pthread_stubs_possible" = xyes; then + PKG_CHECK_MODULES(PTHREADSTUBS, pthread-stubs >= 0.4) + AC_SUBST(PTHREADSTUBS_CFLAGS) + AC_SUBST(PTHREADSTUBS_LIBS) +fi pkgconfigdir=${libdir}/pkgconfig AC_SUBST(pkgconfigdir) +libdrmdatadir=${datadir}/libdrm +AC_SUBST(libdrmdatadir) + AC_ARG_ENABLE([udev], [AS_HELP_STRING([--enable-udev], [Enable support for using udev instead of mknod (default: disabled)])], @@ -127,11 +148,6 @@ AC_ARG_ENABLE(tegra-experimental-api, [Enable support for Tegra's experimental API (default: disabled)]), [TEGRA=$enableval], [TEGRA=no]) -AC_ARG_ENABLE(rockchip-experimental-api, - AS_HELP_STRING([--enable-rockchip-experimental-api], - [Enable support for rockchip's experimental API (default: disabled)]), - [ROCKCHIP=$enableval], [ROCKCHIP=no]) - AC_ARG_ENABLE(vc4, AS_HELP_STRING([--disable-vc4], [Enable support for vc4's API (default: auto, enabled on arm)]), @@ -173,7 +189,9 @@ AC_CHECK_FUNCS([clock_gettime], [CLOCK_LIB=], [AC_MSG_ERROR([Couldn't find clock_gettime])])]) AC_SUBST([CLOCK_LIB]) -AC_CHECK_FUNCS([open_memstream], [HAVE_OPEN_MEMSTREAM=yes]) +AC_CHECK_FUNCS([open_memstream], + [AC_DEFINE([HAVE_OPEN_MEMSTREAM], 1, [Have open_memstream()])], + [AC_DEFINE([HAVE_OPEN_MEMSTREAM], 0)]) dnl Use lots of warning flags with with gcc and compatible compilers @@ -182,7 +200,7 @@ dnl skipped and all flags rechecked. So there's no need to do anything dnl else. If for any reason you need to force a recheck, just change dnl MAYBE_WARN in an ignorable way (like adding whitespace) -MAYBE_WARN="-Wall -Wextra \ +MAYBE_WARN="-Wall -Wextra -Werror=undef \ -Wsign-compare -Werror-implicit-function-declaration \ -Wpointer-arith -Wwrite-strings -Wstrict-prototypes \ -Wmissing-prototypes -Wmissing-declarations -Wnested-externs \ @@ -244,9 +262,13 @@ AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives, [ if test "x$drm_cv_atomic_primitives" = xIntel; then AC_DEFINE(HAVE_LIBDRM_ATOMIC_PRIMITIVES, 1, [Enable if your compiler supports the Intel __sync_* atomic primitives]) +else + AC_DEFINE(HAVE_LIBDRM_ATOMIC_PRIMITIVES, 0) fi if test "x$drm_cv_atomic_primitives" = "xlibatomic-ops"; then AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1, [Enable if you have libatomic-ops-dev installed]) +else + AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 0) fi dnl Print out the approapriate message considering the value set be the @@ -325,6 +347,8 @@ AC_SUBST(PCIACCESS_LIBS) if test "x$UDEV" = xyes; then AC_DEFINE(UDEV, 1, [Have UDEV support]) +else + AC_DEFINE(UDEV, 0) fi AC_CANONICAL_HOST @@ -343,32 +367,34 @@ AM_CONDITIONAL(HAVE_LIBKMS, [test "x$LIBKMS" = xyes]) AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" = xyes]) if test "x$INTEL" = xyes; then AC_DEFINE(HAVE_INTEL, 1, [Have intel support]) +else + AC_DEFINE(HAVE_INTEL, 0) fi AM_CONDITIONAL(HAVE_VMWGFX, [test "x$VMWGFX" = xyes]) if test "x$VMWGFX" = xyes; then AC_DEFINE(HAVE_VMWGFX, 1, [Have vmwgfx kernel headers]) +else + AC_DEFINE(HAVE_VMWGFX, 0) fi AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" = xyes]) if test "x$NOUVEAU" = xyes; then AC_DEFINE(HAVE_NOUVEAU, 1, [Have nouveau (nvidia) support]) +else + AC_DEFINE(HAVE_NOUVEAU, 0) fi AM_CONDITIONAL(HAVE_OMAP, [test "x$OMAP" = xyes]) -if test "x$OMAP" = xyes; then - AC_DEFINE(HAVE_OMAP, 1, [Have OMAP support]) -fi AM_CONDITIONAL(HAVE_EXYNOS, [test "x$EXYNOS" = xyes]) if test "x$EXYNOS" = xyes; then AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support]) +else + AC_DEFINE(HAVE_EXYNOS, 0) fi AM_CONDITIONAL(HAVE_FREEDRENO, [test "x$FREEDRENO" = xyes]) -if test "x$FREEDRENO" = xyes; then - AC_DEFINE(HAVE_FREEDRENO, 1, [Have freedreno support]) -fi if test "x$FREEDRENO_KGSL" = xyes; then if test "x$FREEDRENO" != xyes; then @@ -378,11 +404,15 @@ fi AM_CONDITIONAL(HAVE_FREEDRENO_KGSL, [test "x$FREEDRENO_KGSL" = xyes]) if test "x$FREEDRENO_KGSL" = xyes; then AC_DEFINE(HAVE_FREEDRENO_KGSL, 1, [Have freedreno support for KGSL kernel interface]) +else + AC_DEFINE(HAVE_FREEDRENO_KGSL, 0) fi AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" = xyes]) if test "x$RADEON" = xyes; then AC_DEFINE(HAVE_RADEON, 1, [Have radeon support]) +else + AC_DEFINE(HAVE_RADEON, 0) fi if test "x$AMDGPU" != xno; then @@ -409,36 +439,25 @@ AM_CONDITIONAL(HAVE_AMDGPU, [test "x$AMDGPU" = xyes]) if test "x$AMDGPU" = xyes; then AC_DEFINE(HAVE_AMDGPU, 1, [Have amdgpu support]) - AC_DEFINE(HAVE_CUNIT, [test "x$have_cunit" != "xno"], [Enable CUNIT Have amdgpu support]) - if test "x$have_cunit" = "xno"; then AC_MSG_WARN([Could not find cunit library. Disabling amdgpu tests]) fi +else + AC_DEFINE(HAVE_AMDGPU, 0) fi AM_CONDITIONAL(HAVE_TEGRA, [test "x$TEGRA" = xyes]) -if test "x$TEGRA" = xyes; then - AC_DEFINE(HAVE_TEGRA, 1, [Have Tegra support]) -fi - -AM_CONDITIONAL(HAVE_ROCKCHIP, [test "x$ROCKCHIP" = xyes]) -if test "x$ROCKCHIP" = xyes; then - AC_DEFINE(HAVE_ROCKCHIP, 1, [Have ROCKCHIP support]) AM_CONDITIONAL(HAVE_VC4, [test "x$VC4" = xyes]) if test "x$VC4" = xyes; then AC_DEFINE(HAVE_VC4, 1, [Have VC4 support]) +else + AC_DEFINE(HAVE_VC4, 0) fi AM_CONDITIONAL(HAVE_ETNAVIV, [test "x$ETNAVIV" = xyes]) -if test "x$ETNAVIV" = xyes; then - AC_DEFINE(HAVE_ETNAVIV, 1, [Have etnaviv support]) -fi AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes]) -if test "x$INSTALL_TESTS" = xyes; then - AC_DEFINE(HAVE_INSTALL_TESTS, 1, [Install test programs]) -fi AC_ARG_ENABLE([cairo-tests], [AS_HELP_STRING([--enable-cairo-tests], @@ -456,6 +475,8 @@ if test "x$CAIRO" = xyes; then AC_MSG_ERROR([Cairo support required but not present]) fi AC_DEFINE(HAVE_CAIRO, 1, [Have Cairo support]) +else + AC_DEFINE(HAVE_CAIRO, 0) fi AC_MSG_RESULT([$CAIRO]) AM_CONDITIONAL(HAVE_CAIRO, [test "x$CAIRO" = xyes]) @@ -497,6 +518,8 @@ if test "x$VALGRIND" = "xyes"; then AC_MSG_ERROR([Valgrind support required but not present]) fi AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings]) +else + AC_DEFINE([HAVE_VALGRIND], 0) fi AC_MSG_RESULT([$VALGRIND]) @@ -514,11 +537,16 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([ if test "x$HAVE_ATTRIBUTE_VISIBILITY" = xyes; then AC_DEFINE(HAVE_VISIBILITY, 1, [Compiler supports __attribute__(("hidden"))]) +else + AC_DEFINE(HAVE_VISIBILITY, 0) fi +CFLAGS="$CFLAGS -include config.h" + AC_SUBST(WARN_CFLAGS) AC_CONFIG_FILES([ Makefile + data/Makefile libkms/Makefile libkms/libkms.pc intel/Makefile @@ -537,8 +565,6 @@ AC_CONFIG_FILES([ freedreno/libdrm_freedreno.pc tegra/Makefile tegra/libdrm_tegra.pc - rockchip/Makefile - rockchip/libdrm_rockchip.pc vc4/Makefile vc4/libdrm_vc4.pc etnaviv/Makefile @@ -555,7 +581,6 @@ AC_CONFIG_FILES([ tests/exynos/Makefile tests/tegra/Makefile tests/nouveau/Makefile - tests/planetest/Makefile tests/etnaviv/Makefile tests/util/Makefile man/Makefile @@ -575,7 +600,6 @@ echo " OMAP API $OMAP" echo " EXYNOS API $EXYNOS" echo " Freedreno API $FREEDRENO (kgsl: $FREEDRENO_KGSL)" echo " Tegra API $TEGRA" -echo " Rockchip API $ROCKCHIP" echo " VC4 API $VC4" echo " Etnaviv API $ETNAVIV" echo "" diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 00000000..897a7f35 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,25 @@ +# Copyright © 2017 Advanced Micro Devices, Inc. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +libdrmdatadir = @libdrmdatadir@ +if HAVE_AMDGPU +dist_libdrmdata_DATA = amdgpu.ids +endif diff --git a/data/amdgpu.ids b/data/amdgpu.ids new file mode 100644 index 00000000..d9ed5660 --- /dev/null +++ b/data/amdgpu.ids @@ -0,0 +1,197 @@ +# List of AMDGPU IDs +# +# Syntax: +# device_id, revision_id, product_name <-- single tab after comma + +1.0.0 +6600, 0, AMD Radeon HD 8600/8700M +6600, 81, AMD Radeon (TM) R7 M370 +6601, 0, AMD Radeon (TM) HD 8500M/8700M +6604, 0, AMD Radeon R7 M265 Series +6604, 81, AMD Radeon (TM) R7 M350 +6605, 0, AMD Radeon R7 M260 Series +6605, 81, AMD Radeon (TM) R7 M340 +6606, 0, AMD Radeon HD 8790M +6607, 0, AMD Radeon (TM) HD8530M +6608, 0, AMD FirePro W2100 +6610, 0, AMD Radeon HD 8600 Series +6610, 81, AMD Radeon (TM) R7 350 +6610, 83, AMD Radeon (TM) R5 340 +6611, 0, AMD Radeon HD 8500 Series +6613, 0, AMD Radeon HD 8500 series +6617, C7, AMD Radeon R7 240 Series +6640, 0, AMD Radeon HD 8950 +6640, 80, AMD Radeon (TM) R9 M380 +6646, 0, AMD Radeon R9 M280X +6646, 80, AMD Radeon (TM) R9 M470X +6647, 0, AMD Radeon R9 M270X +6647, 80, AMD Radeon (TM) R9 M380 +6649, 0, AMD FirePro W5100 +6658, 0, AMD Radeon R7 200 Series +665C, 0, AMD Radeon HD 7700 Series +665D, 0, AMD Radeon R7 200 Series +665F, 81, AMD Radeon (TM) R7 300 Series +6660, 0, AMD Radeon HD 8600M Series +6660, 81, AMD Radeon (TM) R5 M335 +6660, 83, AMD Radeon (TM) R5 M330 +6663, 0, AMD Radeon HD 8500M Series +6663, 83, AMD Radeon (TM) R5 M320 +6664, 0, AMD Radeon R5 M200 Series +6665, 0, AMD Radeon R5 M200 Series +6665, 83, AMD Radeon (TM) R5 M320 +6667, 0, AMD Radeon R5 M200 Series +666F, 0, AMD Radeon HD 8500M +6780, 0, ATI FirePro V (FireGL V) Graphics Adapter +678A, 0, ATI FirePro V (FireGL V) Graphics Adapter +6798, 0, AMD Radeon HD 7900 Series +679A, 0, AMD Radeon HD 7900 Series +679B, 0, AMD Radeon HD 7900 Series +679E, 0, AMD Radeon HD 7800 Series +67A0, 0, AMD Radeon FirePro W9100 +67A1, 0, AMD Radeon FirePro W8100 +67B0, 0, AMD Radeon R9 200 Series +67B0, 80, AMD Radeon (TM) R9 390 Series +67B1, 0, AMD Radeon R9 200 Series +67B1, 80, AMD Radeon (TM) R9 390 Series +67B9, 0, AMD Radeon R9 200 Series +67DF, C1, Radeon RX 580 Series +67DF, C2, Radeon RX 570 Series +67DF, C3, Radeon RX 580 Series +67DF, C4, AMD Radeon (TM) RX 480 Graphics +67DF, C5, AMD Radeon (TM) RX 470 Graphics +67DF, C6, Radeon RX 570 Series +67DF, C7, AMD Radeon (TM) RX 480 Graphics +67DF, CF, AMD Radeon (TM) RX 470 Graphics +67DF, D7, Radeon(TM) RX 470 Graphics +67DF, E0, Radeon RX 470 Series +67DF, E1, Radeon RX 590 Series +67DF, E3, Radeon RX Series +67DF, E7, Radeon RX 580 Series +67DF, EF, Radeon RX 570 Series +67DF, F7, Radeon RX P30PH +67C2, 01, AMD Radeon (TM) Pro V7350x2 +67C2, 02, AMD Radeon (TM) Pro V7300X +67C4, 00, AMD Radeon (TM) Pro WX 7100 Graphics +67C7, 00, AMD Radeon (TM) Pro WX 5100 Graphics +67C0, 00, AMD Radeon (TM) Pro WX 7100 Graphics +67D0, 01, AMD Radeon (TM) Pro V7350x2 +67D0, 02, AMD Radeon (TM) Pro V7300X +67E0, 00, AMD Radeon (TM) Pro WX Series +67E3, 00, AMD Radeon (TM) Pro WX 4100 +67E8, 00, AMD Radeon (TM) Pro WX Series +67E8, 01, AMD Radeon (TM) Pro WX Series +67E8, 80, AMD Radeon (TM) E9260 Graphics +67EB, 00, AMD Radeon (TM) Pro V5300X +67EF, C0, AMD Radeon (TM) RX Graphics +67EF, C1, AMD Radeon (TM) RX 460 Graphics +67EF, C3, Radeon RX Series +67EF, C5, AMD Radeon (TM) RX 460 Graphics +67EF, C7, AMD Radeon (TM) RX Graphics +67EF, CF, AMD Radeon (TM) RX 460 Graphics +67EF, E2, RX 560X +67EF, E0, Radeon RX 560 Series +67EF, E1, Radeon RX Series +67EF, E3, Radeon RX Series +67EF, E5, Radeon RX 560 Series +67EF, EF, AMD Radeon (TM) RX Graphics +67EF, FF, Radeon(TM) RX 460 Graphics +67FF, C0, AMD Radeon (TM) RX Graphics +67FF, C1, AMD Radeon (TM) RX Graphics +67FF, CF, Radeon RX 560 Series +67FF, EF, Radeon RX 560 Series +67FF, FF, Radeon RX 550 Series +6800, 0, AMD Radeon HD 7970M +6801, 0, AMD Radeon(TM) HD8970M +6808, 0, ATI FirePro V(FireGL V) Graphics Adapter +6809, 0, ATI FirePro V(FireGL V) Graphics Adapter +6810, 0, AMD Radeon(TM) HD 8800 Series +6810, 81, AMD Radeon (TM) R7 370 Series +6811, 0, AMD Radeon(TM) HD8800 Series +6811, 81, AMD Radeon (TM) R7 300 Series +6818, 0, AMD Radeon HD 7800 Series +6819, 0, AMD Radeon HD 7800 Series +6820, 0, AMD Radeon HD 8800M Series +6820, 81, AMD Radeon (TM) R9 M375 +6820, 83, AMD Radeon (TM) R9 M375X +6821, 0, AMD Radeon HD 8800M Series +6821, 87, AMD Radeon (TM) R7 M380 +6821, 83, AMD Radeon R9 (TM) M370X +6822, 0, AMD Radeon E8860 +6823, 0, AMD Radeon HD 8800M Series +6825, 0, AMD Radeon HD 7800M Series +6827, 0, AMD Radeon HD 7800M Series +6828, 0, ATI FirePro V(FireGL V) Graphics Adapter +682B, 0, AMD Radeon HD 8800M Series +682B, 87, AMD Radeon (TM) R9 M360 +682C, 0, AMD FirePro W4100 +682D, 0, AMD Radeon HD 7700M Series +682F, 0, AMD Radeon HD 7700M Series +6835, 0, AMD Radeon R7 Series / HD 9000 Series +6837, 0, AMD Radeon HD7700 Series +683D, 0, AMD Radeon HD 7700 Series +683F, 0, AMD Radeon HD 7700 Series +6860, 00, Radeon Instinct MI25 +6860, 01, Radeon Instinct MI25 +6860, 02, Radeon Instinct MI25 +6860, 03, Radeon Pro V340 +6860, 04, Radeon Instinct MI25x2 +6861, 00, Radeon Pro WX 9100 +6862, 00, Radeon Pro SSG +6863, 00, Radeon Vega Frontier Edition +6864, 03, Radeon Pro V340 +6864, 04, Instinct MI25x2 +6868, 00, Radeon (TM) PRO WX 8200 +686C, 00, Radeon Instinct MI25 MxGPU +686C, 01, Radeon Instinct MI25 MxGPU +686C, 02, Radeon Instinct MI25 MxGPU +686C, 03, Radeon Pro V340 MxGPU +686C, 04, Radeon Instinct MI25x2 MxGPU +686C, 05, Radeon Pro V340L MxGPU +686C, 06, Radeon Instinct MI25 MxGPU +687F, C0, Radeon RX Vega +687F, C1, Radeon RX Vega +687F, C3, Radeon RX Vega +6900, 0, AMD Radeon R7 M260 +6900, 81, AMD Radeon (TM) R7 M360 +6900, 83, AMD Radeon (TM) R7 M340 +6901, 0, AMD Radeon R5 M255 +6907, 0, AMD Radeon R5 M255 +6907, 87, AMD Radeon (TM) R5 M315 +6920, 0, AMD RADEON R9 M395X +6920, 1, AMD RADEON R9 M390X +6921, 0, AMD Radeon R9 M295X +6929, 0, AMD FirePro S7150 +692B, 0, AMD FirePro W7100 +6938, 0, AMD Radeon R9 200 Series +6938, F0, AMD Radeon R9 200 Series +6938, F1, AMD Radeon (TM) R9 380 Series +6939, F0, AMD Radeon R9 200 Series +6939, 0, AMD Radeon R9 200 Series +6939, F1, AMD Radeon (TM) R9 380 Series +6980, 00, Radeon Pro WX3100 +6985, 00, AMD Radeon Pro WX3100 +6987, 80, AMD Embedded Radeon E9171 +6987, C0, Radeon 550X Series +6987, C3, Radeon 540X Series +6995, 00, AMD Radeon Pro WX2100 +6997, 00, Radeon Pro WX2100 +699F, 81, AMD Embedded Radeon E9170 Series +699F, C0, Radeon 500 Series +699F, C1, Radeon 540 Series +699F, C3, Radeon 500 Series +699F, C7, Radeon 550 Series +7300, C1, AMD FirePro (TM) S9300 x2 +7300, C8, AMD Radeon (TM) R9 Fury Series +7300, C9, Radeon (TM) Pro Duo +7300, CB, AMD Radeon (TM) R9 Fury Series +7300, CA, AMD Radeon (TM) R9 Fury Series +9874, C4, AMD Radeon R7 Graphics +9874, C5, AMD Radeon R6 Graphics +9874, C6, AMD Radeon R6 Graphics +9874, C7, AMD Radeon R5 Graphics +9874, C8, AMD Radeon R7 Graphics +9874, 81, AMD Radeon R6 Graphics +9874, 87, AMD Radeon R5 Graphics +9874, 85, AMD Radeon R6 Graphics +9874, 84, AMD Radeon R7 Graphics +6FDF, EF, AMD Radeon RX 580 2048SP diff --git a/data/meson.build b/data/meson.build new file mode 100644 index 00000000..9c26b66e --- /dev/null +++ b/data/meson.build @@ -0,0 +1,27 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if with_amdgpu + install_data( + 'amdgpu.ids', + install_mode : 'rw-r--r--', + install_dir : datadir_amdgpu, + ) +endif diff --git a/etnaviv/Makefile.am b/etnaviv/Makefile.am index be96ba86..648e3c5b 100644 --- a/etnaviv/Makefile.am +++ b/etnaviv/Makefile.am @@ -2,6 +2,7 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ -I$(top_srcdir)/include/drm @@ -22,5 +23,6 @@ libdrm_etnavivinclude_HEADERS = $(LIBDRM_ETNAVIV_H_FILES) pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_etnaviv.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = etnaviv-symbol-check EXTRA_DIST = $(TESTS) diff --git a/etnaviv/Makefile.sources b/etnaviv/Makefile.sources index 52580567..0eb73783 100644 --- a/etnaviv/Makefile.sources +++ b/etnaviv/Makefile.sources @@ -3,6 +3,7 @@ LIBDRM_ETNAVIV_FILES := \ etnaviv_gpu.c \ etnaviv_bo.c \ etnaviv_bo_cache.c \ + etnaviv_perfmon.c \ etnaviv_pipe.c \ etnaviv_cmd_stream.c \ etnaviv_drm.h \ diff --git a/etnaviv/etnaviv-symbol-check b/etnaviv/etnaviv-symbol-check index 22afd168..18910688 100755 --- a/etnaviv/etnaviv-symbol-check +++ b/etnaviv/etnaviv-symbol-check @@ -1,5 +1,7 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.sources/LIBDRM_ETNAVIV_H_FILES @@ -39,8 +41,14 @@ etna_cmd_stream_new etna_cmd_stream_del etna_cmd_stream_timestamp etna_cmd_stream_flush +etna_cmd_stream_flush2 etna_cmd_stream_finish +etna_cmd_stream_perf etna_cmd_stream_reloc +etna_perfmon_create +etna_perfmon_del +etna_perfmon_get_dom_by_name +etna_perfmon_get_sig_by_name EOF done) diff --git a/etnaviv/etnaviv_bo.c b/etnaviv/etnaviv_bo.c index 4ad0434e..43ce6b4e 100644 --- a/etnaviv/etnaviv_bo.c +++ b/etnaviv/etnaviv_bo.c @@ -24,10 +24,6 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "etnaviv_priv.h" #include "etnaviv_drmif.h" @@ -108,7 +104,7 @@ static struct etna_bo *bo_from_handle(struct etna_device *dev, } /* allocate a new (un-tiled) buffer object */ -struct etna_bo *etna_bo_new(struct etna_device *dev, uint32_t size, +drm_public struct etna_bo *etna_bo_new(struct etna_device *dev, uint32_t size, uint32_t flags) { struct etna_bo *bo; @@ -135,7 +131,7 @@ struct etna_bo *etna_bo_new(struct etna_device *dev, uint32_t size, return bo; } -struct etna_bo *etna_bo_ref(struct etna_bo *bo) +drm_public struct etna_bo *etna_bo_ref(struct etna_bo *bo) { atomic_inc(&bo->refcnt); @@ -163,7 +159,8 @@ static int get_buffer_info(struct etna_bo *bo) } /* import a buffer object from DRI2 name */ -struct etna_bo *etna_bo_from_name(struct etna_device *dev, uint32_t name) +drm_public struct etna_bo *etna_bo_from_name(struct etna_device *dev, + uint32_t name) { struct etna_bo *bo; struct drm_gem_open req = { @@ -173,7 +170,7 @@ struct etna_bo *etna_bo_from_name(struct etna_device *dev, uint32_t name) pthread_mutex_lock(&table_lock); /* check name table first, to see if bo is already open: */ - bo = lookup_bo(dev->name_table, req.handle); + bo = lookup_bo(dev->name_table, name); if (bo) goto out_unlock; @@ -200,16 +197,21 @@ out_unlock: * fd so caller should close() the fd when it is otherwise done * with it (even if it is still using the 'struct etna_bo *') */ -struct etna_bo *etna_bo_from_dmabuf(struct etna_device *dev, int fd) +drm_public struct etna_bo *etna_bo_from_dmabuf(struct etna_device *dev, int fd) { struct etna_bo *bo; int ret, size; uint32_t handle; + /* take the lock before calling drmPrimeFDToHandle to avoid + * racing against etna_bo_del, which might invalidate the + * returned handle. + */ pthread_mutex_lock(&table_lock); ret = drmPrimeFDToHandle(dev->fd, fd, &handle); if (ret) { + pthread_mutex_unlock(&table_lock); return NULL; } @@ -230,7 +232,7 @@ out_unlock: } /* destroy a buffer object */ -void etna_bo_del(struct etna_bo *bo) +drm_public void etna_bo_del(struct etna_bo *bo) { struct etna_device *dev = bo->dev; @@ -252,7 +254,7 @@ out: } /* get the global flink/DRI2 buffer name */ -int etna_bo_get_name(struct etna_bo *bo, uint32_t *name) +drm_public int etna_bo_get_name(struct etna_bo *bo, uint32_t *name) { if (!bo->name) { struct drm_gem_flink req = { @@ -276,7 +278,7 @@ int etna_bo_get_name(struct etna_bo *bo, uint32_t *name) return 0; } -uint32_t etna_bo_handle(struct etna_bo *bo) +drm_public uint32_t etna_bo_handle(struct etna_bo *bo) { return bo->handle; } @@ -284,7 +286,7 @@ uint32_t etna_bo_handle(struct etna_bo *bo) /* caller owns the dmabuf fd that is returned and is responsible * to close() it when done */ -int etna_bo_dmabuf(struct etna_bo *bo) +drm_public int etna_bo_dmabuf(struct etna_bo *bo) { int ret, prime_fd; @@ -300,12 +302,12 @@ int etna_bo_dmabuf(struct etna_bo *bo) return prime_fd; } -uint32_t etna_bo_size(struct etna_bo *bo) +drm_public uint32_t etna_bo_size(struct etna_bo *bo) { return bo->size; } -void *etna_bo_map(struct etna_bo *bo) +drm_public void *etna_bo_map(struct etna_bo *bo) { if (!bo->map) { if (!bo->offset) { @@ -323,7 +325,7 @@ void *etna_bo_map(struct etna_bo *bo) return bo->map; } -int etna_bo_cpu_prep(struct etna_bo *bo, uint32_t op) +drm_public int etna_bo_cpu_prep(struct etna_bo *bo, uint32_t op) { struct drm_etnaviv_gem_cpu_prep req = { .handle = bo->handle, @@ -336,7 +338,7 @@ int etna_bo_cpu_prep(struct etna_bo *bo, uint32_t op) &req, sizeof(req)); } -void etna_bo_cpu_fini(struct etna_bo *bo) +drm_public void etna_bo_cpu_fini(struct etna_bo *bo) { struct drm_etnaviv_gem_cpu_fini req = { .handle = bo->handle, diff --git a/etnaviv/etnaviv_bo_cache.c b/etnaviv/etnaviv_bo_cache.c index 8924651f..c81de262 100644 --- a/etnaviv/etnaviv_bo_cache.c +++ b/etnaviv/etnaviv_bo_cache.c @@ -24,10 +24,6 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "etnaviv_priv.h" #include "etnaviv_drmif.h" @@ -124,20 +120,32 @@ static int is_idle(struct etna_bo *bo) static struct etna_bo *find_in_bucket(struct etna_bo_bucket *bucket, uint32_t flags) { - struct etna_bo *bo = NULL; + struct etna_bo *bo = NULL, *tmp; pthread_mutex_lock(&table_lock); - while (!LIST_IS_EMPTY(&bucket->list)) { - bo = LIST_ENTRY(struct etna_bo, bucket->list.next, list); - if (bo->flags == flags && is_idle(bo)) { - list_del(&bo->list); - break; + if (LIST_IS_EMPTY(&bucket->list)) + goto out_unlock; + + LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bucket->list, list) { + /* skip BOs with different flags */ + if (bo->flags != flags) + continue; + + /* check if the first BO with matching flags is idle */ + if (is_idle(bo)) { + list_delinit(&bo->list); + goto out_unlock; } - bo = NULL; + /* If the oldest BO is still busy, don't try younger ones */ break; } + + /* There was no matching buffer found */ + bo = NULL; + +out_unlock: pthread_mutex_unlock(&table_lock); return bo; diff --git a/etnaviv/etnaviv_cmd_stream.c b/etnaviv/etnaviv_cmd_stream.c index 9ce3f363..7139c324 100644 --- a/etnaviv/etnaviv_cmd_stream.c +++ b/etnaviv/etnaviv_cmd_stream.c @@ -24,10 +24,6 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <assert.h> #include "etnaviv_drmif.h" @@ -59,7 +55,8 @@ etna_cmd_stream_priv(struct etna_cmd_stream *stream) return (struct etna_cmd_stream_priv *)stream; } -struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe, uint32_t size, +drm_public struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe, + uint32_t size, void (*reset_notify)(struct etna_cmd_stream *stream, void *priv), void *priv) { @@ -99,12 +96,13 @@ fail: return NULL; } -void etna_cmd_stream_del(struct etna_cmd_stream *stream) +drm_public void etna_cmd_stream_del(struct etna_cmd_stream *stream) { struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream); free(stream->buffer); free(priv->submit.relocs); + free(priv->submit.pmrs); free(priv); } @@ -115,13 +113,14 @@ static void reset_buffer(struct etna_cmd_stream *stream) stream->offset = 0; priv->submit.nr_bos = 0; priv->submit.nr_relocs = 0; + priv->submit.nr_pmrs = 0; priv->nr_bos = 0; if (priv->reset_notify) priv->reset_notify(stream, priv->reset_notify_priv); } -uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream) +drm_public uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream) { return etna_cmd_stream_priv(stream)->last_timestamp; } @@ -177,7 +176,8 @@ static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo, return idx; } -static void flush(struct etna_cmd_stream *stream) +static void flush(struct etna_cmd_stream *stream, int in_fence_fd, + int *out_fence_fd) { struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream); int ret, id = priv->pipe->id; @@ -190,10 +190,20 @@ static void flush(struct etna_cmd_stream *stream) .nr_bos = priv->submit.nr_bos, .relocs = VOID2U64(priv->submit.relocs), .nr_relocs = priv->submit.nr_relocs, + .pmrs = VOID2U64(priv->submit.pmrs), + .nr_pmrs = priv->submit.nr_pmrs, .stream = VOID2U64(stream->buffer), .stream_size = stream->offset * 4, /* in bytes */ }; + if (in_fence_fd != -1) { + req.flags |= ETNA_SUBMIT_FENCE_FD_IN | ETNA_SUBMIT_NO_IMPLICIT; + req.fence_fd = in_fence_fd; + } + + if (out_fence_fd) + req.flags |= ETNA_SUBMIT_FENCE_FD_OUT; + ret = drmCommandWriteRead(gpu->dev->fd, DRM_ETNAVIV_GEM_SUBMIT, &req, sizeof(req)); @@ -208,24 +218,36 @@ static void flush(struct etna_cmd_stream *stream) bo->current_stream = NULL; etna_bo_del(bo); } + + if (out_fence_fd) + *out_fence_fd = req.fence_fd; } -void etna_cmd_stream_flush(struct etna_cmd_stream *stream) +drm_public void etna_cmd_stream_flush(struct etna_cmd_stream *stream) { - flush(stream); + flush(stream, -1, NULL); reset_buffer(stream); } -void etna_cmd_stream_finish(struct etna_cmd_stream *stream) +drm_public void etna_cmd_stream_flush2(struct etna_cmd_stream *stream, + int in_fence_fd, + int *out_fence_fd) +{ + flush(stream, in_fence_fd, out_fence_fd); + reset_buffer(stream); +} + +drm_public void etna_cmd_stream_finish(struct etna_cmd_stream *stream) { struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream); - flush(stream); + flush(stream, -1, NULL); etna_pipe_wait(priv->pipe, priv->last_timestamp, 5000); reset_buffer(stream); } -void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_reloc *r) +drm_public void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, + const struct etna_reloc *r) { struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream); struct drm_etnaviv_gem_submit_reloc *reloc; @@ -241,3 +263,19 @@ void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_rel etna_cmd_stream_emit(stream, addr); } + +drm_public void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p) +{ + struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream); + struct drm_etnaviv_gem_submit_pmr *pmr; + uint32_t idx = APPEND(&priv->submit, pmrs); + + pmr = &priv->submit.pmrs[idx]; + + pmr->flags = p->flags; + pmr->sequence = p->sequence; + pmr->read_offset = p->offset; + pmr->read_idx = bo2idx(stream, p->bo, ETNA_SUBMIT_BO_READ | ETNA_SUBMIT_BO_WRITE); + pmr->domain = p->signal->domain->id; + pmr->signal = p->signal->signal; +} diff --git a/etnaviv/etnaviv_device.c b/etnaviv/etnaviv_device.c index 3ce92030..699df256 100644 --- a/etnaviv/etnaviv_device.c +++ b/etnaviv/etnaviv_device.c @@ -24,10 +24,6 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <linux/stddef.h> #include <linux/types.h> @@ -45,7 +41,7 @@ static pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER; -struct etna_device *etna_device_new(int fd) +drm_public struct etna_device *etna_device_new(int fd) { struct etna_device *dev = calloc(sizeof(*dev), 1); @@ -63,7 +59,7 @@ struct etna_device *etna_device_new(int fd) /* like etna_device_new() but creates it's own private dup() of the fd * which is close()d when the device is finalized. */ -struct etna_device *etna_device_new_dup(int fd) +drm_public struct etna_device *etna_device_new_dup(int fd) { int dup_fd = dup(fd); struct etna_device *dev = etna_device_new(dup_fd); @@ -76,7 +72,7 @@ struct etna_device *etna_device_new_dup(int fd) return dev; } -struct etna_device *etna_device_ref(struct etna_device *dev) +drm_public struct etna_device *etna_device_ref(struct etna_device *dev) { atomic_inc(&dev->refcnt); @@ -103,7 +99,7 @@ drm_private void etna_device_del_locked(struct etna_device *dev) etna_device_del_impl(dev); } -void etna_device_del(struct etna_device *dev) +drm_public void etna_device_del(struct etna_device *dev) { if (!atomic_dec_and_test(&dev->refcnt)) return; @@ -113,7 +109,7 @@ void etna_device_del(struct etna_device *dev) pthread_mutex_unlock(&table_lock); } -int etna_device_fd(struct etna_device *dev) +drm_public int etna_device_fd(struct etna_device *dev) { return dev->fd; } diff --git a/etnaviv/etnaviv_drm.h b/etnaviv/etnaviv_drm.h index 2584c1cc..0d5c49dc 100644 --- a/etnaviv/etnaviv_drm.h +++ b/etnaviv/etnaviv_drm.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * Copyright (C) 2015 Etnaviv Project * @@ -54,6 +55,12 @@ struct drm_etnaviv_timespec { #define ETNAVIV_PARAM_GPU_FEATURES_4 0x07 #define ETNAVIV_PARAM_GPU_FEATURES_5 0x08 #define ETNAVIV_PARAM_GPU_FEATURES_6 0x09 +#define ETNAVIV_PARAM_GPU_FEATURES_7 0x0a +#define ETNAVIV_PARAM_GPU_FEATURES_8 0x0b +#define ETNAVIV_PARAM_GPU_FEATURES_9 0x0c +#define ETNAVIV_PARAM_GPU_FEATURES_10 0x0d +#define ETNAVIV_PARAM_GPU_FEATURES_11 0x0e +#define ETNAVIV_PARAM_GPU_FEATURES_12 0x0f #define ETNAVIV_PARAM_GPU_STREAM_COUNT 0x10 #define ETNAVIV_PARAM_GPU_REGISTER_MAX 0x11 @@ -150,10 +157,29 @@ struct drm_etnaviv_gem_submit_bo { __u64 presumed; /* in/out, presumed buffer address */ }; +/* performance monitor request (pmr) */ +#define ETNA_PM_PROCESS_PRE 0x0001 +#define ETNA_PM_PROCESS_POST 0x0002 +struct drm_etnaviv_gem_submit_pmr { + __u32 flags; /* in, when to process request (ETNA_PM_PROCESS_x) */ + __u8 domain; /* in, pm domain */ + __u8 pad; + __u16 signal; /* in, pm signal */ + __u32 sequence; /* in, sequence number */ + __u32 read_offset; /* in, offset from read_bo */ + __u32 read_idx; /* in, index of read_bo buffer */ +}; + /* Each cmdstream submit consists of a table of buffers involved, and * one or more cmdstream buffers. This allows for conditional execution * (context-restore), and IB buffers needed for per tile/bin draw cmds. */ +#define ETNA_SUBMIT_NO_IMPLICIT 0x0001 +#define ETNA_SUBMIT_FENCE_FD_IN 0x0002 +#define ETNA_SUBMIT_FENCE_FD_OUT 0x0004 +#define ETNA_SUBMIT_FLAGS (ETNA_SUBMIT_NO_IMPLICIT | \ + ETNA_SUBMIT_FENCE_FD_IN | \ + ETNA_SUBMIT_FENCE_FD_OUT) #define ETNA_PIPE_3D 0x00 #define ETNA_PIPE_2D 0x01 #define ETNA_PIPE_VG 0x02 @@ -167,6 +193,11 @@ struct drm_etnaviv_gem_submit { __u64 bos; /* in, ptr to array of submit_bo's */ __u64 relocs; /* in, ptr to array of submit_reloc's */ __u64 stream; /* in, ptr to cmdstream */ + __u32 flags; /* in, mask of ETNA_SUBMIT_x */ + __s32 fence_fd; /* in/out, fence fd (see ETNA_SUBMIT_FENCE_FD_x) */ + __u64 pmrs; /* in, ptr to array of submit_pmr's */ + __u32 nr_pmrs; /* in, number of submit_pmr's */ + __u32 pad; }; /* The normal way to synchronize with the GPU is just to CPU_PREP on @@ -202,6 +233,27 @@ struct drm_etnaviv_gem_wait { struct drm_etnaviv_timespec timeout; /* in */ }; +/* + * Performance Monitor (PM): + */ + +struct drm_etnaviv_pm_domain { + __u32 pipe; /* in */ + __u8 iter; /* in/out, select pm domain at index iter */ + __u8 id; /* out, id of domain */ + __u16 nr_signals; /* out, how many signals does this domain provide */ + char name[64]; /* out, name of domain */ +}; + +struct drm_etnaviv_pm_signal { + __u32 pipe; /* in */ + __u8 domain; /* in, pm domain index */ + __u8 pad; + __u16 iter; /* in/out, select pm source at index iter */ + __u16 id; /* out, id of signal */ + char name[64]; /* out, name of domain */ +}; + #define DRM_ETNAVIV_GET_PARAM 0x00 /* placeholder: #define DRM_ETNAVIV_SET_PARAM 0x01 @@ -214,7 +266,9 @@ struct drm_etnaviv_gem_wait { #define DRM_ETNAVIV_WAIT_FENCE 0x07 #define DRM_ETNAVIV_GEM_USERPTR 0x08 #define DRM_ETNAVIV_GEM_WAIT 0x09 -#define DRM_ETNAVIV_NUM_IOCTLS 0x0a +#define DRM_ETNAVIV_PM_QUERY_DOM 0x0a +#define DRM_ETNAVIV_PM_QUERY_SIG 0x0b +#define DRM_ETNAVIV_NUM_IOCTLS 0x0c #define DRM_IOCTL_ETNAVIV_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param) #define DRM_IOCTL_ETNAVIV_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new) @@ -225,6 +279,8 @@ struct drm_etnaviv_gem_wait { #define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence) #define DRM_IOCTL_ETNAVIV_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr) #define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait) +#define DRM_IOCTL_ETNAVIV_PM_QUERY_DOM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_DOM, struct drm_etnaviv_pm_domain) +#define DRM_IOCTL_ETNAVIV_PM_QUERY_SIG DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_SIG, struct drm_etnaviv_pm_signal) #if defined(__cplusplus) } diff --git a/etnaviv/etnaviv_drmif.h b/etnaviv/etnaviv_drmif.h index 8119baad..5a6bef8d 100644 --- a/etnaviv/etnaviv_drmif.h +++ b/etnaviv/etnaviv_drmif.h @@ -35,6 +35,9 @@ struct etna_pipe; struct etna_gpu; struct etna_device; struct etna_cmd_stream; +struct etna_perfmon; +struct etna_perfmon_domain; +struct etna_perfmon_signal; enum etna_pipe_id { ETNA_PIPE_3D = 0, @@ -142,6 +145,8 @@ struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe, uint32_t siz void etna_cmd_stream_del(struct etna_cmd_stream *stream); uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream); void etna_cmd_stream_flush(struct etna_cmd_stream *stream); +void etna_cmd_stream_flush2(struct etna_cmd_stream *stream, int in_fence_fd, + int *out_fence_fd); void etna_cmd_stream_finish(struct etna_cmd_stream *stream); static inline uint32_t etna_cmd_stream_avail(struct etna_cmd_stream *stream) @@ -188,4 +193,24 @@ struct etna_reloc { void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_reloc *r); +/* performance monitoring functions: + */ + +struct etna_perfmon *etna_perfmon_create(struct etna_pipe *pipe); +void etna_perfmon_del(struct etna_perfmon *perfmon); +struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name); +struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name); + +struct etna_perf { +#define ETNA_PM_PROCESS_PRE 0x0001 +#define ETNA_PM_PROCESS_POST 0x0002 + uint32_t flags; + uint32_t sequence; + struct etna_perfmon_signal *signal; + struct etna_bo *bo; + uint32_t offset; +}; + +void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p); + #endif /* ETNAVIV_DRMIF_H_ */ diff --git a/etnaviv/etnaviv_gpu.c b/etnaviv/etnaviv_gpu.c index 35dec6cd..dc4c126d 100644 --- a/etnaviv/etnaviv_gpu.c +++ b/etnaviv/etnaviv_gpu.c @@ -24,10 +24,6 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "etnaviv_priv.h" #include "etnaviv_drmif.h" @@ -48,7 +44,7 @@ static uint64_t get_param(struct etna_device *dev, uint32_t core, uint32_t param return req.value; } -struct etna_gpu *etna_gpu_new(struct etna_device *dev, unsigned int core) +drm_public struct etna_gpu *etna_gpu_new(struct etna_device *dev, unsigned int core) { struct etna_gpu *gpu; @@ -61,32 +57,13 @@ struct etna_gpu *etna_gpu_new(struct etna_device *dev, unsigned int core) gpu->dev = dev; gpu->core = core; - /* get specs from kernel space */ - gpu->specs.model = get_param(dev, core, ETNAVIV_PARAM_GPU_MODEL); - gpu->specs.revision = get_param(dev, core, ETNAVIV_PARAM_GPU_REVISION); - gpu->specs.features[0] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_0); - gpu->specs.features[1] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_1); - gpu->specs.features[2] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_2); - gpu->specs.features[3] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_3); - gpu->specs.features[4] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_4); - gpu->specs.features[5] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_5); - gpu->specs.features[6] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_6); - gpu->specs.stream_count = get_param(dev, core, ETNA_GPU_STREAM_COUNT); - gpu->specs.register_max = get_param(dev, core, ETNA_GPU_REGISTER_MAX); - gpu->specs.thread_count = get_param(dev, core, ETNA_GPU_THREAD_COUNT); - gpu->specs.vertex_cache_size = get_param(dev, core, ETNA_GPU_VERTEX_CACHE_SIZE); - gpu->specs.shader_core_count = get_param(dev, core, ETNA_GPU_SHADER_CORE_COUNT); - gpu->specs.pixel_pipes = get_param(dev, core, ETNA_GPU_PIXEL_PIPES); - gpu->specs.vertex_output_buffer_size = get_param(dev, core, ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE); - gpu->specs.buffer_size = get_param(dev, core, ETNA_GPU_BUFFER_SIZE); - gpu->specs.instruction_count = get_param(dev, core, ETNA_GPU_INSTRUCTION_COUNT); - gpu->specs.num_constants = get_param(dev, core, ETNA_GPU_NUM_CONSTANTS); - gpu->specs.num_varyings = get_param(dev, core, ETNA_GPU_NUM_VARYINGS); - - if (!gpu->specs.model) + gpu->model = get_param(dev, core, ETNAVIV_PARAM_GPU_MODEL); + gpu->revision = get_param(dev, core, ETNAVIV_PARAM_GPU_REVISION); + + if (!gpu->model) goto fail; - INFO_MSG(" GPU model: 0x%x (rev %x)", gpu->specs.model, gpu->specs.revision); + INFO_MSG(" GPU model: 0x%x (rev %x)", gpu->model, gpu->revision); return gpu; fail: @@ -96,74 +73,77 @@ fail: return NULL; } -void etna_gpu_del(struct etna_gpu *gpu) +drm_public void etna_gpu_del(struct etna_gpu *gpu) { free(gpu); } -int etna_gpu_get_param(struct etna_gpu *gpu, enum etna_param_id param, +drm_public int etna_gpu_get_param(struct etna_gpu *gpu, enum etna_param_id param, uint64_t *value) { + struct etna_device *dev = gpu->dev; + unsigned int core = gpu->core; + switch(param) { case ETNA_GPU_MODEL: - *value = gpu->specs.model; + *value = gpu->model; return 0; case ETNA_GPU_REVISION: - *value = gpu->specs.revision; + *value = gpu->revision; return 0; case ETNA_GPU_FEATURES_0: - *value = gpu->specs.features[0]; + *value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_0); return 0; case ETNA_GPU_FEATURES_1: - *value = gpu->specs.features[1]; + *value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_1); return 0; case ETNA_GPU_FEATURES_2: - *value = gpu->specs.features[2]; + *value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_2); return 0; case ETNA_GPU_FEATURES_3: - *value = gpu->specs.features[3]; + *value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_3); return 0; case ETNA_GPU_FEATURES_4: - *value = gpu->specs.features[4]; + *value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_4); return 0; case ETNA_GPU_FEATURES_5: - *value = gpu->specs.features[5]; + *value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_5); return 0; case ETNA_GPU_FEATURES_6: - *value = gpu->specs.features[6]; + *value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_6); return 0; case ETNA_GPU_STREAM_COUNT: - *value = gpu->specs.stream_count; + *value = get_param(dev, core, ETNA_GPU_STREAM_COUNT); return 0; case ETNA_GPU_REGISTER_MAX: - *value = gpu->specs.register_max; + *value = get_param(dev, core, ETNA_GPU_REGISTER_MAX); return 0; case ETNA_GPU_THREAD_COUNT: - *value = gpu->specs.thread_count; + *value = get_param(dev, core, ETNA_GPU_THREAD_COUNT); return 0; case ETNA_GPU_VERTEX_CACHE_SIZE: - *value = gpu->specs.vertex_cache_size; + *value = get_param(dev, core, ETNA_GPU_VERTEX_CACHE_SIZE); return 0; case ETNA_GPU_SHADER_CORE_COUNT: - *value = gpu->specs.shader_core_count; + *value = get_param(dev, core, ETNA_GPU_SHADER_CORE_COUNT); return 0; case ETNA_GPU_PIXEL_PIPES: - *value = gpu->specs.pixel_pipes; + *value = get_param(dev, core, ETNA_GPU_PIXEL_PIPES); return 0; case ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE: - *value = gpu->specs.vertex_output_buffer_size; + *value = get_param(dev, core, ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE); return 0; case ETNA_GPU_BUFFER_SIZE: - *value = gpu->specs.buffer_size; + *value = get_param(dev, core, ETNA_GPU_BUFFER_SIZE); return 0; case ETNA_GPU_INSTRUCTION_COUNT: - *value = gpu->specs.instruction_count; + *value = get_param(dev, core, ETNA_GPU_INSTRUCTION_COUNT); return 0; case ETNA_GPU_NUM_CONSTANTS: - *value = gpu->specs.num_constants; + *value = get_param(dev, core, ETNA_GPU_NUM_CONSTANTS); return 0; case ETNA_GPU_NUM_VARYINGS: - *value = gpu->specs.num_varyings; + *value = get_param(dev, core, ETNA_GPU_NUM_VARYINGS); return 0; default: diff --git a/etnaviv/etnaviv_perfmon.c b/etnaviv/etnaviv_perfmon.c new file mode 100644 index 00000000..f6576b8a --- /dev/null +++ b/etnaviv/etnaviv_perfmon.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2017 Etnaviv Project + * Copyright (C) 2017 Zodiac Inflight Innovations + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Christian Gmeiner <christian.gmeiner@gmail.com> + */ + +#include "etnaviv_priv.h" + +static int etna_perfmon_query_signals(struct etna_perfmon *pm, struct etna_perfmon_domain *dom) +{ + struct etna_device *dev = pm->pipe->gpu->dev; + struct drm_etnaviv_pm_signal req = { + .pipe = pm->pipe->id, + .domain = dom->id + }; + + do { + struct etna_perfmon_signal *sig; + int ret; + + ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_SIG, &req, sizeof(req)); + if (ret) + break; + + sig = calloc(1, sizeof(*sig)); + if (!sig) + return -ENOMEM; + + INFO_MSG("perfmon signal:"); + INFO_MSG("id = %d", req.id); + INFO_MSG("name = %s", req.name); + + sig->domain = dom; + sig->signal = req.id; + strncpy(sig->name, req.name, sizeof(sig->name)); + list_addtail(&sig->head, &dom->signals); + } while (req.iter != 0xffff); + + return 0; +} + +static int etna_perfmon_query_domains(struct etna_perfmon *pm) +{ + struct etna_device *dev = pm->pipe->gpu->dev; + struct drm_etnaviv_pm_domain req = { + .pipe = pm->pipe->id + }; + + do { + struct etna_perfmon_domain *dom; + int ret; + + ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_DOM, &req, sizeof(req)); + if (ret) + break; + + dom = calloc(1, sizeof(*dom)); + if (!dom) + return -ENOMEM; + + list_inithead(&dom->signals); + dom->id = req.id; + strncpy(dom->name, req.name, sizeof(dom->name)); + list_addtail(&dom->head, &pm->domains); + + INFO_MSG("perfmon domain:"); + INFO_MSG("id = %d", req.id); + INFO_MSG("name = %s", req.name); + INFO_MSG("nr_signals = %d", req.nr_signals); + + /* Query all available signals for this domain. */ + if (req.nr_signals > 0) { + ret = etna_perfmon_query_signals(pm, dom); + if (ret) + return ret; + } + } while (req.iter != 0xff); + + return 0; +} + +static void etna_perfmon_free_signals(struct etna_perfmon_domain *dom) +{ + struct etna_perfmon_signal *sig, *next; + + LIST_FOR_EACH_ENTRY_SAFE(sig, next, &dom->signals, head) { + list_del(&sig->head); + free(sig); + } +} + +static void etna_perfmon_free_domains(struct etna_perfmon *pm) +{ + struct etna_perfmon_domain *dom, *next; + + LIST_FOR_EACH_ENTRY_SAFE(dom, next, &pm->domains, head) { + etna_perfmon_free_signals(dom); + list_del(&dom->head); + free(dom); + } +} + +drm_public struct etna_perfmon *etna_perfmon_create(struct etna_pipe *pipe) +{ + struct etna_perfmon *pm; + int ret; + + pm = calloc(1, sizeof(*pm)); + if (!pm) { + ERROR_MSG("allocation failed"); + return NULL; + } + + list_inithead(&pm->domains); + pm->pipe = pipe; + + /* query all available domains and sources for this device */ + ret = etna_perfmon_query_domains(pm); + if (ret) + goto fail; + + return pm; + +fail: + etna_perfmon_del(pm); + return NULL; +} + +drm_public void etna_perfmon_del(struct etna_perfmon *pm) +{ + if (!pm) + return; + + etna_perfmon_free_domains(pm); + free(pm); +} + +drm_public struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name) +{ + struct etna_perfmon_domain *dom; + + if (pm) { + LIST_FOR_EACH_ENTRY(dom, &pm->domains, head) { + if (!strcmp(dom->name, name)) + return dom; + } + } + + return NULL; +} + +drm_public struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name) +{ + struct etna_perfmon_signal *signal; + + if (dom) { + LIST_FOR_EACH_ENTRY(signal, &dom->signals, head) { + if (!strcmp(signal->name, name)) + return signal; + } + } + + return NULL; +} diff --git a/etnaviv/etnaviv_pipe.c b/etnaviv/etnaviv_pipe.c index 94c5d377..4120a36f 100644 --- a/etnaviv/etnaviv_pipe.c +++ b/etnaviv/etnaviv_pipe.c @@ -24,18 +24,14 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "etnaviv_priv.h" -int etna_pipe_wait(struct etna_pipe *pipe, uint32_t timestamp, uint32_t ms) +drm_public int etna_pipe_wait(struct etna_pipe *pipe, uint32_t timestamp, uint32_t ms) { return etna_pipe_wait_ns(pipe, timestamp, ms * 1000000); } -int etna_pipe_wait_ns(struct etna_pipe *pipe, uint32_t timestamp, uint64_t ns) +drm_public int etna_pipe_wait_ns(struct etna_pipe *pipe, uint32_t timestamp, uint64_t ns) { struct etna_device *dev = pipe->gpu->dev; int ret; @@ -59,12 +55,12 @@ int etna_pipe_wait_ns(struct etna_pipe *pipe, uint32_t timestamp, uint64_t ns) return 0; } -void etna_pipe_del(struct etna_pipe *pipe) +drm_public void etna_pipe_del(struct etna_pipe *pipe) { free(pipe); } -struct etna_pipe *etna_pipe_new(struct etna_gpu *gpu, enum etna_pipe_id id) +drm_public struct etna_pipe *etna_pipe_new(struct etna_gpu *gpu, enum etna_pipe_id id) { struct etna_pipe *pipe; diff --git a/etnaviv/etnaviv_priv.h b/etnaviv/etnaviv_priv.h index feaa5ad9..e45d364c 100644 --- a/etnaviv/etnaviv_priv.h +++ b/etnaviv/etnaviv_priv.h @@ -47,25 +47,6 @@ #include "etnaviv_drmif.h" #include "etnaviv_drm.h" -#define VIV_FEATURES_WORD_COUNT 7 - -struct etna_specs { - uint32_t model; - uint32_t revision; - uint32_t features[VIV_FEATURES_WORD_COUNT]; - uint32_t stream_count; - uint32_t register_max; - uint32_t thread_count; - uint32_t shader_core_count; - uint32_t vertex_cache_size; - uint32_t vertex_output_buffer_size; - uint32_t pixel_pipes; - uint32_t instruction_count; - uint32_t num_constants; - uint32_t num_varyings; - uint32_t buffer_size; -}; - struct etna_bo_bucket { uint32_t size; struct list_head list; @@ -134,8 +115,9 @@ struct etna_bo { struct etna_gpu { struct etna_device *dev; - struct etna_specs specs; uint32_t core; + uint32_t model; + uint32_t revision; }; struct etna_pipe { @@ -158,6 +140,10 @@ struct etna_cmd_stream_priv { /* reloc's table: */ struct drm_etnaviv_gem_submit_reloc *relocs; uint32_t nr_relocs, max_relocs; + + /* perf's table: */ + struct drm_etnaviv_gem_submit_pmr *pmrs; + uint32_t nr_pmrs, max_pmrs; } submit; /* should have matching entries in submit.bos: */ @@ -169,6 +155,27 @@ struct etna_cmd_stream_priv { void *reset_notify_priv; }; +struct etna_perfmon { + struct list_head domains; + struct etna_pipe *pipe; +}; + +struct etna_perfmon_domain +{ + struct list_head head; + struct list_head signals; + uint8_t id; + char name[64]; +}; + +struct etna_perfmon_signal +{ + struct list_head head; + struct etna_perfmon_domain *domain; + uint8_t signal; + char name[64]; +}; + #define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1)) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) diff --git a/etnaviv/meson.build b/etnaviv/meson.build new file mode 100644 index 00000000..515a4ed0 --- /dev/null +++ b/etnaviv/meson.build @@ -0,0 +1,59 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +libdrm_etnaviv = shared_library( + 'drm_etnaviv', + [ + files( + 'etnaviv_device.c', 'etnaviv_gpu.c', 'etnaviv_bo.c', 'etnaviv_bo_cache.c', + 'etnaviv_perfmon.c', 'etnaviv_pipe.c', 'etnaviv_cmd_stream.c', + ), + config_file + ], + include_directories : [inc_root, inc_drm], + link_with : libdrm, + c_args : libdrm_c_args, + dependencies : [dep_pthread_stubs, dep_rt, dep_atomic_ops], + version : '1.0.0', + install : true, +) + +install_headers('etnaviv_drmif.h', subdir : 'libdrm') + +pkg.generate( + name : 'libdrm_etnaviv', + libraries : libdrm_etnaviv, + subdirs : ['.', 'libdrm'], + version : meson.project_version(), + requires_private : 'libdrm', + description : 'Userspace interface to Tegra kernel DRM services', +) + +ext_libdrm_etnaviv = declare_dependency( + link_with : [libdrm, libdrm_etnaviv], + include_directories : [inc_drm, include_directories('.')], +) + +test( + 'etnaviv-symbol-check', + prog_bash, + args : [files('etnaviv-symbol-check'), libdrm_etnaviv] +) diff --git a/exynos/Makefile.am b/exynos/Makefile.am index f99f8981..76b185d3 100644 --- a/exynos/Makefile.am +++ b/exynos/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ -I$(top_srcdir)/include/drm @@ -23,5 +24,6 @@ libdrm_exynosinclude_HEADERS = exynos_drmif.h pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_exynos.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = exynos-symbol-check EXTRA_DIST = $(TESTS) diff --git a/exynos/exynos-symbol-check b/exynos/exynos-symbol-check index 9692caa6..49d611e6 100755 --- a/exynos/exynos-symbol-check +++ b/exynos/exynos-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.am/libdrm_exynos*_HEADERS -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_exynos.so} | awk '{print $3}'| while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_exynos.so} | awk '{print $3}'| while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c index b961e520..078bf2c5 100644 --- a/exynos/exynos_drm.c +++ b/exynos/exynos_drm.c @@ -24,10 +24,6 @@ * Inki Dae <inki.dae@samsung.com> */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -52,7 +48,7 @@ * * if true, return the device object else NULL. */ -struct exynos_device * exynos_device_create(int fd) +drm_public struct exynos_device * exynos_device_create(int fd) { struct exynos_device *dev; @@ -73,7 +69,7 @@ struct exynos_device * exynos_device_create(int fd) * * @dev: exynos drm device object. */ -void exynos_device_destroy(struct exynos_device *dev) +drm_public void exynos_device_destroy(struct exynos_device *dev) { free(dev); } @@ -91,8 +87,8 @@ void exynos_device_destroy(struct exynos_device *dev) * * if true, return a exynos buffer object else NULL. */ -struct exynos_bo * exynos_bo_create(struct exynos_device *dev, - size_t size, uint32_t flags) +drm_public struct exynos_bo * exynos_bo_create(struct exynos_device *dev, + size_t size, uint32_t flags) { struct exynos_bo *bo; struct drm_exynos_gem_create req = { @@ -145,8 +141,8 @@ fail: * * if true, return 0 else negative. */ -int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle, - size_t *size, uint32_t *flags) +drm_public int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle, + size_t *size, uint32_t *flags) { int ret; struct drm_exynos_gem_info req = { @@ -171,7 +167,7 @@ int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle, * * @bo: a exynos buffer object to be destroyed. */ -void exynos_bo_destroy(struct exynos_bo *bo) +drm_public void exynos_bo_destroy(struct exynos_bo *bo) { if (!bo) return; @@ -203,7 +199,7 @@ void exynos_bo_destroy(struct exynos_bo *bo) * if true, return a exynos buffer object else NULL. * */ -struct exynos_bo * +drm_public struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name) { struct exynos_bo *bo; @@ -246,7 +242,7 @@ err_free_bo: * * if true, return 0 else negative. */ -int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name) +drm_public int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name) { if (!bo->name) { struct drm_gem_flink req = { @@ -269,7 +265,7 @@ int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name) return 0; } -uint32_t exynos_bo_handle(struct exynos_bo *bo) +drm_public uint32_t exynos_bo_handle(struct exynos_bo *bo) { return bo->handle; } @@ -282,7 +278,7 @@ uint32_t exynos_bo_handle(struct exynos_bo *bo) * * if true, user pointer mmaped else NULL. */ -void *exynos_bo_map(struct exynos_bo *bo) +drm_public void *exynos_bo_map(struct exynos_bo *bo) { if (!bo->vaddr) { struct exynos_device *dev = bo->dev; @@ -319,7 +315,7 @@ void *exynos_bo_map(struct exynos_bo *bo) * * @return: 0 on success, -1 on error, and errno will be set */ -int +drm_public int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle, int *fd) { return drmPrimeHandleToFD(dev->fd, handle, 0, fd); @@ -334,7 +330,7 @@ exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle, int *fd) * * @return: 0 on success, -1 on error, and errno will be set */ -int +drm_public int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd, uint32_t *handle) { return drmPrimeFDToHandle(dev->fd, fd, handle); @@ -357,7 +353,7 @@ exynos_prime_fd_to_handle(struct exynos_device *dev, int fd, uint32_t *handle) * * if true, return 0 else negative. */ -int +drm_public int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect, uint32_t ext, void *edid) { @@ -398,7 +394,7 @@ exynos_handle_vendor(int fd, struct drm_event *e, void *ctx) } } -int +drm_public int exynos_handle_event(struct exynos_device *dev, struct exynos_event_context *ctx) { char buffer[1024]; @@ -417,7 +413,7 @@ exynos_handle_event(struct exynos_device *dev, struct exynos_event_context *ctx) i = 0; while (i < len) { - e = (struct drm_event *) &buffer[i]; + e = (struct drm_event *)(buffer + i); switch (e->type) { case DRM_EVENT_VBLANK: if (evctx->version < 1 || diff --git a/exynos/exynos_drmif.h b/exynos/exynos_drmif.h index 626e3998..154439bb 100644 --- a/exynos/exynos_drmif.h +++ b/exynos/exynos_drmif.h @@ -31,6 +31,10 @@ #include <stdint.h> #include "exynos_drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + struct exynos_device { int fd; }; @@ -109,4 +113,8 @@ int exynos_handle_event(struct exynos_device *dev, struct exynos_event_context *ctx); +#if defined(__cplusplus) +} +#endif + #endif /* EXYNOS_DRMIF_H_ */ diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c index 7f1d105a..ac6fa687 100644 --- a/exynos/exynos_fimg2d.c +++ b/exynos/exynos_fimg2d.c @@ -3,17 +3,26 @@ * Authors: * Inki Dae <inki.dae@samsung.com> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -293,20 +302,6 @@ static void g2d_set_direction(struct g2d_context *ctx, } /* - * g2d_reset - reset fimg2d hardware. - * - * @ctx: a pointer to g2d_context structure. - * - */ -static void g2d_reset(struct g2d_context *ctx) -{ - ctx->cmd_nr = 0; - ctx->cmd_buf_nr = 0; - - g2d_add_cmd(ctx, SOFT_RESET_REG, 0x01); -} - -/* * g2d_flush - submit all commands and values in user side command buffer * to command queue aware of fimg2d dma. * @@ -361,7 +356,7 @@ static int g2d_flush(struct g2d_context *ctx) * * fd: a file descriptor to an opened drm device. */ -struct g2d_context *g2d_init(int fd) +drm_public struct g2d_context *g2d_init(int fd) { struct drm_exynos_g2d_get_ver ver; struct g2d_context *ctx; @@ -389,7 +384,7 @@ struct g2d_context *g2d_init(int fd) return ctx; } -void g2d_fini(struct g2d_context *ctx) +drm_public void g2d_fini(struct g2d_context *ctx) { free(ctx); } @@ -405,7 +400,7 @@ void g2d_fini(struct g2d_context *ctx) * @ctx: a pointer to g2d_context structure. * @userdata: a pointer to the user data */ -void g2d_config_event(struct g2d_context *ctx, void *userdata) +drm_public void g2d_config_event(struct g2d_context *ctx, void *userdata) { ctx->event_userdata = userdata; } @@ -415,7 +410,7 @@ void g2d_config_event(struct g2d_context *ctx, void *userdata) * * @ctx: a pointer to g2d_context structure. */ -int g2d_exec(struct g2d_context *ctx) +drm_public int g2d_exec(struct g2d_context *ctx) { struct drm_exynos_g2d_exec exec; int ret; @@ -447,7 +442,7 @@ int g2d_exec(struct g2d_context *ctx) * @w: width value to buffer filled with given color data. * @h: height value to buffer filled with given color data. */ -int +drm_public int g2d_solid_fill(struct g2d_context *ctx, struct g2d_image *img, unsigned int x, unsigned int y, unsigned int w, unsigned int h) @@ -500,7 +495,7 @@ g2d_solid_fill(struct g2d_context *ctx, struct g2d_image *img, * @w: width value to source and destination buffers. * @h: height value to source and destination buffers. */ -int +drm_public int g2d_copy(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int dst_x, unsigned dst_y, unsigned int w, @@ -583,7 +578,7 @@ g2d_copy(struct g2d_context *ctx, struct g2d_image *src, * @w: width of rectangle to move. * @h: height of rectangle to move. */ -int +drm_public int g2d_move(struct g2d_context *ctx, struct g2d_image *img, unsigned int src_x, unsigned int src_y, unsigned int dst_x, unsigned dst_y, unsigned int w, @@ -681,7 +676,7 @@ g2d_move(struct g2d_context *ctx, struct g2d_image *img, * @negative: indicate that it uses color negative to source and * destination buffers. */ -int +drm_public int g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int src_w, @@ -790,7 +785,7 @@ g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src, * @h: height value to source and destination buffer. * @op: blend operation type. */ -int +drm_public int g2d_blend(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int dst_x, unsigned int dst_y, @@ -907,7 +902,7 @@ g2d_blend(struct g2d_context *ctx, struct g2d_image *src, * @dst_h: height value to destination buffer. * @op: blend operation type. */ -int +drm_public int g2d_scale_and_blend(struct g2d_context *ctx, struct g2d_image *src, struct g2d_image *dst, unsigned int src_x, unsigned int src_y, unsigned int src_w, unsigned int src_h, unsigned int dst_x, diff --git a/exynos/exynos_fimg2d.h b/exynos/exynos_fimg2d.h index a825c683..a4dfbe73 100644 --- a/exynos/exynos_fimg2d.h +++ b/exynos/exynos_fimg2d.h @@ -3,11 +3,24 @@ * Authors: * Inki Dae <inki.dae@samsung.com> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _FIMG2D_H_ diff --git a/exynos/fimg2d_reg.h b/exynos/fimg2d_reg.h index 07dd6349..d42296d4 100644 --- a/exynos/fimg2d_reg.h +++ b/exynos/fimg2d_reg.h @@ -3,11 +3,24 @@ * Authors: * Inki Dae <inki.dae@samsung.com> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _FIMG2D_REG_H_ diff --git a/exynos/meson.build b/exynos/meson.build new file mode 100644 index 00000000..bdfc3fc6 --- /dev/null +++ b/exynos/meson.build @@ -0,0 +1,54 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libdrm_exynos = shared_library( + 'drm_exynos', + [files('exynos_drm.c', 'exynos_fimg2d.c'), config_file], + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm], + link_with : libdrm, + dependencies : [dep_pthread_stubs], + version : '1.0.0', + install : true, +) + +install_headers('exynos_drmif.h', subdir : 'libdrm') +install_headers('exynos_drm.h', 'exynos_fimg2d.h', subdir : 'exynos') + +ext_libdrm_exynos = declare_dependency( + link_with : [libdrm, libdrm_exynos], + include_directories : [inc_drm, include_directories('.')], +) + +pkg.generate( + name : 'libdrm_exynos', + libraries : libdrm_exynos, + subdirs : ['.', 'libdrm', 'exynos'], + version : '0.7', + requires_private : 'libdrm', + description : 'Userspace interface to exynos kernel DRM services', +) + +test( + 'exynos-symbol-check', + prog_bash, + env : env_test, + args : [files('exynos-symbol-check'), libdrm_exynos] +) diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am index 0771d146..37845035 100644 --- a/freedreno/Makefile.am +++ b/freedreno/Makefile.am @@ -3,8 +3,10 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ + $(VALGRIND_CFLAGS) \ -I$(top_srcdir)/include/drm libdrm_freedreno_la_LTLIBRARIES = libdrm_freedreno.la @@ -26,5 +28,6 @@ libdrm_freedrenocommoninclude_HEADERS = $(LIBDRM_FREEDRENO_H_FILES) pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_freedreno.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = freedreno-symbol-check EXTRA_DIST = $(TESTS) diff --git a/freedreno/Makefile.sources b/freedreno/Makefile.sources index 68a679bf..ca89511a 100644 --- a/freedreno/Makefile.sources +++ b/freedreno/Makefile.sources @@ -7,7 +7,6 @@ LIBDRM_FREEDRENO_FILES := \ freedreno_bo_cache.c \ msm/msm_bo.c \ msm/msm_device.c \ - msm/msm_drm.h \ msm/msm_pipe.c \ msm/msm_priv.h \ msm/msm_ringbuffer.c diff --git a/freedreno/freedreno-symbol-check b/freedreno/freedreno-symbol-check index 42f2c439..978026c0 100755 --- a/freedreno/freedreno-symbol-check +++ b/freedreno/freedreno-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.sources/LIBDRM_FREEDRENO_H_FILES -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_freedreno.so} | awk '{print $3}'| while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_freedreno.so} | awk '{print $3}'| while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata @@ -18,10 +20,12 @@ fd_bo_from_dmabuf fd_bo_from_fbdev fd_bo_from_handle fd_bo_from_name +fd_bo_get_iova fd_bo_get_name fd_bo_handle fd_bo_map fd_bo_new +fd_bo_put_iova fd_bo_ref fd_bo_size fd_device_del @@ -33,6 +37,8 @@ fd_device_version fd_pipe_del fd_pipe_get_param fd_pipe_new +fd_pipe_new2 +fd_pipe_ref fd_pipe_wait fd_pipe_wait_timeout fd_ringbuffer_cmd_count @@ -42,17 +48,16 @@ fd_ringbuffer_emit_reloc_ring_full fd_ringbuffer_flush fd_ringbuffer_grow fd_ringbuffer_new +fd_ringbuffer_new_flags +fd_ringbuffer_new_object +fd_ringbuffer_ref fd_ringbuffer_reloc fd_ringbuffer_reloc2 fd_ringbuffer_reset fd_ringbuffer_set_parent +fd_ringbuffer_size fd_ringbuffer_timestamp -fd_ringmarker_del -fd_ringmarker_dwords -fd_ringmarker_flush fd_ringbuffer_flush2 -fd_ringmarker_mark -fd_ringmarker_new EOF done) diff --git a/freedreno/freedreno_bo.c b/freedreno/freedreno_bo.c index 996d6b95..efc5b71f 100644 --- a/freedreno/freedreno_bo.c +++ b/freedreno/freedreno_bo.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "freedreno_drmif.h" #include "freedreno_priv.h" @@ -82,14 +78,15 @@ static struct fd_bo * bo_from_handle(struct fd_device *dev, return bo; } -struct fd_bo * -fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) +static struct fd_bo * +bo_new(struct fd_device *dev, uint32_t size, uint32_t flags, + struct fd_bo_cache *cache) { struct fd_bo *bo = NULL; uint32_t handle; int ret; - bo = fd_bo_cache_alloc(&dev->bo_cache, &size, flags); + bo = fd_bo_cache_alloc(cache, &size, flags); if (bo) return bo; @@ -99,13 +96,37 @@ fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) pthread_mutex_lock(&table_lock); bo = bo_from_handle(dev, size, handle); - bo->bo_reuse = TRUE; pthread_mutex_unlock(&table_lock); + VG_BO_ALLOC(bo); + return bo; } -struct fd_bo * +drm_public struct fd_bo * +fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) +{ + struct fd_bo *bo = bo_new(dev, size, flags, &dev->bo_cache); + if (bo) + bo->bo_reuse = BO_CACHE; + return bo; +} + +/* internal function to allocate bo's that use the ringbuffer cache + * instead of the normal bo_cache. The purpose is, because cmdstream + * bo's get vmap'd on the kernel side, and that is expensive, we want + * to re-use cmdstream bo's for cmdstream and not unrelated purposes. + */ +drm_private struct fd_bo * +fd_bo_new_ring(struct fd_device *dev, uint32_t size, uint32_t flags) +{ + struct fd_bo *bo = bo_new(dev, size, flags, &dev->ring_cache); + if (bo) + bo->bo_reuse = RING_CACHE; + return bo; +} + +drm_public struct fd_bo * fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size) { struct fd_bo *bo = NULL; @@ -118,13 +139,15 @@ fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size) bo = bo_from_handle(dev, size, handle); + VG_BO_ALLOC(bo); + out_unlock: pthread_mutex_unlock(&table_lock); return bo; } -struct fd_bo * +drm_public struct fd_bo * fd_bo_from_dmabuf(struct fd_device *dev, int fd) { int ret, size; @@ -134,6 +157,7 @@ fd_bo_from_dmabuf(struct fd_device *dev, int fd) pthread_mutex_lock(&table_lock); ret = drmPrimeFDToHandle(dev->fd, fd, &handle); if (ret) { + pthread_mutex_unlock(&table_lock); return NULL; } @@ -147,13 +171,15 @@ fd_bo_from_dmabuf(struct fd_device *dev, int fd) bo = bo_from_handle(dev, size, handle); + VG_BO_ALLOC(bo); + out_unlock: pthread_mutex_unlock(&table_lock); return bo; } -struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name) +drm_public struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name) { struct drm_gem_open req = { .name = name, @@ -177,8 +203,10 @@ struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name) goto out_unlock; bo = bo_from_handle(dev, req.size, req.handle); - if (bo) + if (bo) { set_name(bo, name); + VG_BO_ALLOC(bo); + } out_unlock: pthread_mutex_unlock(&table_lock); @@ -186,13 +214,23 @@ out_unlock: return bo; } -struct fd_bo * fd_bo_ref(struct fd_bo *bo) +drm_public uint64_t fd_bo_get_iova(struct fd_bo *bo) +{ + return bo->funcs->iova(bo); +} + +drm_public void fd_bo_put_iova(struct fd_bo *bo) +{ + /* currently a no-op */ +} + +drm_public struct fd_bo * fd_bo_ref(struct fd_bo *bo) { atomic_inc(&bo->refcnt); return bo; } -void fd_bo_del(struct fd_bo *bo) +drm_public void fd_bo_del(struct fd_bo *bo) { struct fd_device *dev = bo->dev; @@ -201,7 +239,9 @@ void fd_bo_del(struct fd_bo *bo) pthread_mutex_lock(&table_lock); - if (bo->bo_reuse && (fd_bo_cache_free(&dev->bo_cache, bo) == 0)) + if ((bo->bo_reuse == BO_CACHE) && (fd_bo_cache_free(&dev->bo_cache, bo) == 0)) + goto out; + if ((bo->bo_reuse == RING_CACHE) && (fd_bo_cache_free(&dev->ring_cache, bo) == 0)) goto out; bo_del(bo); @@ -213,6 +253,8 @@ out: /* Called under table_lock */ drm_private void bo_del(struct fd_bo *bo) { + VG_BO_FREE(bo); + if (bo->map) drm_munmap(bo->map, bo->size); @@ -233,7 +275,7 @@ drm_private void bo_del(struct fd_bo *bo) bo->funcs->destroy(bo); } -int fd_bo_get_name(struct fd_bo *bo, uint32_t *name) +drm_public int fd_bo_get_name(struct fd_bo *bo, uint32_t *name) { if (!bo->name) { struct drm_gem_flink req = { @@ -249,7 +291,7 @@ int fd_bo_get_name(struct fd_bo *bo, uint32_t *name) pthread_mutex_lock(&table_lock); set_name(bo, req.name); pthread_mutex_unlock(&table_lock); - bo->bo_reuse = FALSE; + bo->bo_reuse = NO_CACHE; } *name = bo->name; @@ -257,12 +299,12 @@ int fd_bo_get_name(struct fd_bo *bo, uint32_t *name) return 0; } -uint32_t fd_bo_handle(struct fd_bo *bo) +drm_public uint32_t fd_bo_handle(struct fd_bo *bo) { return bo->handle; } -int fd_bo_dmabuf(struct fd_bo *bo) +drm_public int fd_bo_dmabuf(struct fd_bo *bo) { int ret, prime_fd; @@ -273,17 +315,17 @@ int fd_bo_dmabuf(struct fd_bo *bo) return ret; } - bo->bo_reuse = FALSE; + bo->bo_reuse = NO_CACHE; return prime_fd; } -uint32_t fd_bo_size(struct fd_bo *bo) +drm_public uint32_t fd_bo_size(struct fd_bo *bo) { return bo->size; } -void * fd_bo_map(struct fd_bo *bo) +drm_public void * fd_bo_map(struct fd_bo *bo) { if (!bo->map) { uint64_t offset; @@ -305,18 +347,18 @@ void * fd_bo_map(struct fd_bo *bo) } /* a bit odd to take the pipe as an arg, but it's a, umm, quirk of kgsl.. */ -int fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op) +drm_public int fd_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op) { return bo->funcs->cpu_prep(bo, pipe, op); } -void fd_bo_cpu_fini(struct fd_bo *bo) +drm_public void fd_bo_cpu_fini(struct fd_bo *bo) { bo->funcs->cpu_fini(bo); } -#ifndef HAVE_FREEDRENO_KGSL -struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe, int fbfd, uint32_t size) +#if !HAVE_FREEDRENO_KGSL +drm_public struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe, int fbfd, uint32_t size) { return NULL; } diff --git a/freedreno/freedreno_bo_cache.c b/freedreno/freedreno_bo_cache.c index 7becb0d6..bb0605ab 100644 --- a/freedreno/freedreno_bo_cache.c +++ b/freedreno/freedreno_bo_cache.c @@ -26,14 +26,9 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "freedreno_drmif.h" #include "freedreno_priv.h" - drm_private void bo_del(struct fd_bo *bo); drm_private extern pthread_mutex_t table_lock; @@ -54,7 +49,7 @@ add_bucket(struct fd_bo_cache *cache, int size) * fill in for a bit smoother size curve.. */ drm_private void -fd_bo_cache_init(struct fd_bo_cache *cache, int course) +fd_bo_cache_init(struct fd_bo_cache *cache, int coarse) { unsigned long size, cache_max_size = 64 * 1024 * 1024; @@ -68,13 +63,13 @@ fd_bo_cache_init(struct fd_bo_cache *cache, int course) */ add_bucket(cache, 4096); add_bucket(cache, 4096 * 2); - if (!course) + if (!coarse) add_bucket(cache, 4096 * 3); /* Initialize the linked lists for BO reuse cache. */ for (size = 4 * 4096; size <= cache_max_size; size *= 2) { add_bucket(cache, size); - if (!course) { + if (!coarse) { add_bucket(cache, size + size * 1 / 4); add_bucket(cache, size + size * 2 / 4); add_bucket(cache, size + size * 3 / 4); @@ -102,6 +97,7 @@ fd_bo_cache_cleanup(struct fd_bo_cache *cache, time_t time) if (time && ((time - bo->free_time) <= 1)) break; + VG_BO_OBTAIN(bo); list_del(&bo->list); bo_del(bo); } @@ -177,6 +173,7 @@ retry: *size = bucket->size; bo = find_in_bucket(bucket, flags); if (bo) { + VG_BO_OBTAIN(bo); if (bo->funcs->madvise(bo, TRUE) <= 0) { /* we've lost the backing pages, delete and try again: */ pthread_mutex_lock(&table_lock); @@ -207,6 +204,7 @@ fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo) clock_gettime(CLOCK_MONOTONIC, &time); bo->free_time = time.tv_sec; + VG_BO_RELEASE(bo); list_addtail(&bo->list, &bucket->list); fd_bo_cache_cleanup(cache, time.tv_sec); diff --git a/freedreno/freedreno_device.c b/freedreno/freedreno_device.c index fcbf1402..ac234304 100644 --- a/freedreno/freedreno_device.c +++ b/freedreno/freedreno_device.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -42,7 +38,7 @@ static pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER; struct fd_device * kgsl_device_new(int fd); struct fd_device * msm_device_new(int fd); -struct fd_device * fd_device_new(int fd) +drm_public struct fd_device * fd_device_new(int fd) { struct fd_device *dev; drmVersionPtr version; @@ -65,7 +61,7 @@ struct fd_device * fd_device_new(int fd) dev = msm_device_new(fd); dev->version = version->version_minor; -#ifdef HAVE_FREEDRENO_KGSL +#if HAVE_FREEDRENO_KGSL } else if (!strcmp(version->name, "kgsl")) { DEBUG_MSG("kgsl DRM device"); dev = kgsl_device_new(fd); @@ -86,6 +82,7 @@ out: dev->handle_table = drmHashCreate(); dev->name_table = drmHashCreate(); fd_bo_cache_init(&dev->bo_cache, FALSE); + fd_bo_cache_init(&dev->ring_cache, TRUE); return dev; } @@ -93,7 +90,7 @@ out: /* like fd_device_new() but creates it's own private dup() of the fd * which is close()d when the device is finalized. */ -struct fd_device * fd_device_new_dup(int fd) +drm_public struct fd_device * fd_device_new_dup(int fd) { int dup_fd = dup(fd); struct fd_device *dev = fd_device_new(dup_fd); @@ -104,7 +101,7 @@ struct fd_device * fd_device_new_dup(int fd) return dev; } -struct fd_device * fd_device_ref(struct fd_device *dev) +drm_public struct fd_device * fd_device_ref(struct fd_device *dev) { atomic_inc(&dev->refcnt); return dev; @@ -112,12 +109,13 @@ struct fd_device * fd_device_ref(struct fd_device *dev) static void fd_device_del_impl(struct fd_device *dev) { + int close_fd = dev->closefd ? dev->fd : -1; fd_bo_cache_cleanup(&dev->bo_cache, 0); drmHashDestroy(dev->handle_table); drmHashDestroy(dev->name_table); - if (dev->closefd) - close(dev->fd); dev->funcs->destroy(dev); + if (close_fd >= 0) + close(close_fd); } drm_private void fd_device_del_locked(struct fd_device *dev) @@ -127,7 +125,7 @@ drm_private void fd_device_del_locked(struct fd_device *dev) fd_device_del_impl(dev); } -void fd_device_del(struct fd_device *dev) +drm_public void fd_device_del(struct fd_device *dev) { if (!atomic_dec_and_test(&dev->refcnt)) return; @@ -136,12 +134,12 @@ void fd_device_del(struct fd_device *dev) pthread_mutex_unlock(&table_lock); } -int fd_device_fd(struct fd_device *dev) +drm_public int fd_device_fd(struct fd_device *dev) { return dev->fd; } -enum fd_version fd_device_version(struct fd_device *dev) +drm_public enum fd_version fd_device_version(struct fd_device *dev) { return dev->version; } diff --git a/freedreno/freedreno_drmif.h b/freedreno/freedreno_drmif.h index 7a8073ff..c95c21be 100644 --- a/freedreno/freedreno_drmif.h +++ b/freedreno/freedreno_drmif.h @@ -61,6 +61,7 @@ enum fd_param_id { FD_CHIP_ID, FD_MAX_FREQ, FD_TIMESTAMP, + FD_NR_RINGS, /* # of rings == # of distinct priority levels */ }; /* bo flags: */ @@ -93,6 +94,8 @@ enum fd_version { FD_VERSION_MADVISE = 1, /* kernel supports madvise */ FD_VERSION_UNLIMITED_CMDS = 1, /* submits w/ >4 cmd buffers (growable ringbuffer) */ FD_VERSION_FENCE_FD = 2, /* submit command supports in/out fences */ + FD_VERSION_SUBMIT_QUEUES = 3, /* submit queues and multiple priority levels */ + FD_VERSION_BO_IOVA = 3, /* supports fd_bo_get/put_iova() */ }; enum fd_version fd_device_version(struct fd_device *dev); @@ -100,6 +103,8 @@ enum fd_version fd_device_version(struct fd_device *dev); */ struct fd_pipe * fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id); +struct fd_pipe * fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio); +struct fd_pipe * fd_pipe_ref(struct fd_pipe *pipe); void fd_pipe_del(struct fd_pipe *pipe); int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value); @@ -120,6 +125,8 @@ struct fd_bo *fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size); struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name); struct fd_bo * fd_bo_from_dmabuf(struct fd_device *dev, int fd); +uint64_t fd_bo_get_iova(struct fd_bo *bo); +void fd_bo_put_iova(struct fd_bo *bo); struct fd_bo * fd_bo_ref(struct fd_bo *bo); void fd_bo_del(struct fd_bo *bo); int fd_bo_get_name(struct fd_bo *bo, uint32_t *name); diff --git a/freedreno/freedreno_pipe.c b/freedreno/freedreno_pipe.c index 3f8c8342..e82e6448 100644 --- a/freedreno/freedreno_pipe.c +++ b/freedreno/freedreno_pipe.c @@ -26,60 +26,76 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "freedreno_drmif.h" #include "freedreno_priv.h" -struct fd_pipe * -fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id) +/** + * priority of zero is highest priority, and higher numeric values are + * lower priorities + */ +drm_public struct fd_pipe * +fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio) { - struct fd_pipe *pipe = NULL; + struct fd_pipe *pipe; uint64_t val; if (id > FD_PIPE_MAX) { ERROR_MSG("invalid pipe id: %d", id); - goto fail; + return NULL; } - pipe = dev->funcs->pipe_new(dev, id); + if ((prio != 1) && (fd_device_version(dev) < FD_VERSION_SUBMIT_QUEUES)) { + ERROR_MSG("invalid priority!"); + return NULL; + } + + pipe = dev->funcs->pipe_new(dev, id, prio); if (!pipe) { ERROR_MSG("allocation failed"); - goto fail; + return NULL; } pipe->dev = dev; pipe->id = id; + atomic_set(&pipe->refcnt, 1); fd_pipe_get_param(pipe, FD_GPU_ID, &val); pipe->gpu_id = val; return pipe; -fail: - if (pipe) - fd_pipe_del(pipe); - return NULL; } -void fd_pipe_del(struct fd_pipe *pipe) +drm_public struct fd_pipe * +fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id) +{ + return fd_pipe_new2(dev, id, 1); +} + +drm_public struct fd_pipe * fd_pipe_ref(struct fd_pipe *pipe) +{ + atomic_inc(&pipe->refcnt); + return pipe; +} + +drm_public void fd_pipe_del(struct fd_pipe *pipe) { + if (!atomic_dec_and_test(&pipe->refcnt)) + return; pipe->funcs->destroy(pipe); } -int fd_pipe_get_param(struct fd_pipe *pipe, +drm_public int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value) { return pipe->funcs->get_param(pipe, param, value); } -int fd_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp) +drm_public int fd_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp) { return fd_pipe_wait_timeout(pipe, timestamp, ~0); } -int fd_pipe_wait_timeout(struct fd_pipe *pipe, uint32_t timestamp, +drm_public int fd_pipe_wait_timeout(struct fd_pipe *pipe, uint32_t timestamp, uint64_t timeout) { return pipe->funcs->wait(pipe, timestamp, timeout); diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h index 32170391..b8eac4b2 100644 --- a/freedreno/freedreno_priv.h +++ b/freedreno/freedreno_priv.h @@ -29,10 +29,6 @@ #ifndef FREEDRENO_PRIV_H_ #define FREEDRENO_PRIV_H_ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <errno.h> #include <string.h> @@ -49,6 +45,7 @@ #include "xf86atomic.h" #include "util_double_list.h" +#include "util_math.h" #include "freedreno_drmif.h" #include "freedreno_ringbuffer.h" @@ -66,7 +63,8 @@ struct fd_device_funcs { uint32_t flags, uint32_t *handle); struct fd_bo * (*bo_from_handle)(struct fd_device *dev, uint32_t size, uint32_t handle); - struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id); + struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id, + unsigned prio); void (*destroy)(struct fd_device *dev); }; @@ -100,8 +98,12 @@ struct fd_device { const struct fd_device_funcs *funcs; struct fd_bo_cache bo_cache; + struct fd_bo_cache ring_cache; int closefd; /* call close(fd) upon destruction */ + + /* just for valgrind: */ + int bo_size; }; drm_private void fd_bo_cache_init(struct fd_bo_cache *cache, int coarse); @@ -114,7 +116,8 @@ drm_private int fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo); drm_private void fd_device_del_locked(struct fd_device *dev); struct fd_pipe_funcs { - struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size); + struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size, + enum fd_ringbuffer_flags flags); int (*get_param)(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value); int (*wait)(struct fd_pipe *pipe, uint32_t timestamp, uint64_t timeout); void (*destroy)(struct fd_pipe *pipe); @@ -124,14 +127,10 @@ struct fd_pipe { struct fd_device *dev; enum fd_pipe_id id; uint32_t gpu_id; + atomic_t refcnt; const struct fd_pipe_funcs *funcs; }; -struct fd_ringmarker { - struct fd_ringbuffer *ring; - uint32_t *cur; -}; - struct fd_ringbuffer_funcs { void * (*hostptr)(struct fd_ringbuffer *ring); int (*flush)(struct fd_ringbuffer *ring, uint32_t *last_start, @@ -141,8 +140,7 @@ struct fd_ringbuffer_funcs { void (*emit_reloc)(struct fd_ringbuffer *ring, const struct fd_reloc *reloc); uint32_t (*emit_reloc_ring)(struct fd_ringbuffer *ring, - struct fd_ringbuffer *target, uint32_t cmd_idx, - uint32_t submit_offset, uint32_t size); + struct fd_ringbuffer *target, uint32_t cmd_idx); uint32_t (*cmd_count)(struct fd_ringbuffer *ring); void (*destroy)(struct fd_ringbuffer *ring); }; @@ -152,6 +150,7 @@ struct fd_bo_funcs { int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op); void (*cpu_fini)(struct fd_bo *bo); int (*madvise)(struct fd_bo *bo, int willneed); + uint64_t (*iova)(struct fd_bo *bo); void (*destroy)(struct fd_bo *bo); }; @@ -164,12 +163,19 @@ struct fd_bo { atomic_t refcnt; const struct fd_bo_funcs *funcs; - int bo_reuse; + enum { + NO_CACHE = 0, + BO_CACHE = 1, + RING_CACHE = 2, + } bo_reuse; + struct list_head list; /* bucket-list entry */ time_t free_time; /* time when added to bucket-list */ }; -#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1)) +drm_private struct fd_bo *fd_bo_new_ring(struct fd_device *dev, + uint32_t size, uint32_t flags); + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define enable_debug 0 /* TODO make dynamic */ @@ -196,4 +202,57 @@ offset_bytes(void *end, void *start) return ((char *)end) - ((char *)start); } +#if HAVE_VALGRIND +# include <memcheck.h> + +/* + * For tracking the backing memory (if valgrind enabled, we force a mmap + * for the purposes of tracking) + */ +static inline void VG_BO_ALLOC(struct fd_bo *bo) +{ + if (bo && RUNNING_ON_VALGRIND) { + VALGRIND_MALLOCLIKE_BLOCK(fd_bo_map(bo), bo->size, 0, 1); + } +} + +static inline void VG_BO_FREE(struct fd_bo *bo) +{ + VALGRIND_FREELIKE_BLOCK(bo->map, 0); +} + +/* + * For tracking bo structs that are in the buffer-cache, so that valgrind + * doesn't attribute ownership to the first one to allocate the recycled + * bo. + * + * Note that the list_head in fd_bo is used to track the buffers in cache + * so disable error reporting on the range while they are in cache so + * valgrind doesn't squawk about list traversal. + * + */ +static inline void VG_BO_RELEASE(struct fd_bo *bo) +{ + if (RUNNING_ON_VALGRIND) { + VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size); + VALGRIND_MAKE_MEM_NOACCESS(bo, bo->dev->bo_size); + VALGRIND_FREELIKE_BLOCK(bo->map, 0); + } +} +static inline void VG_BO_OBTAIN(struct fd_bo *bo) +{ + if (RUNNING_ON_VALGRIND) { + VALGRIND_MAKE_MEM_DEFINED(bo, bo->dev->bo_size); + VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size); + VALGRIND_MALLOCLIKE_BLOCK(bo->map, bo->size, 0, 1); + } +} +#else +static inline void VG_BO_ALLOC(struct fd_bo *bo) {} +static inline void VG_BO_FREE(struct fd_bo *bo) {} +static inline void VG_BO_RELEASE(struct fd_bo *bo) {} +static inline void VG_BO_OBTAIN(struct fd_bo *bo) {} +#endif + + #endif /* FREEDRENO_PRIV_H_ */ diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c index 7310f1fd..8f0093ae 100644 --- a/freedreno/freedreno_ringbuffer.c +++ b/freedreno/freedreno_ringbuffer.c @@ -26,25 +26,30 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <assert.h> #include "freedreno_drmif.h" #include "freedreno_priv.h" #include "freedreno_ringbuffer.h" -struct fd_ringbuffer * -fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) +drm_public struct fd_ringbuffer * +fd_ringbuffer_new_flags(struct fd_pipe *pipe, uint32_t size, + enum fd_ringbuffer_flags flags) { struct fd_ringbuffer *ring; - ring = pipe->funcs->ringbuffer_new(pipe, size); + /* we can't really support "growable" rb's in general for + * stateobj's since we need a single gpu addr (ie. can't + * do the trick of a chain of IB packets): + */ + if (flags & FD_RINGBUFFER_OBJECT) + assert(size); + + ring = pipe->funcs->ringbuffer_new(pipe, size, flags); if (!ring) return NULL; + ring->flags = flags; ring->pipe = pipe; ring->start = ring->funcs->hostptr(ring); ring->end = &(ring->start[ring->size/4]); @@ -54,23 +59,48 @@ fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) return ring; } -void fd_ringbuffer_del(struct fd_ringbuffer *ring) +drm_public struct fd_ringbuffer * +fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size) +{ + return fd_ringbuffer_new_flags(pipe, size, 0); +} + +drm_public struct fd_ringbuffer * +fd_ringbuffer_new_object(struct fd_pipe *pipe, uint32_t size) +{ + return fd_ringbuffer_new_flags(pipe, size, FD_RINGBUFFER_OBJECT); +} + +drm_public void fd_ringbuffer_del(struct fd_ringbuffer *ring) { + if (!atomic_dec_and_test(&ring->refcnt)) + return; + fd_ringbuffer_reset(ring); ring->funcs->destroy(ring); } +drm_public struct fd_ringbuffer * +fd_ringbuffer_ref(struct fd_ringbuffer *ring) +{ + STATIC_ASSERT(sizeof(ring->refcnt) <= sizeof(ring->__pad)); + atomic_inc(&ring->refcnt); + return ring; +} + /* ringbuffers which are IB targets should set the toplevel rb (ie. * the IB source) as it's parent before emitting reloc's, to ensure * the bookkeeping works out properly. */ -void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, +drm_public void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, struct fd_ringbuffer *parent) { + /* state objects should not be parented! */ + assert(!(ring->flags & FD_RINGBUFFER_OBJECT)); ring->parent = parent; } -void fd_ringbuffer_reset(struct fd_ringbuffer *ring) +drm_public void fd_ringbuffer_reset(struct fd_ringbuffer *ring) { uint32_t *start = ring->start; if (ring->pipe->id == FD_PIPE_2D) @@ -80,18 +110,18 @@ void fd_ringbuffer_reset(struct fd_ringbuffer *ring) ring->funcs->reset(ring); } -int fd_ringbuffer_flush(struct fd_ringbuffer *ring) +drm_public int fd_ringbuffer_flush(struct fd_ringbuffer *ring) { return ring->funcs->flush(ring, ring->last_start, -1, NULL); } -int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd, +drm_public int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd, int *out_fence_fd) { return ring->funcs->flush(ring, ring->last_start, in_fence_fd, out_fence_fd); } -void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords) +drm_public void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords) { assert(ring->funcs->grow); /* unsupported on kgsl */ @@ -107,89 +137,46 @@ void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords) ring->cur = ring->last_start = ring->start; } -uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring) +drm_public uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring) { return ring->last_timestamp; } -void fd_ringbuffer_reloc(struct fd_ringbuffer *ring, +drm_public void fd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc) { assert(ring->pipe->gpu_id < 500); ring->funcs->emit_reloc(ring, reloc); } -void fd_ringbuffer_reloc2(struct fd_ringbuffer *ring, +drm_public void fd_ringbuffer_reloc2(struct fd_ringbuffer *ring, const struct fd_reloc *reloc) { ring->funcs->emit_reloc(ring, reloc); } -void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, - struct fd_ringmarker *target, struct fd_ringmarker *end) -{ - uint32_t submit_offset, size; - - /* This function is deprecated and not supported on 64b devices: */ - assert(ring->pipe->gpu_id < 500); - assert(target->ring == end->ring); - - submit_offset = offset_bytes(target->cur, target->ring->start); - size = offset_bytes(end->cur, target->cur); - - ring->funcs->emit_reloc_ring(ring, target->ring, 0, submit_offset, size); -} - -uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring) +drm_public uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring) { if (!ring->funcs->cmd_count) return 1; return ring->funcs->cmd_count(ring); } -uint32_t +drm_public uint32_t fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, struct fd_ringbuffer *target, uint32_t cmd_idx) { - uint32_t size = offset_bytes(target->cur, target->start); - return ring->funcs->emit_reloc_ring(ring, target, cmd_idx, 0, size); + return ring->funcs->emit_reloc_ring(ring, target, cmd_idx); } -struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring) +drm_public uint32_t +fd_ringbuffer_size(struct fd_ringbuffer *ring) { - struct fd_ringmarker *marker = NULL; - - marker = calloc(1, sizeof(*marker)); - if (!marker) { - ERROR_MSG("allocation failed"); - return NULL; - } - - marker->ring = ring; - - marker->cur = marker->ring->cur; - - return marker; + /* only really needed for stateobj ringbuffers, and won't really + * do what you expect for growable rb's.. so lets just restrict + * this to stateobj's for now: + */ + assert(ring->flags & FD_RINGBUFFER_OBJECT); + return offset_bytes(ring->cur, ring->start); } -void fd_ringmarker_del(struct fd_ringmarker *marker) -{ - free(marker); -} - -void fd_ringmarker_mark(struct fd_ringmarker *marker) -{ - marker->cur = marker->ring->cur; -} - -uint32_t fd_ringmarker_dwords(struct fd_ringmarker *start, - struct fd_ringmarker *end) -{ - return end->cur - start->cur; -} - -int fd_ringmarker_flush(struct fd_ringmarker *marker) -{ - struct fd_ringbuffer *ring = marker->ring; - return ring->funcs->flush(ring, marker->cur, -1, NULL); -} diff --git a/freedreno/freedreno_ringbuffer.h b/freedreno/freedreno_ringbuffer.h index c501fbad..bc41a31c 100644 --- a/freedreno/freedreno_ringbuffer.h +++ b/freedreno/freedreno_ringbuffer.h @@ -33,12 +33,33 @@ /* the ringbuffer object is not opaque so that OUT_RING() type stuff * can be inlined. Note that users should not make assumptions about - * the size of this struct.. more stuff will be added when we eventually - * have a kernel driver that can deal w/ reloc's.. + * the size of this struct. */ struct fd_ringbuffer_funcs; -struct fd_ringmarker; + +enum fd_ringbuffer_flags { + + /* Ringbuffer is a "state object", which is potentially reused + * many times, rather than being used in one-shot mode linked + * to a parent ringbuffer. + */ + FD_RINGBUFFER_OBJECT = 0x1, + + /* Hint that the stateobj will be used for streaming state + * that is used once or a few times and then discarded. + * + * For sub-allocation, non streaming stateobj's should be + * sub-allocated from a page size buffer, so one long lived + * state obj doesn't prevent other pages from being freed. + * (Ie. it would be no worse than allocating a page sized + * bo for each small non-streaming stateobj). + * + * But streaming stateobj's could be sub-allocated from a + * larger buffer to reduce the alloc/del overhead. + */ + FD_RINGBUFFER_STREAMING = 0x2, +}; struct fd_ringbuffer { int size; @@ -47,13 +68,41 @@ struct fd_ringbuffer { const struct fd_ringbuffer_funcs *funcs; uint32_t last_timestamp; struct fd_ringbuffer *parent; + + /* for users of fd_ringbuffer to store their own private per- + * ringbuffer data + */ + void *user; + + enum fd_ringbuffer_flags flags; + + /* This is a bit gross, but we can't use atomic_t in exported + * headers. OTOH, we don't need the refcnt to be publicly + * visible. The only reason that this struct is exported is + * because fd_ringbuffer_emit needs to be something that can + * be inlined for performance reasons. + */ + union { +#ifdef HAS_ATOMIC_OPS + atomic_t refcnt; +#endif + uint64_t __pad; + }; }; struct fd_ringbuffer * fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size); +will_be_deprecated +struct fd_ringbuffer * fd_ringbuffer_new_object(struct fd_pipe *pipe, + uint32_t size); +struct fd_ringbuffer * fd_ringbuffer_new_flags(struct fd_pipe *pipe, + uint32_t size, enum fd_ringbuffer_flags flags); + +struct fd_ringbuffer *fd_ringbuffer_ref(struct fd_ringbuffer *ring); void fd_ringbuffer_del(struct fd_ringbuffer *ring); void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, struct fd_ringbuffer *parent); +will_be_deprecated void fd_ringbuffer_reset(struct fd_ringbuffer *ring); int fd_ringbuffer_flush(struct fd_ringbuffer *ring); /* in_fence_fd: -1 for no in-fence, else fence fd @@ -85,17 +134,9 @@ struct fd_reloc { void fd_ringbuffer_reloc2(struct fd_ringbuffer *ring, const struct fd_reloc *reloc); will_be_deprecated void fd_ringbuffer_reloc(struct fd_ringbuffer *ring, const struct fd_reloc *reloc); -will_be_deprecated void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, - struct fd_ringmarker *target, struct fd_ringmarker *end); uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring); uint32_t fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring, struct fd_ringbuffer *target, uint32_t cmd_idx); - -will_be_deprecated struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring); -will_be_deprecated void fd_ringmarker_del(struct fd_ringmarker *marker); -will_be_deprecated void fd_ringmarker_mark(struct fd_ringmarker *marker); -will_be_deprecated uint32_t fd_ringmarker_dwords(struct fd_ringmarker *start, - struct fd_ringmarker *end); -will_be_deprecated int fd_ringmarker_flush(struct fd_ringmarker *marker); +uint32_t fd_ringbuffer_size(struct fd_ringbuffer *ring); #endif /* FREEDRENO_RINGBUFFER_H_ */ diff --git a/freedreno/kgsl/kgsl_bo.c b/freedreno/kgsl/kgsl_bo.c index ab3485e3..7a6af2f0 100644 --- a/freedreno/kgsl/kgsl_bo.c +++ b/freedreno/kgsl/kgsl_bo.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "kgsl_priv.h" #include <linux/fb.h> @@ -181,7 +177,7 @@ drm_private struct fd_bo * kgsl_bo_from_handle(struct fd_device *dev, return bo; } -struct fd_bo * +drm_public struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe, int fbfd, uint32_t size) { struct fd_bo *bo; diff --git a/freedreno/kgsl/kgsl_device.c b/freedreno/kgsl/kgsl_device.c index 175e8378..914f3412 100644 --- a/freedreno/kgsl/kgsl_device.c +++ b/freedreno/kgsl/kgsl_device.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -61,5 +57,7 @@ drm_private struct fd_device * kgsl_device_new(int fd) dev = &kgsl_dev->base; dev->funcs = &funcs; + dev->bo_size = sizeof(struct kgsl_bo); + return dev; } diff --git a/freedreno/kgsl/kgsl_pipe.c b/freedreno/kgsl/kgsl_pipe.c index 8a39eb49..0a8b6586 100644 --- a/freedreno/kgsl/kgsl_pipe.c +++ b/freedreno/kgsl/kgsl_pipe.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "kgsl_priv.h" @@ -52,6 +48,7 @@ static int kgsl_pipe_get_param(struct fd_pipe *pipe, return 0; case FD_MAX_FREQ: case FD_TIMESTAMP: + case FD_NR_RINGS: /* unsupported on kgsl */ return -1; default: @@ -210,7 +207,7 @@ static int getprop(int fd, enum kgsl_property_type type, drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev, - enum fd_pipe_id id) + enum fd_pipe_id id, uint32_t prio) { static const char *paths[] = { [FD_PIPE_3D] = "/dev/kgsl-3d0", diff --git a/freedreno/kgsl/kgsl_priv.h b/freedreno/kgsl/kgsl_priv.h index 6ab64965..a6bf2d40 100644 --- a/freedreno/kgsl/kgsl_priv.h +++ b/freedreno/kgsl/kgsl_priv.h @@ -103,10 +103,10 @@ drm_private void kgsl_pipe_post_submit(struct kgsl_pipe *pipe, drm_private void kgsl_pipe_process_pending(struct kgsl_pipe *pipe, uint32_t timestamp); drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev, - enum fd_pipe_id id); + enum fd_pipe_id id, uint32_t prio); drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size); + uint32_t size, enum fd_ringbuffer_flags flags); drm_private int kgsl_bo_new_handle(struct fd_device *dev, uint32_t size, uint32_t flags, uint32_t *handle); diff --git a/freedreno/kgsl/kgsl_ringbuffer.c b/freedreno/kgsl/kgsl_ringbuffer.c index e4696b1b..9abf0adf 100644 --- a/freedreno/kgsl/kgsl_ringbuffer.c +++ b/freedreno/kgsl/kgsl_ringbuffer.c @@ -26,12 +26,9 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <assert.h> +#include "xf86atomic.h" #include "freedreno_ringbuffer.h" #include "kgsl_priv.h" @@ -146,7 +143,7 @@ static int kgsl_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_star ibdesc.gpuaddr = kgsl_ring->bo->gpuaddr; ibdesc.hostptr = kgsl_ring->bo->hostptr; ibdesc.sizedwords = 0x145; - req.timestamp = (uint32_t)kgsl_ring->bo->hostptr; + req.timestamp = (uintptr_t)kgsl_ring->bo->hostptr; } do { @@ -178,13 +175,12 @@ static void kgsl_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, } static uint32_t kgsl_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, - struct fd_ringbuffer *target, uint32_t cmd_idx, - uint32_t submit_offset, uint32_t size) + struct fd_ringbuffer *target, uint32_t cmd_idx) { struct kgsl_ringbuffer *target_ring = to_kgsl_ringbuffer(target); assert(cmd_idx == 0); - (*ring->cur++) = target_ring->bo->gpuaddr + submit_offset; - return size; + (*ring->cur++) = target_ring->bo->gpuaddr; + return offset_bytes(target->cur, target->start); } static void kgsl_ringbuffer_destroy(struct fd_ringbuffer *ring) @@ -206,11 +202,13 @@ static const struct fd_ringbuffer_funcs funcs = { }; drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size) + uint32_t size, enum fd_ringbuffer_flags flags) { struct kgsl_ringbuffer *kgsl_ring; struct fd_ringbuffer *ring = NULL; + assert(!flags); + kgsl_ring = calloc(1, sizeof(*kgsl_ring)); if (!kgsl_ring) { ERROR_MSG("allocation failed"); @@ -218,6 +216,8 @@ drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe, } ring = &kgsl_ring->base; + atomic_set(&ring->refcnt, 1); + ring->funcs = &funcs; ring->size = size; diff --git a/freedreno/meson.build b/freedreno/meson.build new file mode 100644 index 00000000..c9aba060 --- /dev/null +++ b/freedreno/meson.build @@ -0,0 +1,77 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +files_freedreno = files( + 'freedreno_device.c', + 'freedreno_pipe.c', + 'freedreno_ringbuffer.c', + 'freedreno_bo.c', + 'freedreno_bo_cache.c', + 'msm/msm_bo.c', + 'msm/msm_device.c', + 'msm/msm_pipe.c', + 'msm/msm_ringbuffer.c', +) + +if with_freedreno_kgsl + files_freedreno += files( + 'kgsl/kgsl_bo.c', + 'kgsl/kgsl_device.c', + 'kgsl/kgsl_pipe.c', + 'kgsl/kgsl_ringbuffer.c', + ) +endif + +libdrm_freedreno = shared_library( + 'drm_freedreno', + [files_freedreno, config_file], + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm], + dependencies : [dep_valgrind, dep_pthread_stubs, dep_rt, dep_atomic_ops], + link_with : libdrm, + version : '1.0.0', + install : true, +) + +ext_libdrm_freedreno = declare_dependency( + link_with : [libdrm, libdrm_freedreno], + include_directories : [inc_drm, include_directories('.')], +) + +install_headers( + 'freedreno_drmif.h', 'freedreno_ringbuffer.h', + subdir : 'freedreno' +) + +pkg.generate( + name : 'libdrm_freedreno', + libraries : libdrm_freedreno, + subdirs : ['.', 'libdrm', 'freedreno'], + version : meson.project_version(), + requires_private : 'libdrm', + description : 'Userspace interface to freedreno kernel DRM services', +) + +test( + 'freedreno-symbol-check', + prog_bash, + env : env_test, + args : [files('freedreno-symbol-check'), libdrm_freedreno] +) diff --git a/freedreno/msm/msm_bo.c b/freedreno/msm/msm_bo.c index 72471df6..8b3d0bcb 100644 --- a/freedreno/msm/msm_bo.c +++ b/freedreno/msm/msm_bo.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "msm_priv.h" static int bo_allocate(struct msm_bo *msm_bo) @@ -108,6 +104,18 @@ static int msm_bo_madvise(struct fd_bo *bo, int willneed) return req.retained; } +static uint64_t msm_bo_iova(struct fd_bo *bo) +{ + struct drm_msm_gem_info req = { + .handle = bo->handle, + .flags = MSM_INFO_IOVA, + }; + + drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req)); + + return req.offset; +} + static void msm_bo_destroy(struct fd_bo *bo) { struct msm_bo *msm_bo = to_msm_bo(bo); @@ -120,6 +128,7 @@ static const struct fd_bo_funcs funcs = { .cpu_prep = msm_bo_cpu_prep, .cpu_fini = msm_bo_cpu_fini, .madvise = msm_bo_madvise, + .iova = msm_bo_iova, .destroy = msm_bo_destroy, }; diff --git a/freedreno/msm/msm_device.c b/freedreno/msm/msm_device.c index 727baa44..58b0746d 100644 --- a/freedreno/msm/msm_device.c +++ b/freedreno/msm/msm_device.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -39,7 +35,6 @@ static void msm_device_destroy(struct fd_device *dev) { struct msm_device *msm_dev = to_msm_device(dev); - fd_bo_cache_cleanup(&msm_dev->ring_cache, 0); free(msm_dev); } @@ -62,7 +57,7 @@ drm_private struct fd_device * msm_device_new(int fd) dev = &msm_dev->base; dev->funcs = &funcs; - fd_bo_cache_init(&msm_dev->ring_cache, TRUE); + dev->bo_size = sizeof(struct msm_bo); return dev; } diff --git a/freedreno/msm/msm_pipe.c b/freedreno/msm/msm_pipe.c index f872e245..e070b317 100644 --- a/freedreno/msm/msm_pipe.c +++ b/freedreno/msm/msm_pipe.c @@ -26,10 +26,6 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include "msm_priv.h" static int query_param(struct fd_pipe *pipe, uint32_t param, @@ -71,6 +67,8 @@ static int msm_pipe_get_param(struct fd_pipe *pipe, return query_param(pipe, MSM_PARAM_MAX_FREQ, value); case FD_TIMESTAMP: return query_param(pipe, MSM_PARAM_TIMESTAMP, value); + case FD_NR_RINGS: + return query_param(pipe, MSM_PARAM_NR_RINGS, value); default: ERROR_MSG("invalid param id: %d", param); return -1; @@ -83,6 +81,7 @@ static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp, struct fd_device *dev = pipe->dev; struct drm_msm_wait_fence req = { .fence = timestamp, + .queueid = to_msm_pipe(pipe)->queue_id, }; int ret; @@ -97,9 +96,54 @@ static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp, return 0; } +static int open_submitqueue(struct fd_pipe *pipe, uint32_t prio) +{ + struct drm_msm_submitqueue req = { + .flags = 0, + .prio = prio, + }; + uint64_t nr_rings = 1; + int ret; + + if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES) { + to_msm_pipe(pipe)->queue_id = 0; + return 0; + } + + msm_pipe_get_param(pipe, FD_NR_RINGS, &nr_rings); + + req.prio = MIN2(req.prio, MAX2(nr_rings, 1) - 1); + + ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_NEW, + &req, sizeof(req)); + if (ret) { + ERROR_MSG("could not create submitqueue! %d (%s)", ret, strerror(errno)); + return ret; + } + + to_msm_pipe(pipe)->queue_id = req.id; + return 0; +} + +static void close_submitqueue(struct fd_pipe *pipe, uint32_t queue_id) +{ + if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES) + return; + + drmCommandWrite(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_CLOSE, + &queue_id, sizeof(queue_id)); +} + static void msm_pipe_destroy(struct fd_pipe *pipe) { struct msm_pipe *msm_pipe = to_msm_pipe(pipe); + close_submitqueue(pipe, msm_pipe->queue_id); + + if (msm_pipe->suballoc_ring) { + fd_ringbuffer_del(msm_pipe->suballoc_ring); + msm_pipe->suballoc_ring = NULL; + } + free(msm_pipe); } @@ -122,7 +166,7 @@ static uint64_t get_param(struct fd_pipe *pipe, uint32_t param) } drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev, - enum fd_pipe_id id) + enum fd_pipe_id id, uint32_t prio) { static const uint32_t pipe_id[] = { [FD_PIPE_3D] = MSM_PIPE_3D0, @@ -157,6 +201,9 @@ drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev, INFO_MSG(" Chip-id: 0x%08x", msm_pipe->chip_id); INFO_MSG(" GMEM size: 0x%08x", msm_pipe->gmem); + if (open_submitqueue(pipe, prio)) + goto fail; + return pipe; fail: if (pipe) diff --git a/freedreno/msm/msm_priv.h b/freedreno/msm/msm_priv.h index 6d670aab..cc951fba 100644 --- a/freedreno/msm/msm_priv.h +++ b/freedreno/msm/msm_priv.h @@ -56,6 +56,18 @@ struct msm_pipe { uint32_t gpu_id; uint32_t gmem; uint32_t chip_id; + uint32_t queue_id; + + /* Allow for sub-allocation of stateobj ring buffers (ie. sharing + * the same underlying bo).. + * + * This takes advantage of each context having it's own fd_pipe, + * so we don't have to worry about access from multiple threads. + * + * We also rely on previous stateobj having been fully constructed + * so we can reclaim extra space at it's end. + */ + struct fd_ringbuffer *suballoc_ring; }; static inline struct msm_pipe * to_msm_pipe(struct fd_pipe *x) @@ -64,10 +76,10 @@ static inline struct msm_pipe * to_msm_pipe(struct fd_pipe *x) } drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev, - enum fd_pipe_id id); + enum fd_pipe_id id, uint32_t prio); drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size); + uint32_t size, enum fd_ringbuffer_flags flags); struct msm_bo { struct fd_bo base; @@ -100,4 +112,30 @@ static inline void get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns) tv->tv_nsec = t.tv_nsec + ns - (s * 1000000000); } +/* + * Stupid/simple growable array implementation: + */ + +static inline void * +grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz) +{ + if ((nr + 1) > *max) { + if ((*max * 2) < (nr + 1)) + *max = nr + 5; + else + *max = *max * 2; + ptr = realloc(ptr, *max * sz); + } + return ptr; +} + +#define DECLARE_ARRAY(type, name) \ + unsigned nr_ ## name, max_ ## name; \ + type * name; + +#define APPEND(x, name) ({ \ + (x)->name = grow((x)->name, (x)->nr_ ## name, &(x)->max_ ## name, sizeof((x)->name[0])); \ + (x)->nr_ ## name ++; \ +}) + #endif /* MSM_PRIV_H_ */ diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index 17194f4c..475c65d7 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -26,13 +26,10 @@ * Rob Clark <robclark@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <assert.h> #include <inttypes.h> +#include "xf86atomic.h" #include "freedreno_ringbuffer.h" #include "msm_priv.h" @@ -46,10 +43,12 @@ struct msm_cmd { struct fd_bo *ring_bo; /* reloc's table: */ - struct drm_msm_gem_submit_reloc *relocs; - uint32_t nr_relocs, max_relocs; + DECLARE_ARRAY(struct drm_msm_gem_submit_reloc, relocs); uint32_t size; + + /* has cmd already been added to parent rb's submit.cmds table? */ + int is_appended_to_submit; }; struct msm_ringbuffer { @@ -62,22 +61,18 @@ struct msm_ringbuffer { */ struct { /* bo's table: */ - struct drm_msm_gem_submit_bo *bos; - uint32_t nr_bos, max_bos; + DECLARE_ARRAY(struct drm_msm_gem_submit_bo, bos); /* cmd's table: */ - struct drm_msm_gem_submit_cmd *cmds; - uint32_t nr_cmds, max_cmds; + DECLARE_ARRAY(struct drm_msm_gem_submit_cmd, cmds); } submit; /* should have matching entries in submit.bos: */ /* Note, only in parent ringbuffer */ - struct fd_bo **bos; - uint32_t nr_bos, max_bos; + DECLARE_ARRAY(struct fd_bo *, bos); /* should have matching entries in submit.cmds: */ - struct msm_cmd **cmds; - uint32_t nr_cmds, max_cmds; + DECLARE_ARRAY(struct msm_cmd *, cmds); /* List of physical cmdstream buffers (msm_cmd) assocated with this * logical fd_ringbuffer. @@ -93,10 +88,24 @@ struct msm_ringbuffer { int is_growable; unsigned cmd_count; + unsigned offset; /* for sub-allocated stateobj rb's */ + unsigned seqno; /* maps fd_bo to idx: */ void *bo_table; + + /* maps msm_cmd to drm_msm_gem_submit_cmd in parent rb. Each rb has a + * list of msm_cmd's which correspond to each chunk of cmdstream in + * a 'growable' rb. For each of those we need to create one + * drm_msm_gem_submit_cmd in the parent rb which collects the state + * for the submit ioctl. Because we can have multiple IB's to the same + * target rb (for example, or same stateobj emit multiple times), and + * because in theory we can have multiple different rb's that have a + * reference to a given target, we need a hashtable to track this per + * rb. + */ + void *cmd_table; }; static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x) @@ -107,51 +116,25 @@ static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x) #define INIT_SIZE 0x1000 static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER; -drm_private extern pthread_mutex_t table_lock; - -static void ring_bo_del(struct fd_device *dev, struct fd_bo *bo) -{ - int ret; - - pthread_mutex_lock(&table_lock); - ret = fd_bo_cache_free(&to_msm_device(dev)->ring_cache, bo); - pthread_mutex_unlock(&table_lock); - if (ret == 0) - return; - - fd_bo_del(bo); -} - -static struct fd_bo * ring_bo_new(struct fd_device *dev, uint32_t size) +static struct msm_cmd *current_cmd(struct fd_ringbuffer *ring) { - struct fd_bo *bo; - - bo = fd_bo_cache_alloc(&to_msm_device(dev)->ring_cache, &size, 0); - if (bo) - return bo; - - bo = fd_bo_new(dev, size, 0); - if (!bo) - return NULL; - - /* keep ringbuffer bo's out of the normal bo cache: */ - bo->bo_reuse = FALSE; - - return bo; + struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); + assert(!LIST_IS_EMPTY(&msm_ring->cmd_list)); + return LIST_LAST_ENTRY(&msm_ring->cmd_list, struct msm_cmd, list); } static void ring_cmd_del(struct msm_cmd *cmd) { - if (cmd->ring_bo) - ring_bo_del(cmd->ring->pipe->dev, cmd->ring_bo); + fd_bo_del(cmd->ring_bo); list_del(&cmd->list); to_msm_ringbuffer(cmd->ring)->cmd_count--; free(cmd->relocs); free(cmd); } -static struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size) +static struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size, + enum fd_ringbuffer_flags flags) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); struct msm_cmd *cmd = calloc(1, sizeof(*cmd)); @@ -160,7 +143,48 @@ static struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size) return NULL; cmd->ring = ring; - cmd->ring_bo = ring_bo_new(ring->pipe->dev, size); + + /* TODO separate suballoc buffer for small non-streaming state, using + * smaller page-sized backing bo's. + */ + if (flags & FD_RINGBUFFER_STREAMING) { + struct msm_pipe *msm_pipe = to_msm_pipe(ring->pipe); + unsigned suballoc_offset = 0; + struct fd_bo *suballoc_bo = NULL; + + if (msm_pipe->suballoc_ring) { + struct msm_ringbuffer *suballoc_ring = to_msm_ringbuffer(msm_pipe->suballoc_ring); + + assert(msm_pipe->suballoc_ring->flags & FD_RINGBUFFER_OBJECT); + assert(suballoc_ring->cmd_count == 1); + + suballoc_bo = current_cmd(msm_pipe->suballoc_ring)->ring_bo; + + suballoc_offset = fd_ringbuffer_size(msm_pipe->suballoc_ring) + + suballoc_ring->offset; + + suballoc_offset = ALIGN(suballoc_offset, 0x10); + + if ((size + suballoc_offset) > suballoc_bo->size) { + suballoc_bo = NULL; + } + } + + if (!suballoc_bo) { + cmd->ring_bo = fd_bo_new_ring(ring->pipe->dev, 0x8000, 0); + msm_ring->offset = 0; + } else { + cmd->ring_bo = fd_bo_ref(suballoc_bo); + msm_ring->offset = suballoc_offset; + } + + if (msm_pipe->suballoc_ring) + fd_ringbuffer_del(msm_pipe->suballoc_ring); + + msm_pipe->suballoc_ring = fd_ringbuffer_ref(ring); + } else { + cmd->ring_bo = fd_bo_new_ring(ring->pipe->dev, size, 0); + } if (!cmd->ring_bo) goto fail; @@ -174,30 +198,6 @@ fail: return NULL; } -static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz) -{ - if ((nr + 1) > *max) { - if ((*max * 2) < (nr + 1)) - *max = nr + 5; - else - *max = *max * 2; - ptr = realloc(ptr, *max * sz); - } - return ptr; -} - -#define APPEND(x, name) ({ \ - (x)->name = grow((x)->name, (x)->nr_ ## name, &(x)->max_ ## name, sizeof((x)->name[0])); \ - (x)->nr_ ## name ++; \ -}) - -static struct msm_cmd *current_cmd(struct fd_ringbuffer *ring) -{ - struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); - assert(!LIST_IS_EMPTY(&msm_ring->cmd_list)); - return LIST_LAST_ENTRY(&msm_ring->cmd_list, struct msm_cmd, list); -} - static uint32_t append_bo(struct fd_ringbuffer *ring, struct fd_bo *bo) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); @@ -249,31 +249,43 @@ static uint32_t bo2idx(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t fl return idx; } -static int check_cmd_bo(struct fd_ringbuffer *ring, - struct drm_msm_gem_submit_cmd *cmd, struct fd_bo *bo) -{ - struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); - return msm_ring->submit.bos[cmd->submit_idx].handle == bo->handle; -} - /* Ensure that submit has corresponding entry in cmds table for the * target cmdstream buffer: + * + * Returns TRUE if new cmd added (else FALSE if it was already in + * the cmds table) */ -static void get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd, +static int get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd, uint32_t submit_offset, uint32_t size, uint32_t type) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); struct drm_msm_gem_submit_cmd *cmd; uint32_t i; + void *val; - /* figure out if we already have a cmd buf: */ - for (i = 0; i < msm_ring->submit.nr_cmds; i++) { + if (!msm_ring->cmd_table) + msm_ring->cmd_table = drmHashCreate(); + + /* figure out if we already have a cmd buf.. short-circuit hash + * lookup if: + * - target cmd has never been added to submit.cmds + * - target cmd is not a streaming stateobj (which unlike longer + * lived CSO stateobj, is not expected to be reused with multiple + * submits) + */ + if (target_cmd->is_appended_to_submit && + !(target_cmd->ring->flags & FD_RINGBUFFER_STREAMING) && + !drmHashLookup(msm_ring->cmd_table, (unsigned long)target_cmd, &val)) { + i = VOID2U64(val); cmd = &msm_ring->submit.cmds[i]; - if ((cmd->submit_offset == submit_offset) && - (cmd->size == size) && - (cmd->type == type) && - check_cmd_bo(ring, cmd, target_cmd->ring_bo)) - return; + + assert(cmd->submit_offset == submit_offset); + assert(cmd->size == size); + assert(cmd->type == type); + assert(msm_ring->submit.bos[cmd->submit_idx].handle == + target_cmd->ring_bo->handle); + + return FALSE; } /* create cmd buf if not: */ @@ -287,27 +299,23 @@ static void get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd, cmd->size = size; cmd->pad = 0; + target_cmd->is_appended_to_submit = TRUE; + + if (!(target_cmd->ring->flags & FD_RINGBUFFER_STREAMING)) { + drmHashInsert(msm_ring->cmd_table, (unsigned long)target_cmd, + U642VOID(i)); + } + target_cmd->size = size; -} -static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring) -{ - return fd_bo_map(current_cmd(ring)->ring_bo); + return TRUE; } -static uint32_t find_next_reloc_idx(struct msm_cmd *msm_cmd, - uint32_t start, uint32_t offset) +static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring) { - uint32_t i; - - /* a binary search would be more clever.. */ - for (i = start; i < msm_cmd->nr_relocs; i++) { - struct drm_msm_gem_submit_reloc *reloc = &msm_cmd->relocs[i]; - if (reloc->submit_offset >= offset) - return i; - } - - return i; + struct msm_cmd *cmd = current_cmd(ring); + uint8_t *base = fd_bo_map(cmd->ring_bo); + return base + to_msm_ringbuffer(ring)->offset; } static void delete_cmds(struct msm_ringbuffer *msm_ring) @@ -326,14 +334,20 @@ static void flush_reset(struct fd_ringbuffer *ring) for (i = 0; i < msm_ring->nr_bos; i++) { struct msm_bo *msm_bo = to_msm_bo(msm_ring->bos[i]); + if (!msm_bo) + continue; msm_bo->current_ring_seqno = 0; fd_bo_del(&msm_bo->base); } - /* for each of the cmd buffers, clear their reloc's: */ - for (i = 0; i < msm_ring->submit.nr_cmds; i++) { - struct msm_cmd *target_cmd = msm_ring->cmds[i]; - target_cmd->nr_relocs = 0; + for (i = 0; i < msm_ring->nr_cmds; i++) { + struct msm_cmd *msm_cmd = msm_ring->cmds[i]; + + if (msm_cmd->ring == ring) + continue; + + if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) + fd_ringbuffer_del(msm_cmd->ring); } msm_ring->submit.nr_cmds = 0; @@ -346,6 +360,11 @@ static void flush_reset(struct fd_ringbuffer *ring) msm_ring->bo_table = NULL; } + if (msm_ring->cmd_table) { + drmHashDestroy(msm_ring->cmd_table); + msm_ring->cmd_table = NULL; + } + if (msm_ring->is_growable) { delete_cmds(msm_ring); } else { @@ -395,16 +414,63 @@ static void dump_submit(struct msm_ringbuffer *msm_ring) } } +static struct drm_msm_gem_submit_reloc * +handle_stateobj_relocs(struct fd_ringbuffer *parent, struct fd_ringbuffer *stateobj, + struct drm_msm_gem_submit_reloc *orig_relocs, unsigned nr_relocs) +{ + struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(stateobj); + struct drm_msm_gem_submit_reloc *relocs = malloc(nr_relocs * sizeof(*relocs)); + unsigned i; + + for (i = 0; i < nr_relocs; i++) { + unsigned idx = orig_relocs[i].reloc_idx; + struct fd_bo *bo = msm_ring->bos[idx]; + unsigned flags = 0; + + if (msm_ring->submit.bos[idx].flags & MSM_SUBMIT_BO_READ) + flags |= FD_RELOC_READ; + if (msm_ring->submit.bos[idx].flags & MSM_SUBMIT_BO_WRITE) + flags |= FD_RELOC_WRITE; + + relocs[i] = orig_relocs[i]; + relocs[i].reloc_idx = bo2idx(parent, bo, flags); + } + + /* stateobj rb's could have reloc's to other stateobj rb's which didn't + * get propagated to the parent rb at _emit_reloc_ring() time (because + * the parent wasn't known then), so fix that up now: + */ + for (i = 0; i < msm_ring->nr_cmds; i++) { + struct msm_cmd *msm_cmd = msm_ring->cmds[i]; + struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; + + if (msm_ring->cmds[i]->ring == stateobj) + continue; + + assert(msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT); + + if (get_cmd(parent, msm_cmd, cmd->submit_offset, cmd->size, cmd->type)) { + fd_ringbuffer_ref(msm_cmd->ring); + } + } + + return relocs; +} + static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start, int in_fence_fd, int *out_fence_fd) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); + struct msm_pipe *msm_pipe = to_msm_pipe(ring->pipe); struct drm_msm_gem_submit req = { - .flags = to_msm_pipe(ring->pipe)->pipe, + .flags = msm_pipe->pipe, + .queueid = msm_pipe->queue_id, }; uint32_t i; int ret; + assert(!ring->parent); + if (in_fence_fd != -1) { req.flags |= MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_NO_IMPLICIT; req.fence_fd = in_fence_fd; @@ -416,22 +482,35 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start finalize_current_cmd(ring, last_start); + /* for each of the cmd's fix up their reloc's: */ + for (i = 0; i < msm_ring->submit.nr_cmds; i++) { + struct msm_cmd *msm_cmd = msm_ring->cmds[i]; + struct drm_msm_gem_submit_reloc *relocs = msm_cmd->relocs; + struct drm_msm_gem_submit_cmd *cmd; + unsigned nr_relocs = msm_cmd->nr_relocs; + + /* for reusable stateobjs, the reloc table has reloc_idx that + * points into it's own private bos table, rather than the global + * bos table used for the submit, so we need to add the stateobj's + * bos to the global table and construct new relocs table with + * corresponding reloc_idx + */ + if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) { + relocs = handle_stateobj_relocs(ring, msm_cmd->ring, + relocs, nr_relocs); + } + + cmd = &msm_ring->submit.cmds[i]; + cmd->relocs = VOID2U64(relocs); + cmd->nr_relocs = nr_relocs; + } + /* needs to be after get_cmd() as that could create bos/cmds table: */ req.bos = VOID2U64(msm_ring->submit.bos), req.nr_bos = msm_ring->submit.nr_bos; req.cmds = VOID2U64(msm_ring->submit.cmds), req.nr_cmds = msm_ring->submit.nr_cmds; - /* for each of the cmd's fix up their reloc's: */ - for (i = 0; i < msm_ring->submit.nr_cmds; i++) { - struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; - struct msm_cmd *msm_cmd = msm_ring->cmds[i]; - uint32_t a = find_next_reloc_idx(msm_cmd, 0, cmd->submit_offset); - uint32_t b = find_next_reloc_idx(msm_cmd, a, cmd->submit_offset + cmd->size); - cmd->relocs = VOID2U64(&msm_cmd->relocs[a]); - cmd->nr_relocs = (b > a) ? b - a : 0; - } - DEBUG_MSG("nr_cmds=%u, nr_bos=%u", req.nr_cmds, req.nr_bos); ret = drmCommandWriteRead(ring->pipe->dev->fd, DRM_MSM_GEM_SUBMIT, @@ -451,6 +530,15 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start } } + /* free dynamically constructed stateobj relocs tables: */ + for (i = 0; i < msm_ring->submit.nr_cmds; i++) { + struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; + struct msm_cmd *msm_cmd = msm_ring->cmds[i]; + if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) { + free(U642VOID(cmd->relocs)); + } + } + flush_reset(ring); return ret; @@ -460,7 +548,7 @@ static void msm_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t size) { assert(to_msm_ringbuffer(ring)->is_growable); finalize_current_cmd(ring, ring->last_start); - ring_cmd_new(ring, size); + ring_cmd_new(ring, size, 0); } static void msm_ringbuffer_reset(struct fd_ringbuffer *ring) @@ -484,7 +572,8 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, reloc->reloc_offset = r->offset; reloc->or = r->or; reloc->shift = r->shift; - reloc->submit_offset = offset_bytes(ring->cur, ring->start); + reloc->submit_offset = offset_bytes(ring->cur, ring->start) + + to_msm_ringbuffer(ring)->offset; addr = msm_bo->presumed; if (reloc->shift < 0) @@ -496,15 +585,21 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, if (ring->pipe->gpu_id >= 500) { struct drm_msm_gem_submit_reloc *reloc_hi; + /* NOTE: grab reloc_idx *before* APPEND() since that could + * realloc() meaning that 'reloc' ptr is no longer valid: + */ + uint32_t reloc_idx = reloc->reloc_idx; + idx = APPEND(cmd, relocs); reloc_hi = &cmd->relocs[idx]; - reloc_hi->reloc_idx = reloc->reloc_idx; + reloc_hi->reloc_idx = reloc_idx; reloc_hi->reloc_offset = r->offset; reloc_hi->or = r->orhi; reloc_hi->shift = r->shift - 32; - reloc_hi->submit_offset = offset_bytes(ring->cur, ring->start); + reloc_hi->submit_offset = offset_bytes(ring->cur, ring->start) + + to_msm_ringbuffer(ring)->offset; addr = msm_bo->presumed >> 32; if (reloc_hi->shift < 0) @@ -516,13 +611,16 @@ static void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, } static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, - struct fd_ringbuffer *target, uint32_t cmd_idx, - uint32_t submit_offset, uint32_t size) + struct fd_ringbuffer *target, uint32_t cmd_idx) { struct msm_cmd *cmd = NULL; + struct msm_ringbuffer *msm_target = to_msm_ringbuffer(target); uint32_t idx = 0; + int added_cmd = FALSE; + uint32_t size; + uint32_t submit_offset = msm_target->offset; - LIST_FOR_EACH_ENTRY(cmd, &to_msm_ringbuffer(target)->cmd_list, list) { + LIST_FOR_EACH_ENTRY(cmd, &msm_target->cmd_list, list) { if (idx == cmd_idx) break; idx++; @@ -530,7 +628,7 @@ static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, assert(cmd && (idx == cmd_idx)); - if (idx < (to_msm_ringbuffer(target)->cmd_count - 1)) { + if (idx < (msm_target->cmd_count - 1)) { /* All but the last cmd buffer is fully "baked" (ie. already has * done get_cmd() to add it to the cmds table). But in this case, * the size we get is invalid (since it is calculated from the @@ -538,7 +636,10 @@ static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, */ size = cmd->size; } else { - get_cmd(ring, cmd, submit_offset, size, MSM_SUBMIT_CMD_IB_TARGET_BUF); + struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring; + size = offset_bytes(target->cur, target->start); + added_cmd = get_cmd(parent, cmd, submit_offset, size, + MSM_SUBMIT_CMD_IB_TARGET_BUF); } msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){ @@ -547,6 +648,14 @@ static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, .offset = submit_offset, }); + /* Unlike traditional ringbuffers which are deleted as a set (after + * being flushed), mesa can't really guarantee that a stateobj isn't + * destroyed after emitted but before flush, so we must hold a ref: + */ + if (added_cmd && (target->flags & FD_RINGBUFFER_OBJECT)) { + fd_ringbuffer_ref(target); + } + return size; } @@ -581,15 +690,15 @@ static const struct fd_ringbuffer_funcs funcs = { }; drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, - uint32_t size) + uint32_t size, enum fd_ringbuffer_flags flags) { struct msm_ringbuffer *msm_ring; - struct fd_ringbuffer *ring = NULL; + struct fd_ringbuffer *ring; msm_ring = calloc(1, sizeof(*msm_ring)); if (!msm_ring) { ERROR_MSG("allocation failed"); - goto fail; + return NULL; } if (size == 0) { @@ -602,15 +711,13 @@ drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, msm_ring->seqno = ++to_msm_device(pipe->dev)->ring_cnt; ring = &msm_ring->base; + atomic_set(&ring->refcnt, 1); + ring->funcs = &funcs; ring->size = size; ring->pipe = pipe; /* needed in ring_cmd_new() */ - ring_cmd_new(ring, size); + ring_cmd_new(ring, size, flags); return ring; -fail: - if (ring) - fd_ringbuffer_del(ring); - return NULL; } diff --git a/include/drm/README b/include/drm/README index a50b02c0..ea2320cc 100644 --- a/include/drm/README +++ b/include/drm/README @@ -67,9 +67,11 @@ That said, it's up-to the individual developers to sync with newer version When and how to update these files ---------------------------------- +Note: One should not do _any_ changes to the files apart from the steps below. + In order to update the files do the following: - Switch to a Linux kernel tree/branch which is not rebased. -For example: airlied/drm-next + For example: drm-next (https://cgit.freedesktop.org/drm/drm) - Install the headers via `make headers_install' to a separate location. - Copy the drm header[s] + git add + git commit. - Note: Your commit message must include: @@ -84,47 +86,21 @@ Outdated or Broken Headers This section contains a list of headers and the respective "issues" they might have relative to their kernel equivalent. -Nearly all headers: - - Missing extern C notation. -Status: Trivial. - Most UMS headers: - Not using fixed size integers - compat ioctls are broken. Status: ? Promote to fixed size ints, which match the current (32bit) ones. - -amdgpu_drm.h - - Using the stdint.h uint*_t over the respective __u* ones -Status: Trivial. - -drm_mode.h - - Missing DPI encode/connector pair. -Status: Trivial. - -i915_drm.h - - Missing PARAMS - HAS_POOLED_EU, MIN_EU_IN_POOL CONTEXT_PARAM_NO_ERROR_CAPTURE -Status: Trivial. - -mga_drm.h - - Typo fix, use struct over typedef. -Status: Trivial. - nouveau_drm.h - Missing macros NOUVEAU_GETPARAM*, NOUVEAU_DRM_HEADER_PATCHLEVEL, structs, -enums, using stdint.h over the __u* types. -Status: ? - -qxl_drm.h - - Using the stdint.h uint*_t over the respective __u* ones -Status: Trivial. +enums +Status: Deliberate UABI choice; nouveau hides the exact kernel ABI behind libdrm r128_drm.h - Broken compat ioctls. radeon_drm.h - - Missing RADEON_TILING_R600_NO_SCANOUT, CIK_TILE_MODE_*, broken UMS ioctls, -using stdint types. + - Missing RADEON_TILING_R600_NO_SCANOUT, CIK_TILE_MODE_*, broken UMS ioctls - Both kernel and libdrm: missing padding - drm_radeon_gem_{create,{g,s}et_tiling,set_domain} others ? Status: ? @@ -146,11 +122,6 @@ omap_drm.h (living in $TOP/omap) - License mismatch, missing DRM_IOCTL_OMAP_GEM_NEW and related struct Status: ? -msm_drm.h (located in $TOP/freedreno/msm/) - - License mismatch, missing MSM_PIPE_*, MSM_SUBMIT_*. Renamed -drm_msm_gem_submit::flags, missing drm_msm_gem_submit::fence_fd. -Status: ? - exynos_drm.h (living in $TOP/exynos) - License mismatch, now using fixed size ints (but not everywhere). Lots of new stuff. diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h index d8f24976..be84e43c 100644 --- a/include/drm/amdgpu_drm.h +++ b/include/drm/amdgpu_drm.h @@ -50,6 +50,10 @@ extern "C" { #define DRM_AMDGPU_WAIT_CS 0x09 #define DRM_AMDGPU_GEM_OP 0x10 #define DRM_AMDGPU_GEM_USERPTR 0x11 +#define DRM_AMDGPU_WAIT_FENCES 0x12 +#define DRM_AMDGPU_VM 0x13 +#define DRM_AMDGPU_FENCE_TO_HANDLE 0x14 +#define DRM_AMDGPU_SCHED 0x15 #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) @@ -63,13 +67,46 @@ extern "C" { #define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs) #define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op) #define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr) +#define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences) +#define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm) +#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle) +#define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched) +/** + * DOC: memory domains + * + * %AMDGPU_GEM_DOMAIN_CPU System memory that is not GPU accessible. + * Memory in this pool could be swapped out to disk if there is pressure. + * + * %AMDGPU_GEM_DOMAIN_GTT GPU accessible system memory, mapped into the + * GPU's virtual address space via gart. Gart memory linearizes non-contiguous + * pages of system memory, allows GPU access system memory in a linezrized + * fashion. + * + * %AMDGPU_GEM_DOMAIN_VRAM Local video memory. For APUs, it is memory + * carved out by the BIOS. + * + * %AMDGPU_GEM_DOMAIN_GDS Global on-chip data storage used to share data + * across shader threads. + * + * %AMDGPU_GEM_DOMAIN_GWS Global wave sync, used to synchronize the + * execution of all the waves on a device. + * + * %AMDGPU_GEM_DOMAIN_OA Ordered append, used by 3D or Compute engines + * for appending data. + */ #define AMDGPU_GEM_DOMAIN_CPU 0x1 #define AMDGPU_GEM_DOMAIN_GTT 0x2 #define AMDGPU_GEM_DOMAIN_VRAM 0x4 #define AMDGPU_GEM_DOMAIN_GDS 0x8 #define AMDGPU_GEM_DOMAIN_GWS 0x10 #define AMDGPU_GEM_DOMAIN_OA 0x20 +#define AMDGPU_GEM_DOMAIN_MASK (AMDGPU_GEM_DOMAIN_CPU | \ + AMDGPU_GEM_DOMAIN_GTT | \ + AMDGPU_GEM_DOMAIN_VRAM | \ + AMDGPU_GEM_DOMAIN_GDS | \ + AMDGPU_GEM_DOMAIN_GWS | \ + AMDGPU_GEM_DOMAIN_OA) /* Flag that CPU access will be required for the case of VRAM domain */ #define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED (1 << 0) @@ -79,22 +116,34 @@ extern "C" { #define AMDGPU_GEM_CREATE_CPU_GTT_USWC (1 << 2) /* Flag that the memory should be in VRAM and cleared */ #define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3) +/* Flag that create shadow bo(GTT) while allocating vram bo */ +#define AMDGPU_GEM_CREATE_SHADOW (1 << 4) +/* Flag that allocating the BO should use linear VRAM */ +#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5) +/* Flag that BO is always valid in this VM */ +#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6) +/* Flag that BO sharing will be explicitly synchronized */ +#define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7) +/* Flag that indicates allocating MQD gart on GFX9, where the mtype + * for the second page onward should be set to NC. + */ +#define AMDGPU_GEM_CREATE_MQD_GFX9 (1 << 8) struct drm_amdgpu_gem_create_in { /** the requested memory size */ - uint64_t bo_size; + __u64 bo_size; /** physical start_addr alignment in bytes for some HW requirements */ - uint64_t alignment; + __u64 alignment; /** the requested memory domains */ - uint64_t domains; + __u64 domains; /** allocation flags */ - uint64_t domain_flags; + __u64 domain_flags; }; struct drm_amdgpu_gem_create_out { /** returned GEM object handle */ - uint32_t handle; - uint32_t _pad; + __u32 handle; + __u32 _pad; }; union drm_amdgpu_gem_create { @@ -111,28 +160,28 @@ union drm_amdgpu_gem_create { struct drm_amdgpu_bo_list_in { /** Type of operation */ - uint32_t operation; + __u32 operation; /** Handle of list or 0 if we want to create one */ - uint32_t list_handle; + __u32 list_handle; /** Number of BOs in list */ - uint32_t bo_number; + __u32 bo_number; /** Size of each element describing BO */ - uint32_t bo_info_size; + __u32 bo_info_size; /** Pointer to array describing BOs */ - uint64_t bo_info_ptr; + __u64 bo_info_ptr; }; struct drm_amdgpu_bo_list_entry { /** Handle of BO */ - uint32_t bo_handle; + __u32 bo_handle; /** New (if specified) BO priority to be used during migration */ - uint32_t bo_priority; + __u32 bo_priority; }; struct drm_amdgpu_bo_list_out { /** Handle of resource list */ - uint32_t list_handle; - uint32_t _pad; + __u32 list_handle; + __u32 _pad; }; union drm_amdgpu_bo_list { @@ -144,6 +193,7 @@ union drm_amdgpu_bo_list { #define AMDGPU_CTX_OP_ALLOC_CTX 1 #define AMDGPU_CTX_OP_FREE_CTX 2 #define AMDGPU_CTX_OP_QUERY_STATE 3 +#define AMDGPU_CTX_OP_QUERY_STATE2 4 /* GPU reset status */ #define AMDGPU_CTX_NO_RESET 0 @@ -154,28 +204,44 @@ union drm_amdgpu_bo_list { /* unknown cause */ #define AMDGPU_CTX_UNKNOWN_RESET 3 +/* indicate gpu reset occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_RESET (1<<0) +/* indicate vram lost occured after ctx created */ +#define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1<<1) +/* indicate some job from this context once cause gpu hang */ +#define AMDGPU_CTX_QUERY2_FLAGS_GUILTY (1<<2) + +/* Context priority level */ +#define AMDGPU_CTX_PRIORITY_UNSET -2048 +#define AMDGPU_CTX_PRIORITY_VERY_LOW -1023 +#define AMDGPU_CTX_PRIORITY_LOW -512 +#define AMDGPU_CTX_PRIORITY_NORMAL 0 +/* Selecting a priority above NORMAL requires CAP_SYS_NICE or DRM_MASTER */ +#define AMDGPU_CTX_PRIORITY_HIGH 512 +#define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023 + struct drm_amdgpu_ctx_in { /** AMDGPU_CTX_OP_* */ - uint32_t op; + __u32 op; /** For future use, no flags defined so far */ - uint32_t flags; - uint32_t ctx_id; - uint32_t _pad; + __u32 flags; + __u32 ctx_id; + __s32 priority; }; union drm_amdgpu_ctx_out { struct { - uint32_t ctx_id; - uint32_t _pad; + __u32 ctx_id; + __u32 _pad; } alloc; struct { /** For future use, no flags defined so far */ - uint64_t flags; + __u64 flags; /** Number of resets caused by this context so far. */ - uint32_t hangs; + __u32 hangs; /** Reset status since the last call of the ioctl. */ - uint32_t reset_status; + __u32 reset_status; } state; }; @@ -184,6 +250,41 @@ union drm_amdgpu_ctx { union drm_amdgpu_ctx_out out; }; +/* vm ioctl */ +#define AMDGPU_VM_OP_RESERVE_VMID 1 +#define AMDGPU_VM_OP_UNRESERVE_VMID 2 + +struct drm_amdgpu_vm_in { + /** AMDGPU_VM_OP_* */ + __u32 op; + __u32 flags; +}; + +struct drm_amdgpu_vm_out { + /** For future use, no flags defined so far */ + __u64 flags; +}; + +union drm_amdgpu_vm { + struct drm_amdgpu_vm_in in; + struct drm_amdgpu_vm_out out; +}; + +/* sched ioctl */ +#define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE 1 + +struct drm_amdgpu_sched_in { + /* AMDGPU_SCHED_OP_* */ + __u32 op; + __u32 fd; + __s32 priority; + __u32 flags; +}; + +union drm_amdgpu_sched { + struct drm_amdgpu_sched_in in; +}; + /* * This is not a reliable API and you should expect it to fail for any * number of reasons and have fallback path that do not use userptr to @@ -195,14 +296,15 @@ union drm_amdgpu_ctx { #define AMDGPU_GEM_USERPTR_REGISTER (1 << 3) struct drm_amdgpu_gem_userptr { - uint64_t addr; - uint64_t size; + __u64 addr; + __u64 size; /* AMDGPU_GEM_USERPTR_* */ - uint32_t flags; + __u32 flags; /* Resulting GEM handle */ - uint32_t handle; + __u32 handle; }; +/* SI-CI-VI: */ /* same meaning as the GB_TILE_MODE and GL_MACRO_TILE_MODE fields */ #define AMDGPU_TILING_ARRAY_MODE_SHIFT 0 #define AMDGPU_TILING_ARRAY_MODE_MASK 0xf @@ -221,10 +323,21 @@ struct drm_amdgpu_gem_userptr { #define AMDGPU_TILING_NUM_BANKS_SHIFT 21 #define AMDGPU_TILING_NUM_BANKS_MASK 0x3 +/* GFX9 and later: */ +#define AMDGPU_TILING_SWIZZLE_MODE_SHIFT 0 +#define AMDGPU_TILING_SWIZZLE_MODE_MASK 0x1f +#define AMDGPU_TILING_DCC_OFFSET_256B_SHIFT 5 +#define AMDGPU_TILING_DCC_OFFSET_256B_MASK 0xFFFFFF +#define AMDGPU_TILING_DCC_PITCH_MAX_SHIFT 29 +#define AMDGPU_TILING_DCC_PITCH_MAX_MASK 0x3FFF +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_SHIFT 43 +#define AMDGPU_TILING_DCC_INDEPENDENT_64B_MASK 0x1 + +/* Set/Get helpers for tiling flags. */ #define AMDGPU_TILING_SET(field, value) \ - (((value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT) + (((__u64)(value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT) #define AMDGPU_TILING_GET(value, field) \ - (((value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK) + (((__u64)(value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK) #define AMDGPU_GEM_METADATA_OP_SET_METADATA 1 #define AMDGPU_GEM_METADATA_OP_GET_METADATA 2 @@ -232,28 +345,28 @@ struct drm_amdgpu_gem_userptr { /** The same structure is shared for input/output */ struct drm_amdgpu_gem_metadata { /** GEM Object handle */ - uint32_t handle; + __u32 handle; /** Do we want get or set metadata */ - uint32_t op; + __u32 op; struct { /** For future use, no flags defined so far */ - uint64_t flags; + __u64 flags; /** family specific tiling info */ - uint64_t tiling_info; - uint32_t data_size_bytes; - uint32_t data[64]; + __u64 tiling_info; + __u32 data_size_bytes; + __u32 data[64]; } data; }; struct drm_amdgpu_gem_mmap_in { /** the GEM object handle */ - uint32_t handle; - uint32_t _pad; + __u32 handle; + __u32 _pad; }; struct drm_amdgpu_gem_mmap_out { /** mmap offset from the vma offset manager */ - uint64_t addr_ptr; + __u64 addr_ptr; }; union drm_amdgpu_gem_mmap { @@ -263,18 +376,18 @@ union drm_amdgpu_gem_mmap { struct drm_amdgpu_gem_wait_idle_in { /** GEM object handle */ - uint32_t handle; + __u32 handle; /** For future use, no flags defined so far */ - uint32_t flags; + __u32 flags; /** Absolute timeout to wait */ - uint64_t timeout; + __u64 timeout; }; struct drm_amdgpu_gem_wait_idle_out { /** BO status: 0 - BO is idle, 1 - BO is busy */ - uint32_t status; + __u32 status; /** Returned current memory domain */ - uint32_t domain; + __u32 domain; }; union drm_amdgpu_gem_wait_idle { @@ -283,19 +396,22 @@ union drm_amdgpu_gem_wait_idle { }; struct drm_amdgpu_wait_cs_in { - /** Command submission handle */ - uint64_t handle; + /* Command submission handle + * handle equals 0 means none to wait for + * handle equals ~0ull means wait for the latest sequence number + */ + __u64 handle; /** Absolute timeout to wait */ - uint64_t timeout; - uint32_t ip_type; - uint32_t ip_instance; - uint32_t ring; - uint32_t ctx_id; + __u64 timeout; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; }; struct drm_amdgpu_wait_cs_out { /** CS status: 0 - CS completed, 1 - CS still busy */ - uint64_t status; + __u64 status; }; union drm_amdgpu_wait_cs { @@ -303,21 +419,49 @@ union drm_amdgpu_wait_cs { struct drm_amdgpu_wait_cs_out out; }; +struct drm_amdgpu_fence { + __u32 ctx_id; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u64 seq_no; +}; + +struct drm_amdgpu_wait_fences_in { + /** This points to uint64_t * which points to fences */ + __u64 fences; + __u32 fence_count; + __u32 wait_all; + __u64 timeout_ns; +}; + +struct drm_amdgpu_wait_fences_out { + __u32 status; + __u32 first_signaled; +}; + +union drm_amdgpu_wait_fences { + struct drm_amdgpu_wait_fences_in in; + struct drm_amdgpu_wait_fences_out out; +}; + #define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0 #define AMDGPU_GEM_OP_SET_PLACEMENT 1 /* Sets or returns a value associated with a buffer. */ struct drm_amdgpu_gem_op { /** GEM object handle */ - uint32_t handle; + __u32 handle; /** AMDGPU_GEM_OP_* */ - uint32_t op; + __u32 op; /** Input or return value */ - uint64_t value; + __u64 value; }; #define AMDGPU_VA_OP_MAP 1 #define AMDGPU_VA_OP_UNMAP 2 +#define AMDGPU_VA_OP_CLEAR 3 +#define AMDGPU_VA_OP_REPLACE 4 /* Delay the page table update till the next CS */ #define AMDGPU_VM_DELAY_UPDATE (1 << 0) @@ -329,21 +473,35 @@ struct drm_amdgpu_gem_op { #define AMDGPU_VM_PAGE_WRITEABLE (1 << 2) /* executable mapping, new for VI */ #define AMDGPU_VM_PAGE_EXECUTABLE (1 << 3) +/* partially resident texture */ +#define AMDGPU_VM_PAGE_PRT (1 << 4) +/* MTYPE flags use bit 5 to 8 */ +#define AMDGPU_VM_MTYPE_MASK (0xf << 5) +/* Default MTYPE. Pre-AI must use this. Recommended for newer ASICs. */ +#define AMDGPU_VM_MTYPE_DEFAULT (0 << 5) +/* Use NC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_NC (1 << 5) +/* Use WC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_WC (2 << 5) +/* Use CC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_CC (3 << 5) +/* Use UC MTYPE instead of default MTYPE */ +#define AMDGPU_VM_MTYPE_UC (4 << 5) struct drm_amdgpu_gem_va { /** GEM object handle */ - uint32_t handle; - uint32_t _pad; + __u32 handle; + __u32 _pad; /** AMDGPU_VA_OP_* */ - uint32_t operation; + __u32 operation; /** AMDGPU_VM_PAGE_* */ - uint32_t flags; + __u32 flags; /** va address to assign . Must be correctly aligned.*/ - uint64_t va_address; + __u64 va_address; /** Specify offset inside of BO to assign. Must be correctly aligned.*/ - uint64_t offset_in_bo; + __u64 offset_in_bo; /** Specify mapping size. Must be correctly aligned. */ - uint64_t map_size; + __u64 map_size; }; #define AMDGPU_HW_IP_GFX 0 @@ -351,33 +509,40 @@ struct drm_amdgpu_gem_va { #define AMDGPU_HW_IP_DMA 2 #define AMDGPU_HW_IP_UVD 3 #define AMDGPU_HW_IP_VCE 4 -#define AMDGPU_HW_IP_NUM 5 +#define AMDGPU_HW_IP_UVD_ENC 5 +#define AMDGPU_HW_IP_VCN_DEC 6 +#define AMDGPU_HW_IP_VCN_ENC 7 +#define AMDGPU_HW_IP_VCN_JPEG 8 +#define AMDGPU_HW_IP_NUM 9 #define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1 #define AMDGPU_CHUNK_ID_IB 0x01 #define AMDGPU_CHUNK_ID_FENCE 0x02 #define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03 +#define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04 +#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05 +#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06 struct drm_amdgpu_cs_chunk { - uint32_t chunk_id; - uint32_t length_dw; - uint64_t chunk_data; + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; }; struct drm_amdgpu_cs_in { /** Rendering context id */ - uint32_t ctx_id; + __u32 ctx_id; /** Handle of resource list associated with CS */ - uint32_t bo_list_handle; - uint32_t num_chunks; - uint32_t _pad; - /** this points to uint64_t * which point to cs chunks */ - uint64_t chunks; + __u32 bo_list_handle; + __u32 num_chunks; + __u32 _pad; + /** this points to __u64 * which point to cs chunks */ + __u64 chunks; }; struct drm_amdgpu_cs_out { - uint64_t handle; + __u64 handle; }; union drm_amdgpu_cs { @@ -390,36 +555,62 @@ union drm_amdgpu_cs { /* This IB should be submitted to CE */ #define AMDGPU_IB_FLAG_CE (1<<0) -/* CE Preamble */ +/* Preamble flag, which means the IB could be dropped if no context switch */ #define AMDGPU_IB_FLAG_PREAMBLE (1<<1) +/* Preempt flag, IB should set Pre_enb bit if PREEMPT flag detected */ +#define AMDGPU_IB_FLAG_PREEMPT (1<<2) + +/* The IB fence should do the L2 writeback but not invalidate any shader + * caches (L2/vL1/sL1/I$). */ +#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3) + struct drm_amdgpu_cs_chunk_ib { - uint32_t _pad; + __u32 _pad; /** AMDGPU_IB_FLAG_* */ - uint32_t flags; + __u32 flags; /** Virtual address to begin IB execution */ - uint64_t va_start; + __u64 va_start; /** Size of submission */ - uint32_t ib_bytes; + __u32 ib_bytes; /** HW IP to submit to */ - uint32_t ip_type; + __u32 ip_type; /** HW IP index of the same type to submit to */ - uint32_t ip_instance; + __u32 ip_instance; /** Ring index to submit to */ - uint32_t ring; + __u32 ring; }; struct drm_amdgpu_cs_chunk_dep { - uint32_t ip_type; - uint32_t ip_instance; - uint32_t ring; - uint32_t ctx_id; - uint64_t handle; + __u32 ip_type; + __u32 ip_instance; + __u32 ring; + __u32 ctx_id; + __u64 handle; }; struct drm_amdgpu_cs_chunk_fence { - uint32_t handle; - uint32_t offset; + __u32 handle; + __u32 offset; +}; + +struct drm_amdgpu_cs_chunk_sem { + __u32 handle; +}; + +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1 +#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2 + +union drm_amdgpu_fence_to_handle { + struct { + struct drm_amdgpu_fence fence; + __u32 what; + __u32 pad; + } in; + struct { + __u32 handle; + } out; }; struct drm_amdgpu_cs_chunk_data { @@ -434,6 +625,7 @@ struct drm_amdgpu_cs_chunk_data { * */ #define AMDGPU_IDS_FLAGS_FUSION 0x1 +#define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 /* indicate if acceleration can be working */ #define AMDGPU_INFO_ACCEL_WORKING 0x00 @@ -467,6 +659,20 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_FW_SMC 0x0a /* Subquery id: Query SDMA firmware version */ #define AMDGPU_INFO_FW_SDMA 0x0b + /* Subquery id: Query PSP SOS firmware version */ + #define AMDGPU_INFO_FW_SOS 0x0c + /* Subquery id: Query PSP ASD firmware version */ + #define AMDGPU_INFO_FW_ASD 0x0d + /* Subquery id: Query VCN firmware version */ + #define AMDGPU_INFO_FW_VCN 0x0e + /* Subquery id: Query GFX RLC SRLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL 0x0f + /* Subquery id: Query GFX RLC SRLG firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10 + /* Subquery id: Query GFX RLC SRLS firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11 + /* Subquery id: Query DMCU firmware version */ + #define AMDGPU_INFO_FW_DMCU 0x12 /* number of bytes moved for TTM migration */ #define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f /* the used VRAM size */ @@ -483,6 +689,43 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_DEV_INFO 0x16 /* visible vram usage */ #define AMDGPU_INFO_VIS_VRAM_USAGE 0x17 +/* number of TTM buffer evictions */ +#define AMDGPU_INFO_NUM_EVICTIONS 0x18 +/* Query memory about VRAM and GTT domains */ +#define AMDGPU_INFO_MEMORY 0x19 +/* Query vce clock table */ +#define AMDGPU_INFO_VCE_CLOCK_TABLE 0x1A +/* Query vbios related information */ +#define AMDGPU_INFO_VBIOS 0x1B + /* Subquery id: Query vbios size */ + #define AMDGPU_INFO_VBIOS_SIZE 0x1 + /* Subquery id: Query vbios image */ + #define AMDGPU_INFO_VBIOS_IMAGE 0x2 +/* Query UVD handles */ +#define AMDGPU_INFO_NUM_HANDLES 0x1C +/* Query sensor related information */ +#define AMDGPU_INFO_SENSOR 0x1D + /* Subquery id: Query GPU shader clock */ + #define AMDGPU_INFO_SENSOR_GFX_SCLK 0x1 + /* Subquery id: Query GPU memory clock */ + #define AMDGPU_INFO_SENSOR_GFX_MCLK 0x2 + /* Subquery id: Query GPU temperature */ + #define AMDGPU_INFO_SENSOR_GPU_TEMP 0x3 + /* Subquery id: Query GPU load */ + #define AMDGPU_INFO_SENSOR_GPU_LOAD 0x4 + /* Subquery id: Query average GPU power */ + #define AMDGPU_INFO_SENSOR_GPU_AVG_POWER 0x5 + /* Subquery id: Query northbridge voltage */ + #define AMDGPU_INFO_SENSOR_VDDNB 0x6 + /* Subquery id: Query graphics voltage */ + #define AMDGPU_INFO_SENSOR_VDDGFX 0x7 + /* Subquery id: Query GPU stable pstate shader clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_SCLK 0x8 + /* Subquery id: Query GPU stable pstate memory clock */ + #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK 0x9 +/* Number of VRAM page faults on CPU access. */ +#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E +#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0 #define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff @@ -491,86 +734,123 @@ struct drm_amdgpu_cs_chunk_data { struct drm_amdgpu_query_fw { /** AMDGPU_INFO_FW_* */ - uint32_t fw_type; + __u32 fw_type; /** * Index of the IP if there are more IPs of * the same type. */ - uint32_t ip_instance; + __u32 ip_instance; /** * Index of the engine. Whether this is used depends * on the firmware type. (e.g. MEC, SDMA) */ - uint32_t index; - uint32_t _pad; + __u32 index; + __u32 _pad; }; /* Input structure for the INFO ioctl */ struct drm_amdgpu_info { /* Where the return value will be stored */ - uint64_t return_pointer; + __u64 return_pointer; /* The size of the return value. Just like "size" in "snprintf", * it limits how many bytes the kernel can write. */ - uint32_t return_size; + __u32 return_size; /* The query request id. */ - uint32_t query; + __u32 query; union { struct { - uint32_t id; - uint32_t _pad; + __u32 id; + __u32 _pad; } mode_crtc; struct { /** AMDGPU_HW_IP_* */ - uint32_t type; + __u32 type; /** * Index of the IP if there are more IPs of the same * type. Ignored by AMDGPU_INFO_HW_IP_COUNT. */ - uint32_t ip_instance; + __u32 ip_instance; } query_hw_ip; struct { - uint32_t dword_offset; + __u32 dword_offset; /** number of registers to read */ - uint32_t count; - uint32_t instance; + __u32 count; + __u32 instance; /** For future use, no flags defined so far */ - uint32_t flags; + __u32 flags; } read_mmr_reg; struct drm_amdgpu_query_fw query_fw; + + struct { + __u32 type; + __u32 offset; + } vbios_info; + + struct { + __u32 type; + } sensor_info; }; }; struct drm_amdgpu_info_gds { /** GDS GFX partition size */ - uint32_t gds_gfx_partition_size; + __u32 gds_gfx_partition_size; /** GDS compute partition size */ - uint32_t compute_partition_size; + __u32 compute_partition_size; /** total GDS memory size */ - uint32_t gds_total_size; + __u32 gds_total_size; /** GWS size per GFX partition */ - uint32_t gws_per_gfx_partition; + __u32 gws_per_gfx_partition; /** GSW size per compute partition */ - uint32_t gws_per_compute_partition; + __u32 gws_per_compute_partition; /** OA size per GFX partition */ - uint32_t oa_per_gfx_partition; + __u32 oa_per_gfx_partition; /** OA size per compute partition */ - uint32_t oa_per_compute_partition; - uint32_t _pad; + __u32 oa_per_compute_partition; + __u32 _pad; }; struct drm_amdgpu_info_vram_gtt { - uint64_t vram_size; - uint64_t vram_cpu_accessible_size; - uint64_t gtt_size; + __u64 vram_size; + __u64 vram_cpu_accessible_size; + __u64 gtt_size; +}; + +struct drm_amdgpu_heap_info { + /** max. physical memory */ + __u64 total_heap_size; + + /** Theoretical max. available memory in the given heap */ + __u64 usable_heap_size; + + /** + * Number of bytes allocated in the heap. This includes all processes + * and private allocations in the kernel. It changes when new buffers + * are allocated, freed, and moved. It cannot be larger than + * heap_size. + */ + __u64 heap_usage; + + /** + * Theoretical possible max. size of buffer which + * could be allocated in the given heap + */ + __u64 max_allocation; +}; + +struct drm_amdgpu_memory_info { + struct drm_amdgpu_heap_info vram; + struct drm_amdgpu_heap_info cpu_accessible_vram; + struct drm_amdgpu_heap_info gtt; }; struct drm_amdgpu_info_firmware { - uint32_t ver; - uint32_t feature; + __u32 ver; + __u32 feature; }; #define AMDGPU_VRAM_TYPE_UNKNOWN 0 @@ -581,74 +861,139 @@ struct drm_amdgpu_info_firmware { #define AMDGPU_VRAM_TYPE_GDDR5 5 #define AMDGPU_VRAM_TYPE_HBM 6 #define AMDGPU_VRAM_TYPE_DDR3 7 +#define AMDGPU_VRAM_TYPE_DDR4 8 struct drm_amdgpu_info_device { /** PCI Device ID */ - uint32_t device_id; + __u32 device_id; /** Internal chip revision: A0, A1, etc.) */ - uint32_t chip_rev; - uint32_t external_rev; + __u32 chip_rev; + __u32 external_rev; /** Revision id in PCI Config space */ - uint32_t pci_rev; - uint32_t family; - uint32_t num_shader_engines; - uint32_t num_shader_arrays_per_engine; + __u32 pci_rev; + __u32 family; + __u32 num_shader_engines; + __u32 num_shader_arrays_per_engine; /* in KHz */ - uint32_t gpu_counter_freq; - uint64_t max_engine_clock; - uint64_t max_memory_clock; + __u32 gpu_counter_freq; + __u64 max_engine_clock; + __u64 max_memory_clock; /* cu information */ - uint32_t cu_active_number; - uint32_t cu_ao_mask; - uint32_t cu_bitmap[4][4]; + __u32 cu_active_number; + /* NOTE: cu_ao_mask is INVALID, DON'T use it */ + __u32 cu_ao_mask; + __u32 cu_bitmap[4][4]; /** Render backend pipe mask. One render backend is CB+DB. */ - uint32_t enabled_rb_pipes_mask; - uint32_t num_rb_pipes; - uint32_t num_hw_gfx_contexts; - uint32_t _pad; - uint64_t ids_flags; + __u32 enabled_rb_pipes_mask; + __u32 num_rb_pipes; + __u32 num_hw_gfx_contexts; + __u32 _pad; + __u64 ids_flags; /** Starting virtual address for UMDs. */ - uint64_t virtual_address_offset; + __u64 virtual_address_offset; /** The maximum virtual address */ - uint64_t virtual_address_max; + __u64 virtual_address_max; /** Required alignment of virtual addresses. */ - uint32_t virtual_address_alignment; + __u32 virtual_address_alignment; /** Page table entry - fragment size */ - uint32_t pte_fragment_size; - uint32_t gart_page_size; + __u32 pte_fragment_size; + __u32 gart_page_size; /** constant engine ram size*/ - uint32_t ce_ram_size; + __u32 ce_ram_size; /** video memory type info*/ - uint32_t vram_type; + __u32 vram_type; /** video memory bit width*/ - uint32_t vram_bit_width; + __u32 vram_bit_width; /* vce harvesting instance */ - uint32_t vce_harvest_config; + __u32 vce_harvest_config; + /* gfx double offchip LDS buffers */ + __u32 gc_double_offchip_lds_buf; + /* NGG Primitive Buffer */ + __u64 prim_buf_gpu_addr; + /* NGG Position Buffer */ + __u64 pos_buf_gpu_addr; + /* NGG Control Sideband */ + __u64 cntl_sb_buf_gpu_addr; + /* NGG Parameter Cache */ + __u64 param_buf_gpu_addr; + __u32 prim_buf_size; + __u32 pos_buf_size; + __u32 cntl_sb_buf_size; + __u32 param_buf_size; + /* wavefront size*/ + __u32 wave_front_size; + /* shader visible vgprs*/ + __u32 num_shader_visible_vgprs; + /* CU per shader array*/ + __u32 num_cu_per_sh; + /* number of tcc blocks*/ + __u32 num_tcc_blocks; + /* gs vgt table depth*/ + __u32 gs_vgt_table_depth; + /* gs primitive buffer depth*/ + __u32 gs_prim_buffer_depth; + /* max gs wavefront per vgt*/ + __u32 max_gs_waves_per_vgt; + __u32 _pad1; + /* always on cu bitmap */ + __u32 cu_ao_bitmap[4][4]; + /** Starting high virtual address for UMDs. */ + __u64 high_va_offset; + /** The maximum high virtual address */ + __u64 high_va_max; }; struct drm_amdgpu_info_hw_ip { /** Version of h/w IP */ - uint32_t hw_ip_version_major; - uint32_t hw_ip_version_minor; + __u32 hw_ip_version_major; + __u32 hw_ip_version_minor; /** Capabilities */ - uint64_t capabilities_flags; + __u64 capabilities_flags; /** command buffer address start alignment*/ - uint32_t ib_start_alignment; + __u32 ib_start_alignment; /** command buffer size alignment*/ - uint32_t ib_size_alignment; + __u32 ib_size_alignment; /** Bitmask of available rings. Bit 0 means ring 0, etc. */ - uint32_t available_rings; - uint32_t _pad; + __u32 available_rings; + __u32 _pad; +}; + +struct drm_amdgpu_info_num_handles { + /** Max handles as supported by firmware for UVD */ + __u32 uvd_max_handles; + /** Handles currently in use for UVD */ + __u32 uvd_used_handles; +}; + +#define AMDGPU_VCE_CLOCK_TABLE_ENTRIES 6 + +struct drm_amdgpu_info_vce_clock_table_entry { + /** System clock */ + __u32 sclk; + /** Memory clock */ + __u32 mclk; + /** VCE clock */ + __u32 eclk; + __u32 pad; +}; + +struct drm_amdgpu_info_vce_clock_table { + struct drm_amdgpu_info_vce_clock_table_entry entries[AMDGPU_VCE_CLOCK_TABLE_ENTRIES]; + __u32 num_valid_entries; + __u32 pad; }; /* * Supported GPU families */ #define AMDGPU_FAMILY_UNKNOWN 0 +#define AMDGPU_FAMILY_SI 110 /* Hainan, Oland, Verde, Pitcairn, Tahiti */ #define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */ #define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */ #define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */ #define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */ +#define AMDGPU_FAMILY_AI 141 /* Vega10 */ +#define AMDGPU_FAMILY_RV 142 /* Raven */ #if defined(__cplusplus) } diff --git a/include/drm/drm.h b/include/drm/drm.h index f6fd5c2c..85c685a2 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -641,6 +641,8 @@ struct drm_gem_open { #define DRM_CAP_CURSOR_HEIGHT 0x9 #define DRM_CAP_ADDFB2_MODIFIERS 0x10 #define DRM_CAP_PAGE_FLIP_TARGET 0x11 +#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 +#define DRM_CAP_SYNCOBJ 0x13 /** DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { @@ -672,6 +674,22 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_ATOMIC 3 +/** + * DRM_CLIENT_CAP_ASPECT_RATIO + * + * If set to 1, the DRM core will provide aspect ratio information in modes. + */ +#define DRM_CLIENT_CAP_ASPECT_RATIO 4 + +/** + * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS + * + * If set to 1, the DRM core will expose special connectors to be used for + * writing back to memory the scene setup in the commit. Depends on client + * also supporting DRM_CLIENT_CAP_ATOMIC + */ +#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; @@ -690,6 +708,67 @@ struct drm_prime_handle { __s32 fd; }; +struct drm_syncobj_create { + __u32 handle; +#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0) + __u32 flags; +}; + +struct drm_syncobj_destroy { + __u32 handle; + __u32 pad; +}; + +#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) +#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) +struct drm_syncobj_handle { + __u32 handle; + __u32 flags; + + __s32 fd; + __u32 pad; +}; + +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) +struct drm_syncobj_wait { + __u64 handles; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + +struct drm_syncobj_array { + __u64 handles; + __u32 count_handles; + __u32 pad; +}; + +/* Query current scanout sequence number */ +struct drm_crtc_get_sequence { + __u32 crtc_id; /* requested crtc_id */ + __u32 active; /* return: crtc output is active */ + __u64 sequence; /* return: most recent vblank sequence */ + __s64 sequence_ns; /* return: most recent time of first pixel out */ +}; + +/* Queue event to be delivered at specified sequence. Time stamp marks + * when the first pixel of the refresh cycle leaves the display engine + * for the display + */ +#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001 /* sequence is relative to current */ +#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002 /* Use next sequence if we've missed */ + +struct drm_crtc_queue_sequence { + __u32 crtc_id; + __u32 flags; + __u64 sequence; /* on input, target sequence. on output, actual sequence */ + __u64 user_data; /* user data passed to event */ +}; + #if defined(__cplusplus) } #endif @@ -772,6 +851,9 @@ extern "C" { #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) +#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence) +#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence) + #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) #define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) @@ -808,6 +890,19 @@ extern "C" { #define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) #define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) +#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create) +#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) +#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait) +#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array) +#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array) + +#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease) +#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees) +#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease) +#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease) + /** * Device specific ioctls should only be in their respective headers * The device specific ioctl range is from 0x40 to 0x9f. @@ -838,6 +933,7 @@ struct drm_event { #define DRM_EVENT_VBLANK 0x01 #define DRM_EVENT_FLIP_COMPLETE 0x02 +#define DRM_EVENT_CRTC_SEQUENCE 0x03 struct drm_event_vblank { struct drm_event base; @@ -845,7 +941,17 @@ struct drm_event_vblank { __u32 tv_sec; __u32 tv_usec; __u32 sequence; - __u32 reserved; + __u32 crtc_id; /* 0 on older kernels that do not support this */ +}; + +/* Event delivered at sequence. Time stamp marks when the first pixel + * of the refresh cycle leaves the display engine for the display + */ +struct drm_event_crtc_sequence { + struct drm_event base; + __u64 user_data; + __s64 time_ns; + __u64 sequence; }; /* typedef area */ diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 4d8da699..139632b8 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -26,21 +26,71 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * DOC: overview + * + * In the DRM subsystem, framebuffer pixel formats are described using the + * fourcc codes defined in `include/uapi/drm/drm_fourcc.h`. In addition to the + * fourcc code, a Format Modifier may optionally be provided, in order to + * further describe the buffer's format - for example tiling or compression. + * + * Format Modifiers + * ---------------- + * + * Format modifiers are used in conjunction with a fourcc code, forming a + * unique fourcc:modifier pair. This format:modifier pair must fully define the + * format and data layout of the buffer, and should be the only way to describe + * that particular buffer. + * + * Having multiple fourcc:modifier pairs which describe the same layout should + * be avoided, as such aliases run the risk of different drivers exposing + * different names for the same data format, forcing userspace to understand + * that they are aliases. + * + * Format modifiers may change any property of the buffer, including the number + * of planes and/or the required allocation size. Format modifiers are + * vendor-namespaced, and as such the relationship between a fourcc code and a + * modifier is specific to the modifer being used. For example, some modifiers + * may preserve meaning - such as number of planes - from the fourcc code, + * whereas others may not. + * + * Vendors should document their modifier usage in as much detail as + * possible, to ensure maximum compatibility across devices, drivers and + * applications. + * + * The authoritative list of format modifier codes is found in + * `include/uapi/drm/drm_fourcc.h` + */ + #define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \ ((__u32)(c) << 16) | ((__u32)(d) << 24)) #define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ +/* Reserve 0 for the invalid format specifier */ +#define DRM_FORMAT_INVALID 0 + /* color index */ #define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ /* 8 bpp Red */ #define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ +/* 16 bpp Red */ +#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ + /* 16 bpp RG */ #define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */ #define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ +/* 32 bpp RG */ +#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */ +#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */ + /* 8 bpp RGB */ #define DRM_FORMAT_RGB332 fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ #define DRM_FORMAT_BGR233 fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ @@ -103,6 +153,20 @@ #define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ /* + * 2 plane RGB + A + * index 0 = RGB plane, same format as the corresponding non _A8 format has + * index 1 = A plane, [7:0] A + */ +#define DRM_FORMAT_XRGB8888_A8 fourcc_code('X', 'R', 'A', '8') +#define DRM_FORMAT_XBGR8888_A8 fourcc_code('X', 'B', 'A', '8') +#define DRM_FORMAT_RGBX8888_A8 fourcc_code('R', 'X', 'A', '8') +#define DRM_FORMAT_BGRX8888_A8 fourcc_code('B', 'X', 'A', '8') +#define DRM_FORMAT_RGB888_A8 fourcc_code('R', '8', 'A', '8') +#define DRM_FORMAT_BGR888_A8 fourcc_code('B', '8', 'A', '8') +#define DRM_FORMAT_RGB565_A8 fourcc_code('R', '5', 'A', '8') +#define DRM_FORMAT_BGR565_A8 fourcc_code('B', '5', 'A', '8') + +/* * 2 plane YCbCr * index 0 = Y plane, [7:0] Y * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian @@ -150,15 +214,21 @@ /* Vendor Ids: */ #define DRM_FORMAT_MOD_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_NONE 0 #define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 #define DRM_FORMAT_MOD_VENDOR_AMD 0x02 -#define DRM_FORMAT_MOD_VENDOR_NV 0x03 +#define DRM_FORMAT_MOD_VENDOR_NVIDIA 0x03 #define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04 #define DRM_FORMAT_MOD_VENDOR_QCOM 0x05 +#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06 +#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 +#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 /* add more to the end as needed */ +#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) + #define fourcc_mod_code(vendor, val) \ - ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL)) + ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL)) /* * Format Modifier tokens: @@ -168,6 +238,25 @@ * authoritative source for all of these. */ +/* + * Invalid Modifier + * + * This modifier can be used as a sentinel to terminate the format modifiers + * list, or to initialize a variable with an invalid modifier. It might also be + * used to report an error back to userspace for certain APIs. + */ +#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED) + +/* + * Linear Layout + * + * Just plain linear layout. Note that this is different from no specifying any + * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl), + * which tells the driver to also take driver-internal information into account + * and so might actually result in a tiled framebuffer. + */ +#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0) + /* Intel framebuffer modifiers */ /* @@ -215,6 +304,26 @@ #define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3) /* + * Intel color control surface (CCS) for render compression + * + * The framebuffer format must be one of the 8:8:8:8 RGB formats. + * The main surface will be plane index 0 and must be Y/Yf-tiled, + * the CCS will be plane index 1. + * + * Each CCS tile matches a 1024x512 pixel area of the main surface. + * To match certain aspects of the 3D hardware the CCS is + * considered to be made up of normal 128Bx32 Y tiles, Thus + * the CCS pitch must be specified in multiples of 128 bytes. + * + * In reality the CCS tile appears to be a 64Bx64 Y tile, composed + * of QWORD (8 bytes) chunks instead of OWORD (16 bytes) chunks. + * But that fact is not relevant unless the memory is accessed + * directly. + */ +#define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4) +#define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5) + +/* * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks * * Macroblocks are laid in a Z-shape, and each pixel data is following the @@ -229,4 +338,290 @@ */ #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1) +/* + * Qualcomm Compressed Format + * + * Refers to a compressed variant of the base format that is compressed. + * Implementation may be platform and base-format specific. + * + * Each macrotile consists of m x n (mostly 4 x 4) tiles. + * Pixel data pitch/stride is aligned with macrotile width. + * Pixel data height is aligned with macrotile height. + * Entire pixel data buffer is aligned with 4k(bytes). + */ +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) + +/* Vivante framebuffer modifiers */ + +/* + * Vivante 4x4 tiling layout + * + * This is a simple tiled layout using tiles of 4x4 pixels in a row-major + * layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1) + +/* + * Vivante 64x64 super-tiling layout + * + * This is a tiled layout using 64x64 pixel super-tiles, where each super-tile + * contains 8x4 groups of 2x4 tiles of 4x4 pixels (like above) each, all in row- + * major layout. + * + * For more information: see + * https://github.com/etnaviv/etna_viv/blob/master/doc/hardware.md#texture-tiling + */ +#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2) + +/* + * Vivante 4x4 tiling layout for dual-pipe + * + * Same as the 4x4 tiling layout, except every second 4x4 pixel tile starts at a + * different base address. Offsets from the base addresses are therefore halved + * compared to the non-split tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3) + +/* + * Vivante 64x64 super-tiling layout for dual-pipe + * + * Same as the 64x64 super-tiling layout, except every second 4x4 pixel tile + * starts at a different base address. Offsets from the base addresses are + * therefore halved compared to the non-split super-tiled layout. + */ +#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4) + +/* NVIDIA frame buffer modifiers */ + +/* + * Tegra Tiled Layout, used by Tegra 2, 3 and 4. + * + * Pixels are arranged in simple tiles of 16 x 16 bytes. + */ +#define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1) + +/* + * 16Bx2 Block Linear layout, used by desktop GPUs, and Tegra K1 and later + * + * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked + * vertically by a power of 2 (1 to 32 GOBs) to form a block. + * + * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape. + * + * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically. + * Valid values are: + * + * 0 == ONE_GOB + * 1 == TWO_GOBS + * 2 == FOUR_GOBS + * 3 == EIGHT_GOBS + * 4 == SIXTEEN_GOBS + * 5 == THIRTYTWO_GOBS + * + * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format + * in full detail. + */ +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) \ + fourcc_mod_code(NVIDIA, 0x10 | ((v) & 0xf)) + +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB \ + fourcc_mod_code(NVIDIA, 0x10) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB \ + fourcc_mod_code(NVIDIA, 0x11) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB \ + fourcc_mod_code(NVIDIA, 0x12) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB \ + fourcc_mod_code(NVIDIA, 0x13) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB \ + fourcc_mod_code(NVIDIA, 0x14) +#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \ + fourcc_mod_code(NVIDIA, 0x15) + +/* + * Some Broadcom modifiers take parameters, for example the number of + * vertical lines in the image. Reserve the lower 32 bits for modifier + * type, and the next 24 bits for parameters. Top 8 bits are the + * vendor code. + */ +#define __fourcc_mod_broadcom_param_shift 8 +#define __fourcc_mod_broadcom_param_bits 48 +#define fourcc_mod_broadcom_code(val, params) \ + fourcc_mod_code(BROADCOM, ((((__u64)params) << __fourcc_mod_broadcom_param_shift) | val)) +#define fourcc_mod_broadcom_param(m) \ + ((int)(((m) >> __fourcc_mod_broadcom_param_shift) & \ + ((1ULL << __fourcc_mod_broadcom_param_bits) - 1))) +#define fourcc_mod_broadcom_mod(m) \ + ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) << \ + __fourcc_mod_broadcom_param_shift)) + +/* + * Broadcom VC4 "T" format + * + * This is the primary layout that the V3D GPU can texture from (it + * can't do linear). The T format has: + * + * - 64b utiles of pixels in a raster-order grid according to cpp. It's 4x4 + * pixels at 32 bit depth. + * + * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually + * 16x16 pixels). + * + * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels). On + * even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows + * they're (TR, BR, BL, TL), where bottom left is start of memory. + * + * - an image made of 4k tiles in rows either left-to-right (even rows of 4k + * tiles) or right-to-left (odd rows of 4k tiles). + */ +#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1) + +/* + * Broadcom SAND format + * + * This is the native format that the H.264 codec block uses. For VC4 + * HVS, it is only valid for H.264 (NV12/21) and RGBA modes. + * + * The image can be considered to be split into columns, and the + * columns are placed consecutively into memory. The width of those + * columns can be either 32, 64, 128, or 256 pixels, but in practice + * only 128 pixel columns are used. + * + * The pitch between the start of each column is set to optimally + * switch between SDRAM banks. This is passed as the number of lines + * of column width in the modifier (we can't use the stride value due + * to various core checks that look at it , so you should set the + * stride to width*cpp). + * + * Note that the column height for this format modifier is the same + * for all of the planes, assuming that each column contains both Y + * and UV. Some SAND-using hardware stores UV in a separate tiled + * image from Y to reduce the column height, which is not supported + * with these modifiers. + */ + +#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(2, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(3, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(4, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(5, v) + +#define DRM_FORMAT_MOD_BROADCOM_SAND32 \ + DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND64 \ + DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND128 \ + DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND256 \ + DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0) + +/* Broadcom UIF format + * + * This is the common format for the current Broadcom multimedia + * blocks, including V3D 3.x and newer, newer video codecs, and + * displays. + * + * The image consists of utiles (64b blocks), UIF blocks (2x2 utiles), + * and macroblocks (4x4 UIF blocks). Those 4x4 UIF block groups are + * stored in columns, with padding between the columns to ensure that + * moving from one column to the next doesn't hit the same SDRAM page + * bank. + * + * To calculate the padding, it is assumed that each hardware block + * and the software driving it knows the platform's SDRAM page size, + * number of banks, and XOR address, and that it's identical between + * all blocks using the format. This tiling modifier will use XOR as + * necessary to reduce the padding. If a hardware block can't do XOR, + * the assumption is that a no-XOR tiling modifier will be created. + */ +#define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6) + +/* + * Arm Framebuffer Compression (AFBC) modifiers + * + * AFBC is a proprietary lossless image compression protocol and format. + * It provides fine-grained random access and minimizes the amount of data + * transferred between IP blocks. + * + * AFBC has several features which may be supported and/or used, which are + * represented using bits in the modifier. Not all combinations are valid, + * and different devices or use-cases may support different combinations. + */ +#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode) + +/* + * AFBC superblock size + * + * Indicates the superblock size(s) used for the AFBC buffer. The buffer + * size (in pixels) must be aligned to a multiple of the superblock size. + * Four lowest significant bits(LSBs) are reserved for block size. + */ +#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf +#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL) + +/* + * AFBC lossless colorspace transform + * + * Indicates that the buffer makes use of the AFBC lossless colorspace + * transform. + */ +#define AFBC_FORMAT_MOD_YTR (1ULL << 4) + +/* + * AFBC block-split + * + * Indicates that the payload of each superblock is split. The second + * half of the payload is positioned at a predefined offset from the start + * of the superblock payload. + */ +#define AFBC_FORMAT_MOD_SPLIT (1ULL << 5) + +/* + * AFBC sparse layout + * + * This flag indicates that the payload of each superblock must be stored at a + * predefined position relative to the other superblocks in the same AFBC + * buffer. This order is the same order used by the header buffer. In this mode + * each superblock is given the same amount of space as an uncompressed + * superblock of the particular format would require, rounding up to the next + * multiple of 128 bytes in size. + */ +#define AFBC_FORMAT_MOD_SPARSE (1ULL << 6) + +/* + * AFBC copy-block restrict + * + * Buffers with this flag must obey the copy-block restriction. The restriction + * is such that there are no copy-blocks referring across the border of 8x8 + * blocks. For the subsampled data the 8x8 limitation is also subsampled. + */ +#define AFBC_FORMAT_MOD_CBR (1ULL << 7) + +/* + * AFBC tiled layout + * + * The tiled layout groups superblocks in 8x8 or 4x4 tiles, where all + * superblocks inside a tile are stored together in memory. 8x8 tiles are used + * for pixel formats up to and including 32 bpp while 4x4 tiles are used for + * larger bpp formats. The order between the tiles is scan line. + * When the tiled layout is used, the buffer size (in pixels) must be aligned + * to the tile size. + */ +#define AFBC_FORMAT_MOD_TILED (1ULL << 8) + +/* + * AFBC solid color blocks + * + * Indicates that the buffer makes use of solid-color blocks, whereby bandwidth + * can be reduced if a whole superblock is a single color. + */ +#define AFBC_FORMAT_MOD_SC (1ULL << 9) + +#if defined(__cplusplus) +} +#endif + #endif /* DRM_FOURCC_H */ diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 6708e2b7..d3e0fe31 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -38,16 +38,28 @@ extern "C" { #define DRM_DISPLAY_MODE_LEN 32 #define DRM_PROP_NAME_LEN 32 -#define DRM_MODE_TYPE_BUILTIN (1<<0) -#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) -#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_BUILTIN (1<<0) /* deprecated */ +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ #define DRM_MODE_TYPE_PREFERRED (1<<3) -#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_DEFAULT (1<<4) /* deprecated */ #define DRM_MODE_TYPE_USERDEF (1<<5) #define DRM_MODE_TYPE_DRIVER (1<<6) +#define DRM_MODE_TYPE_ALL (DRM_MODE_TYPE_PREFERRED | \ + DRM_MODE_TYPE_USERDEF | \ + DRM_MODE_TYPE_DRIVER) + /* Video mode flags */ -/* bit compatible with the xorg definitions. */ +/* bit compatible with the xrandr RR_ definitions (bits 0-13) + * + * ABI warning: Existing userspace really expects + * the mode flags to match the xrandr definitions. Any + * changes that don't match the xrandr definitions will + * likely need a new client cap or some other mechanism + * to avoid breaking existing userspace. This includes + * allocating new flags in the previously unused bits! + */ #define DRM_MODE_FLAG_PHSYNC (1<<0) #define DRM_MODE_FLAG_NHSYNC (1<<1) #define DRM_MODE_FLAG_PVSYNC (1<<2) @@ -58,8 +70,8 @@ extern "C" { #define DRM_MODE_FLAG_PCSYNC (1<<7) #define DRM_MODE_FLAG_NCSYNC (1<<8) #define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ -#define DRM_MODE_FLAG_BCAST (1<<10) -#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_BCAST (1<<10) /* deprecated */ +#define DRM_MODE_FLAG_PIXMUX (1<<11) /* deprecated */ #define DRM_MODE_FLAG_DBLCLK (1<<12) #define DRM_MODE_FLAG_CLKDIV2 (1<<13) /* @@ -67,7 +79,7 @@ extern "C" { * (define not exposed to user space). */ #define DRM_MODE_FLAG_3D_MASK (0x1f<<14) -#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) #define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) #define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) #define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) @@ -77,6 +89,46 @@ extern "C" { #define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) #define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) +/* Picture aspect ratio options */ +#define DRM_MODE_PICTURE_ASPECT_NONE 0 +#define DRM_MODE_PICTURE_ASPECT_4_3 1 +#define DRM_MODE_PICTURE_ASPECT_16_9 2 +#define DRM_MODE_PICTURE_ASPECT_64_27 3 +#define DRM_MODE_PICTURE_ASPECT_256_135 4 + +/* Content type options */ +#define DRM_MODE_CONTENT_TYPE_NO_DATA 0 +#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1 +#define DRM_MODE_CONTENT_TYPE_PHOTO 2 +#define DRM_MODE_CONTENT_TYPE_CINEMA 3 +#define DRM_MODE_CONTENT_TYPE_GAME 4 + +/* Aspect ratio flag bitmask (4 bits 22:19) */ +#define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) +#define DRM_MODE_FLAG_PIC_AR_NONE \ + (DRM_MODE_PICTURE_ASPECT_NONE<<19) +#define DRM_MODE_FLAG_PIC_AR_4_3 \ + (DRM_MODE_PICTURE_ASPECT_4_3<<19) +#define DRM_MODE_FLAG_PIC_AR_16_9 \ + (DRM_MODE_PICTURE_ASPECT_16_9<<19) +#define DRM_MODE_FLAG_PIC_AR_64_27 \ + (DRM_MODE_PICTURE_ASPECT_64_27<<19) +#define DRM_MODE_FLAG_PIC_AR_256_135 \ + (DRM_MODE_PICTURE_ASPECT_256_135<<19) + +#define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ + DRM_MODE_FLAG_NHSYNC | \ + DRM_MODE_FLAG_PVSYNC | \ + DRM_MODE_FLAG_NVSYNC | \ + DRM_MODE_FLAG_INTERLACE | \ + DRM_MODE_FLAG_DBLSCAN | \ + DRM_MODE_FLAG_CSYNC | \ + DRM_MODE_FLAG_PCSYNC | \ + DRM_MODE_FLAG_NCSYNC | \ + DRM_MODE_FLAG_HSKEW | \ + DRM_MODE_FLAG_DBLCLK | \ + DRM_MODE_FLAG_CLKDIV2 | \ + DRM_MODE_FLAG_3D_MASK) /* DPMS flags */ /* bit compatible with the xorg definitions. */ @@ -92,11 +144,6 @@ extern "C" { #define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ #define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ -/* Picture aspect ratio options */ -#define DRM_MODE_PICTURE_ASPECT_NONE 0 -#define DRM_MODE_PICTURE_ASPECT_4_3 1 -#define DRM_MODE_PICTURE_ASPECT_16_9 2 - /* Dithering mode options */ #define DRM_MODE_DITHERING_OFF 0 #define DRM_MODE_DITHERING_ON 1 @@ -107,13 +154,61 @@ extern "C" { #define DRM_MODE_DIRTY_ON 1 #define DRM_MODE_DIRTY_ANNOTATE 2 -/* rotation property bits */ -#define DRM_ROTATE_0 0 -#define DRM_ROTATE_90 1 -#define DRM_ROTATE_180 2 -#define DRM_ROTATE_270 3 -#define DRM_REFLECT_X 4 -#define DRM_REFLECT_Y 5 +/* Link Status options */ +#define DRM_MODE_LINK_STATUS_GOOD 0 +#define DRM_MODE_LINK_STATUS_BAD 1 + +/* + * DRM_MODE_ROTATE_<degrees> + * + * Signals that a drm plane is been rotated <degrees> degrees in counter + * clockwise direction. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_ROTATE_0 (1<<0) +#define DRM_MODE_ROTATE_90 (1<<1) +#define DRM_MODE_ROTATE_180 (1<<2) +#define DRM_MODE_ROTATE_270 (1<<3) + +/* + * DRM_MODE_ROTATE_MASK + * + * Bitmask used to look for drm plane rotations. + */ +#define DRM_MODE_ROTATE_MASK (\ + DRM_MODE_ROTATE_0 | \ + DRM_MODE_ROTATE_90 | \ + DRM_MODE_ROTATE_180 | \ + DRM_MODE_ROTATE_270) + +/* + * DRM_MODE_REFLECT_<axis> + * + * Signals that the contents of a drm plane is reflected along the <axis> axis, + * in the same way as mirroring. + * See kerneldoc chapter "Plane Composition Properties" for more details. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_REFLECT_X (1<<4) +#define DRM_MODE_REFLECT_Y (1<<5) + +/* + * DRM_MODE_REFLECT_MASK + * + * Bitmask used to look for drm plane reflections. + */ +#define DRM_MODE_REFLECT_MASK (\ + DRM_MODE_REFLECT_X | \ + DRM_MODE_REFLECT_Y) + +/* Content Protection Flags */ +#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED 0 +#define DRM_MODE_CONTENT_PROTECTION_DESIRED 1 +#define DRM_MODE_CONTENT_PROTECTION_ENABLED 2 struct drm_mode_modeinfo { __u32 clock; @@ -228,14 +323,16 @@ struct drm_mode_get_encoder { /* This is for connectors with multiple signal types. */ /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ -#define DRM_MODE_SUBCONNECTOR_Automatic 0 -#define DRM_MODE_SUBCONNECTOR_Unknown 0 -#define DRM_MODE_SUBCONNECTOR_DVID 3 -#define DRM_MODE_SUBCONNECTOR_DVIA 4 -#define DRM_MODE_SUBCONNECTOR_Composite 5 -#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 -#define DRM_MODE_SUBCONNECTOR_Component 8 -#define DRM_MODE_SUBCONNECTOR_SCART 9 +enum drm_mode_subconnector { + DRM_MODE_SUBCONNECTOR_Automatic = 0, + DRM_MODE_SUBCONNECTOR_Unknown = 0, + DRM_MODE_SUBCONNECTOR_DVID = 3, + DRM_MODE_SUBCONNECTOR_DVIA = 4, + DRM_MODE_SUBCONNECTOR_Composite = 5, + DRM_MODE_SUBCONNECTOR_SVIDEO = 6, + DRM_MODE_SUBCONNECTOR_Component = 8, + DRM_MODE_SUBCONNECTOR_SCART = 9, +}; #define DRM_MODE_CONNECTOR_Unknown 0 #define DRM_MODE_CONNECTOR_VGA 1 @@ -255,6 +352,7 @@ struct drm_mode_get_encoder { #define DRM_MODE_CONNECTOR_VIRTUAL 15 #define DRM_MODE_CONNECTOR_DSI 16 #define DRM_MODE_CONNECTOR_DPI 17 +#define DRM_MODE_CONNECTOR_WRITEBACK 18 struct drm_mode_get_connector { @@ -280,7 +378,7 @@ struct drm_mode_get_connector { __u32 pad; }; -#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */ #define DRM_MODE_PROP_RANGE (1<<1) #define DRM_MODE_PROP_IMMUTABLE (1<<2) #define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ @@ -400,17 +498,20 @@ struct drm_mode_fb_cmd2 { * offsets[1]. Note that offsets[0] will generally * be 0 (but this is not required). * - * To accommodate tiled, compressed, etc formats, a per-plane + * To accommodate tiled, compressed, etc formats, a * modifier can be specified. The default value of zero * indicates "native" format as specified by the fourcc. - * Vendor specific modifier token. This allows, for example, - * different tiling/swizzling pattern on different planes. - * See discussion above of DRM_FORMAT_MOD_xxx. + * Vendor specific modifier token. Note that even though + * it looks like we have a modifier per-plane, we in fact + * do not. The modifier for each plane must be identical. + * Thus all combinations of different data layouts for + * multi plane formats must be enumerated as separate + * modifiers. */ __u32 handles[4]; __u32 pitches[4]; /* pitch for each plane */ __u32 offsets[4]; /* offset of each plane */ - __u64 modifier[4]; /* ie, tiling, compressed (per plane) */ + __u64 modifier[4]; /* ie, tiling, compress */ }; #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 @@ -512,8 +613,11 @@ struct drm_mode_crtc_lut { }; struct drm_color_ctm { - /* Conversion matrix in S31.32 format. */ - __s64 matrix[9]; + /* + * Conversion matrix in S31.32 sign-magnitude + * (not two's complement!) format. + */ + __u64 matrix[9]; }; struct drm_color_lut { @@ -637,13 +741,6 @@ struct drm_mode_destroy_dumb { DRM_MODE_ATOMIC_NONBLOCK |\ DRM_MODE_ATOMIC_ALLOW_MODESET) -#define DRM_MODE_ATOMIC_FLAGS (\ - DRM_MODE_PAGE_FLIP_EVENT |\ - DRM_MODE_PAGE_FLIP_ASYNC |\ - DRM_MODE_ATOMIC_TEST_ONLY |\ - DRM_MODE_ATOMIC_NONBLOCK |\ - DRM_MODE_ATOMIC_ALLOW_MODESET) - struct drm_mode_atomic { __u32 flags; __u32 count_objs; @@ -655,6 +752,56 @@ struct drm_mode_atomic { __u64 user_data; }; +struct drm_format_modifier_blob { +#define FORMAT_BLOB_CURRENT 1 + /* Version of this blob format */ + __u32 version; + + /* Flags */ + __u32 flags; + + /* Number of fourcc formats supported */ + __u32 count_formats; + + /* Where in this blob the formats exist (in bytes) */ + __u32 formats_offset; + + /* Number of drm_format_modifiers */ + __u32 count_modifiers; + + /* Where in this blob the modifiers exist (in bytes) */ + __u32 modifiers_offset; + + /* __u32 formats[] */ + /* struct drm_format_modifier modifiers[] */ +}; + +struct drm_format_modifier { + /* Bitmask of formats in get_plane format list this info applies to. The + * offset allows a sliding window of which 64 formats (bits). + * + * Some examples: + * In today's world with < 65 formats, and formats 0, and 2 are + * supported + * 0x0000000000000005 + * ^-offset = 0, formats = 5 + * + * If the number formats grew to 128, and formats 98-102 are + * supported with the modifier: + * + * 0x0000007c00000000 0000000000000000 + * ^ + * |__offset = 64, formats = 0x7c00000000 + * + */ + __u64 formats; + __u32 offset; + __u32 pad; + + /* The modifier that applies to the >get_plane format list bitmask. */ + __u64 modifier; +}; + /** * Create a new 'blob' data property, copying length bytes from data pointer, * and returning new blob ID. @@ -675,6 +822,72 @@ struct drm_mode_destroy_blob { __u32 blob_id; }; +/** + * Lease mode resources, creating another drm_master. + */ +struct drm_mode_create_lease { + /** Pointer to array of object ids (__u32) */ + __u64 object_ids; + /** Number of object ids */ + __u32 object_count; + /** flags for new FD (O_CLOEXEC, etc) */ + __u32 flags; + + /** Return: unique identifier for lessee. */ + __u32 lessee_id; + /** Return: file descriptor to new drm_master file */ + __u32 fd; +}; + +/** + * List lesses from a drm_master + */ +struct drm_mode_list_lessees { + /** Number of lessees. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_lessees; + __u32 pad; + + /** Pointer to lessees. + * pointer to __u64 array of lessee ids + */ + __u64 lessees_ptr; +}; + +/** + * Get leased objects + */ +struct drm_mode_get_lease { + /** Number of leased objects. + * On input, provides length of the array. + * On output, provides total number. No + * more than the input number will be written + * back, so two calls can be used to get + * the size and then the data. + */ + __u32 count_objects; + __u32 pad; + + /** Pointer to objects. + * pointer to __u32 array of object ids + */ + __u64 objects_ptr; +}; + +/** + * Revoke lease + */ +struct drm_mode_revoke_lease { + /** Unique ID of lessee + */ + __u32 lessee_id; +}; + #if defined(__cplusplus) } #endif diff --git a/include/drm/drm_sarea.h b/include/drm/drm_sarea.h index 502934ed..93025be8 100644 --- a/include/drm/drm_sarea.h +++ b/include/drm/drm_sarea.h @@ -34,6 +34,10 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + /* SAREA area needs to be at least a page */ #if defined(__alpha__) #define SAREA_MAX 0x2000U @@ -81,4 +85,8 @@ typedef struct drm_sarea_drawable drm_sarea_drawable_t; typedef struct drm_sarea_frame drm_sarea_frame_t; typedef struct drm_sarea drm_sarea_t; +#if defined(__cplusplus) +} +#endif + #endif /* _DRM_SAREA_H_ */ diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 5ebe0462..268b585f 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -86,6 +86,62 @@ enum i915_mocs_table_index { I915_MOCS_CACHED, }; +/* + * Different engines serve different roles, and there may be more than one + * engine serving each role. enum drm_i915_gem_engine_class provides a + * classification of the role of the engine, which may be used when requesting + * operations to be performed on a certain subset of engines, or for providing + * information about that group. + */ +enum drm_i915_gem_engine_class { + I915_ENGINE_CLASS_RENDER = 0, + I915_ENGINE_CLASS_COPY = 1, + I915_ENGINE_CLASS_VIDEO = 2, + I915_ENGINE_CLASS_VIDEO_ENHANCE = 3, + + I915_ENGINE_CLASS_INVALID = -1 +}; + +/** + * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915 + * + */ + +enum drm_i915_pmu_engine_sample { + I915_SAMPLE_BUSY = 0, + I915_SAMPLE_WAIT = 1, + I915_SAMPLE_SEMA = 2 +}; + +#define I915_PMU_SAMPLE_BITS (4) +#define I915_PMU_SAMPLE_MASK (0xf) +#define I915_PMU_SAMPLE_INSTANCE_BITS (8) +#define I915_PMU_CLASS_SHIFT \ + (I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS) + +#define __I915_PMU_ENGINE(class, instance, sample) \ + ((class) << I915_PMU_CLASS_SHIFT | \ + (instance) << I915_PMU_SAMPLE_BITS | \ + (sample)) + +#define I915_PMU_ENGINE_BUSY(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY) + +#define I915_PMU_ENGINE_WAIT(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT) + +#define I915_PMU_ENGINE_SEMA(class, instance) \ + __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA) + +#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x)) + +#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0) +#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1) +#define I915_PMU_INTERRUPTS __I915_PMU_OTHER(2) +#define I915_PMU_RC6_RESIDENCY __I915_PMU_OTHER(3) + +#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY + /* Each region is a minimum of 16k, and there are at most 255 of them. */ #define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use @@ -260,6 +316,9 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_CONTEXT_GETPARAM 0x34 #define DRM_I915_GEM_CONTEXT_SETPARAM 0x35 #define DRM_I915_PERF_OPEN 0x36 +#define DRM_I915_PERF_ADD_CONFIG 0x37 +#define DRM_I915_PERF_REMOVE_CONFIG 0x38 +#define DRM_I915_QUERY 0x39 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -315,6 +374,9 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param) #define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param) #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) +#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) +#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -393,10 +455,20 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_MIN_EU_IN_POOL 39 #define I915_PARAM_MMAP_GTT_VERSION 40 -/* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution * priorities and the driver will attempt to execute batches in priority order. + * The param returns a capability bitmask, nonzero implies that the scheduler + * is enabled, with different features present according to the mask. + * + * The initial priority for each batch is supplied by the context and is + * controlled via I915_CONTEXT_PARAM_PRIORITY. */ #define I915_PARAM_HAS_SCHEDULER 41 +#define I915_SCHEDULER_CAP_ENABLED (1ul << 0) +#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1) +#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2) + #define I915_PARAM_HUC_STATUS 42 /* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of @@ -412,6 +484,73 @@ typedef struct drm_i915_irq_wait { */ #define I915_PARAM_HAS_EXEC_FENCE 44 +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture + * user specified bufffers for post-mortem debugging of GPU hangs. See + * EXEC_OBJECT_CAPTURE. + */ +#define I915_PARAM_HAS_EXEC_CAPTURE 45 + +#define I915_PARAM_SLICE_MASK 46 + +/* Assuming it's uniform for each slice, this queries the mask of subslices + * per-slice for this system. + */ +#define I915_PARAM_SUBSLICE_MASK 47 + +/* + * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer + * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST. + */ +#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48 + +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of + * drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY. + */ +#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49 + +/* + * Query whether every context (both per-file default and user created) is + * isolated (insofar as HW supports). If this parameter is not true, then + * freshly created contexts may inherit values from an existing context, + * rather than default HW values. If true, it also ensures (insofar as HW + * supports) that all state set by this context will not leak to any other + * context. + * + * As not every engine across every gen support contexts, the returned + * value reports the support of context isolation for individual engines by + * returning a bitmask of each engine class set to true if that class supports + * isolation. + */ +#define I915_PARAM_HAS_CONTEXT_ISOLATION 50 + +/* Frequency of the command streamer timestamps given by the *_TIMESTAMP + * registers. This used to be fixed per platform but from CNL onwards, this + * might vary depending on the parts. + */ +#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51 + +/* + * Once upon a time we supposed that writes through the GGTT would be + * immediately in physical memory (once flushed out of the CPU path). However, + * on a few different processors and chipsets, this is not necessarily the case + * as the writes appear to be buffered internally. Thus a read of the backing + * storage (physical memory) via a different path (with different physical tags + * to the indirect write via the GGTT) will see stale values from before + * the GGTT write. Inside the kernel, we can for the most part keep track of + * the different read/write domains in use (e.g. set-domain), but the assumption + * of coherency is baked into the ABI, hence reporting its true state in this + * parameter. + * + * Reports true when writes via mmap_gtt are immediately visible following an + * lfence to flush the WCB. + * + * Reports false when writes via mmap_gtt are indeterminately delayed in an in + * internal buffer and are _not_ immediately visible to third parties accessing + * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC + * communications channel when reporting false is strongly disadvised. + */ +#define I915_PARAM_MMAP_GTT_COHERENT 52 + typedef struct drm_i915_getparam { __s32 param; /* @@ -666,6 +805,8 @@ struct drm_i915_gem_relocation_entry { #define I915_GEM_DOMAIN_VERTEX 0x00000020 /** GTT domain - aperture and scanout */ #define I915_GEM_DOMAIN_GTT 0x00000040 +/** WC domain - uncached access */ +#define I915_GEM_DOMAIN_WC 0x00000080 /** @} */ struct drm_i915_gem_exec_object { @@ -773,8 +914,15 @@ struct drm_i915_gem_exec_object2 { * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously. */ #define EXEC_OBJECT_ASYNC (1<<6) +/* Request that the contents of this execobject be copied into the error + * state upon a GPU hang involving this batch for post-mortem debugging. + * These buffers are recorded in no particular order as "user" in + * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see + * if the kernel supports this flag. + */ +#define EXEC_OBJECT_CAPTURE (1<<7) /* All remaining bits are MBZ and RESERVED FOR FUTURE USE */ -#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_ASYNC<<1) +#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1) __u64 flags; union { @@ -784,6 +932,18 @@ struct drm_i915_gem_exec_object2 { __u64 rsvd2; }; +struct drm_i915_gem_exec_fence { + /** + * User's handle for a drm_syncobj to wait on or signal. + */ + __u32 handle; + +#define I915_EXEC_FENCE_WAIT (1<<0) +#define I915_EXEC_FENCE_SIGNAL (1<<1) +#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1)) + __u32 flags; +}; + struct drm_i915_gem_execbuffer2 { /** * List of gem_exec_object2 structs @@ -798,7 +958,11 @@ struct drm_i915_gem_execbuffer2 { __u32 DR1; __u32 DR4; __u32 num_cliprects; - /** This is a struct drm_clip_rect *cliprects */ + /** + * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY + * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a + * struct drm_i915_gem_exec_fence *fences. + */ __u64 cliprects_ptr; #define I915_EXEC_RING_MASK (7<<0) #define I915_EXEC_DEFAULT (0<<0) @@ -889,7 +1053,24 @@ struct drm_i915_gem_execbuffer2 { */ #define I915_EXEC_FENCE_OUT (1<<17) -#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_OUT<<1)) +/* + * Traditionally the execbuf ioctl has only considered the final element in + * the execobject[] to be the executable batch. Often though, the client + * will known the batch object prior to construction and being able to place + * it into the execobject[] array first can simplify the relocation tracking. + * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the + * execobject[] as the * batch instead (the default is to use the last + * element). + */ +#define I915_EXEC_BATCH_FIRST (1<<18) + +/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr + * define an array of i915_gem_exec_fence structures which specify a set of + * dma fences to wait upon or signal. + */ +#define I915_EXEC_FENCE_ARRAY (1<<19) + +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1)) #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ @@ -1201,7 +1382,9 @@ struct drm_intel_overlay_attrs { * active on a given plane. */ -#define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ +#define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set + * flags==0 to disable colorkeying. + */ #define I915_SET_COLORKEY_DESTINATION (1<<1) #define I915_SET_COLORKEY_SOURCE (1<<2) struct drm_intel_sprite_colorkey { @@ -1239,14 +1422,16 @@ struct drm_i915_reg_read { * be specified */ __u64 offset; +#define I915_REG_READ_8B_WA (1ul << 0) + __u64 val; /* Return value */ }; /* Known registers: * * Render engine timestamp - 0x2358 + 64bit - gen7+ * - Note this register returns an invalid value if using the default - * single instruction 8byte read, in order to workaround that use - * offset (0x2538 | 1) instead. + * single instruction 8byte read, in order to workaround that pass + * flag I915_REG_READ_8B_WA in offset field. * */ @@ -1289,17 +1474,26 @@ struct drm_i915_gem_context_param { #define I915_CONTEXT_PARAM_GTT_SIZE 0x3 #define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4 #define I915_CONTEXT_PARAM_BANNABLE 0x5 +#define I915_CONTEXT_PARAM_PRIORITY 0x6 +#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */ +#define I915_CONTEXT_DEFAULT_PRIORITY 0 +#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */ __u64 value; }; enum drm_i915_oa_format { - I915_OA_FORMAT_A13 = 1, - I915_OA_FORMAT_A29, - I915_OA_FORMAT_A13_B8_C8, - I915_OA_FORMAT_B4_C8, - I915_OA_FORMAT_A45_B8_C8, - I915_OA_FORMAT_B4_C8_A16, - I915_OA_FORMAT_C4_B8, + I915_OA_FORMAT_A13 = 1, /* HSW only */ + I915_OA_FORMAT_A29, /* HSW only */ + I915_OA_FORMAT_A13_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8, /* HSW only */ + I915_OA_FORMAT_A45_B8_C8, /* HSW only */ + I915_OA_FORMAT_B4_C8_A16, /* HSW only */ + I915_OA_FORMAT_C4_B8, /* HSW+ */ + + /* Gen8+ */ + I915_OA_FORMAT_A12, + I915_OA_FORMAT_A12_B8_C8, + I915_OA_FORMAT_A32u40_A4u32_B8_C8, I915_OA_FORMAT_MAX /* non-ABI */ }; @@ -1424,6 +1618,127 @@ enum drm_i915_perf_record_type { DRM_I915_PERF_RECORD_MAX /* non-ABI */ }; +/** + * Structure to upload perf dynamic configuration into the kernel. + */ +struct drm_i915_perf_oa_config { + /** String formatted like "%08x-%04x-%04x-%04x-%012x" */ + char uuid[36]; + + __u32 n_mux_regs; + __u32 n_boolean_regs; + __u32 n_flex_regs; + + /* + * These fields are pointers to tuples of u32 values (register address, + * value). For example the expected length of the buffer pointed by + * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). + */ + __u64 mux_regs_ptr; + __u64 boolean_regs_ptr; + __u64 flex_regs_ptr; +}; + +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_TOPOLOGY_INFO 1 + + /* + * When set to zero by userspace, this is filled with the size of the + * data to be written at the data_ptr pointer. The kernel sets this + * value to a negative value to signal an error on a particular query + * item. + */ + __s32 length; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * Data will be written at the location pointed by data_ptr when the + * value of length matches the length of the data to be written by the + * kernel. + */ + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 flags; + + /* + * This points to an array of num_items drm_i915_query_item structures. + */ + __u64 items_ptr; +}; + +/* + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : + * + * data: contains the 3 pieces of information : + * + * - the slice mask with one bit per slice telling whether a slice is + * available. The availability of slice X can be queried with the following + * formula : + * + * (data[X / 8] >> (X % 8)) & 1 + * + * - the subslice mask for each slice with one bit per subslice telling + * whether a subslice is available. The availability of subslice Y in slice + * X can be queried with the following formula : + * + * (data[subslice_offset + + * X * subslice_stride + + * Y / 8] >> (Y % 8)) & 1 + * + * - the EU mask for each subslice in each slice with one bit per EU telling + * whether an EU is available. The availability of EU Z in subslice Y in + * slice X can be queried with the following formula : + * + * (data[eu_offset + + * (X * max_subslices + Y) * eu_stride + + * Z / 8] >> (Z % 8)) & 1 + */ +struct drm_i915_query_topology_info { + /* + * Unused for now. Must be cleared to zero. + */ + __u16 flags; + + __u16 max_slices; + __u16 max_subslices; + __u16 max_eus_per_subslice; + + /* + * Offset in data[] at which the subslice masks are stored. + */ + __u16 subslice_offset; + + /* + * Stride at which each of the subslice masks for each slice are + * stored. + */ + __u16 subslice_stride; + + /* + * Offset in data[] at which the EU masks are stored. + */ + __u16 eu_offset; + + /* + * Stride at which each of the EU masks for each subslice are stored. + */ + __u16 eu_stride; + + __u8 data[]; +}; + #if defined(__cplusplus) } #endif diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h index b630e8fa..79300111 100644 --- a/include/drm/mga_drm.h +++ b/include/drm/mga_drm.h @@ -37,6 +37,10 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (mga_sarea.h) */ @@ -107,7 +111,7 @@ */ #define MGA_NR_SAREA_CLIPRECTS 8 -/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between @@ -248,7 +252,7 @@ typedef struct _drm_mga_sarea { #define DRM_MGA_DMA_BOOTSTRAP 0x0c #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) -#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) #define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) #define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) @@ -416,4 +420,8 @@ typedef struct drm_mga_getparam { void *value; } drm_mga_getparam_t; +#if defined(__cplusplus) +} +#endif + #endif diff --git a/freedreno/msm/msm_drm.h b/include/drm/msm_drm.h index ed4c8d47..c06d0a5b 100644 --- a/freedreno/msm/msm_drm.h +++ b/include/drm/msm_drm.h @@ -25,7 +25,6 @@ #ifndef __MSM_DRM_H__ #define __MSM_DRM_H__ -#include <stddef.h> #include "drm.h" #if defined(__cplusplus) @@ -73,6 +72,8 @@ struct drm_msm_timespec { #define MSM_PARAM_CHIP_ID 0x03 #define MSM_PARAM_MAX_FREQ 0x04 #define MSM_PARAM_TIMESTAMP 0x05 +#define MSM_PARAM_GMEM_BASE 0x06 +#define MSM_PARAM_NR_RINGS 0x07 struct drm_msm_param { __u32 pipe; /* in, MSM_PIPE_x */ @@ -104,10 +105,14 @@ struct drm_msm_gem_new { __u32 handle; /* out */ }; +#define MSM_INFO_IOVA 0x01 + +#define MSM_INFO_FLAGS (MSM_INFO_IOVA) + struct drm_msm_gem_info { __u32 handle; /* in */ - __u32 pad; - __u64 offset; /* out, offset to pass to mmap() */ + __u32 flags; /* in - combination of MSM_INFO_* flags */ + __u64 offset; /* out, mmap() offset or iova */ }; #define MSM_PREP_READ 0x01 @@ -167,7 +172,7 @@ struct drm_msm_gem_submit_cmd { __u32 size; /* in, cmdstream size */ __u32 pad; __u32 nr_relocs; /* in, number of submit_reloc's */ - __u64 __user relocs; /* in, ptr to array of submit_reloc's */ + __u64 relocs; /* in, ptr to array of submit_reloc's */ }; /* Each buffer referenced elsewhere in the cmdstream submit (ie. the @@ -196,10 +201,12 @@ struct drm_msm_gem_submit_bo { #define MSM_SUBMIT_NO_IMPLICIT 0x80000000 /* disable implicit sync */ #define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */ #define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */ +#define MSM_SUBMIT_SUDO 0x10000000 /* run submitted cmds from RB */ #define MSM_SUBMIT_FLAGS ( \ MSM_SUBMIT_NO_IMPLICIT | \ MSM_SUBMIT_FENCE_FD_IN | \ MSM_SUBMIT_FENCE_FD_OUT | \ + MSM_SUBMIT_SUDO | \ 0) /* Each cmdstream submit consists of a table of buffers involved, and @@ -211,9 +218,10 @@ struct drm_msm_gem_submit { __u32 fence; /* out */ __u32 nr_bos; /* in, number of submit_bo's */ __u32 nr_cmds; /* in, number of submit_cmd's */ - __u64 __user bos; /* in, ptr to array of submit_bo's */ - __u64 __user cmds; /* in, ptr to array of submit_cmd's */ + __u64 bos; /* in, ptr to array of submit_bo's */ + __u64 cmds; /* in, ptr to array of submit_cmd's */ __s32 fence_fd; /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */ + __u32 queueid; /* in, submitqueue id */ }; /* The normal way to synchronize with the GPU is just to CPU_PREP on @@ -227,6 +235,7 @@ struct drm_msm_wait_fence { __u32 fence; /* in */ __u32 pad; struct drm_msm_timespec timeout; /* in */ + __u32 queueid; /* in, submitqueue id */ }; /* madvise provides a way to tell the kernel in case a buffers contents @@ -250,6 +259,20 @@ struct drm_msm_gem_madvise { __u32 retained; /* out, whether backing store still exists */ }; +/* + * Draw queues allow the user to set specific submission parameter. Command + * submissions specify a specific submitqueue to use. ID 0 is reserved for + * backwards compatibility as a "default" submitqueue + */ + +#define MSM_SUBMITQUEUE_FLAGS (0) + +struct drm_msm_submitqueue { + __u32 flags; /* in, MSM_SUBMITQUEUE_x */ + __u32 prio; /* in, Priority level */ + __u32 id; /* out, identifier */ +}; + #define DRM_MSM_GET_PARAM 0x00 /* placeholder: #define DRM_MSM_SET_PARAM 0x01 @@ -261,7 +284,11 @@ struct drm_msm_gem_madvise { #define DRM_MSM_GEM_SUBMIT 0x06 #define DRM_MSM_WAIT_FENCE 0x07 #define DRM_MSM_GEM_MADVISE 0x08 -#define DRM_MSM_NUM_IOCTLS 0x09 +/* placeholder: +#define DRM_MSM_GEM_SVM_NEW 0x09 + */ +#define DRM_MSM_SUBMITQUEUE_NEW 0x0A +#define DRM_MSM_SUBMITQUEUE_CLOSE 0x0B #define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param) #define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new) @@ -271,6 +298,8 @@ struct drm_msm_gem_madvise { #define DRM_IOCTL_MSM_GEM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_SUBMIT, struct drm_msm_gem_submit) #define DRM_IOCTL_MSM_WAIT_FENCE DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_WAIT_FENCE, struct drm_msm_wait_fence) #define DRM_IOCTL_MSM_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_MADVISE, struct drm_msm_gem_madvise) +#define DRM_IOCTL_MSM_SUBMITQUEUE_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_NEW, struct drm_msm_submitqueue) +#define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32) #if defined(__cplusplus) } diff --git a/include/drm/nouveau_class.h b/include/drm/nouveau_class.h deleted file mode 100644 index 8d63877a..00000000 --- a/include/drm/nouveau_class.h +++ /dev/null @@ -1,651 +0,0 @@ -#ifndef __NVIF_CLASS_H__ -#define __NVIF_CLASS_H__ - -/******************************************************************************* - * class identifiers - ******************************************************************************/ - -/* the below match nvidia-assigned (either in hw, or sw) class numbers */ -#define NV_DEVICE 0x00000080 - -#define NV_DMA_FROM_MEMORY 0x00000002 -#define NV_DMA_TO_MEMORY 0x00000003 -#define NV_DMA_IN_MEMORY 0x0000003d - -#define FERMI_TWOD_A 0x0000902d - -#define FERMI_MEMORY_TO_MEMORY_FORMAT_A 0x0000903d - -#define KEPLER_INLINE_TO_MEMORY_A 0x0000a040 -#define KEPLER_INLINE_TO_MEMORY_B 0x0000a140 - -#define NV04_DISP 0x00000046 - -#define NV03_CHANNEL_DMA 0x0000006b -#define NV10_CHANNEL_DMA 0x0000006e -#define NV17_CHANNEL_DMA 0x0000176e -#define NV40_CHANNEL_DMA 0x0000406e -#define NV50_CHANNEL_DMA 0x0000506e -#define G82_CHANNEL_DMA 0x0000826e - -#define NV50_CHANNEL_GPFIFO 0x0000506f -#define G82_CHANNEL_GPFIFO 0x0000826f -#define FERMI_CHANNEL_GPFIFO 0x0000906f -#define KEPLER_CHANNEL_GPFIFO_A 0x0000a06f -#define MAXWELL_CHANNEL_GPFIFO_A 0x0000b06f - -#define NV50_DISP 0x00005070 -#define G82_DISP 0x00008270 -#define GT200_DISP 0x00008370 -#define GT214_DISP 0x00008570 -#define GT206_DISP 0x00008870 -#define GF110_DISP 0x00009070 -#define GK104_DISP 0x00009170 -#define GK110_DISP 0x00009270 -#define GM107_DISP 0x00009470 -#define GM204_DISP 0x00009570 - -#define NV50_DISP_CURSOR 0x0000507a -#define G82_DISP_CURSOR 0x0000827a -#define GT214_DISP_CURSOR 0x0000857a -#define GF110_DISP_CURSOR 0x0000907a -#define GK104_DISP_CURSOR 0x0000917a - -#define NV50_DISP_OVERLAY 0x0000507b -#define G82_DISP_OVERLAY 0x0000827b -#define GT214_DISP_OVERLAY 0x0000857b -#define GF110_DISP_OVERLAY 0x0000907b -#define GK104_DISP_OVERLAY 0x0000917b - -#define NV50_DISP_BASE_CHANNEL_DMA 0x0000507c -#define G82_DISP_BASE_CHANNEL_DMA 0x0000827c -#define GT200_DISP_BASE_CHANNEL_DMA 0x0000837c -#define GT214_DISP_BASE_CHANNEL_DMA 0x0000857c -#define GF110_DISP_BASE_CHANNEL_DMA 0x0000907c -#define GK104_DISP_BASE_CHANNEL_DMA 0x0000917c -#define GK110_DISP_BASE_CHANNEL_DMA 0x0000927c - -#define NV50_DISP_CORE_CHANNEL_DMA 0x0000507d -#define G82_DISP_CORE_CHANNEL_DMA 0x0000827d -#define GT200_DISP_CORE_CHANNEL_DMA 0x0000837d -#define GT214_DISP_CORE_CHANNEL_DMA 0x0000857d -#define GT206_DISP_CORE_CHANNEL_DMA 0x0000887d -#define GF110_DISP_CORE_CHANNEL_DMA 0x0000907d -#define GK104_DISP_CORE_CHANNEL_DMA 0x0000917d -#define GK110_DISP_CORE_CHANNEL_DMA 0x0000927d -#define GM107_DISP_CORE_CHANNEL_DMA 0x0000947d -#define GM204_DISP_CORE_CHANNEL_DMA 0x0000957d - -#define NV50_DISP_OVERLAY_CHANNEL_DMA 0x0000507e -#define G82_DISP_OVERLAY_CHANNEL_DMA 0x0000827e -#define GT200_DISP_OVERLAY_CHANNEL_DMA 0x0000837e -#define GT214_DISP_OVERLAY_CHANNEL_DMA 0x0000857e -#define GF110_DISP_OVERLAY_CONTROL_DMA 0x0000907e -#define GK104_DISP_OVERLAY_CONTROL_DMA 0x0000917e - -#define FERMI_A 0x00009097 -#define FERMI_B 0x00009197 -#define FERMI_C 0x00009297 - -#define KEPLER_A 0x0000a097 -#define KEPLER_B 0x0000a197 -#define KEPLER_C 0x0000a297 - -#define MAXWELL_A 0x0000b097 -#define MAXWELL_B 0x0000b197 - -#define FERMI_COMPUTE_A 0x000090c0 -#define FERMI_COMPUTE_B 0x000091c0 - -#define KEPLER_COMPUTE_A 0x0000a0c0 -#define KEPLER_COMPUTE_B 0x0000a1c0 - -#define MAXWELL_COMPUTE_A 0x0000b0c0 -#define MAXWELL_COMPUTE_B 0x0000b1c0 - -#define MAXWELL_DMA_COPY_A 0x0000b0b5 - -/******************************************************************************* - * client - ******************************************************************************/ - -#define NV_CLIENT_DEVLIST 0x00 - -struct nv_client_devlist_v0 { - __u8 version; - __u8 count; - __u8 pad02[6]; - __u64 device[]; -}; - - -/******************************************************************************* - * device - ******************************************************************************/ - -struct nv_device_v0 { - __u8 version; - __u8 pad01[7]; - __u64 device; /* device identifier, ~0 for client default */ -#define NV_DEVICE_V0_DISABLE_IDENTIFY 0x0000000000000001ULL -#define NV_DEVICE_V0_DISABLE_MMIO 0x0000000000000002ULL -#define NV_DEVICE_V0_DISABLE_VBIOS 0x0000000000000004ULL -#define NV_DEVICE_V0_DISABLE_CORE 0x0000000000000008ULL -#define NV_DEVICE_V0_DISABLE_DISP 0x0000000000010000ULL -#define NV_DEVICE_V0_DISABLE_FIFO 0x0000000000020000ULL -#define NV_DEVICE_V0_DISABLE_GR 0x0000000100000000ULL -#define NV_DEVICE_V0_DISABLE_MPEG 0x0000000200000000ULL -#define NV_DEVICE_V0_DISABLE_ME 0x0000000400000000ULL -#define NV_DEVICE_V0_DISABLE_VP 0x0000000800000000ULL -#define NV_DEVICE_V0_DISABLE_CIPHER 0x0000001000000000ULL -#define NV_DEVICE_V0_DISABLE_BSP 0x0000002000000000ULL -#define NV_DEVICE_V0_DISABLE_MSPPP 0x0000004000000000ULL -#define NV_DEVICE_V0_DISABLE_CE0 0x0000008000000000ULL -#define NV_DEVICE_V0_DISABLE_CE1 0x0000010000000000ULL -#define NV_DEVICE_V0_DISABLE_VIC 0x0000020000000000ULL -#define NV_DEVICE_V0_DISABLE_MSENC 0x0000040000000000ULL -#define NV_DEVICE_V0_DISABLE_CE2 0x0000080000000000ULL -#define NV_DEVICE_V0_DISABLE_MSVLD 0x0000100000000000ULL -#define NV_DEVICE_V0_DISABLE_SEC 0x0000200000000000ULL -#define NV_DEVICE_V0_DISABLE_MSPDEC 0x0000400000000000ULL - __u64 disable; /* disable particular subsystems */ - __u64 debug0; /* as above, but *internal* ids, and *NOT* ABI */ -}; - -#define NV_DEVICE_V0_INFO 0x00 -#define NV_DEVICE_V0_ZCULL_INFO 0x01 - -struct nv_device_info_v0 { - __u8 version; -#define NV_DEVICE_INFO_V0_IGP 0x00 -#define NV_DEVICE_INFO_V0_PCI 0x01 -#define NV_DEVICE_INFO_V0_AGP 0x02 -#define NV_DEVICE_INFO_V0_PCIE 0x03 -#define NV_DEVICE_INFO_V0_SOC 0x04 - __u8 platform; - __u16 chipset; /* from NV_PMC_BOOT_0 */ - __u8 revision; /* from NV_PMC_BOOT_0 */ -#define NV_DEVICE_INFO_V0_TNT 0x01 -#define NV_DEVICE_INFO_V0_CELSIUS 0x02 -#define NV_DEVICE_INFO_V0_KELVIN 0x03 -#define NV_DEVICE_INFO_V0_RANKINE 0x04 -#define NV_DEVICE_INFO_V0_CURIE 0x05 -#define NV_DEVICE_INFO_V0_TESLA 0x06 -#define NV_DEVICE_INFO_V0_FERMI 0x07 -#define NV_DEVICE_INFO_V0_KEPLER 0x08 -#define NV_DEVICE_INFO_V0_MAXWELL 0x09 - __u8 family; - __u8 pad06[2]; - __u64 ram_size; - __u64 ram_user; -}; - -struct nv_device_zcull_info_v0 { - __u8 version; - __u8 pad03[3]; - __u32 image_size; - __u32 width_align_pixels; - __u32 height_align_pixels; - __u32 pixel_squares_by_aliquots; - __u32 aliquot_total; - __u32 region_byte_multiplier; - __u32 region_header_size; - __u32 subregion_header_size; - __u32 subregion_width_align_pixels; - __u32 subregion_height_align_pixels; - __u32 subregion_count; -}; - -/******************************************************************************* - * context dma - ******************************************************************************/ - -struct nv_dma_v0 { - __u8 version; -#define NV_DMA_V0_TARGET_VM 0x00 -#define NV_DMA_V0_TARGET_VRAM 0x01 -#define NV_DMA_V0_TARGET_PCI 0x02 -#define NV_DMA_V0_TARGET_PCI_US 0x03 -#define NV_DMA_V0_TARGET_AGP 0x04 - __u8 target; -#define NV_DMA_V0_ACCESS_VM 0x00 -#define NV_DMA_V0_ACCESS_RD 0x01 -#define NV_DMA_V0_ACCESS_WR 0x02 -#define NV_DMA_V0_ACCESS_RDWR (NV_DMA_V0_ACCESS_RD | NV_DMA_V0_ACCESS_WR) - __u8 access; - __u8 pad03[5]; - __u64 start; - __u64 limit; - /* ... chipset-specific class data */ -}; - -struct nv50_dma_v0 { - __u8 version; -#define NV50_DMA_V0_PRIV_VM 0x00 -#define NV50_DMA_V0_PRIV_US 0x01 -#define NV50_DMA_V0_PRIV__S 0x02 - __u8 priv; -#define NV50_DMA_V0_PART_VM 0x00 -#define NV50_DMA_V0_PART_256 0x01 -#define NV50_DMA_V0_PART_1KB 0x02 - __u8 part; -#define NV50_DMA_V0_COMP_NONE 0x00 -#define NV50_DMA_V0_COMP_1 0x01 -#define NV50_DMA_V0_COMP_2 0x02 -#define NV50_DMA_V0_COMP_VM 0x03 - __u8 comp; -#define NV50_DMA_V0_KIND_PITCH 0x00 -#define NV50_DMA_V0_KIND_VM 0x7f - __u8 kind; - __u8 pad05[3]; -}; - -struct gf100_dma_v0 { - __u8 version; -#define GF100_DMA_V0_PRIV_VM 0x00 -#define GF100_DMA_V0_PRIV_US 0x01 -#define GF100_DMA_V0_PRIV__S 0x02 - __u8 priv; -#define GF100_DMA_V0_KIND_PITCH 0x00 -#define GF100_DMA_V0_KIND_VM 0xff - __u8 kind; - __u8 pad03[5]; -}; - -struct gf110_dma_v0 { - __u8 version; -#define GF110_DMA_V0_PAGE_LP 0x00 -#define GF110_DMA_V0_PAGE_SP 0x01 - __u8 page; -#define GF110_DMA_V0_KIND_PITCH 0x00 -#define GF110_DMA_V0_KIND_VM 0xff - __u8 kind; - __u8 pad03[5]; -}; - - -/******************************************************************************* - * perfmon - ******************************************************************************/ - -struct nvif_perfctr_v0 { - __u8 version; - __u8 pad01[1]; - __u16 logic_op; - __u8 pad04[4]; - char name[4][64]; -}; - -#define NVIF_PERFCTR_V0_QUERY 0x00 -#define NVIF_PERFCTR_V0_SAMPLE 0x01 -#define NVIF_PERFCTR_V0_READ 0x02 - -struct nvif_perfctr_query_v0 { - __u8 version; - __u8 pad01[3]; - __u32 iter; - char name[64]; -}; - -struct nvif_perfctr_sample { -}; - -struct nvif_perfctr_read_v0 { - __u8 version; - __u8 pad01[7]; - __u32 ctr; - __u32 clk; -}; - - -/******************************************************************************* - * device control - ******************************************************************************/ - -#define NVIF_CONTROL_PSTATE_INFO 0x00 -#define NVIF_CONTROL_PSTATE_ATTR 0x01 -#define NVIF_CONTROL_PSTATE_USER 0x02 - -struct nvif_ustate { - __s8 min; - __s8 max; -}; - -struct nvif_control_pstate_info_v0 { - __u8 version; - __u8 count; /* out: number of power states */ -#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE (-1) -#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_PERFMON (-2) - struct { - struct nvif_ustate dc; // pwrsrc == 0 - struct nvif_ustate ac; // pwrsrc == 1 - } ustate; /* out: target pstate index */ - __s8 pwrsrc; /* out: current power source */ -#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN (-1) -#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_PERFMON (-2) - __s8 pstate; /* out: current pstate index */ - __u8 pad06[2]; -}; - -struct nvif_control_pstate_attr_v0 { - __u8 version; -#define NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT (-1) - __s8 state; /* in: index of pstate to query - * out: pstate identifier - */ - __u8 index; /* in: index of attribute to query - * out: index of next attribute, or 0 if no more - */ - __u8 pad03[5]; - __u32 min; - __u32 max; - char name[32]; - char unit[16]; -}; - -struct nvif_control_pstate_user_v0 { - __u8 version; -#define NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN (-1) -#define NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON (-2) - struct nvif_ustate ustate; /* in: pstate identifier */ - __s8 pwrsrc; /* in: target power source */ - __u8 pad03[5]; -}; - - -/******************************************************************************* - * DMA FIFO channels - ******************************************************************************/ - -struct nv03_channel_dma_v0 { - __u8 version; - __u8 chid; - __u8 pad02[2]; - __u32 pushbuf; - __u64 offset; -}; - -#define G82_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 - -/******************************************************************************* - * GPFIFO channels - ******************************************************************************/ - -struct nv50_channel_gpfifo_v0 { - __u8 version; - __u8 chid; - __u8 pad01[6]; - __u32 pushbuf; - __u32 ilength; - __u64 ioffset; -}; - -struct kepler_channel_gpfifo_a_v0 { - __u8 version; -#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR 0x01 -#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPDEC 0x02 -#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSPPP 0x04 -#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_MSVLD 0x08 -#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0 0x10 -#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1 0x20 -#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC 0x40 - __u8 engine; - __u16 chid; - __u8 pad04[4]; - __u32 pushbuf; - __u32 ilength; - __u64 ioffset; -}; - -#define CHANNEL_GPFIFO_ERROR_NOTIFIER_EEVENT 0x01 - -/******************************************************************************* - * legacy display - ******************************************************************************/ - -#define NV04_DISP_NTFY_VBLANK 0x00 -#define NV04_DISP_NTFY_CONN 0x01 - -struct nv04_disp_mthd_v0 { - __u8 version; -#define NV04_DISP_SCANOUTPOS 0x00 - __u8 method; - __u8 head; - __u8 pad03[5]; -}; - -struct nv04_disp_scanoutpos_v0 { - __u8 version; - __u8 pad01[7]; - __s64 time[2]; - __u16 vblanks; - __u16 vblanke; - __u16 vtotal; - __u16 vline; - __u16 hblanks; - __u16 hblanke; - __u16 htotal; - __u16 hline; -}; - -/******************************************************************************* - * display - ******************************************************************************/ - -#define NV50_DISP_MTHD 0x00 - -struct nv50_disp_mthd_v0 { - __u8 version; -#define NV50_DISP_SCANOUTPOS 0x00 - __u8 method; - __u8 head; - __u8 pad03[5]; -}; - -struct nv50_disp_mthd_v1 { - __u8 version; -#define NV50_DISP_MTHD_V1_DAC_PWR 0x10 -#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11 -#define NV50_DISP_MTHD_V1_SOR_PWR 0x20 -#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 -#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 -#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23 -#define NV50_DISP_MTHD_V1_SOR_DP_PWR 0x24 -#define NV50_DISP_MTHD_V1_PIOR_PWR 0x30 - __u8 method; - __u16 hasht; - __u16 hashm; - __u8 pad06[2]; -}; - -struct nv50_disp_dac_pwr_v0 { - __u8 version; - __u8 state; - __u8 data; - __u8 vsync; - __u8 hsync; - __u8 pad05[3]; -}; - -struct nv50_disp_dac_load_v0 { - __u8 version; - __u8 load; - __u8 pad02[2]; - __u32 data; -}; - -struct nv50_disp_sor_pwr_v0 { - __u8 version; - __u8 state; - __u8 pad02[6]; -}; - -struct nv50_disp_sor_hda_eld_v0 { - __u8 version; - __u8 pad01[7]; - __u8 data[]; -}; - -struct nv50_disp_sor_hdmi_pwr_v0 { - __u8 version; - __u8 state; - __u8 max_ac_packet; - __u8 rekey; - __u8 pad04[4]; -}; - -struct nv50_disp_sor_lvds_script_v0 { - __u8 version; - __u8 pad01[1]; - __u16 script; - __u8 pad04[4]; -}; - -struct nv50_disp_sor_dp_pwr_v0 { - __u8 version; - __u8 state; - __u8 pad02[6]; -}; - -struct nv50_disp_pior_pwr_v0 { - __u8 version; - __u8 state; - __u8 type; - __u8 pad03[5]; -}; - -/* core */ -struct nv50_disp_core_channel_dma_v0 { - __u8 version; - __u8 pad01[3]; - __u32 pushbuf; -}; - -#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 - -/* cursor immediate */ -struct nv50_disp_cursor_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; -}; - -#define NV50_DISP_CURSOR_V0_NTFY_UEVENT 0x00 - -/* base */ -struct nv50_disp_base_channel_dma_v0 { - __u8 version; - __u8 pad01[2]; - __u8 head; - __u32 pushbuf; -}; - -#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 - -/* overlay */ -struct nv50_disp_overlay_channel_dma_v0 { - __u8 version; - __u8 pad01[2]; - __u8 head; - __u32 pushbuf; -}; - -#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 - -/* overlay immediate */ -struct nv50_disp_overlay_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; -}; - -#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00 - -/******************************************************************************* - * fermi - ******************************************************************************/ - -#define FERMI_A_ZBC_COLOR 0x00 -#define FERMI_A_ZBC_DEPTH 0x01 -#define FERMI_A_ZCULL_BIND 0x02 -#define FERMI_A_ZBC_QUERY_COLOR 0x03 -#define FERMI_A_ZBC_QUERY_DEPTH 0x04 -#define FERMI_A_ZBC_QUERY_TABLE_SIZE 0x05 - -struct fermi_a_zbc_color_v0 { - __u8 version; -#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO 0x01 -#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE 0x02 -#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32 0x04 -#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16 0x08 -#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16 0x0c -#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16 0x10 -#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16 0x14 -#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16 0x16 -#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8 0x18 -#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8 0x1c -#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10 0x20 -#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10 0x24 -#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8 0x28 -#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8 0x2c -#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8 0x30 -#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8 0x34 -#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8 0x38 -#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10 0x3c -#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11 0x40 - __u8 format; - __u8 index; - __u8 pad03[5]; - __u32 ds[4]; - __u32 l2[4]; -}; - -struct fermi_a_zbc_query_v0 { - __u8 version; - __u8 pad03[3]; - __u32 ds[4]; - __u32 l2[4]; - __u32 format; - __u32 index; - __u32 table_size; -}; - -struct fermi_a_zbc_depth_v0 { - __u8 version; -#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32 0x01 - __u8 format; - __u8 index; - __u8 pad03[5]; - __u32 ds; - __u32 l2; -}; - -struct fermi_a_zcull_bind_v0 { - __u8 version; - __u8 pad03[3]; -#define FERMI_A_ZCULL_BIND_MODE_GLOBAL 0x00 -#define FERMI_A_ZCULL_BIND_MODE_NO_CTXSW 0x01 -#define FERMI_A_ZCULL_BIND_MODE_SEPARATE_BUFFER 0x02 - __u32 mode; - __u64 gpu_va; -}; - -#define KEPLER_SET_CHANNEL_PRIORITY 0x00 -#define KEPLER_SET_CHANNEL_TIMEOUT 0x01 - -struct kepler_set_channel_priority_v0 { - __u8 version; -#define KEPLER_SET_CHANNEL_PRIORITY_LOW 0x00 -#define KEPLER_SET_CHANNEL_PRIORITY_MEDIUM 0x01 -#define KEPLER_SET_CHANNEL_PRIORITY_HIGH 0x02 - __u8 priority; - __u8 pad03[6]; -}; - -struct kepler_set_channel_timeout_v0 { - __u8 version; - __u8 pad03[3]; - __u32 timeout_ms; -}; - -#endif diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h index 1372f533..d42105c8 100644 --- a/include/drm/nouveau_drm.h +++ b/include/drm/nouveau_drm.h @@ -27,13 +27,11 @@ #define NOUVEAU_DRM_HEADER_PATCHLEVEL 16 -/* reserved object handles when using deprecated object APIs - these - * are here so that libdrm can allow interoperability with the new - * object APIs - */ -#define NOUVEAU_ABI16_CLIENT 0xffffffff -#define NOUVEAU_ABI16_DEVICE 0xdddddddd -#define NOUVEAU_ABI16_CHAN(n) (0xcccc0000 | (n)) +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; @@ -106,6 +104,7 @@ struct drm_nouveau_setparam { #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) #define NOUVEAU_GEM_DOMAIN_COHERENT (1 << 4) +#define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */ #define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 #define NOUVEAU_GEM_TILE_16BPP 0x00000001 #define NOUVEAU_GEM_TILE_32BPP 0x00000002 @@ -113,40 +112,34 @@ struct drm_nouveau_setparam { #define NOUVEAU_GEM_TILE_NONCONTIG 0x00000008 struct drm_nouveau_gem_info { - uint32_t handle; - uint32_t domain; - uint64_t size; - uint64_t offset; - uint64_t map_handle; - uint32_t tile_mode; - uint32_t tile_flags; -}; - -struct drm_nouveau_gem_set_tiling { - uint32_t handle; - uint32_t tile_mode; - uint32_t tile_flags; + __u32 handle; + __u32 domain; + __u64 size; + __u64 offset; + __u64 map_handle; + __u32 tile_mode; + __u32 tile_flags; }; struct drm_nouveau_gem_new { struct drm_nouveau_gem_info info; - uint32_t channel_hint; - uint32_t align; + __u32 channel_hint; + __u32 align; }; #define NOUVEAU_GEM_MAX_BUFFERS 1024 struct drm_nouveau_gem_pushbuf_bo_presumed { - uint32_t valid; - uint32_t domain; - uint64_t offset; + __u32 valid; + __u32 domain; + __u64 offset; }; struct drm_nouveau_gem_pushbuf_bo { - uint64_t user_priv; - uint32_t handle; - uint32_t read_domains; - uint32_t write_domains; - uint32_t valid_domains; + __u64 user_priv; + __u32 handle; + __u32 read_domains; + __u32 write_domains; + __u32 valid_domains; struct drm_nouveau_gem_pushbuf_bo_presumed presumed; }; @@ -155,75 +148,47 @@ struct drm_nouveau_gem_pushbuf_bo { #define NOUVEAU_GEM_RELOC_OR (1 << 2) #define NOUVEAU_GEM_MAX_RELOCS 1024 struct drm_nouveau_gem_pushbuf_reloc { - uint32_t reloc_bo_index; - uint32_t reloc_bo_offset; - uint32_t bo_index; - uint32_t flags; - uint32_t data; - uint32_t vor; - uint32_t tor; + __u32 reloc_bo_index; + __u32 reloc_bo_offset; + __u32 bo_index; + __u32 flags; + __u32 data; + __u32 vor; + __u32 tor; }; #define NOUVEAU_GEM_MAX_PUSH 512 struct drm_nouveau_gem_pushbuf_push { - uint32_t bo_index; - uint32_t pad; - uint64_t offset; - uint64_t length; + __u32 bo_index; + __u32 pad; + __u64 offset; + __u64 length; }; struct drm_nouveau_gem_pushbuf { - uint32_t channel; - uint32_t nr_buffers; - uint64_t buffers; - uint32_t nr_relocs; - uint32_t nr_push; - uint64_t relocs; - uint64_t push; - uint32_t suffix0; - uint32_t suffix1; - uint64_t vram_available; - uint64_t gart_available; -}; - -#define NOUVEAU_GEM_PUSHBUF_2_FENCE_WAIT 0x00000001 -#define NOUVEAU_GEM_PUSHBUF_2_FENCE_EMIT 0x00000002 -struct drm_nouveau_gem_pushbuf_2 { - uint32_t channel; - uint32_t flags; - uint32_t nr_push; - uint32_t nr_buffers; - int32_t fence; /* in/out, depends on flags */ - uint32_t pad; - uint64_t push; /* in raw hw format */ - uint64_t buffers; /* ptr to drm_nouveau_gem_pushbuf_bo */ - uint64_t vram_available; - uint64_t gart_available; + __u32 channel; + __u32 nr_buffers; + __u64 buffers; + __u32 nr_relocs; + __u32 nr_push; + __u64 relocs; + __u64 push; + __u32 suffix0; + __u32 suffix1; + __u64 vram_available; + __u64 gart_available; }; #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 #define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 struct drm_nouveau_gem_cpu_prep { - uint32_t handle; - uint32_t flags; + __u32 handle; + __u32 flags; }; struct drm_nouveau_gem_cpu_fini { - uint32_t handle; -}; - -#define NOUVEAU_GEM_AS_SPARSE 0x00000001 -struct drm_nouveau_gem_as_alloc { - uint64_t pages; /* in, page length */ - uint32_t page_size; /* in, byte page size */ - uint32_t flags; /* in, flags of address space */ - uint64_t align; /* in, requested alignment in bytes */ - uint64_t address; /* in/out, non-zero for fixed address allocation */ -}; - -struct drm_nouveau_gem_as_free { - uint64_t address; /* in, byte address */ + __u32 handle; }; enum nouveau_bus_type { @@ -235,34 +200,6 @@ enum nouveau_bus_type { struct drm_nouveau_sarea { }; -#define NOUVEAU_GEM_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT 8 -#define NOUVEAU_GEM_CHANNEL_GR_ERROR_SW_NOTIFY 13 -#define NOUVEAU_GEM_CHANNEL_FIFO_ERROR_MMU_ERR_FLT 31 -#define NOUVEAU_GEM_CHANNEL_PBDMA_ERROR 32 -struct drm_nouveau_gem_set_error_notifier { - uint32_t channel; - uint32_t buffer; - uint32_t offset; /* in bytes, u32-aligned */ -}; - -struct drm_nouveau_gem_map { - uint32_t handle; - uint32_t domain; - uint64_t offset; - uint64_t delta; - uint64_t length; - uint32_t tile_mode; - uint32_t tile_flags; -}; - -struct drm_nouveau_gem_unmap { - uint32_t handle; - uint32_t pad; - uint64_t offset; - uint64_t delta; - uint64_t length; -}; - #define DRM_NOUVEAU_GETPARAM 0x00 #define DRM_NOUVEAU_SETPARAM 0x01 #define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 @@ -277,14 +214,8 @@ struct drm_nouveau_gem_unmap { #define DRM_NOUVEAU_GEM_CPU_FINI 0x43 #define DRM_NOUVEAU_GEM_INFO 0x44 -/* The ioctls below are marked as staging */ -#define DRM_NOUVEAU_GEM_SET_TILING 0x50 -#define DRM_NOUVEAU_GEM_PUSHBUF_2 0x51 -#define DRM_NOUVEAU_GEM_SET_INFO 0x52 -#define DRM_NOUVEAU_GEM_AS_ALLOC 0x53 -#define DRM_NOUVEAU_GEM_AS_FREE 0x54 -#define DRM_NOUVEAU_GEM_SET_ERROR_NOTIFIER 0x55 -#define DRM_NOUVEAU_GEM_MAP 0x56 -#define DRM_NOUVEAU_GEM_UNMAP 0x57 +#if defined(__cplusplus) +} +#endif #endif /* __NOUVEAU_DRM_H__ */ diff --git a/include/drm/nouveau_ioctl.h b/include/drm/nouveau_ioctl.h deleted file mode 100644 index 4cd8e323..00000000 --- a/include/drm/nouveau_ioctl.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef __NVIF_IOCTL_H__ -#define __NVIF_IOCTL_H__ - -struct nvif_ioctl_v0 { - __u8 version; -#define NVIF_IOCTL_V0_OWNER_NVIF 0x00 -#define NVIF_IOCTL_V0_OWNER_ANY 0xff - __u8 owner; -#define NVIF_IOCTL_V0_NOP 0x00 -#define NVIF_IOCTL_V0_SCLASS 0x01 -#define NVIF_IOCTL_V0_NEW 0x02 -#define NVIF_IOCTL_V0_DEL 0x03 -#define NVIF_IOCTL_V0_MTHD 0x04 -#define NVIF_IOCTL_V0_RD 0x05 -#define NVIF_IOCTL_V0_WR 0x06 -#define NVIF_IOCTL_V0_MAP 0x07 -#define NVIF_IOCTL_V0_UNMAP 0x08 -#define NVIF_IOCTL_V0_NTFY_NEW 0x09 -#define NVIF_IOCTL_V0_NTFY_DEL 0x0a -#define NVIF_IOCTL_V0_NTFY_GET 0x0b -#define NVIF_IOCTL_V0_NTFY_PUT 0x0c - __u8 type; - __u8 path_nr; -#define NVIF_IOCTL_V0_ROUTE_NVIF 0x00 -#define NVIF_IOCTL_V0_ROUTE_HIDDEN 0xff - __u8 pad04[3]; - __u8 route; - __u64 token; - __u32 path[8]; /* in reverse */ - __u8 data[]; /* ioctl data (below) */ -}; - -struct nvif_ioctl_nop { -}; - -struct nvif_ioctl_sclass_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 count; - __u8 pad02[6]; - __u32 oclass[]; -}; - -struct nvif_ioctl_new_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 pad01[6]; - __u8 route; - __u64 token; - __u32 handle; -/* these class numbers are made up by us, and not nvidia-assigned */ -#define NVIF_IOCTL_NEW_V0_PERFCTR 0x0000ffff -#define NVIF_IOCTL_NEW_V0_CONTROL 0x0000fffe - __u32 oclass; - __u8 data[]; /* class data (class.h) */ -}; - -struct nvif_ioctl_del { -}; - -struct nvif_ioctl_rd_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 size; - __u8 pad02[2]; - __u32 data; - __u64 addr; -}; - -struct nvif_ioctl_wr_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 size; - __u8 pad02[2]; - __u32 data; - __u64 addr; -}; - -struct nvif_ioctl_map_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 pad01[3]; - __u32 length; - __u64 handle; -}; - -struct nvif_ioctl_unmap { -}; - -struct nvif_ioctl_ntfy_new_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 event; - __u8 index; - __u8 pad03[5]; - __u8 data[]; /* event request data (event.h) */ -}; - -struct nvif_ioctl_ntfy_del_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 index; - __u8 pad02[6]; -}; - -struct nvif_ioctl_ntfy_get_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 index; - __u8 pad02[6]; -}; - -struct nvif_ioctl_ntfy_put_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 index; - __u8 pad02[6]; -}; - -struct nvif_ioctl_mthd_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 method; - __u8 pad02[6]; - __u8 data[]; /* method data (class.h) */ -}; - -#endif diff --git a/include/drm/qxl_drm.h b/include/drm/qxl_drm.h index 1e331a86..880999d2 100644 --- a/include/drm/qxl_drm.h +++ b/include/drm/qxl_drm.h @@ -24,13 +24,16 @@ #ifndef QXL_DRM_H #define QXL_DRM_H -#include <stddef.h> #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + /* Please note that modifications to all structs defined here are * subject to backwards-compatibility constraints. * - * Do not use pointers, use uint64_t instead for 32 bit / 64 bit user/kernel + * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel * compatibility Keep fields aligned to their size */ @@ -48,14 +51,14 @@ #define DRM_QXL_ALLOC_SURF 0x06 struct drm_qxl_alloc { - uint32_t size; - uint32_t handle; /* 0 is an invalid handle */ + __u32 size; + __u32 handle; /* 0 is an invalid handle */ }; struct drm_qxl_map { - uint64_t offset; /* use for mmap system call */ - uint32_t handle; - uint32_t pad; + __u64 offset; /* use for mmap system call */ + __u32 handle; + __u32 pad; }; /* @@ -68,59 +71,58 @@ struct drm_qxl_map { #define QXL_RELOC_TYPE_SURF 2 struct drm_qxl_reloc { - uint64_t src_offset; /* offset into src_handle or src buffer */ - uint64_t dst_offset; /* offset in dest handle */ - uint32_t src_handle; /* dest handle to compute address from */ - uint32_t dst_handle; /* 0 if to command buffer */ - uint32_t reloc_type; - uint32_t pad; + __u64 src_offset; /* offset into src_handle or src buffer */ + __u64 dst_offset; /* offset in dest handle */ + __u32 src_handle; /* dest handle to compute address from */ + __u32 dst_handle; /* 0 if to command buffer */ + __u32 reloc_type; + __u32 pad; }; struct drm_qxl_command { - uint64_t command; /* void* */ - uint64_t relocs; /* struct drm_qxl_reloc* */ - uint32_t type; - uint32_t command_size; - uint32_t relocs_num; - uint32_t pad; + __u64 command; /* void* */ + __u64 relocs; /* struct drm_qxl_reloc* */ + __u32 type; + __u32 command_size; + __u32 relocs_num; + __u32 pad; }; -/* XXX: call it drm_qxl_commands? */ struct drm_qxl_execbuffer { - uint32_t flags; /* for future use */ - uint32_t commands_num; - uint64_t commands; /* struct drm_qxl_command* */ + __u32 flags; /* for future use */ + __u32 commands_num; + __u64 commands; /* struct drm_qxl_command* */ }; struct drm_qxl_update_area { - uint32_t handle; - uint32_t top; - uint32_t left; - uint32_t bottom; - uint32_t right; - uint32_t pad; + __u32 handle; + __u32 top; + __u32 left; + __u32 bottom; + __u32 right; + __u32 pad; }; #define QXL_PARAM_NUM_SURFACES 1 /* rom->n_surfaces */ #define QXL_PARAM_MAX_RELOCS 2 struct drm_qxl_getparam { - uint64_t param; - uint64_t value; + __u64 param; + __u64 value; }; /* these are one bit values */ struct drm_qxl_clientcap { - uint32_t index; - uint32_t pad; + __u32 index; + __u32 pad; }; struct drm_qxl_alloc_surf { - uint32_t format; - uint32_t width; - uint32_t height; - int32_t stride; - uint32_t handle; - uint32_t pad; + __u32 format; + __u32 width; + __u32 height; + __s32 stride; + __u32 handle; + __u32 pad; }; #define DRM_IOCTL_QXL_ALLOC \ @@ -149,4 +151,8 @@ struct drm_qxl_alloc_surf { DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC_SURF,\ struct drm_qxl_alloc_surf) +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/r128_drm.h b/include/drm/r128_drm.h index ede78ff9..bf431a02 100644 --- a/include/drm/r128_drm.h +++ b/include/drm/r128_drm.h @@ -33,6 +33,12 @@ #ifndef __R128_DRM_H__ #define __R128_DRM_H__ +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (r128_sarea.h) */ @@ -323,4 +329,8 @@ typedef struct drm_r128_getparam { void *value; } drm_r128_getparam_t; +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index f09cc04c..a1e385d6 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -797,9 +797,9 @@ typedef struct drm_radeon_surface_free { #define RADEON_GEM_DOMAIN_VRAM 0x4 struct drm_radeon_gem_info { - uint64_t gart_size; - uint64_t vram_size; - uint64_t vram_visible; + __u64 gart_size; + __u64 vram_size; + __u64 vram_visible; }; #define RADEON_GEM_NO_BACKING_STORE (1 << 0) @@ -811,11 +811,11 @@ struct drm_radeon_gem_info { #define RADEON_GEM_NO_CPU_ACCESS (1 << 4) struct drm_radeon_gem_create { - uint64_t size; - uint64_t alignment; - uint32_t handle; - uint32_t initial_domain; - uint32_t flags; + __u64 size; + __u64 alignment; + __u32 handle; + __u32 initial_domain; + __u32 flags; }; /* @@ -829,10 +829,10 @@ struct drm_radeon_gem_create { #define RADEON_GEM_USERPTR_REGISTER (1 << 3) struct drm_radeon_gem_userptr { - uint64_t addr; - uint64_t size; - uint32_t flags; - uint32_t handle; + __u64 addr; + __u64 size; + __u32 flags; + __u32 handle; }; #define RADEON_TILING_MACRO 0x1 @@ -855,72 +855,72 @@ struct drm_radeon_gem_userptr { #define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf struct drm_radeon_gem_set_tiling { - uint32_t handle; - uint32_t tiling_flags; - uint32_t pitch; + __u32 handle; + __u32 tiling_flags; + __u32 pitch; }; struct drm_radeon_gem_get_tiling { - uint32_t handle; - uint32_t tiling_flags; - uint32_t pitch; + __u32 handle; + __u32 tiling_flags; + __u32 pitch; }; struct drm_radeon_gem_mmap { - uint32_t handle; - uint32_t pad; - uint64_t offset; - uint64_t size; - uint64_t addr_ptr; + __u32 handle; + __u32 pad; + __u64 offset; + __u64 size; + __u64 addr_ptr; }; struct drm_radeon_gem_set_domain { - uint32_t handle; - uint32_t read_domains; - uint32_t write_domain; + __u32 handle; + __u32 read_domains; + __u32 write_domain; }; struct drm_radeon_gem_wait_idle { - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; }; struct drm_radeon_gem_busy { - uint32_t handle; - uint32_t domain; + __u32 handle; + __u32 domain; }; struct drm_radeon_gem_pread { /** Handle for the object being read. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** Offset into the object to read from */ - uint64_t offset; + __u64 offset; /** Length of data to read */ - uint64_t size; + __u64 size; /** Pointer to write the data into. */ /* void *, but pointers are not 32/64 compatible */ - uint64_t data_ptr; + __u64 data_ptr; }; struct drm_radeon_gem_pwrite { /** Handle for the object being written to. */ - uint32_t handle; - uint32_t pad; + __u32 handle; + __u32 pad; /** Offset into the object to write to */ - uint64_t offset; + __u64 offset; /** Length of data to write */ - uint64_t size; + __u64 size; /** Pointer to read the data from. */ /* void *, but pointers are not 32/64 compatible */ - uint64_t data_ptr; + __u64 data_ptr; }; /* Sets or returns a value associated with a buffer. */ struct drm_radeon_gem_op { - uint32_t handle; /* buffer */ - uint32_t op; /* RADEON_GEM_OP_* */ - uint64_t value; /* input or return value */ + __u32 handle; /* buffer */ + __u32 op; /* RADEON_GEM_OP_* */ + __u64 value; /* input or return value */ }; #define RADEON_GEM_OP_GET_INITIAL_DOMAIN 0 @@ -940,11 +940,11 @@ struct drm_radeon_gem_op { #define RADEON_VM_PAGE_SNOOPED (1 << 4) struct drm_radeon_gem_va { - uint32_t handle; - uint32_t operation; - uint32_t vm_id; - uint32_t flags; - uint64_t offset; + __u32 handle; + __u32 operation; + __u32 vm_id; + __u32 flags; + __u64 offset; }; #define RADEON_CHUNK_ID_RELOCS 0x01 @@ -966,29 +966,29 @@ struct drm_radeon_gem_va { /* 0 = normal, + = higher priority, - = lower priority */ struct drm_radeon_cs_chunk { - uint32_t chunk_id; - uint32_t length_dw; - uint64_t chunk_data; + __u32 chunk_id; + __u32 length_dw; + __u64 chunk_data; }; /* drm_radeon_cs_reloc.flags */ #define RADEON_RELOC_PRIO_MASK (0xf << 0) struct drm_radeon_cs_reloc { - uint32_t handle; - uint32_t read_domains; - uint32_t write_domain; - uint32_t flags; + __u32 handle; + __u32 read_domains; + __u32 write_domain; + __u32 flags; }; struct drm_radeon_cs { - uint32_t num_chunks; - uint32_t cs_id; - /* this points to uint64_t * which point to cs chunks */ - uint64_t chunks; + __u32 num_chunks; + __u32 cs_id; + /* this points to __u64 * which point to cs chunks */ + __u64 chunks; /* updates to the limits after this CS ioctl */ - uint64_t gart_limit; - uint64_t vram_limit; + __u64 gart_limit; + __u64 vram_limit; }; #define RADEON_INFO_DEVICE_ID 0x00 @@ -1047,9 +1047,9 @@ struct drm_radeon_cs { #define RADEON_INFO_GPU_RESET_COUNTER 0x26 struct drm_radeon_info { - uint32_t request; - uint32_t pad; - uint64_t value; + __u32 request; + __u32 pad; + __u64 value; }; /* Those correspond to the tile index to use, this is to explicitly state diff --git a/include/drm/savage_drm.h b/include/drm/savage_drm.h index f7a75eff..1a91234e 100644 --- a/include/drm/savage_drm.h +++ b/include/drm/savage_drm.h @@ -26,10 +26,16 @@ #ifndef __SAVAGE_DRM_H__ #define __SAVAGE_DRM_H__ +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + #ifndef __SAVAGE_SAREA_DEFINES__ #define __SAVAGE_SAREA_DEFINES__ -/* 2 heaps (1 for card, 1 for agp), each divided into upto 128 +/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 * regions, subject to a minimum region size of (1<<16) == 64k. * * Clients may subdivide regions internally, but when sharing between @@ -63,10 +69,10 @@ typedef struct _drm_savage_sarea { #define DRM_SAVAGE_BCI_EVENT_EMIT 0x02 #define DRM_SAVAGE_BCI_EVENT_WAIT 0x03 -#define DRM_IOCTL_SAVAGE_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) -#define DRM_IOCTL_SAVAGE_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) -#define DRM_IOCTL_SAVAGE_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) -#define DRM_IOCTL_SAVAGE_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) +#define DRM_IOCTL_SAVAGE_BCI_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) +#define DRM_IOCTL_SAVAGE_BCI_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) +#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) #define SAVAGE_DMA_PCI 1 #define SAVAGE_DMA_AGP 3 @@ -207,4 +213,8 @@ union drm_savage_cmd_header { } clear1; /* SAVAGE_CMD_CLEAR data */ }; +#if defined(__cplusplus) +} +#endif + #endif diff --git a/include/drm/sis_drm.h b/include/drm/sis_drm.h index 30f7b382..8e51bb9a 100644 --- a/include/drm/sis_drm.h +++ b/include/drm/sis_drm.h @@ -27,6 +27,12 @@ #ifndef __SIS_DRM_H__ #define __SIS_DRM_H__ +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + /* SiS specific ioctls */ #define NOT_USED_0_3 #define DRM_SIS_FB_ALLOC 0x04 @@ -64,4 +70,8 @@ typedef struct { unsigned int offset, size; } drm_sis_fb_t; +#if defined(__cplusplus) +} +#endif + #endif /* __SIS_DRM_H__ */ diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h index 1be09c4b..6c07919c 100644 --- a/include/drm/tegra_drm.h +++ b/include/drm/tegra_drm.h @@ -1,194 +1,647 @@ /* * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _UAPI_TEGRA_DRM_H_ -#define _UAPI_TEGRA_DRM_H_ +#ifndef _TEGRA_DRM_H_ +#define _TEGRA_DRM_H_ -#include <drm/drm.h> +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif #define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) +/** + * struct drm_tegra_gem_create - parameters for the GEM object creation IOCTL + */ struct drm_tegra_gem_create { + /** + * @size: + * + * The size, in bytes, of the buffer object to be created. + */ __u64 size; + + /** + * @flags: + * + * A bitmask of flags that influence the creation of GEM objects: + * + * DRM_TEGRA_GEM_CREATE_TILED + * Use the 16x16 tiling format for this buffer. + * + * DRM_TEGRA_GEM_CREATE_BOTTOM_UP + * The buffer has a bottom-up layout. + */ __u32 flags; + + /** + * @handle: + * + * The handle of the created GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ __u32 handle; }; +/** + * struct drm_tegra_gem_mmap - parameters for the GEM mmap IOCTL + */ struct drm_tegra_gem_mmap { + /** + * @handle: + * + * Handle of the GEM object to obtain an mmap offset for. + */ __u32 handle; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; + + /** + * @offset: + * + * The mmap offset for the given GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ __u64 offset; }; +/** + * struct drm_tegra_syncpt_read - parameters for the read syncpoint IOCTL + */ struct drm_tegra_syncpt_read { + /** + * @id: + * + * ID of the syncpoint to read the current value from. + */ __u32 id; + + /** + * @value: + * + * The current syncpoint value. Set by the kernel upon successful + * completion of the IOCTL. + */ __u32 value; }; +/** + * struct drm_tegra_syncpt_incr - parameters for the increment syncpoint IOCTL + */ struct drm_tegra_syncpt_incr { + /** + * @id: + * + * ID of the syncpoint to increment. + */ __u32 id; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_syncpt_wait - parameters for the wait syncpoint IOCTL + */ struct drm_tegra_syncpt_wait { + /** + * @id: + * + * ID of the syncpoint to wait on. + */ __u32 id; + + /** + * @thresh: + * + * Threshold value for which to wait. + */ __u32 thresh; + + /** + * @timeout: + * + * Timeout, in milliseconds, to wait. + */ __u32 timeout; + + /** + * @value: + * + * The new syncpoint value after the wait. Set by the kernel upon + * successful completion of the IOCTL. + */ __u32 value; }; #define DRM_TEGRA_NO_TIMEOUT (0xffffffff) +/** + * struct drm_tegra_open_channel - parameters for the open channel IOCTL + */ struct drm_tegra_open_channel { + /** + * @client: + * + * The client ID for this channel. + */ __u32 client; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; + + /** + * @context: + * + * The application context of this channel. Set by the kernel upon + * successful completion of the IOCTL. This context needs to be passed + * to the DRM_TEGRA_CHANNEL_CLOSE or the DRM_TEGRA_SUBMIT IOCTLs. + */ __u64 context; }; +/** + * struct drm_tegra_close_channel - parameters for the close channel IOCTL + */ struct drm_tegra_close_channel { + /** + * @context: + * + * The application context of this channel. This is obtained from the + * DRM_TEGRA_OPEN_CHANNEL IOCTL. + */ __u64 context; }; +/** + * struct drm_tegra_get_syncpt - parameters for the get syncpoint IOCTL + */ struct drm_tegra_get_syncpt { + /** + * @context: + * + * The application context identifying the channel for which to obtain + * the syncpoint ID. + */ __u64 context; + + /** + * @index: + * + * Index of the client syncpoint for which to obtain the ID. + */ __u32 index; + + /** + * @id: + * + * The ID of the given syncpoint. Set by the kernel upon successful + * completion of the IOCTL. + */ __u32 id; }; +/** + * struct drm_tegra_get_syncpt_base - parameters for the get wait base IOCTL + */ struct drm_tegra_get_syncpt_base { + /** + * @context: + * + * The application context identifying for which channel to obtain the + * wait base. + */ __u64 context; + + /** + * @syncpt: + * + * ID of the syncpoint for which to obtain the wait base. + */ __u32 syncpt; + + /** + * @id: + * + * The ID of the wait base corresponding to the client syncpoint. Set + * by the kernel upon successful completion of the IOCTL. + */ __u32 id; }; +/** + * struct drm_tegra_syncpt - syncpoint increment operation + */ struct drm_tegra_syncpt { + /** + * @id: + * + * ID of the syncpoint to operate on. + */ __u32 id; + + /** + * @incrs: + * + * Number of increments to perform for the syncpoint. + */ __u32 incrs; }; +/** + * struct drm_tegra_cmdbuf - structure describing a command buffer + */ struct drm_tegra_cmdbuf { + /** + * @handle: + * + * Handle to a GEM object containing the command buffer. + */ __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, into the GEM object identified by @handle at + * which the command buffer starts. + */ __u32 offset; + + /** + * @words: + * + * Number of 32-bit words in this command buffer. + */ __u32 words; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_reloc - GEM object relocation structure + */ struct drm_tegra_reloc { struct { + /** + * @cmdbuf.handle: + * + * Handle to the GEM object containing the command buffer for + * which to perform this GEM object relocation. + */ __u32 handle; + + /** + * @cmdbuf.offset: + * + * Offset, in bytes, into the command buffer at which to + * insert the relocated address. + */ __u32 offset; } cmdbuf; struct { + /** + * @target.handle: + * + * Handle to the GEM object to be relocated. + */ __u32 handle; + + /** + * @target.offset: + * + * Offset, in bytes, into the target GEM object at which the + * relocated data starts. + */ __u32 offset; } target; + + /** + * @shift: + * + * The number of bits by which to shift relocated addresses. + */ __u32 shift; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_waitchk - wait check structure + */ struct drm_tegra_waitchk { + /** + * @handle: + * + * Handle to the GEM object containing a command stream on which to + * perform the wait check. + */ __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, of the location in the command stream to perform + * the wait check on. + */ __u32 offset; + + /** + * @syncpt: + * + * ID of the syncpoint to wait check. + */ __u32 syncpt; + + /** + * @thresh: + * + * Threshold value for which to check. + */ __u32 thresh; }; +/** + * struct drm_tegra_submit - job submission structure + */ struct drm_tegra_submit { + /** + * @context: + * + * The application context identifying the channel to use for the + * execution of this job. + */ __u64 context; + + /** + * @num_syncpts: + * + * The number of syncpoints operated on by this job. This defines the + * length of the array pointed to by @syncpts. + */ __u32 num_syncpts; + + /** + * @num_cmdbufs: + * + * The number of command buffers to execute as part of this job. This + * defines the length of the array pointed to by @cmdbufs. + */ __u32 num_cmdbufs; + + /** + * @num_relocs: + * + * The number of relocations to perform before executing this job. + * This defines the length of the array pointed to by @relocs. + */ __u32 num_relocs; + + /** + * @num_waitchks: + * + * The number of wait checks to perform as part of this job. This + * defines the length of the array pointed to by @waitchks. + */ __u32 num_waitchks; + + /** + * @waitchk_mask: + * + * Bitmask of valid wait checks. + */ __u32 waitchk_mask; + + /** + * @timeout: + * + * Timeout, in milliseconds, before this job is cancelled. + */ __u32 timeout; - __u32 pad; + + /** + * @syncpts: + * + * A pointer to an array of &struct drm_tegra_syncpt structures that + * specify the syncpoint operations performed as part of this job. + * The number of elements in the array must be equal to the value + * given by @num_syncpts. + */ __u64 syncpts; + + /** + * @cmdbufs: + * + * A pointer to an array of &struct drm_tegra_cmdbuf structures that + * define the command buffers to execute as part of this job. The + * number of elements in the array must be equal to the value given + * by @num_syncpts. + */ __u64 cmdbufs; + + /** + * @relocs: + * + * A pointer to an array of &struct drm_tegra_reloc structures that + * specify the relocations that need to be performed before executing + * this job. The number of elements in the array must be equal to the + * value given by @num_relocs. + */ __u64 relocs; + + /** + * @waitchks: + * + * A pointer to an array of &struct drm_tegra_waitchk structures that + * specify the wait checks to be performed while executing this job. + * The number of elements in the array must be equal to the value + * given by @num_waitchks. + */ __u64 waitchks; - __u32 fence; /* Return value */ - __u32 reserved[5]; /* future expansion */ + /** + * @fence: + * + * The threshold of the syncpoint associated with this job after it + * has been completed. Set by the kernel upon successful completion of + * the IOCTL. This can be used with the DRM_TEGRA_SYNCPT_WAIT IOCTL to + * wait for this job to be finished. + */ + __u32 fence; + + /** + * @reserved: + * + * This field is reserved for future use. Must be 0. + */ + __u32 reserved[5]; }; #define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 #define DRM_TEGRA_GEM_TILING_MODE_TILED 1 #define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 +/** + * struct drm_tegra_gem_set_tiling - parameters for the set tiling IOCTL + */ struct drm_tegra_gem_set_tiling { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to set the tiling parameters. + */ __u32 handle; + + /** + * @mode: + * + * The tiling mode to set. Must be one of: + * + * DRM_TEGRA_GEM_TILING_MODE_PITCH + * pitch linear format + * + * DRM_TEGRA_GEM_TILING_MODE_TILED + * 16x16 tiling format + * + * DRM_TEGRA_GEM_TILING_MODE_BLOCK + * 16Bx2 tiling format + */ __u32 mode; + + /** + * @value: + * + * The value to set for the tiling mode parameter. + */ __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_gem_get_tiling - parameters for the get tiling IOCTL + */ struct drm_tegra_gem_get_tiling { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to query the tiling parameters. + */ __u32 handle; - /* output */ + + /** + * @mode: + * + * The tiling mode currently associated with the GEM object. Set by + * the kernel upon successful completion of the IOCTL. + */ __u32 mode; + + /** + * @value: + * + * The tiling mode parameter currently associated with the GEM object. + * Set by the kernel upon successful completion of the IOCTL. + */ __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; #define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0) #define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP) +/** + * struct drm_tegra_gem_set_flags - parameters for the set flags IOCTL + */ struct drm_tegra_gem_set_flags { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to set the flags. + */ __u32 handle; - /* output */ + + /** + * @flags: + * + * The flags to set for the GEM object. + */ __u32 flags; }; +/** + * struct drm_tegra_gem_get_flags - parameters for the get flags IOCTL + */ struct drm_tegra_gem_get_flags { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to query the flags. + */ __u32 handle; - /* output */ - __u32 flags; -}; -enum request_type { - DRM_TEGRA_REQ_TYPE_CLK_KHZ = 0, - DRM_TEGRA_REQ_TYPE_BW_KBPS, -}; - -struct drm_tegra_get_clk_rate { - /* class ID*/ - __u32 id; - /* request type: KBps or KHz */ - __u32 type; - /* numeric value for type */ - __u64 data; -}; - -struct drm_tegra_set_clk_rate { - /* class ID*/ - __u32 id; - /* request type: KBps or KHz */ - __u32 type; - /* numeric value for type */ - __u64 data; -}; - -struct drm_tegra_keepon { - /* channel context (from opening a channel) */ - __u64 context; + /** + * @flags: + * + * The flags currently associated with the GEM object. Set by the + * kernel upon successful completion of the IOCTL. + */ + __u32 flags; }; #define DRM_TEGRA_GEM_CREATE 0x00 @@ -205,10 +658,6 @@ struct drm_tegra_keepon { #define DRM_TEGRA_GEM_GET_TILING 0x0b #define DRM_TEGRA_GEM_SET_FLAGS 0x0c #define DRM_TEGRA_GEM_GET_FLAGS 0x0d -#define DRM_TEGRA_GET_CLK_RATE 0x0e -#define DRM_TEGRA_SET_CLK_RATE 0x0f -#define DRM_TEGRA_START_KEEPON 0x10 -#define DRM_TEGRA_STOP_KEEPON 0x11 #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) @@ -216,7 +665,7 @@ struct drm_tegra_keepon { #define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr) #define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait) #define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel) -#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel) +#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_close_channel) #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) @@ -224,9 +673,9 @@ struct drm_tegra_keepon { #define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) #define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags) #define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags) -#define DRM_IOCTL_TEGRA_GET_CLK_RATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_CLK_RATE, struct drm_tegra_get_clk_rate) -#define DRM_IOCTL_TEGRA_SET_CLK_RATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SET_CLK_RATE, struct drm_tegra_set_clk_rate) -#define DRM_IOCTL_TEGRA_START_KEEPON DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_START_KEEPON, struct drm_tegra_keepon) -#define DRM_IOCTL_TEGRA_STOP_KEEPON DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_STOP_KEEPON, struct drm_tegra_keepon) + +#if defined(__cplusplus) +} +#endif #endif diff --git a/include/drm/vc4_drm.h b/include/drm/vc4_drm.h index 319881d8..31f50de3 100644 --- a/include/drm/vc4_drm.h +++ b/include/drm/vc4_drm.h @@ -38,6 +38,13 @@ extern "C" { #define DRM_VC4_CREATE_SHADER_BO 0x05 #define DRM_VC4_GET_HANG_STATE 0x06 #define DRM_VC4_GET_PARAM 0x07 +#define DRM_VC4_SET_TILING 0x08 +#define DRM_VC4_GET_TILING 0x09 +#define DRM_VC4_LABEL_BO 0x0a +#define DRM_VC4_GEM_MADVISE 0x0b +#define DRM_VC4_PERFMON_CREATE 0x0c +#define DRM_VC4_PERFMON_DESTROY 0x0d +#define DRM_VC4_PERFMON_GET_VALUES 0x0e #define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) #define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) @@ -47,6 +54,13 @@ extern "C" { #define DRM_IOCTL_VC4_CREATE_SHADER_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo) #define DRM_IOCTL_VC4_GET_HANG_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state) #define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param) +#define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling) +#define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling) +#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo) +#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise) +#define DRM_IOCTL_VC4_PERFMON_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_CREATE, struct drm_vc4_perfmon_create) +#define DRM_IOCTL_VC4_PERFMON_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_DESTROY, struct drm_vc4_perfmon_destroy) +#define DRM_IOCTL_VC4_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_GET_VALUES, struct drm_vc4_perfmon_get_values) struct drm_vc4_submit_rcl_surface { __u32 hindex; /* Handle index, or ~0 if not present. */ @@ -149,12 +163,38 @@ struct drm_vc4_submit_cl { __u32 pad:24; #define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0) +/* By default, the kernel gets to choose the order that the tiles are + * rendered in. If this is set, then the tiles will be rendered in a + * raster order, with the right-to-left vs left-to-right and + * top-to-bottom vs bottom-to-top dictated by + * VC4_SUBMIT_CL_RCL_ORDER_INCREASING_*. This allows overlapping + * blits to be implemented using the 3D engine. + */ +#define VC4_SUBMIT_CL_FIXED_RCL_ORDER (1 << 1) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X (1 << 2) +#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y (1 << 3) __u32 flags; /* Returned value of the seqno of this render job (for the * wait ioctl). */ __u64 seqno; + + /* ID of the perfmon to attach to this job. 0 means no perfmon. */ + __u32 perfmonid; + + /* Syncobj handle to wait on. If set, processing of this render job + * will not start until the syncobj is signaled. 0 means ignore. + */ + __u32 in_sync; + + /* Syncobj handle to export fence to. If set, the fence in the syncobj + * will be replaced with a fence that signals upon completion of this + * render job. 0 means ignore. + */ + __u32 out_sync; + + __u32 pad2; }; /** @@ -288,6 +328,9 @@ struct drm_vc4_get_hang_state { #define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 #define DRM_VC4_PARAM_SUPPORTS_ETC1 4 #define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5 +#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6 +#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7 +#define DRM_VC4_PARAM_SUPPORTS_PERFMON 8 struct drm_vc4_get_param { __u32 param; @@ -295,6 +338,103 @@ struct drm_vc4_get_param { __u64 value; }; +struct drm_vc4_get_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +struct drm_vc4_set_tiling { + __u32 handle; + __u32 flags; + __u64 modifier; +}; + +/** + * struct drm_vc4_label_bo - Attach a name to a BO for debug purposes. + */ +struct drm_vc4_label_bo { + __u32 handle; + __u32 len; + __u64 name; +}; + +/* + * States prefixed with '__' are internal states and cannot be passed to the + * DRM_IOCTL_VC4_GEM_MADVISE ioctl. + */ +#define VC4_MADV_WILLNEED 0 +#define VC4_MADV_DONTNEED 1 +#define __VC4_MADV_PURGED 2 +#define __VC4_MADV_NOTSUPP 3 + +struct drm_vc4_gem_madvise { + __u32 handle; + __u32 madv; + __u32 retained; + __u32 pad; +}; + +enum { + VC4_PERFCNT_FEP_VALID_PRIMS_NO_RENDER, + VC4_PERFCNT_FEP_VALID_PRIMS_RENDER, + VC4_PERFCNT_FEP_CLIPPED_QUADS, + VC4_PERFCNT_FEP_VALID_QUADS, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_STENCIL, + VC4_PERFCNT_TLB_QUADS_NOT_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_PASSING_Z_AND_STENCIL, + VC4_PERFCNT_TLB_QUADS_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_NON_ZERO_COVERAGE, + VC4_PERFCNT_TLB_QUADS_WRITTEN_TO_COLOR_BUF, + VC4_PERFCNT_PLB_PRIMS_OUTSIDE_VIEWPORT, + VC4_PERFCNT_PLB_PRIMS_NEED_CLIPPING, + VC4_PERFCNT_PSE_PRIMS_REVERSED, + VC4_PERFCNT_QPU_TOTAL_IDLE_CYCLES, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_VERTEX_COORD_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_FRAGMENT_SHADING, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_EXEC_VALID_INST, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_TMUS, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_SCOREBOARD, + VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_VARYINGS, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_INST_CACHE_MISS, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_HIT, + VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_MISS, + VC4_PERFCNT_TMU_TOTAL_TEXT_QUADS_PROCESSED, + VC4_PERFCNT_TMU_TOTAL_TEXT_CACHE_MISS, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VDW_STALLED, + VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VCD_STALLED, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_HIT, + VC4_PERFCNT_L2C_TOTAL_L2_CACHE_MISS, + VC4_PERFCNT_NUM_EVENTS, +}; + +#define DRM_VC4_MAX_PERF_COUNTERS 16 + +struct drm_vc4_perfmon_create { + __u32 id; + __u32 ncounters; + __u8 events[DRM_VC4_MAX_PERF_COUNTERS]; +}; + +struct drm_vc4_perfmon_destroy { + __u32 id; +}; + +/* + * Returns the values of the performance counters tracked by this + * perfmon (as an array of ncounters u64 values). + * + * No implicit synchronization is performed, so the user has to + * guarantee that any jobs using this perfmon have already been + * completed (probably by blocking on the seqno returned by the + * last exec that used the perfmon). + */ +struct drm_vc4_perfmon_get_values { + __u32 id; + __u64 values_ptr; +}; + #if defined(__cplusplus) } #endif diff --git a/include/drm/via_drm.h b/include/drm/via_drm.h index 182f8792..8b69e819 100644 --- a/include/drm/via_drm.h +++ b/include/drm/via_drm.h @@ -26,6 +26,10 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + /* WARNING: These defines must be the same as what the Xserver uses. * if you change them, you must change the defines in the Xserver. */ @@ -272,4 +276,8 @@ typedef struct drm_via_dmablit { drm_via_blitsync_t sync; } drm_via_dmablit_t; +#if defined(__cplusplus) +} +#endif + #endif /* _VIA_DRM_H_ */ diff --git a/include/drm/virtgpu_drm.h b/include/drm/virtgpu_drm.h index 91a31ffe..9a781f06 100644 --- a/include/drm/virtgpu_drm.h +++ b/include/drm/virtgpu_drm.h @@ -63,6 +63,7 @@ struct drm_virtgpu_execbuffer { }; #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ +#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */ struct drm_virtgpu_getparam { __u64 param; diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h index 5b68b4d1..0bc784f5 100644 --- a/include/drm/vmwgfx_drm.h +++ b/include/drm/vmwgfx_drm.h @@ -30,6 +30,10 @@ #include "drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + #define DRM_VMW_MAX_SURFACE_FACES 6 #define DRM_VMW_MAX_MIP_LEVELS 24 @@ -37,6 +41,7 @@ #define DRM_VMW_GET_PARAM 0 #define DRM_VMW_ALLOC_DMABUF 1 #define DRM_VMW_UNREF_DMABUF 2 +#define DRM_VMW_HANDLE_CLOSE 2 #define DRM_VMW_CURSOR_BYPASS 3 /* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/ #define DRM_VMW_CONTROL_STREAM 4 @@ -292,13 +297,17 @@ union drm_vmw_surface_reference_arg { * @version: Allows expanding the execbuf ioctl parameters without breaking * backwards compatibility, since user-space will always tell the kernel * which version it uses. - * @flags: Execbuf flags. None currently. + * @flags: Execbuf flags. + * @imported_fence_fd: FD for a fence imported from another device * * Argument to the DRM_VMW_EXECBUF Ioctl. */ #define DRM_VMW_EXECBUF_VERSION 2 +#define DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD (1 << 0) +#define DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD (1 << 1) + struct drm_vmw_execbuf_arg { __u64 commands; __u32 command_size; @@ -307,7 +316,7 @@ struct drm_vmw_execbuf_arg { __u32 version; __u32 flags; __u32 context_handle; - __u32 pad64; + __s32 imported_fence_fd; }; /** @@ -323,6 +332,7 @@ struct drm_vmw_execbuf_arg { * @passed_seqno: The highest seqno number processed by the hardware * so far. This can be used to mark user-space fence objects as signaled, and * to determine whether a fence seqno might be stale. + * @fd: FD associated with the fence, -1 if not exported * @error: This member should've been set to -EFAULT on submission. * The following actions should be take on completion: * error == -EFAULT: Fence communication failed. The host is synchronized. @@ -340,7 +350,7 @@ struct drm_vmw_fence_rep { __u32 mask; __u32 seqno; __u32 passed_seqno; - __u32 pad64; + __s32 fd; __s32 error; }; @@ -1087,4 +1097,32 @@ union drm_vmw_extended_context_arg { enum drm_vmw_extended_context req; struct drm_vmw_context_arg rep; }; + +/*************************************************************************/ +/* + * DRM_VMW_HANDLE_CLOSE - Close a user-space handle and release its + * underlying resource. + * + * Note that this ioctl is overlaid on the DRM_VMW_UNREF_DMABUF Ioctl. + * The ioctl arguments therefore need to be identical in layout. + * + */ + +/** + * struct drm_vmw_handle_close_arg + * + * @handle: Handle to close. + * + * Argument to the DRM_VMW_HANDLE_CLOSE Ioctl. + */ +struct drm_vmw_handle_close_arg { + __u32 handle; + __u32 pad64; +}; + + +#if defined(__cplusplus) +} +#endif + #endif diff --git a/intel/Android.sources.bp b/intel/Android.sources.bp index 459c070f..46e0328f 100644 --- a/intel/Android.sources.bp +++ b/intel/Android.sources.bp @@ -7,6 +7,7 @@ cc_defaults { "intel_bufmgr_fake.c", "intel_bufmgr_gem.c", "intel_decode.c", + "intel_chipset.c", "mm.c", ], } diff --git a/intel/Makefile.am b/intel/Makefile.am index c52e8c08..bad44f5f 100644 --- a/intel/Makefile.am +++ b/intel/Makefile.am @@ -26,6 +26,7 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ $(PCIACCESS_CFLAGS) \ @@ -56,6 +57,7 @@ BATCHES = \ tests/gen7-2d-copy.batch \ tests/gen7-3d.batch +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = \ $(BATCHES:.batch=.batch.sh) \ intel-symbol-check diff --git a/intel/Makefile.sources b/intel/Makefile.sources index 6947ab74..aa27e273 100644 --- a/intel/Makefile.sources +++ b/intel/Makefile.sources @@ -1,10 +1,12 @@ LIBDRM_INTEL_FILES := \ + i915_pciids.h \ intel_bufmgr.c \ intel_bufmgr_priv.h \ intel_bufmgr_fake.c \ intel_bufmgr_gem.c \ intel_decode.c \ intel_chipset.h \ + intel_chipset.c \ mm.c \ mm.h \ uthash.h diff --git a/intel/i915_pciids.h b/intel/i915_pciids.h new file mode 100644 index 00000000..fd965ffb --- /dev/null +++ b/intel/i915_pciids.h @@ -0,0 +1,461 @@ +/* + * Copyright 2013 Intel Corporation + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _I915_PCIIDS_H +#define _I915_PCIIDS_H + +/* + * A pci_device_id struct { + * __u32 vendor, device; + * __u32 subvendor, subdevice; + * __u32 class, class_mask; + * kernel_ulong_t driver_data; + * }; + * Don't use C99 here because "class" is reserved and we want to + * give userspace flexibility. + */ +#define INTEL_VGA_DEVICE(id, info) { \ + 0x8086, id, \ + ~0, ~0, \ + 0x030000, 0xff0000, \ + (unsigned long) info } + +#define INTEL_QUANTA_VGA_DEVICE(info) { \ + 0x8086, 0x16a, \ + 0x152d, 0x8990, \ + 0x030000, 0xff0000, \ + (unsigned long) info } + +#define INTEL_I810_IDS(info) \ + INTEL_VGA_DEVICE(0x7121, info), /* I810 */ \ + INTEL_VGA_DEVICE(0x7123, info), /* I810_DC100 */ \ + INTEL_VGA_DEVICE(0x7125, info) /* I810_E */ + +#define INTEL_I815_IDS(info) \ + INTEL_VGA_DEVICE(0x1132, info) /* I815*/ + +#define INTEL_I830_IDS(info) \ + INTEL_VGA_DEVICE(0x3577, info) + +#define INTEL_I845G_IDS(info) \ + INTEL_VGA_DEVICE(0x2562, info) + +#define INTEL_I85X_IDS(info) \ + INTEL_VGA_DEVICE(0x3582, info), /* I855_GM */ \ + INTEL_VGA_DEVICE(0x358e, info) + +#define INTEL_I865G_IDS(info) \ + INTEL_VGA_DEVICE(0x2572, info) /* I865_G */ + +#define INTEL_I915G_IDS(info) \ + INTEL_VGA_DEVICE(0x2582, info), /* I915_G */ \ + INTEL_VGA_DEVICE(0x258a, info) /* E7221_G */ + +#define INTEL_I915GM_IDS(info) \ + INTEL_VGA_DEVICE(0x2592, info) /* I915_GM */ + +#define INTEL_I945G_IDS(info) \ + INTEL_VGA_DEVICE(0x2772, info) /* I945_G */ + +#define INTEL_I945GM_IDS(info) \ + INTEL_VGA_DEVICE(0x27a2, info), /* I945_GM */ \ + INTEL_VGA_DEVICE(0x27ae, info) /* I945_GME */ + +#define INTEL_I965G_IDS(info) \ + INTEL_VGA_DEVICE(0x2972, info), /* I946_GZ */ \ + INTEL_VGA_DEVICE(0x2982, info), /* G35_G */ \ + INTEL_VGA_DEVICE(0x2992, info), /* I965_Q */ \ + INTEL_VGA_DEVICE(0x29a2, info) /* I965_G */ + +#define INTEL_G33_IDS(info) \ + INTEL_VGA_DEVICE(0x29b2, info), /* Q35_G */ \ + INTEL_VGA_DEVICE(0x29c2, info), /* G33_G */ \ + INTEL_VGA_DEVICE(0x29d2, info) /* Q33_G */ + +#define INTEL_I965GM_IDS(info) \ + INTEL_VGA_DEVICE(0x2a02, info), /* I965_GM */ \ + INTEL_VGA_DEVICE(0x2a12, info) /* I965_GME */ + +#define INTEL_GM45_IDS(info) \ + INTEL_VGA_DEVICE(0x2a42, info) /* GM45_G */ + +#define INTEL_G45_IDS(info) \ + INTEL_VGA_DEVICE(0x2e02, info), /* IGD_E_G */ \ + INTEL_VGA_DEVICE(0x2e12, info), /* Q45_G */ \ + INTEL_VGA_DEVICE(0x2e22, info), /* G45_G */ \ + INTEL_VGA_DEVICE(0x2e32, info), /* G41_G */ \ + INTEL_VGA_DEVICE(0x2e42, info), /* B43_G */ \ + INTEL_VGA_DEVICE(0x2e92, info) /* B43_G.1 */ + +#define INTEL_PINEVIEW_IDS(info) \ + INTEL_VGA_DEVICE(0xa001, info), \ + INTEL_VGA_DEVICE(0xa011, info) + +#define INTEL_IRONLAKE_D_IDS(info) \ + INTEL_VGA_DEVICE(0x0042, info) + +#define INTEL_IRONLAKE_M_IDS(info) \ + INTEL_VGA_DEVICE(0x0046, info) + +#define INTEL_SNB_D_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x0102, info), \ + INTEL_VGA_DEVICE(0x010A, info) + +#define INTEL_SNB_D_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x0112, info), \ + INTEL_VGA_DEVICE(0x0122, info) + +#define INTEL_SNB_D_IDS(info) \ + INTEL_SNB_D_GT1_IDS(info), \ + INTEL_SNB_D_GT2_IDS(info) + +#define INTEL_SNB_M_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x0106, info) + +#define INTEL_SNB_M_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x0116, info), \ + INTEL_VGA_DEVICE(0x0126, info) + +#define INTEL_SNB_M_IDS(info) \ + INTEL_SNB_M_GT1_IDS(info), \ + INTEL_SNB_M_GT2_IDS(info) + +#define INTEL_IVB_M_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x0156, info) /* GT1 mobile */ + +#define INTEL_IVB_M_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x0166, info) /* GT2 mobile */ + +#define INTEL_IVB_M_IDS(info) \ + INTEL_IVB_M_GT1_IDS(info), \ + INTEL_IVB_M_GT2_IDS(info) + +#define INTEL_IVB_D_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x0152, info), /* GT1 desktop */ \ + INTEL_VGA_DEVICE(0x015a, info) /* GT1 server */ + +#define INTEL_IVB_D_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x0162, info), /* GT2 desktop */ \ + INTEL_VGA_DEVICE(0x016a, info) /* GT2 server */ + +#define INTEL_IVB_D_IDS(info) \ + INTEL_IVB_D_GT1_IDS(info), \ + INTEL_IVB_D_GT2_IDS(info) + +#define INTEL_IVB_Q_IDS(info) \ + INTEL_QUANTA_VGA_DEVICE(info) /* Quanta transcode */ + +#define INTEL_HSW_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x0402, info), /* GT1 desktop */ \ + INTEL_VGA_DEVICE(0x040a, info), /* GT1 server */ \ + INTEL_VGA_DEVICE(0x040B, info), /* GT1 reserved */ \ + INTEL_VGA_DEVICE(0x040E, info), /* GT1 reserved */ \ + INTEL_VGA_DEVICE(0x0C02, info), /* SDV GT1 desktop */ \ + INTEL_VGA_DEVICE(0x0C0A, info), /* SDV GT1 server */ \ + INTEL_VGA_DEVICE(0x0C0B, info), /* SDV GT1 reserved */ \ + INTEL_VGA_DEVICE(0x0C0E, info), /* SDV GT1 reserved */ \ + INTEL_VGA_DEVICE(0x0A02, info), /* ULT GT1 desktop */ \ + INTEL_VGA_DEVICE(0x0A0A, info), /* ULT GT1 server */ \ + INTEL_VGA_DEVICE(0x0A0B, info), /* ULT GT1 reserved */ \ + INTEL_VGA_DEVICE(0x0D02, info), /* CRW GT1 desktop */ \ + INTEL_VGA_DEVICE(0x0D0A, info), /* CRW GT1 server */ \ + INTEL_VGA_DEVICE(0x0D0B, info), /* CRW GT1 reserved */ \ + INTEL_VGA_DEVICE(0x0D0E, info), /* CRW GT1 reserved */ \ + INTEL_VGA_DEVICE(0x0406, info), /* GT1 mobile */ \ + INTEL_VGA_DEVICE(0x0C06, info), /* SDV GT1 mobile */ \ + INTEL_VGA_DEVICE(0x0A06, info), /* ULT GT1 mobile */ \ + INTEL_VGA_DEVICE(0x0A0E, info), /* ULX GT1 mobile */ \ + INTEL_VGA_DEVICE(0x0D06, info) /* CRW GT1 mobile */ + +#define INTEL_HSW_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x0412, info), /* GT2 desktop */ \ + INTEL_VGA_DEVICE(0x041a, info), /* GT2 server */ \ + INTEL_VGA_DEVICE(0x041B, info), /* GT2 reserved */ \ + INTEL_VGA_DEVICE(0x041E, info), /* GT2 reserved */ \ + INTEL_VGA_DEVICE(0x0C12, info), /* SDV GT2 desktop */ \ + INTEL_VGA_DEVICE(0x0C1A, info), /* SDV GT2 server */ \ + INTEL_VGA_DEVICE(0x0C1B, info), /* SDV GT2 reserved */ \ + INTEL_VGA_DEVICE(0x0C1E, info), /* SDV GT2 reserved */ \ + INTEL_VGA_DEVICE(0x0A12, info), /* ULT GT2 desktop */ \ + INTEL_VGA_DEVICE(0x0A1A, info), /* ULT GT2 server */ \ + INTEL_VGA_DEVICE(0x0A1B, info), /* ULT GT2 reserved */ \ + INTEL_VGA_DEVICE(0x0D12, info), /* CRW GT2 desktop */ \ + INTEL_VGA_DEVICE(0x0D1A, info), /* CRW GT2 server */ \ + INTEL_VGA_DEVICE(0x0D1B, info), /* CRW GT2 reserved */ \ + INTEL_VGA_DEVICE(0x0D1E, info), /* CRW GT2 reserved */ \ + INTEL_VGA_DEVICE(0x0416, info), /* GT2 mobile */ \ + INTEL_VGA_DEVICE(0x0426, info), /* GT2 mobile */ \ + INTEL_VGA_DEVICE(0x0C16, info), /* SDV GT2 mobile */ \ + INTEL_VGA_DEVICE(0x0A16, info), /* ULT GT2 mobile */ \ + INTEL_VGA_DEVICE(0x0A1E, info), /* ULX GT2 mobile */ \ + INTEL_VGA_DEVICE(0x0D16, info) /* CRW GT2 mobile */ + +#define INTEL_HSW_GT3_IDS(info) \ + INTEL_VGA_DEVICE(0x0422, info), /* GT3 desktop */ \ + INTEL_VGA_DEVICE(0x042a, info), /* GT3 server */ \ + INTEL_VGA_DEVICE(0x042B, info), /* GT3 reserved */ \ + INTEL_VGA_DEVICE(0x042E, info), /* GT3 reserved */ \ + INTEL_VGA_DEVICE(0x0C22, info), /* SDV GT3 desktop */ \ + INTEL_VGA_DEVICE(0x0C2A, info), /* SDV GT3 server */ \ + INTEL_VGA_DEVICE(0x0C2B, info), /* SDV GT3 reserved */ \ + INTEL_VGA_DEVICE(0x0C2E, info), /* SDV GT3 reserved */ \ + INTEL_VGA_DEVICE(0x0A22, info), /* ULT GT3 desktop */ \ + INTEL_VGA_DEVICE(0x0A2A, info), /* ULT GT3 server */ \ + INTEL_VGA_DEVICE(0x0A2B, info), /* ULT GT3 reserved */ \ + INTEL_VGA_DEVICE(0x0D22, info), /* CRW GT3 desktop */ \ + INTEL_VGA_DEVICE(0x0D2A, info), /* CRW GT3 server */ \ + INTEL_VGA_DEVICE(0x0D2B, info), /* CRW GT3 reserved */ \ + INTEL_VGA_DEVICE(0x0D2E, info), /* CRW GT3 reserved */ \ + INTEL_VGA_DEVICE(0x0C26, info), /* SDV GT3 mobile */ \ + INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \ + INTEL_VGA_DEVICE(0x0A2E, info), /* ULT GT3 reserved */ \ + INTEL_VGA_DEVICE(0x0D26, info) /* CRW GT3 mobile */ + +#define INTEL_HSW_IDS(info) \ + INTEL_HSW_GT1_IDS(info), \ + INTEL_HSW_GT2_IDS(info), \ + INTEL_HSW_GT3_IDS(info) + +#define INTEL_VLV_IDS(info) \ + INTEL_VGA_DEVICE(0x0f30, info), \ + INTEL_VGA_DEVICE(0x0f31, info), \ + INTEL_VGA_DEVICE(0x0f32, info), \ + INTEL_VGA_DEVICE(0x0f33, info), \ + INTEL_VGA_DEVICE(0x0157, info), \ + INTEL_VGA_DEVICE(0x0155, info) + +#define INTEL_BDW_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x1602, info), /* GT1 ULT */ \ + INTEL_VGA_DEVICE(0x1606, info), /* GT1 ULT */ \ + INTEL_VGA_DEVICE(0x160B, info), /* GT1 Iris */ \ + INTEL_VGA_DEVICE(0x160E, info), /* GT1 ULX */ \ + INTEL_VGA_DEVICE(0x160A, info), /* GT1 Server */ \ + INTEL_VGA_DEVICE(0x160D, info) /* GT1 Workstation */ + +#define INTEL_BDW_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x1612, info), /* GT2 Halo */ \ + INTEL_VGA_DEVICE(0x1616, info), /* GT2 ULT */ \ + INTEL_VGA_DEVICE(0x161B, info), /* GT2 ULT */ \ + INTEL_VGA_DEVICE(0x161E, info), /* GT2 ULX */ \ + INTEL_VGA_DEVICE(0x161A, info), /* GT2 Server */ \ + INTEL_VGA_DEVICE(0x161D, info) /* GT2 Workstation */ + +#define INTEL_BDW_GT3_IDS(info) \ + INTEL_VGA_DEVICE(0x1622, info), /* ULT */ \ + INTEL_VGA_DEVICE(0x1626, info), /* ULT */ \ + INTEL_VGA_DEVICE(0x162B, info), /* Iris */ \ + INTEL_VGA_DEVICE(0x162E, info), /* ULX */\ + INTEL_VGA_DEVICE(0x162A, info), /* Server */ \ + INTEL_VGA_DEVICE(0x162D, info) /* Workstation */ + +#define INTEL_BDW_RSVD_IDS(info) \ + INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \ + INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \ + INTEL_VGA_DEVICE(0x163B, info), /* Iris */ \ + INTEL_VGA_DEVICE(0x163E, info), /* ULX */ \ + INTEL_VGA_DEVICE(0x163A, info), /* Server */ \ + INTEL_VGA_DEVICE(0x163D, info) /* Workstation */ + +#define INTEL_BDW_IDS(info) \ + INTEL_BDW_GT1_IDS(info), \ + INTEL_BDW_GT2_IDS(info), \ + INTEL_BDW_GT3_IDS(info), \ + INTEL_BDW_RSVD_IDS(info) + +#define INTEL_CHV_IDS(info) \ + INTEL_VGA_DEVICE(0x22b0, info), \ + INTEL_VGA_DEVICE(0x22b1, info), \ + INTEL_VGA_DEVICE(0x22b2, info), \ + INTEL_VGA_DEVICE(0x22b3, info) + +#define INTEL_SKL_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x1906, info), /* ULT GT1 */ \ + INTEL_VGA_DEVICE(0x190E, info), /* ULX GT1 */ \ + INTEL_VGA_DEVICE(0x1902, info), /* DT GT1 */ \ + INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */ \ + INTEL_VGA_DEVICE(0x190A, info) /* SRV GT1 */ + +#define INTEL_SKL_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */ \ + INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */ \ + INTEL_VGA_DEVICE(0x191E, info), /* ULX GT2 */ \ + INTEL_VGA_DEVICE(0x1912, info), /* DT GT2 */ \ + INTEL_VGA_DEVICE(0x191B, info), /* Halo GT2 */ \ + INTEL_VGA_DEVICE(0x191A, info), /* SRV GT2 */ \ + INTEL_VGA_DEVICE(0x191D, info) /* WKS GT2 */ + +#define INTEL_SKL_GT3_IDS(info) \ + INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \ + INTEL_VGA_DEVICE(0x192D, info) /* SRV GT3 */ + +#define INTEL_SKL_GT4_IDS(info) \ + INTEL_VGA_DEVICE(0x1932, info), /* DT GT4 */ \ + INTEL_VGA_DEVICE(0x193B, info), /* Halo GT4 */ \ + INTEL_VGA_DEVICE(0x193D, info), /* WKS GT4 */ \ + INTEL_VGA_DEVICE(0x192A, info), /* SRV GT4 */ \ + INTEL_VGA_DEVICE(0x193A, info) /* SRV GT4e */ + +#define INTEL_SKL_IDS(info) \ + INTEL_SKL_GT1_IDS(info), \ + INTEL_SKL_GT2_IDS(info), \ + INTEL_SKL_GT3_IDS(info), \ + INTEL_SKL_GT4_IDS(info) + +#define INTEL_BXT_IDS(info) \ + INTEL_VGA_DEVICE(0x0A84, info), \ + INTEL_VGA_DEVICE(0x1A84, info), \ + INTEL_VGA_DEVICE(0x1A85, info), \ + INTEL_VGA_DEVICE(0x5A84, info), /* APL HD Graphics 505 */ \ + INTEL_VGA_DEVICE(0x5A85, info) /* APL HD Graphics 500 */ + +#define INTEL_GLK_IDS(info) \ + INTEL_VGA_DEVICE(0x3184, info), \ + INTEL_VGA_DEVICE(0x3185, info) + +#define INTEL_KBL_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \ + INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \ + INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */ \ + INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */ \ + INTEL_VGA_DEVICE(0x5902, info), /* DT GT1 */ \ + INTEL_VGA_DEVICE(0x5908, info), /* Halo GT1 */ \ + INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */ \ + INTEL_VGA_DEVICE(0x590A, info) /* SRV GT1 */ + +#define INTEL_KBL_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \ + INTEL_VGA_DEVICE(0x5917, info), /* Mobile GT2 */ \ + INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \ + INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \ + INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */ \ + INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */ \ + INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */ \ + INTEL_VGA_DEVICE(0x591D, info) /* WKS GT2 */ + +#define INTEL_KBL_GT3_IDS(info) \ + INTEL_VGA_DEVICE(0x5923, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x5927, info) /* ULT GT3 */ + +#define INTEL_KBL_GT4_IDS(info) \ + INTEL_VGA_DEVICE(0x593B, info) /* Halo GT4 */ + +/* AML/KBL Y GT2 */ +#define INTEL_AML_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x591C, info), /* ULX GT2 */ \ + INTEL_VGA_DEVICE(0x87C0, info) /* ULX GT2 */ + +#define INTEL_KBL_IDS(info) \ + INTEL_KBL_GT1_IDS(info), \ + INTEL_KBL_GT2_IDS(info), \ + INTEL_KBL_GT3_IDS(info), \ + INTEL_KBL_GT4_IDS(info), \ + INTEL_AML_GT2_IDS(info) + +/* CFL S */ +#define INTEL_CFL_S_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x3E90, info), /* SRV GT1 */ \ + INTEL_VGA_DEVICE(0x3E93, info), /* SRV GT1 */ \ + INTEL_VGA_DEVICE(0x3E99, info) /* SRV GT1 */ + +#define INTEL_CFL_S_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x3E91, info), /* SRV GT2 */ \ + INTEL_VGA_DEVICE(0x3E92, info), /* SRV GT2 */ \ + INTEL_VGA_DEVICE(0x3E96, info), /* SRV GT2 */ \ + INTEL_VGA_DEVICE(0x3E98, info), /* SRV GT2 */ \ + INTEL_VGA_DEVICE(0x3E9A, info) /* SRV GT2 */ + +/* CFL H */ +#define INTEL_CFL_H_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x3E9B, info), /* Halo GT2 */ \ + INTEL_VGA_DEVICE(0x3E94, info) /* Halo GT2 */ + +/* CFL U GT2 */ +#define INTEL_CFL_U_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x3EA9, info) + +/* CFL U GT3 */ +#define INTEL_CFL_U_GT3_IDS(info) \ + INTEL_VGA_DEVICE(0x3EA5, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x3EA6, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x3EA7, info), /* ULT GT3 */ \ + INTEL_VGA_DEVICE(0x3EA8, info) /* ULT GT3 */ + +/* WHL/CFL U GT1 */ +#define INTEL_WHL_U_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x3EA1, info) + +/* WHL/CFL U GT2 */ +#define INTEL_WHL_U_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x3EA0, info) + +/* WHL/CFL U GT3 */ +#define INTEL_WHL_U_GT3_IDS(info) \ + INTEL_VGA_DEVICE(0x3EA2, info), \ + INTEL_VGA_DEVICE(0x3EA3, info), \ + INTEL_VGA_DEVICE(0x3EA4, info) + +#define INTEL_CFL_IDS(info) \ + INTEL_CFL_S_GT1_IDS(info), \ + INTEL_CFL_S_GT2_IDS(info), \ + INTEL_CFL_H_GT2_IDS(info), \ + INTEL_CFL_U_GT2_IDS(info), \ + INTEL_CFL_U_GT3_IDS(info), \ + INTEL_WHL_U_GT1_IDS(info), \ + INTEL_WHL_U_GT2_IDS(info), \ + INTEL_WHL_U_GT3_IDS(info) + +/* CNL */ +#define INTEL_CNL_IDS(info) \ + INTEL_VGA_DEVICE(0x5A51, info), \ + INTEL_VGA_DEVICE(0x5A59, info), \ + INTEL_VGA_DEVICE(0x5A41, info), \ + INTEL_VGA_DEVICE(0x5A49, info), \ + INTEL_VGA_DEVICE(0x5A52, info), \ + INTEL_VGA_DEVICE(0x5A5A, info), \ + INTEL_VGA_DEVICE(0x5A42, info), \ + INTEL_VGA_DEVICE(0x5A4A, info), \ + INTEL_VGA_DEVICE(0x5A50, info), \ + INTEL_VGA_DEVICE(0x5A40, info), \ + INTEL_VGA_DEVICE(0x5A54, info), \ + INTEL_VGA_DEVICE(0x5A5C, info), \ + INTEL_VGA_DEVICE(0x5A44, info), \ + INTEL_VGA_DEVICE(0x5A4C, info) + +/* ICL */ +#define INTEL_ICL_11_IDS(info) \ + INTEL_VGA_DEVICE(0x8A50, info), \ + INTEL_VGA_DEVICE(0x8A51, info), \ + INTEL_VGA_DEVICE(0x8A5C, info), \ + INTEL_VGA_DEVICE(0x8A5D, info), \ + INTEL_VGA_DEVICE(0x8A52, info), \ + INTEL_VGA_DEVICE(0x8A5A, info), \ + INTEL_VGA_DEVICE(0x8A5B, info), \ + INTEL_VGA_DEVICE(0x8A71, info), \ + INTEL_VGA_DEVICE(0x8A70, info) + +#endif /* _I915_PCIIDS_H */ diff --git a/intel/intel-symbol-check b/intel/intel-symbol-check index 2aa2d819..de377bef 100755 --- a/intel/intel-symbol-check +++ b/intel/intel-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.sources/LIBDRM_INTEL_H_FILES -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_intel.so} | awk '{print $3}' | while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_intel.so} | awk '{print $3}' | while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata diff --git a/intel/intel_bufmgr.c b/intel/intel_bufmgr.c index 5bad93fa..68d97c0e 100644 --- a/intel/intel_bufmgr.c +++ b/intel/intel_bufmgr.c @@ -25,10 +25,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <string.h> #include <stdlib.h> #include <stdint.h> @@ -49,21 +45,21 @@ * Convenience functions for buffer management methods. */ -drm_intel_bo * +drm_public drm_intel_bo * drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, unsigned long size, unsigned int alignment) { return bufmgr->bo_alloc(bufmgr, name, size, alignment); } -drm_intel_bo * +drm_public drm_intel_bo * drm_intel_bo_alloc_for_render(drm_intel_bufmgr *bufmgr, const char *name, unsigned long size, unsigned int alignment) { return bufmgr->bo_alloc_for_render(bufmgr, name, size, alignment); } -drm_intel_bo * +drm_public drm_intel_bo * drm_intel_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, const char *name, void *addr, uint32_t tiling_mode, @@ -77,7 +73,7 @@ drm_intel_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, return NULL; } -drm_intel_bo * +drm_public drm_intel_bo * drm_intel_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, int x, int y, int cpp, uint32_t *tiling_mode, unsigned long *pitch, unsigned long flags) @@ -86,13 +82,13 @@ drm_intel_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, tiling_mode, pitch, flags); } -void +drm_public void drm_intel_bo_reference(drm_intel_bo *bo) { bo->bufmgr->bo_reference(bo); } -void +drm_public void drm_intel_bo_unreference(drm_intel_bo *bo) { if (bo == NULL) @@ -101,26 +97,26 @@ drm_intel_bo_unreference(drm_intel_bo *bo) bo->bufmgr->bo_unreference(bo); } -int +drm_public int drm_intel_bo_map(drm_intel_bo *buf, int write_enable) { return buf->bufmgr->bo_map(buf, write_enable); } -int +drm_public int drm_intel_bo_unmap(drm_intel_bo *buf) { return buf->bufmgr->bo_unmap(buf); } -int +drm_public int drm_intel_bo_subdata(drm_intel_bo *bo, unsigned long offset, unsigned long size, const void *data) { return bo->bufmgr->bo_subdata(bo, offset, size, data); } -int +drm_public int drm_intel_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, unsigned long size, void *data) { @@ -139,26 +135,26 @@ drm_intel_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, return 0; } -void +drm_public void drm_intel_bo_wait_rendering(drm_intel_bo *bo) { bo->bufmgr->bo_wait_rendering(bo); } -void +drm_public void drm_intel_bufmgr_destroy(drm_intel_bufmgr *bufmgr) { bufmgr->destroy(bufmgr); } -int +drm_public int drm_intel_bo_exec(drm_intel_bo *bo, int used, drm_clip_rect_t * cliprects, int num_cliprects, int DR4) { return bo->bufmgr->bo_exec(bo, used, cliprects, num_cliprects, DR4); } -int +drm_public int drm_intel_bo_mrb_exec(drm_intel_bo *bo, int used, drm_clip_rect_t *cliprects, int num_cliprects, int DR4, unsigned int rings) @@ -178,19 +174,19 @@ drm_intel_bo_mrb_exec(drm_intel_bo *bo, int used, } } -void +drm_public void drm_intel_bufmgr_set_debug(drm_intel_bufmgr *bufmgr, int enable_debug) { bufmgr->debug = enable_debug; } -int +drm_public int drm_intel_bufmgr_check_aperture_space(drm_intel_bo ** bo_array, int count) { return bo_array[0]->bufmgr->check_aperture_space(bo_array, count); } -int +drm_public int drm_intel_bo_flink(drm_intel_bo *bo, uint32_t * name) { if (bo->bufmgr->bo_flink) @@ -199,7 +195,7 @@ drm_intel_bo_flink(drm_intel_bo *bo, uint32_t * name) return -ENODEV; } -int +drm_public int drm_intel_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, drm_intel_bo *target_bo, uint32_t target_offset, uint32_t read_domains, uint32_t write_domain) @@ -210,7 +206,7 @@ drm_intel_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, } /* For fence registers, not GL fences */ -int +drm_public int drm_intel_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset, drm_intel_bo *target_bo, uint32_t target_offset, uint32_t read_domains, uint32_t write_domain) @@ -221,7 +217,7 @@ drm_intel_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset, } -int +drm_public int drm_intel_bo_pin(drm_intel_bo *bo, uint32_t alignment) { if (bo->bufmgr->bo_pin) @@ -230,7 +226,7 @@ drm_intel_bo_pin(drm_intel_bo *bo, uint32_t alignment) return -ENODEV; } -int +drm_public int drm_intel_bo_unpin(drm_intel_bo *bo) { if (bo->bufmgr->bo_unpin) @@ -239,7 +235,7 @@ drm_intel_bo_unpin(drm_intel_bo *bo) return -ENODEV; } -int +drm_public int drm_intel_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, uint32_t stride) { @@ -250,7 +246,7 @@ drm_intel_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, return 0; } -int +drm_public int drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, uint32_t * swizzle_mode) { @@ -262,7 +258,7 @@ drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, return 0; } -int +drm_public int drm_intel_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) { if (bo->bufmgr->bo_set_softpin_offset) @@ -271,7 +267,7 @@ drm_intel_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) return -ENODEV; } -int +drm_public int drm_intel_bo_disable_reuse(drm_intel_bo *bo) { if (bo->bufmgr->bo_disable_reuse) @@ -279,7 +275,7 @@ drm_intel_bo_disable_reuse(drm_intel_bo *bo) return 0; } -int +drm_public int drm_intel_bo_is_reusable(drm_intel_bo *bo) { if (bo->bufmgr->bo_is_reusable) @@ -287,7 +283,7 @@ drm_intel_bo_is_reusable(drm_intel_bo *bo) return 0; } -int +drm_public int drm_intel_bo_busy(drm_intel_bo *bo) { if (bo->bufmgr->bo_busy) @@ -295,7 +291,7 @@ drm_intel_bo_busy(drm_intel_bo *bo) return 0; } -int +drm_public int drm_intel_bo_madvise(drm_intel_bo *bo, int madv) { if (bo->bufmgr->bo_madvise) @@ -303,7 +299,7 @@ drm_intel_bo_madvise(drm_intel_bo *bo, int madv) return -1; } -int +drm_public int drm_intel_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) { if (bo->bufmgr->bo_use_48b_address_range) { @@ -314,13 +310,13 @@ drm_intel_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) return -ENODEV; } -int +drm_public int drm_intel_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) { return bo->bufmgr->bo_references(bo, target_bo); } -int +drm_public int drm_intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id) { if (bufmgr->get_pipe_from_crtc_id) @@ -364,7 +360,7 @@ drm_intel_probe_agp_aperture_size(int fd) } #endif -int +drm_public int drm_intel_get_aperture_sizes(int fd, size_t *mappable, size_t *total) { diff --git a/intel/intel_bufmgr_fake.c b/intel/intel_bufmgr_fake.c index 641df6a1..0cec51f5 100644 --- a/intel/intel_bufmgr_fake.c +++ b/intel/intel_bufmgr_fake.c @@ -34,10 +34,6 @@ * the bugs in the old texture manager. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <string.h> #include <assert.h> @@ -245,7 +241,7 @@ FENCE_LTE(unsigned a, unsigned b) return 0; } -void +drm_public void drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr, unsigned int (*emit) (void *priv), void (*wait) (unsigned int fence, @@ -768,7 +764,7 @@ drm_intel_fake_bo_wait_rendering(drm_intel_bo *bo) * -- just evict everything * -- and wait for idle */ -void +drm_public void drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr) { drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; @@ -864,7 +860,7 @@ drm_intel_fake_bo_alloc_tiled(drm_intel_bufmgr * bufmgr, 4096); } -drm_intel_bo * +drm_public drm_intel_bo * drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr, const char *name, unsigned long offset, @@ -959,7 +955,7 @@ drm_intel_fake_bo_unreference(drm_intel_bo *bo) * Set the buffer as not requiring backing store, and instead get the callback * invoked whenever it would be set dirty. */ -void +drm_public void drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo, void (*invalidate_cb) (drm_intel_bo *bo, void *ptr), @@ -1413,7 +1409,7 @@ drm_intel_bo_fake_post_submit(drm_intel_bo *bo) bo_fake->write_domain = 0; } -void +drm_public void drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr, int (*exec) (drm_intel_bo *bo, unsigned int used, @@ -1536,7 +1532,7 @@ drm_intel_fake_check_aperture_space(drm_intel_bo ** bo_array, int count) * Used by the X Server on LeaveVT, when the card memory is no longer our * own. */ -void +drm_public void drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr) { drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; @@ -1571,7 +1567,7 @@ drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr) pthread_mutex_unlock(&bufmgr_fake->lock); } -void +drm_public void drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr, volatile unsigned int *last_dispatch) @@ -1581,7 +1577,7 @@ drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr, bufmgr_fake->last_dispatch = (volatile int *)last_dispatch; } -drm_intel_bufmgr * +drm_public drm_intel_bufmgr * drm_intel_bufmgr_fake_init(int fd, unsigned long low_offset, void *low_virtual, unsigned long size, volatile unsigned int *last_dispatch) diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index a6656003..fbf48730 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -34,10 +34,6 @@ * Dave Airlie <airlied@linux.ie> */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <xf86drm.h> #include <xf86atomic.h> #include <fcntl.h> @@ -66,7 +62,7 @@ #include "i915_drm.h" #include "uthash.h" -#ifdef HAVE_VALGRIND +#if HAVE_VALGRIND #include <valgrind.h> #include <memcheck.h> #define VG(x) x @@ -270,20 +266,6 @@ struct _drm_intel_bo_gem { bool is_userptr; /** - * Boolean of whether this buffer can be placed in the full 48-bit - * address range on gen8+. - * - * By default, buffers will be keep in a 32-bit range, unless this - * flag is explicitly set. - */ - bool use_48b_address_range; - - /** - * Whether this buffer is softpinned at offset specified by the user - */ - bool is_softpin; - - /** * Size in bytes of this buffer and its relocation descendents. * * Used to avoid costly tree walking in @@ -438,7 +420,7 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) { DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle, - bo_gem->is_softpin ? "*" : "", + bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", bo_gem->name); continue; } @@ -452,7 +434,7 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) "%d (%s)@0x%08x %08x + 0x%08x\n", i, bo_gem->gem_handle, - bo_gem->is_softpin ? "*" : "", + bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", bo_gem->name, upper_32_bits(bo_gem->relocs[j].offset), lower_32_bits(bo_gem->relocs[j].offset), @@ -471,7 +453,7 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) "%d *(%s)@0x%08x %08x\n", i, bo_gem->gem_handle, - bo_gem->is_softpin ? "*" : "", + bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", bo_gem->name, target_gem->gem_handle, target_gem->name, @@ -541,14 +523,11 @@ drm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; int index; - int flags = 0; + unsigned long flags; + flags = 0; if (need_fence) flags |= EXEC_OBJECT_NEEDS_FENCE; - if (bo_gem->use_48b_address_range) - flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; - if (bo_gem->is_softpin) - flags |= EXEC_OBJECT_PINNED; if (bo_gem->validate_index != -1) { bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags; @@ -579,7 +558,7 @@ drm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs; bufmgr_gem->exec2_objects[index].alignment = bo->align; bufmgr_gem->exec2_objects[index].offset = bo->offset64; - bufmgr_gem->exec2_objects[index].flags = flags | bo_gem->kflags; + bufmgr_gem->exec2_objects[index].flags = bo_gem->kflags | flags; bufmgr_gem->exec2_objects[index].rsvd1 = 0; bufmgr_gem->exec2_objects[index].rsvd2 = 0; bufmgr_gem->exec_bos[index] = bo; @@ -676,7 +655,6 @@ drm_intel_gem_bo_busy(drm_intel_bo *bo) } else { return false; } - return (ret == 0 && busy.busy); } static int @@ -832,6 +810,10 @@ retry: } bo_gem->gem_handle = create.handle; + HASH_ADD(handle_hh, bufmgr_gem->handle_table, + gem_handle, sizeof(bo_gem->gem_handle), + bo_gem); + bo_gem->bo.handle = bo_gem->gem_handle; bo_gem->bo.bufmgr = bufmgr; bo_gem->bo.align = alignment; @@ -844,10 +826,6 @@ retry: tiling_mode, stride)) goto err_free; - - HASH_ADD(handle_hh, bufmgr_gem->handle_table, - gem_handle, sizeof(bo_gem->gem_handle), - bo_gem); } bo_gem->name = name; @@ -857,7 +835,6 @@ retry: bo_gem->used_as_reloc_target = false; bo_gem->has_error = false; bo_gem->reusable = true; - bo_gem->use_48b_address_range = false; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment); pthread_mutex_unlock(&bufmgr_gem->lock); @@ -1016,7 +993,6 @@ drm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, bo_gem->used_as_reloc_target = false; bo_gem->has_error = false; bo_gem->reusable = false; - bo_gem->use_48b_address_range = false; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); pthread_mutex_unlock(&bufmgr_gem->lock); @@ -1099,7 +1075,7 @@ check_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, * This can be used when one application needs to pass a buffer object * to another. */ -drm_intel_bo * +drm_public drm_intel_bo * drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, const char *name, unsigned int handle) @@ -1164,7 +1140,6 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, bo_gem->bo.handle = open_arg.handle; bo_gem->global_name = handle; bo_gem->reusable = false; - bo_gem->use_48b_address_range = false; HASH_ADD(handle_hh, bufmgr_gem->handle_table, gem_handle, sizeof(bo_gem->gem_handle), bo_gem); @@ -1411,8 +1386,6 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) bo_gem->name = NULL; bo_gem->validate_index = -1; - bo_gem->kflags = 0; - DRMLISTADDTAIL(&bo_gem->head, &bucket->head); } else { drm_intel_gem_bo_free(bo); @@ -1589,7 +1562,7 @@ map_gtt(drm_intel_bo *bo) return 0; } -int +drm_public int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; @@ -1648,11 +1621,11 @@ drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) * undefined). */ -int +drm_public int drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; -#ifdef HAVE_VALGRIND +#if HAVE_VALGRIND drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; #endif int ret; @@ -1737,7 +1710,7 @@ static int drm_intel_gem_bo_unmap(drm_intel_bo *bo) return ret; } -int +drm_public int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo) { return drm_intel_gem_bo_unmap(bo); @@ -1862,7 +1835,7 @@ drm_intel_gem_bo_wait_rendering(drm_intel_bo *bo) * Note that some kernels have broken the inifite wait for negative values * promise, upgrade to latest stable kernels if this is the case. */ -int +drm_public int drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; @@ -1898,7 +1871,7 @@ drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns) * In combination with drm_intel_gem_bo_pin() and manual fence management, we * can do tiled pixmaps this way. */ -void +drm_public void drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; @@ -2054,7 +2027,11 @@ static void drm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) { drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; - bo_gem->use_48b_address_range = enable; + + if (enable) + bo_gem->kflags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; + else + bo_gem->kflags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS; } static int @@ -2071,7 +2048,7 @@ drm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo) return -ENOMEM; } - if (!target_bo_gem->is_softpin) + if (!(target_bo_gem->kflags & EXEC_OBJECT_PINNED)) return -EINVAL; if (target_bo_gem == bo_gem) return -EINVAL; @@ -2103,7 +2080,7 @@ drm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo; - if (target_bo_gem->is_softpin) + if (target_bo_gem->kflags & EXEC_OBJECT_PINNED) return drm_intel_gem_bo_add_softpin_target(bo, target_bo); else return do_bo_emit_reloc(bo, offset, target_bo, target_offset, @@ -2121,7 +2098,7 @@ drm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset, read_domains, write_domain, true); } -int +drm_public int drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo) { drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; @@ -2144,7 +2121,7 @@ drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo) * * This also removes all softpinned targets being referenced by the BO. */ -void +drm_public void drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; @@ -2287,7 +2264,7 @@ drm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem) /* If we're seeing softpinned object here it means that the kernel * has relocated our object... Indicating a programming error */ - assert(!bo_gem->is_softpin); + assert(!(bo_gem->kflags & EXEC_OBJECT_PINNED)); DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", bo_gem->gem_handle, bo_gem->name, upper_32_bits(bo->offset64), @@ -2300,7 +2277,7 @@ drm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem) } } -void +drm_public void drm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo, int x1, int y1, int width, int height, enum aub_dump_bmp_format format, @@ -2502,14 +2479,14 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used, -1, NULL, flags); } -int +drm_public int drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx, int used, unsigned int flags) { return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags); } -int +drm_public int drm_intel_gem_bo_fence_exec(drm_intel_bo *bo, drm_intel_context *ctx, int used, @@ -2643,13 +2620,14 @@ drm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) { drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; - bo_gem->is_softpin = true; bo->offset64 = offset; bo->offset = offset; + bo_gem->kflags |= EXEC_OBJECT_PINNED; + return 0; } -drm_intel_bo * +drm_public drm_intel_bo * drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; @@ -2709,7 +2687,6 @@ drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int s bo_gem->used_as_reloc_target = false; bo_gem->has_error = false; bo_gem->reusable = false; - bo_gem->use_48b_address_range = false; memclear(get_tiling); get_tiling.handle = bo_gem->gem_handle; @@ -2733,7 +2710,7 @@ err: return NULL; } -int +drm_public int drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; @@ -2785,7 +2762,7 @@ drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name) * size is only bounded by how many buffers of that size we've managed to have * in flight at once. */ -void +drm_public void drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; @@ -2807,7 +2784,7 @@ drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr) * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync, * or subsequent execbufs involving the bo will generate EINVAL. */ -void +drm_public void drm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo) { drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; @@ -2826,7 +2803,7 @@ drm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo) * function can be used to restore the implicit sync before subsequent * rendering. */ -void +drm_public void drm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo) { drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; @@ -2838,7 +2815,7 @@ drm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo) * Query whether the kernel supports disabling of its implicit synchronisation * before execbuf. See drm_intel_gem_bo_disable_implicit_sync() */ -int +drm_public int drm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; @@ -2853,7 +2830,7 @@ drm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr) * allocation. If this option is not enabled, all relocs will have fence * register allocated. */ -void +drm_public void drm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; @@ -3132,7 +3109,7 @@ init_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem) } } -void +drm_public void drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; @@ -3201,7 +3178,7 @@ get_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem) return devid; } -int +drm_public int drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; @@ -3215,7 +3192,7 @@ drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr) * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump() * for it to have any effect. */ -void +drm_public void drm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr, const char *filename) { @@ -3229,7 +3206,7 @@ drm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr, * You can set up a GTT and upload your objects into the referenced * space, then send off batchbuffers and get BMPs out the other end. */ -void +drm_public void drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable) { fprintf(stderr, "libdrm aub dumping is deprecated.\n\n" @@ -3239,7 +3216,7 @@ drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable) "See the intel_aubdump man page for more details.\n"); } -drm_intel_context * +drm_public drm_intel_context * drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; @@ -3266,7 +3243,7 @@ drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr) return context; } -int +drm_public int drm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id) { if (ctx == NULL) @@ -3277,7 +3254,7 @@ drm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id) return 0; } -void +drm_public void drm_intel_gem_context_destroy(drm_intel_context *ctx) { drm_intel_bufmgr_gem *bufmgr_gem; @@ -3300,7 +3277,7 @@ drm_intel_gem_context_destroy(drm_intel_context *ctx) free(ctx); } -int +drm_public int drm_intel_get_reset_stats(drm_intel_context *ctx, uint32_t *reset_count, uint32_t *active, @@ -3334,7 +3311,7 @@ drm_intel_get_reset_stats(drm_intel_context *ctx, return ret; } -int +drm_public int drm_intel_reg_read(drm_intel_bufmgr *bufmgr, uint32_t offset, uint64_t *result) @@ -3352,7 +3329,7 @@ drm_intel_reg_read(drm_intel_bufmgr *bufmgr, return ret; } -int +drm_public int drm_intel_get_subslice_total(int fd, unsigned int *subslice_total) { drm_i915_getparam_t gp; @@ -3368,7 +3345,7 @@ drm_intel_get_subslice_total(int fd, unsigned int *subslice_total) return 0; } -int +drm_public int drm_intel_get_eu_total(int fd, unsigned int *eu_total) { drm_i915_getparam_t gp; @@ -3384,7 +3361,7 @@ drm_intel_get_eu_total(int fd, unsigned int *eu_total) return 0; } -int +drm_public int drm_intel_get_pooled_eu(int fd) { drm_i915_getparam_t gp; @@ -3399,7 +3376,7 @@ drm_intel_get_pooled_eu(int fd) return ret; } -int +drm_public int drm_intel_get_min_eu_in_pool(int fd) { drm_i915_getparam_t gp; @@ -3435,8 +3412,7 @@ drm_intel_get_min_eu_in_pool(int fd) * default state (no annotations), call this function with a \c count * of zero. */ -void -drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo, +drm_public void drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo, drm_intel_aub_annotation *annotations, unsigned count) { @@ -3477,7 +3453,7 @@ drm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr) } } -void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo) +drm_public void *drm_intel_gem_bo_map__gtt(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; @@ -3525,7 +3501,7 @@ void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo) return bo_gem->gtt_virtual; } -void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo) +drm_public void *drm_intel_gem_bo_map__cpu(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; @@ -3569,7 +3545,7 @@ void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo) return bo_gem->mem_virtual; } -void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo) +drm_public void *drm_intel_gem_bo_map__wc(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; @@ -3618,7 +3594,7 @@ void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo) * * \param fd File descriptor of the opened DRM device. */ -drm_intel_bufmgr * +drm_public drm_intel_bufmgr * drm_intel_bufmgr_gem_init(int fd, int batch_size) { drm_intel_bufmgr_gem *bufmgr_gem; @@ -3679,9 +3655,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size) bufmgr_gem->gen = 7; else if (IS_GEN8(bufmgr_gem->pci_device)) bufmgr_gem->gen = 8; - else if (IS_GEN9(bufmgr_gem->pci_device)) - bufmgr_gem->gen = 9; - else { + else if (!intel_get_genx(bufmgr_gem->pci_device, &bufmgr_gem->gen)) { free(bufmgr_gem); bufmgr_gem = NULL; goto exit; diff --git a/intel/intel_chipset.c b/intel/intel_chipset.c new file mode 100644 index 00000000..5aa4a2f2 --- /dev/null +++ b/intel/intel_chipset.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include "intel_chipset.h" + +#include <inttypes.h> +#include <stdbool.h> + +#include "i915_pciids.h" + +#undef INTEL_VGA_DEVICE +#define INTEL_VGA_DEVICE(id, gen) { id, gen } + +static const struct pci_device { + uint16_t device; + uint16_t gen; +} pciids[] = { + /* Keep ids sorted by gen; latest gen first */ + INTEL_ICL_11_IDS(11), + INTEL_CNL_IDS(10), + INTEL_CFL_IDS(9), + INTEL_GLK_IDS(9), + INTEL_KBL_IDS(9), + INTEL_BXT_IDS(9), + INTEL_SKL_IDS(9), +}; + +drm_private bool intel_is_genx(unsigned int devid, int gen) +{ + const struct pci_device *p, + *pend = pciids + sizeof(pciids) / sizeof(pciids[0]); + + for (p = pciids; p < pend; p++) { + /* PCI IDs are sorted */ + if (p->gen < gen) + break; + + if (p->device != devid) + continue; + + if (gen == p->gen) + return true; + + break; + } + + return false; +} + +drm_private bool intel_get_genx(unsigned int devid, int *gen) +{ + const struct pci_device *p, + *pend = pciids + sizeof(pciids) / sizeof(pciids[0]); + + for (p = pciids; p < pend; p++) { + if (p->device != devid) + continue; + + if (gen) + *gen = p->gen; + + return true; + } + + return false; +} diff --git a/intel/intel_chipset.h b/intel/intel_chipset.h index 41fc0da0..5db207cc 100644 --- a/intel/intel_chipset.h +++ b/intel/intel_chipset.h @@ -165,61 +165,8 @@ #define PCI_CHIP_CHERRYVIEW_2 0x22b2 #define PCI_CHIP_CHERRYVIEW_3 0x22b3 -#define PCI_CHIP_SKYLAKE_DT_GT1 0x1902 -#define PCI_CHIP_SKYLAKE_ULT_GT1 0x1906 -#define PCI_CHIP_SKYLAKE_SRV_GT1 0x190A /* Reserved */ -#define PCI_CHIP_SKYLAKE_H_GT1 0x190B -#define PCI_CHIP_SKYLAKE_ULX_GT1 0x190E /* Reserved */ #define PCI_CHIP_SKYLAKE_DT_GT2 0x1912 -#define PCI_CHIP_SKYLAKE_FUSED0_GT2 0x1913 /* Reserved */ -#define PCI_CHIP_SKYLAKE_FUSED1_GT2 0x1915 /* Reserved */ -#define PCI_CHIP_SKYLAKE_ULT_GT2 0x1916 -#define PCI_CHIP_SKYLAKE_FUSED2_GT2 0x1917 /* Reserved */ -#define PCI_CHIP_SKYLAKE_SRV_GT2 0x191A /* Reserved */ -#define PCI_CHIP_SKYLAKE_HALO_GT2 0x191B -#define PCI_CHIP_SKYLAKE_WKS_GT2 0x191D -#define PCI_CHIP_SKYLAKE_ULX_GT2 0x191E -#define PCI_CHIP_SKYLAKE_MOBILE_GT2 0x1921 /* Reserved */ -#define PCI_CHIP_SKYLAKE_ULT_GT3_0 0x1923 -#define PCI_CHIP_SKYLAKE_ULT_GT3_1 0x1926 -#define PCI_CHIP_SKYLAKE_ULT_GT3_2 0x1927 -#define PCI_CHIP_SKYLAKE_SRV_GT4 0x192A -#define PCI_CHIP_SKYLAKE_HALO_GT3 0x192B /* Reserved */ -#define PCI_CHIP_SKYLAKE_SRV_GT3 0x192D -#define PCI_CHIP_SKYLAKE_DT_GT4 0x1932 -#define PCI_CHIP_SKYLAKE_SRV_GT4X 0x193A -#define PCI_CHIP_SKYLAKE_H_GT4 0x193B -#define PCI_CHIP_SKYLAKE_WKS_GT4 0x193D - -#define PCI_CHIP_KABYLAKE_ULT_GT2 0x5916 -#define PCI_CHIP_KABYLAKE_ULT_GT1_5 0x5913 -#define PCI_CHIP_KABYLAKE_ULT_GT1 0x5906 -#define PCI_CHIP_KABYLAKE_ULT_GT3_0 0x5923 -#define PCI_CHIP_KABYLAKE_ULT_GT3_1 0x5926 -#define PCI_CHIP_KABYLAKE_ULT_GT3_2 0x5927 -#define PCI_CHIP_KABYLAKE_ULT_GT2F 0x5921 -#define PCI_CHIP_KABYLAKE_ULX_GT1_5 0x5915 -#define PCI_CHIP_KABYLAKE_ULX_GT1 0x590E -#define PCI_CHIP_KABYLAKE_ULX_GT2 0x591E #define PCI_CHIP_KABYLAKE_DT_GT2 0x5912 -#define PCI_CHIP_KABYLAKE_DT_GT1_5 0x5917 -#define PCI_CHIP_KABYLAKE_DT_GT1 0x5902 -#define PCI_CHIP_KABYLAKE_HALO_GT2 0x591B -#define PCI_CHIP_KABYLAKE_HALO_GT4 0x593B -#define PCI_CHIP_KABYLAKE_HALO_GT1_0 0x5908 -#define PCI_CHIP_KABYLAKE_HALO_GT1_1 0x590B -#define PCI_CHIP_KABYLAKE_SRV_GT2 0x591A -#define PCI_CHIP_KABYLAKE_SRV_GT1 0x590A -#define PCI_CHIP_KABYLAKE_WKS_GT2 0x591D - -#define PCI_CHIP_BROXTON_0 0x0A84 -#define PCI_CHIP_BROXTON_1 0x1A84 -#define PCI_CHIP_BROXTON_2 0x5A84 -#define PCI_CHIP_BROXTON_3 0x1A85 -#define PCI_CHIP_BROXTON_4 0x5A85 - -#define PCI_CHIP_GLK 0x3184 -#define PCI_CHIP_GLK_2X6 0x3185 #define IS_MOBILE(devid) ((devid) == PCI_CHIP_I855_GM || \ (devid) == PCI_CHIP_I915_GM || \ @@ -380,82 +327,16 @@ #define IS_GEN8(devid) (IS_BROADWELL(devid) || \ IS_CHERRYVIEW(devid)) -#define IS_SKL_GT1(devid) ((devid) == PCI_CHIP_SKYLAKE_DT_GT1 || \ - (devid) == PCI_CHIP_SKYLAKE_ULT_GT1 || \ - (devid) == PCI_CHIP_SKYLAKE_SRV_GT1 || \ - (devid) == PCI_CHIP_SKYLAKE_H_GT1 || \ - (devid) == PCI_CHIP_SKYLAKE_ULX_GT1) - -#define IS_SKL_GT2(devid) ((devid) == PCI_CHIP_SKYLAKE_DT_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_FUSED0_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_FUSED1_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_ULT_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_FUSED2_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_SRV_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_HALO_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_WKS_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_ULX_GT2 || \ - (devid) == PCI_CHIP_SKYLAKE_MOBILE_GT2) - -#define IS_SKL_GT3(devid) ((devid) == PCI_CHIP_SKYLAKE_ULT_GT3_0 || \ - (devid) == PCI_CHIP_SKYLAKE_ULT_GT3_1 || \ - (devid) == PCI_CHIP_SKYLAKE_ULT_GT3_2 || \ - (devid) == PCI_CHIP_SKYLAKE_HALO_GT3 || \ - (devid) == PCI_CHIP_SKYLAKE_SRV_GT3) - -#define IS_SKL_GT4(devid) ((devid) == PCI_CHIP_SKYLAKE_SRV_GT4 || \ - (devid) == PCI_CHIP_SKYLAKE_DT_GT4 || \ - (devid) == PCI_CHIP_SKYLAKE_SRV_GT4X || \ - (devid) == PCI_CHIP_SKYLAKE_H_GT4 || \ - (devid) == PCI_CHIP_SKYLAKE_WKS_GT4) - -#define IS_KBL_GT1(devid) ((devid) == PCI_CHIP_KABYLAKE_ULT_GT1_5 || \ - (devid) == PCI_CHIP_KABYLAKE_ULX_GT1_5 || \ - (devid) == PCI_CHIP_KABYLAKE_DT_GT1_5 || \ - (devid) == PCI_CHIP_KABYLAKE_ULT_GT1 || \ - (devid) == PCI_CHIP_KABYLAKE_ULX_GT1 || \ - (devid) == PCI_CHIP_KABYLAKE_DT_GT1 || \ - (devid) == PCI_CHIP_KABYLAKE_HALO_GT1_0 || \ - (devid) == PCI_CHIP_KABYLAKE_HALO_GT1_1 || \ - (devid) == PCI_CHIP_KABYLAKE_SRV_GT1) - -#define IS_KBL_GT2(devid) ((devid) == PCI_CHIP_KABYLAKE_ULT_GT2 || \ - (devid) == PCI_CHIP_KABYLAKE_ULT_GT2F || \ - (devid) == PCI_CHIP_KABYLAKE_ULX_GT2 || \ - (devid) == PCI_CHIP_KABYLAKE_DT_GT2 || \ - (devid) == PCI_CHIP_KABYLAKE_HALO_GT2 || \ - (devid) == PCI_CHIP_KABYLAKE_SRV_GT2 || \ - (devid) == PCI_CHIP_KABYLAKE_WKS_GT2) - -#define IS_KBL_GT3(devid) ((devid) == PCI_CHIP_KABYLAKE_ULT_GT3_0 || \ - (devid) == PCI_CHIP_KABYLAKE_ULT_GT3_1 || \ - (devid) == PCI_CHIP_KABYLAKE_ULT_GT3_2) - -#define IS_KBL_GT4(devid) ((devid) == PCI_CHIP_KABYLAKE_HALO_GT4) - -#define IS_KABYLAKE(devid) (IS_KBL_GT1(devid) || \ - IS_KBL_GT2(devid) || \ - IS_KBL_GT3(devid) || \ - IS_KBL_GT4(devid)) - -#define IS_SKYLAKE(devid) (IS_SKL_GT1(devid) || \ - IS_SKL_GT2(devid) || \ - IS_SKL_GT3(devid) || \ - IS_SKL_GT4(devid)) - -#define IS_BROXTON(devid) ((devid) == PCI_CHIP_BROXTON_0 || \ - (devid) == PCI_CHIP_BROXTON_1 || \ - (devid) == PCI_CHIP_BROXTON_2 || \ - (devid) == PCI_CHIP_BROXTON_3 || \ - (devid) == PCI_CHIP_BROXTON_4) - -#define IS_GEMINILAKE(devid) ((devid) == PCI_CHIP_GLK || \ - (devid) == PCI_CHIP_GLK_2X6) - -#define IS_GEN9(devid) (IS_SKYLAKE(devid) || \ - IS_BROXTON(devid) || \ - IS_KABYLAKE(devid) || \ - IS_GEMINILAKE(devid)) +/* New platforms use kernel pci ids */ +#include <stdbool.h> +#include <libdrm_macros.h> + +drm_private bool intel_is_genx(unsigned int devid, int gen); +drm_private bool intel_get_genx(unsigned int devid, int *gen); + +#define IS_GEN9(devid) intel_is_genx(devid, 9) +#define IS_GEN10(devid) intel_is_genx(devid, 10) +#define IS_GEN11(devid) intel_is_genx(devid, 11) #define IS_9XX(dev) (IS_GEN3(dev) || \ IS_GEN4(dev) || \ @@ -463,7 +344,6 @@ IS_GEN6(dev) || \ IS_GEN7(dev) || \ IS_GEN8(dev) || \ - IS_GEN9(dev)) - + intel_get_genx(dev, NULL)) #endif /* _INTEL_CHIPSET_H */ diff --git a/intel/intel_decode.c b/intel/intel_decode.c index 803d2029..e0a51664 100644 --- a/intel/intel_decode.c +++ b/intel/intel_decode.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <assert.h> #include <stdint.h> #include <stdlib.h> @@ -3815,7 +3811,7 @@ decode_3d_i830(struct drm_intel_decode *ctx) return 1; } -struct drm_intel_decode * +drm_public struct drm_intel_decode * drm_intel_decode_context_alloc(uint32_t devid) { struct drm_intel_decode *ctx; @@ -3827,8 +3823,8 @@ drm_intel_decode_context_alloc(uint32_t devid) ctx->devid = devid; ctx->out = stdout; - if (IS_GEN9(devid)) - ctx->gen = 9; + if (intel_get_genx(devid, &ctx->gen)) + ; else if (IS_GEN8(devid)) ctx->gen = 8; else if (IS_GEN7(devid)) @@ -3849,20 +3845,20 @@ drm_intel_decode_context_alloc(uint32_t devid) return ctx; } -void +drm_public void drm_intel_decode_context_free(struct drm_intel_decode *ctx) { free(ctx); } -void +drm_public void drm_intel_decode_set_dump_past_end(struct drm_intel_decode *ctx, int dump_past_end) { ctx->dump_past_end = !!dump_past_end; } -void +drm_public void drm_intel_decode_set_batch_pointer(struct drm_intel_decode *ctx, void *data, uint32_t hw_offset, int count) { @@ -3871,7 +3867,7 @@ drm_intel_decode_set_batch_pointer(struct drm_intel_decode *ctx, ctx->base_count = count; } -void +drm_public void drm_intel_decode_set_head_tail(struct drm_intel_decode *ctx, uint32_t head, uint32_t tail) { @@ -3879,7 +3875,7 @@ drm_intel_decode_set_head_tail(struct drm_intel_decode *ctx, ctx->tail = tail; } -void +drm_public void drm_intel_decode_set_output_file(struct drm_intel_decode *ctx, FILE *output) { @@ -3893,13 +3889,13 @@ drm_intel_decode_set_output_file(struct drm_intel_decode *ctx, * \param count number of DWORDs to decode in the batch buffer * \param hw_offset hardware address for the buffer */ -void +drm_public void drm_intel_decode(struct drm_intel_decode *ctx) { int ret; unsigned int index = 0; uint32_t devid; - int size = ctx->base_count * 4; + int size; void *temp; if (!ctx) @@ -3909,6 +3905,7 @@ drm_intel_decode(struct drm_intel_decode *ctx) * the batchbuffer. This lets us avoid a bunch of length * checking in statically sized packets. */ + size = ctx->base_count * 4; temp = malloc(size + 4096); memcpy(temp, ctx->base_data, size); memset((char *)temp + size, 0xd0, 4096); diff --git a/intel/meson.build b/intel/meson.build new file mode 100644 index 00000000..3d6bbac6 --- /dev/null +++ b/intel/meson.build @@ -0,0 +1,106 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libdrm_intel = shared_library( + 'drm_intel', + [ + files( + 'intel_bufmgr.c', 'intel_bufmgr_fake.c', 'intel_bufmgr_gem.c', + 'intel_decode.c', 'mm.c', 'intel_chipset.c', + ), + config_file, + ], + include_directories : [inc_root, inc_drm], + link_with : libdrm, + dependencies : [dep_pciaccess, dep_pthread_stubs, dep_rt, dep_valgrind, dep_atomic_ops], + c_args : libdrm_c_args, + version : '1.0.0', + install : true, +) + +ext_libdrm_intel = declare_dependency( + link_with : [libdrm, libdrm_intel], + include_directories : [inc_drm, include_directories('.')], +) + +install_headers( + 'intel_bufmgr.h', 'intel_aub.h', 'intel_debug.h', + subdir : 'libdrm', +) + +pkg.generate( + name : 'libdrm_intel', + libraries : libdrm_intel, + subdirs : ['.', 'libdrm'], + version : meson.project_version(), + requires : 'libdrm', + description : 'Userspace interface to intel kernel DRM services', +) + +test_decode = executable( + 'test_decode', + files('test_decode.c'), + include_directories : [inc_root, inc_drm], + link_with : [libdrm, libdrm_intel], + c_args : libdrm_c_args, +) + +test( + 'gen4-3d.batch', + prog_bash, + args : files('tests/gen4-3d.batch.sh'), + workdir : meson.current_build_dir(), +) +test( + 'gen45-3d.batch', + prog_bash, + args : files('tests/gm45-3d.batch.sh'), + workdir : meson.current_build_dir(), +) +test( + 'gen5-3d.batch', + prog_bash, + args : files('tests/gen5-3d.batch.sh'), + workdir : meson.current_build_dir(), +) +test( + 'gen6-3d.batch', + prog_bash, + args : files('tests/gen6-3d.batch.sh'), + workdir : meson.current_build_dir(), +) +test( + 'gen7-3d.batch', + prog_bash, + args : files('tests/gen7-3d.batch.sh'), + workdir : meson.current_build_dir(), +) +test( + 'gen7-2d-copy.batch', + prog_bash, + args : files('tests/gen7-2d-copy.batch.sh'), + workdir : meson.current_build_dir(), +) +test( + 'intel-symbol-check', + prog_bash, + env : env_test, + args : [files('intel-symbol-check'), libdrm_intel] +) @@ -22,10 +22,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <assert.h> @@ -29,10 +29,6 @@ #ifndef MM_H #define MM_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include "libdrm_macros.h" struct mem_block { diff --git a/intel/test_decode.c b/intel/test_decode.c index b4eddcd1..b9f5b927 100644 --- a/intel/test_decode.c +++ b/intel/test_decode.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -91,7 +87,7 @@ compare_batch(struct drm_intel_decode *ctx, const char *batch_filename) { FILE *out = NULL; void *ptr, *ref_ptr, *batch_ptr; -#ifdef HAVE_OPEN_MEMSTREAM +#if HAVE_OPEN_MEMSTREAM size_t size; #endif size_t ref_size, batch_size; @@ -109,7 +105,7 @@ compare_batch(struct drm_intel_decode *ctx, const char *batch_filename) * figure out how to output to a file in a safe and sane way * inside of an automake project's test infrastructure. */ -#ifdef HAVE_OPEN_MEMSTREAM +#if HAVE_OPEN_MEMSTREAM out = open_memstream((char **)&ptr, &size); #else fprintf(stderr, "platform lacks open_memstream, skipping.\n"); diff --git a/libdrm_macros.h b/libdrm_macros.h index b88fdcef..0dca8273 100644 --- a/libdrm_macros.h +++ b/libdrm_macros.h @@ -23,10 +23,12 @@ #ifndef LIBDRM_LIBDRM_H #define LIBDRM_LIBDRM_H -#if defined(HAVE_VISIBILITY) +#if HAVE_VISIBILITY # define drm_private __attribute__((visibility("hidden"))) +# define drm_public __attribute__((visibility("default"))) #else # define drm_private +# define drm_public #endif diff --git a/libkms/Makefile.am b/libkms/Makefile.am index 461fc35b..ff4c1b2a 100644 --- a/libkms/Makefile.am +++ b/libkms/Makefile.am @@ -2,6 +2,7 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir)/include/drm \ -I$(top_srcdir) @@ -39,5 +40,6 @@ libkmsinclude_HEADERS = $(LIBKMS_H_FILES) pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libkms.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = kms-symbol-check EXTRA_DIST = $(TESTS) diff --git a/libkms/api.c b/libkms/api.c index 354d8a2e..caca1a87 100644 --- a/libkms/api.c +++ b/libkms/api.c @@ -26,10 +26,6 @@ **************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdlib.h> #include <string.h> @@ -37,12 +33,12 @@ #include "libdrm_macros.h" #include "internal.h" -int kms_create(int fd, struct kms_driver **out) +drm_public int kms_create(int fd, struct kms_driver **out) { return linux_create(fd, out); } -int kms_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) +drm_public int kms_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) { switch (key) { case KMS_BO_TYPE: @@ -53,7 +49,7 @@ int kms_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) return kms->get_prop(kms, key, out); } -int kms_destroy(struct kms_driver **kms) +drm_public int kms_destroy(struct kms_driver **kms) { if (!(*kms)) return 0; @@ -63,7 +59,7 @@ int kms_destroy(struct kms_driver **kms) return 0; } -int kms_bo_create(struct kms_driver *kms, const unsigned *attr, struct kms_bo **out) +drm_public int kms_bo_create(struct kms_driver *kms, const unsigned *attr, struct kms_bo **out) { unsigned width = 0; unsigned height = 0; @@ -101,7 +97,7 @@ int kms_bo_create(struct kms_driver *kms, const unsigned *attr, struct kms_bo ** return kms->bo_create(kms, width, height, type, attr, out); } -int kms_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out) +drm_public int kms_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out) { switch (key) { case KMS_PITCH: @@ -117,17 +113,17 @@ int kms_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out) return 0; } -int kms_bo_map(struct kms_bo *bo, void **out) +drm_public int kms_bo_map(struct kms_bo *bo, void **out) { return bo->kms->bo_map(bo, out); } -int kms_bo_unmap(struct kms_bo *bo) +drm_public int kms_bo_unmap(struct kms_bo *bo) { return bo->kms->bo_unmap(bo); } -int kms_bo_destroy(struct kms_bo **bo) +drm_public int kms_bo_destroy(struct kms_bo **bo) { int ret; diff --git a/libkms/dumb.c b/libkms/dumb.c index b95a072c..17efc10a 100644 --- a/libkms/dumb.c +++ b/libkms/dumb.c @@ -26,10 +26,6 @@ **************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/libkms/exynos.c b/libkms/exynos.c index 0e97fb51..ef64a668 100644 --- a/libkms/exynos.c +++ b/libkms/exynos.c @@ -5,16 +5,26 @@ * SooChan Lim <sc1.lim@samsung.com> * Sangjin LEE <lsj119@samsung.com> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/libkms/intel.c b/libkms/intel.c index 3d8ca055..859e7a0f 100644 --- a/libkms/intel.c +++ b/libkms/intel.c @@ -26,10 +26,6 @@ **************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/libkms/internal.h b/libkms/internal.h index 905f5b17..8b386db6 100644 --- a/libkms/internal.h +++ b/libkms/internal.h @@ -29,10 +29,6 @@ #ifndef INTERNAL_H_ #define INTERNAL_H_ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include "libdrm_macros.h" #include "libkms.h" diff --git a/libkms/kms-symbol-check b/libkms/kms-symbol-check index 658b2692..30f444f7 100755 --- a/libkms/kms-symbol-check +++ b/libkms/kms-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.sources/LIBKMS_H_FILES -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libkms.so} | awk '{print $3}'| while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libkms.so} | awk '{print $3}'| while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata diff --git a/libkms/linux.c b/libkms/linux.c index 0b50777e..56205054 100644 --- a/libkms/linux.c +++ b/libkms/linux.c @@ -29,10 +29,6 @@ * going from fd to pci id via fstat and udev. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -110,27 +106,27 @@ linux_from_sysfs(int fd, struct kms_driver **out) if (ret) return ret; -#ifdef HAVE_INTEL +#if HAVE_INTEL if (!strcmp(name, "intel")) ret = intel_create(fd, out); else #endif -#ifdef HAVE_VMWGFX +#if HAVE_VMWGFX if (!strcmp(name, "vmwgfx")) ret = vmwgfx_create(fd, out); else #endif -#ifdef HAVE_NOUVEAU +#if HAVE_NOUVEAU if (!strcmp(name, "nouveau")) ret = nouveau_create(fd, out); else #endif -#ifdef HAVE_RADEON +#if HAVE_RADEON if (!strcmp(name, "radeon")) ret = radeon_create(fd, out); else #endif -#ifdef HAVE_EXYNOS +#if HAVE_EXYNOS if (!strcmp(name, "exynos")) ret = exynos_create(fd, out); else diff --git a/libkms/meson.build b/libkms/meson.build new file mode 100644 index 00000000..dc931608 --- /dev/null +++ b/libkms/meson.build @@ -0,0 +1,75 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libkms_include = [inc_root, inc_drm] +files_libkms = files( + 'linux.c', + 'dumb.c', + 'api.c', +) +if with_vmwgfx + files_libkms += files('vmwgfx.c') +endif +if with_intel + files_libkms += files('intel.c') +endif +if with_nouveau + files_libkms += files('nouveau.c') +endif +if with_radeon + files_libkms += files('radeon.c') +endif +if with_exynos + files_libkms += files('exynos.c') + libkms_include += include_directories('../exynos') +endif + +libkms = shared_library( + 'kms', + [files_libkms, config_file], + c_args : libdrm_c_args, + include_directories : libkms_include, + link_with : libdrm, + version : '1.0.0', + install : true, +) + +ext_libkms = declare_dependency( + link_with : [libdrm, libkms], + include_directories : [libkms_include], +) + +install_headers('libkms.h', subdir : 'libkms') + +pkg.generate( + name : 'libkms', + libraries : libkms, + subdirs : ['libkms'], + version : '1.0.0', + requires_private : 'libdrm', + description : 'Library that abstracts away the different mm interfaces for kernel drivers', +) + +test( + 'kms-symbol-check', + prog_bash, + env : env_test, + args : [files('kms-symbol-check'), libkms] +) diff --git a/libkms/nouveau.c b/libkms/nouveau.c index d10e0fdb..7fe23db3 100644 --- a/libkms/nouveau.c +++ b/libkms/nouveau.c @@ -26,10 +26,6 @@ **************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/libkms/radeon.c b/libkms/radeon.c index aaeeaf31..2cb2b11f 100644 --- a/libkms/radeon.c +++ b/libkms/radeon.c @@ -26,10 +26,6 @@ **************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/libkms/vmwgfx.c b/libkms/vmwgfx.c index 6a24fd4d..f0e40be7 100644 --- a/libkms/vmwgfx.c +++ b/libkms/vmwgfx.c @@ -26,10 +26,6 @@ **************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdlib.h> #include <string.h> diff --git a/man/drm-kms.xml b/man/drm-kms.xml index ae38dc8d..eb04c263 100644 --- a/man/drm-kms.xml +++ b/man/drm-kms.xml @@ -309,8 +309,8 @@ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn) <refsect1> <title>Reporting Bugs</title> <para>Bugs in this manual should be reported to - http://bugs.freedesktop.org under the "Mesa" product, with "Other" or - "libdrm" as the component.</para> + https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&component=libdrm + under the "DRI" product, component "libdrm"</para> </refsect1> <refsect1> diff --git a/man/drm-memory.xml b/man/drm-memory.xml index 6b4f0759..3aa7cf25 100644 --- a/man/drm-memory.xml +++ b/man/drm-memory.xml @@ -410,8 +410,8 @@ memset(map, 0, creq.size); <refsect1> <title>Reporting Bugs</title> <para>Bugs in this manual should be reported to - http://bugs.freedesktop.org under the "Mesa" product, with "Other" or - "libdrm" as the component.</para> + https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&component=libdrm + under the "DRI" product, component "libdrm"</para> </refsect1> <refsect1> diff --git a/man/drm.xml b/man/drm.xml index 5a49fe13..1f559669 100644 --- a/man/drm.xml +++ b/man/drm.xml @@ -50,7 +50,7 @@ <para>In earlier days, the kernel framework was solely used to provide raw hardware access to priviledged user-space processes which implement - all the hardware abstraction layers. But more and more tasks where + all the hardware abstraction layers. But more and more tasks were moved into the kernel. All these interfaces are based on <citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> commands on the DRM character device. The <emphasis>libdrm</emphasis> @@ -119,8 +119,8 @@ <refsect1> <title>Reporting Bugs</title> <para>Bugs in this manual should be reported to - http://bugs.freedesktop.org under the "Mesa" product, with "Other" or - "libdrm" as the component.</para> + https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&component=libdrm + under the "DRI" product, component "libdrm"</para> </refsect1> <refsect1> diff --git a/man/drmAvailable.xml b/man/drmAvailable.xml index 55bef94a..1e5d7873 100644 --- a/man/drmAvailable.xml +++ b/man/drmAvailable.xml @@ -61,8 +61,8 @@ <refsect1> <title>Reporting Bugs</title> <para>Bugs in this function should be reported to - http://bugs.freedesktop.org under the "Mesa" product, with "Other" or - "libdrm" as the component.</para> + https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&component=libdrm + under the "DRI" product, component "libdrm"</para> </refsect1> <refsect1> diff --git a/man/drmHandleEvent.xml b/man/drmHandleEvent.xml index b1006e51..83304428 100644 --- a/man/drmHandleEvent.xml +++ b/man/drmHandleEvent.xml @@ -86,8 +86,8 @@ typedef struct _drmEventContext { <refsect1> <title>Reporting Bugs</title> <para>Bugs in this function should be reported to - http://bugs.freedesktop.org under the "Mesa" product, with "Other" or - "libdrm" as the component.</para> + https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&component=libdrm + under the "DRI" product, component "libdrm"</para> </refsect1> <refsect1> diff --git a/man/drmModeGetResources.xml b/man/drmModeGetResources.xml index 2f5e8c2c..0ab6a68b 100644 --- a/man/drmModeGetResources.xml +++ b/man/drmModeGetResources.xml @@ -116,8 +116,8 @@ typedef struct _drmModeRes { <refsect1> <title>Reporting Bugs</title> <para>Bugs in this function should be reported to - http://bugs.freedesktop.org under the "Mesa" product, with "Other" or - "libdrm" as the component.</para> + https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&component=libdrm + under the "DRI" product, component "libdrm"</para> </refsect1> <refsect1> diff --git a/man/meson.build b/man/meson.build new file mode 100644 index 00000000..45eaeda0 --- /dev/null +++ b/man/meson.build @@ -0,0 +1,67 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +xsltproc_args = [ + '--stringparam', 'man.authors.section.enabled', '0', + '--stringparam', 'man.copyright.section.enabled', '0', + '--stringparam', 'funcsynopsis.style', 'ansi', + '--stringparam', 'man.output.quietly', '1', + '--nonet', manpage_style, +] + +xmls = [ + ['drm', '7'], ['drm-kms', '7'], ['drm-memory', '7'], ['drmAvailable', '3'], + ['drmHandleEvent', '3'], ['drmModeGetResources', '3'] +] +foreach x : xmls + m = x[0] + s = x[1] + custom_target( + m, + input : files('@0@.xml'.format(m)), + output : '@0@.@1@'.format(m, s), + command : [prog_xslt, '-o', '@OUTPUT@', xsltproc_args, '@INPUT0@'], + install : true, + install_dir : join_paths(get_option('mandir'), 'man@0@'.format(s)), + build_by_default : true, + ) +endforeach + +foreach x : ['drm-mm', 'drm-gem', 'drm-ttm'] + gen = custom_target( + 'gen-@0@'.format(x), + input : 'drm-memory.xml', + output : '@0@.xml'.format(x), + command : [ + prog_sed, '-e', 's@^\.so \([a-z_]\+\)\.\([0-9]\)$$@\.so man\2\/\1\.\2@', + '@INPUT@', + ], + capture : true, + ) + custom_target( + '@0@.7'.format(x), + input : gen, + output : '@0@.7'.format(x, '7'), + command : [prog_xslt, '-o', '@OUTPUT@', xsltproc_args, '@INPUT@'], + install : true, + install_dir : join_paths(get_option('mandir'), 'man7'), + build_by_default : true, + ) +endforeach diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..b3eb8467 --- /dev/null +++ b/meson.build @@ -0,0 +1,386 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +project( + 'libdrm', + ['c'], + version : '2.4.97', + license : 'MIT', + meson_version : '>= 0.43', + default_options : ['buildtype=debugoptimized', 'c_std=gnu99'], +) + +pkg = import('pkgconfig') + +config = configuration_data() + +config.set10('UDEV', get_option('udev')) +with_freedreno_kgsl = get_option('freedreno-kgsl') +with_install_tests = get_option('install-test-programs') + +if ['freebsd', 'dragonfly', 'netbsd'].contains(host_machine.system()) + dep_pthread_stubs = dependency('pthread-stubs', version : '>= 0.4') +else + dep_pthread_stubs = [] +endif +dep_threads = dependency('threads') + +cc = meson.get_compiler('c') + +# Check for atomics +intel_atomics = false +lib_atomics = false + +dep_atomic_ops = dependency('atomic_ops', required : false) +if cc.compiles(''' + int atomic_add(int *i) { return __sync_add_and_fetch (i, 1); } + int atomic_cmpxchg(int *i, int j, int k) { return __sync_val_compare_and_swap (i, j, k); } + ''', + name : 'Intel Atomics') + intel_atomics = true + with_atomics = true + dep_atomic_ops = [] +elif dep_atomic_ops.found() + lib_atomics = true + with_atomics = true +elif cc.has_function('atomic_cas_uint') + with_atomics = true +else + with_atomics = false +endif + +config.set10('HAVE_LIBDRM_ATOMIC_PRIMITIVES', intel_atomics) +config.set10('HAVE_LIB_ATOMIC_OPS', lib_atomics) + +with_intel = false +_intel = get_option('intel') +if _intel != 'false' + if _intel == 'true' and not with_atomics + error('libdrm_intel requires atomics.') + else + with_intel = _intel == 'true' or host_machine.cpu_family().startswith('x86') + endif +endif + +with_radeon = false +_radeon = get_option('radeon') +if _radeon != 'false' + if _radeon == 'true' and not with_atomics + error('libdrm_radeon requires atomics.') + endif + with_radeon = true +endif + +with_amdgpu = false +_amdgpu = get_option('amdgpu') +if _amdgpu != 'false' + if _amdgpu == 'true' and not with_atomics + error('libdrm_amdgpu requires atomics.') + endif + with_amdgpu = true +endif + +with_nouveau = false +_nouveau = get_option('nouveau') +if _nouveau != 'false' + if _nouveau == 'true' and not with_atomics + error('libdrm_nouveau requires atomics.') + endif + with_nouveau = true +endif + +with_vmwgfx = false +_vmwgfx = get_option('vmwgfx') +if _vmwgfx != 'false' + with_vmwgfx = true +endif + +with_omap = false +_omap = get_option('omap') +if _omap == 'true' + if not with_atomics + error('libdrm_omap requires atomics.') + endif + with_omap = true +endif + +with_freedreno = false +_freedreno = get_option('freedreno') +if _freedreno != 'false' + if _freedreno == 'true' and not with_atomics + error('libdrm_freedreno requires atomics.') + else + with_freedreno = _freedreno == 'true' or ['arm', 'aarch64'].contains(host_machine.cpu_family()) + endif +endif + +with_tegra = false +_tegra = get_option('tegra') +if _tegra == 'true' + if not with_atomics + error('libdrm_tegra requires atomics.') + endif + with_tegra = true +endif + +with_etnaviv = false +_etnaviv = get_option('etnaviv') +if _etnaviv == 'true' + if not with_atomics + error('libdrm_etnaviv requires atomics.') + endif + with_etnaviv = true +endif + +with_exynos = get_option('exynos') == 'true' + +with_vc4 = false +_vc4 = get_option('vc4') +if _vc4 != 'false' + with_vc4 = _vc4 == 'true' or ['arm', 'aarch64'].contains(host_machine.cpu_family()) +endif + +# XXX: Aparently only freebsd and dragonfly bsd actually need this (and +# gnu/kfreebsd), not openbsd and netbsd +with_libkms = false +_libkms = get_option('libkms') +if _libkms != 'false' + with_libkms = _libkms == 'true' or ['linux', 'freebsd', 'dragonfly'].contains(host_machine.system()) +endif + +# Among others FreeBSD does not have a separate dl library. +if not cc.has_function('dlsym') + dep_dl = cc.find_library('dl', required : with_nouveau) +else + dep_dl = [] +endif +# clock_gettime might require -rt, or it might not. find out +if not cc.has_function('clock_gettime', prefix : '#define _GNU_SOURCE\n#include <time.h>') + # XXX: untested + dep_rt = cc.find_library('rt') +else + dep_rt = [] +endif +dep_m = cc.find_library('m', required : false) +foreach header : ['sys/sysctl.h', 'sys/select.h', 'alloca.h'] + config.set('HAVE_' + header.underscorify().to_upper(), + cc.compiles('#include <@0@>'.format(header), name : '@0@ works'.format(header))) +endforeach +if cc.has_header_symbol('sys/sysmacros.h', 'major') + config.set10('MAJOR_IN_SYSMACROS', true) +elif cc.has_header_symbol('sys/mkdev.h', 'major') + config.set10('MAJOR_IN_MKDEV', true) +endif +config.set10('HAVE_OPEN_MEMSTREAM', cc.has_function('open_memstream')) + +warn_c_args = [] +foreach a : ['-Wall', '-Wextra', '-Wsign-compare', '-Werror=undef', + '-Werror=implicit-function-declaration', '-Wpointer-arith', + '-Wwrite-strings', '-Wstrict-prototypes', '-Wmissing-prototypes', + '-Wmissing-declarations', '-Wnested-externs', '-Wpacked', + '-Wswitch-enum', '-Wmissing-format-attribute', + '-Wstrict-aliasing=2', '-Winit-self', '-Winline', '-Wshadow', + '-Wdeclaration-after-statement', '-Wold-style-definition'] + if cc.has_argument(a) + warn_c_args += a + endif +endforeach +# GCC will never error for -Wno-*, so check for -W* then add -Wno-* to the list +# of options +foreach a : ['unused-parameter', 'attributes', 'long-long', + 'missing-field-initializers'] + if cc.has_argument('-W@0@'.format(a)) + warn_c_args += '-Wno-@0@'.format(a) + endif +endforeach + +# all c args: +libdrm_c_args = warn_c_args + ['-fvisibility=hidden'] + + +dep_pciaccess = dependency('pciaccess', version : '>= 0.10', required : with_intel) +dep_cunit = dependency('cunit', version : '>= 2.1', required : false) +_cairo_tests = get_option('cairo-tests') +if _cairo_tests != 'false' + dep_cairo = dependency('cairo', required : _cairo_tests == 'true') + with_cairo_tests = dep_cairo.found() +else + dep_cairo = [] + with_cairo_tests = false +endif +_valgrind = get_option('valgrind') +if _valgrind != 'false' + dep_valgrind = dependency('valgrind', required : _valgrind == 'true') + with_valgrind = dep_valgrind.found() +else + dep_valgrind = [] + with_valgrind = false +endif + +with_man_pages = get_option('man-pages') +prog_xslt = find_program('xsltproc', required : with_man_pages == 'true') +prog_sed = find_program('sed', required : with_man_pages == 'true') +manpage_style = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl' +if prog_xslt.found() + if run_command(prog_xslt, '--nonet', manpage_style).returncode() != 0 + if with_man_pages == 'true' + error('Manpage style sheet cannot be found') + endif + with_man_pages = 'false' + endif +endif +with_man_pages = with_man_pages != 'false' and prog_xslt.found() and prog_sed.found() + +# Used for tets +prog_bash = find_program('bash') + +config.set10('HAVE_VISIBILITY', + cc.compiles('''int foo_hidden(void) __attribute__((visibility(("hidden"))));''', + name : 'compiler supports __attribute__(("hidden"))')) + +foreach t : [ + [with_exynos, 'EXYNOS'], + [with_freedreno_kgsl, 'FREEDRENO_KGSL'], + [with_intel, 'INTEL'], + [with_nouveau, 'NOUVEAU'], + [with_radeon, 'RADEON'], + [with_vc4, 'VC4'], + [with_vmwgfx, 'VMWGFX'], + [with_cairo_tests, 'CAIRO'], + [with_valgrind, 'VALGRIND'], + ] + config.set10('HAVE_@0@'.format(t[1]), t[0]) +endforeach +if with_freedreno_kgsl and not with_freedreno + error('cannot enable freedreno-kgsl without freedreno support') +endif +config.set10('_GNU_SOURCE', true) +config_file = configure_file( + configuration : config, + output : 'config.h', +) +add_project_arguments('-include', 'config.h', language : 'c') + +inc_root = include_directories('.') +inc_drm = include_directories('include/drm') + +libdrm = shared_library( + 'drm', + [files( + 'xf86drm.c', 'xf86drmHash.c', 'xf86drmRandom.c', 'xf86drmSL.c', + 'xf86drmMode.c' + ), + config_file, + ], + c_args : libdrm_c_args, + dependencies : [dep_valgrind, dep_rt, dep_m], + include_directories : inc_drm, + version : '2.4.0', + install : true, +) + +ext_libdrm = declare_dependency( + link_with : libdrm, + include_directories : [inc_root, inc_drm], +) + +install_headers('libsync.h', 'xf86drm.h', 'xf86drmMode.h') +install_headers( + 'include/drm/drm.h', 'include/drm/drm_fourcc.h', 'include/drm/drm_mode.h', + 'include/drm/drm_sarea.h', 'include/drm/i915_drm.h', + 'include/drm/mach64_drm.h', 'include/drm/mga_drm.h', + 'include/drm/msm_drm.h', 'include/drm/nouveau_drm.h', + 'include/drm/qxl_drm.h', 'include/drm/r128_drm.h', + 'include/drm/radeon_drm.h', 'include/drm/amdgpu_drm.h', + 'include/drm/savage_drm.h', 'include/drm/sis_drm.h', + 'include/drm/tegra_drm.h', 'include/drm/vc4_drm.h', + 'include/drm/via_drm.h', 'include/drm/virtgpu_drm.h', + subdir : 'libdrm', +) +if with_vmwgfx + install_headers('include/drm/vmwgfx_drm.h', subdir : 'libdrm') +endif + +pkg.generate( + name : 'libdrm', + libraries : libdrm, + subdirs : ['.', 'libdrm'], + version : meson.project_version(), + description : 'Userspace interface to kernel DRM services', +) + +env_test = environment() +env_test.set('NM', find_program('nm').path()) + +if with_libkms + subdir('libkms') +endif +if with_intel + subdir('intel') +endif +if with_nouveau + subdir('nouveau') +endif +if with_radeon + subdir('radeon') +endif +if with_amdgpu + subdir('amdgpu') +endif +if with_omap + subdir('omap') +endif +if with_exynos + subdir('exynos') +endif +if with_freedreno + subdir('freedreno') +endif +if with_tegra + subdir('tegra') +endif +if with_vc4 + subdir('vc4') +endif +if with_etnaviv + subdir('etnaviv') +endif +if with_man_pages + subdir('man') +endif +subdir('data') +subdir('tests') + +message('') +message('@0@ will be compiled with:'.format(meson.project_name())) +message('') +message(' libkms @0@'.format(with_libkms)) +message(' Intel API @0@'.format(with_intel)) +message(' vmwgfx API @0@'.format(with_vmwgfx)) +message(' Radeon API @0@'.format(with_radeon)) +message(' AMDGPU API @0@'.format(with_amdgpu)) +message(' Nouveau API @0@'.format(with_nouveau)) +message(' OMAP API @0@'.format(with_omap)) +message(' EXYNOS API @0@'.format(with_exynos)) +message(' Freedreno API @0@ (kgsl: @1@)'.format(with_freedreno, with_freedreno_kgsl)) +message(' Tegra API @0@'.format(with_tegra)) +message(' VC4 API @0@'.format(with_vc4)) +message(' Etnaviv API @0@'.format(with_etnaviv)) +message('') diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..8af33f1c --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,143 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option( + 'libkms', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : 'Build libkms mm abstraction library.', +) +option( + 'intel', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : '''Enable support for Intel's KMS API.''', +) +option( + 'radeon', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : '''Enable support for radeons's KMS API.''', +) +option( + 'amdgpu', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : '''Enable support for amdgpu's KMS API.''', +) +option( + 'nouveau', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : '''Enable support for nouveau's KMS API.''', +) +option( + 'vmwgfx', + type : 'combo', + value : 'true', + choices : ['true', 'false', 'auto'], + description : '''Enable support for vmgfx's KMS API.''', +) +option( + 'omap', + type : 'combo', + value : 'false', + choices : ['true', 'false', 'auto'], + description : '''Enable support for OMAP's experimental KMS API.''', +) +option( + 'exynos', + type : 'combo', + value : 'false', + choices : ['true', 'false', 'auto'], + description : '''Enable support for EXYNOS's experimental KMS API.''', +) +option( + 'freedreno', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : '''Enable support for freedreno's KMS API.''', +) +option( + 'tegra', + type : 'combo', + value : 'false', + choices : ['true', 'false', 'auto'], + description : '''Enable support for Tegra's experimental KMS API.''', +) +option( + 'vc4', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : '''Enable support for vc4's KMS API.''', +) +option( + 'etnaviv', + type : 'combo', + value : 'false', + choices : ['true', 'false', 'auto'], + description : '''Enable support for etnaviv's experimental KMS API.''', +) +option( + 'cairo-tests', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : 'Enable support for Cairo rendering in tests.', +) +option( + 'man-pages', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : 'Enable manpage generation and installation.', +) +option( + 'valgrind', + type : 'combo', + value : 'auto', + choices : ['true', 'false', 'auto'], + description : 'Build libdrm with valgrind support.', +) +option( + 'freedreno-kgsl', + type : 'boolean', + value : false, + description : 'Enable support for freedreno to use downstream android kernel API.', +) +option( + 'install-test-programs', + type : 'boolean', + value : false, + description : 'Install test programs.', +) +option( + 'udev', + type : 'boolean', + value : false, + description : 'Enable support for using udev instead of mknod.', +) diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am index 344a8445..5574fd8f 100644 --- a/nouveau/Makefile.am +++ b/nouveau/Makefile.am @@ -2,6 +2,7 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ -I$(top_srcdir)/include/drm \ @@ -29,5 +30,6 @@ libdrm_nouveaunvifinclude_HEADERS = nvif/class.h \ pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_nouveau.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = nouveau-symbol-check EXTRA_DIST = $(TESTS) diff --git a/nouveau/abi16.c b/nouveau/abi16.c index ee38c0cb..ba2501ea 100644 --- a/nouveau/abi16.c +++ b/nouveau/abi16.c @@ -22,10 +22,6 @@ * Authors: Ben Skeggs */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - #include <stdlib.h> #include <stdint.h> #include <stddef.h> diff --git a/nouveau/bufctx.c b/nouveau/bufctx.c index 4f76e5df..00924b3c 100644 --- a/nouveau/bufctx.c +++ b/nouveau/bufctx.c @@ -22,10 +22,6 @@ * Authors: Ben Skeggs */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -62,7 +58,7 @@ nouveau_bufctx(struct nouveau_bufctx *bctx) return (struct nouveau_bufctx_priv *)bctx; } -int +drm_public int nouveau_bufctx_new(struct nouveau_client *client, int bins, struct nouveau_bufctx **pbctx) { @@ -82,7 +78,7 @@ nouveau_bufctx_new(struct nouveau_client *client, int bins, return -ENOMEM; } -void +drm_public void nouveau_bufctx_del(struct nouveau_bufctx **pbctx) { struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx); @@ -99,7 +95,7 @@ nouveau_bufctx_del(struct nouveau_bufctx **pbctx) } } -void +drm_public void nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin) { struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); @@ -117,7 +113,7 @@ nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin) pbin->relocs = 0; } -struct nouveau_bufref * +drm_public struct nouveau_bufref * nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin, struct nouveau_bo *bo, uint32_t flags) { @@ -144,7 +140,7 @@ nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin, return &pref->base; } -struct nouveau_bufref * +drm_public struct nouveau_bufref * nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet, struct nouveau_bo *bo, uint64_t data, uint32_t flags, uint32_t vor, uint32_t tor) diff --git a/nouveau/meson.build b/nouveau/meson.build new file mode 100644 index 00000000..0c1498d7 --- /dev/null +++ b/nouveau/meson.build @@ -0,0 +1,59 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +libdrm_nouveau = shared_library( + 'drm_nouveau', + [files( 'nouveau.c', 'pushbuf.c', 'bufctx.c', 'abi16.c'), config_file], + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm], + link_with : libdrm, + dependencies : [dep_threads, dep_atomic_ops], + version : '2.0.0', + install : true, +) + +ext_libdrm_nouveau = declare_dependency( + link_with : [libdrm, libdrm_nouveau], + include_directories : [inc_drm, include_directories('.')], +) + +install_headers('nouveau.h', subdir : 'libdrm/nouveau') +install_headers( + 'nvif/class.h', 'nvif/cl0080.h', 'nvif/cl9097.h', 'nvif/if0002.h', + 'nvif/if0003.h', 'nvif/ioctl.h', 'nvif/unpack.h', + subdir : 'libdrm/nouveau/nvif' +) + +pkg.generate( + name : 'libdrm_nouveau', + libraries : libdrm_nouveau, + subdirs : ['.', 'libdrm', 'libdrm/nouveau'], + version : meson.project_version(), + requires_private : 'libdrm', + description : 'Userspace interface to nouveau kernel DRM services', +) + +test( + 'nouveau-symbol-check', + prog_bash, + env : env_test, + args : [files('nouveau-symbol-check'), libdrm_nouveau] +) diff --git a/nouveau/nouveau-symbol-check b/nouveau/nouveau-symbol-check index b265cea4..6296244c 100755 --- a/nouveau/nouveau-symbol-check +++ b/nouveau/nouveau-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.sources/LIBDRM_NOUVEAU_H_FILES -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_nouveau.so} | awk '{print $3}'| while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_nouveau.so} | awk '{print $3}'| while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c index e113a8fe..f18d1426 100644 --- a/nouveau/nouveau.c +++ b/nouveau/nouveau.c @@ -22,10 +22,6 @@ * Authors: Ben Skeggs */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -92,7 +88,7 @@ nouveau_object_ioctl(struct nouveau_object *obj, void *data, uint32_t size) return drmCommandWriteRead(drm->fd, DRM_NOUVEAU_NVIF, args, argc); } -int +drm_public int nouveau_object_mthd(struct nouveau_object *obj, uint32_t mthd, void *data, uint32_t size) { @@ -127,14 +123,14 @@ nouveau_object_mthd(struct nouveau_object *obj, return ret; } -void +drm_public void nouveau_object_sclass_put(struct nouveau_sclass **psclass) { free(*psclass); *psclass = NULL; } -int +drm_public int nouveau_object_sclass_get(struct nouveau_object *obj, struct nouveau_sclass **psclass) { @@ -184,7 +180,7 @@ nouveau_object_sclass_get(struct nouveau_object *obj, return ret; } -int +drm_public int nouveau_object_mclass(struct nouveau_object *obj, const struct nouveau_mclass *mclass) { @@ -286,7 +282,7 @@ nouveau_object_init(struct nouveau_object *parent, uint32_t handle, return 0; } -int +drm_public int nouveau_object_new(struct nouveau_object *parent, uint64_t handle, uint32_t oclass, void *data, uint32_t length, struct nouveau_object **pobj) @@ -307,7 +303,7 @@ nouveau_object_new(struct nouveau_object *parent, uint64_t handle, return 0; } -void +drm_public void nouveau_object_del(struct nouveau_object **pobj) { struct nouveau_object *obj = *pobj; @@ -318,14 +314,14 @@ nouveau_object_del(struct nouveau_object **pobj) } } -void +drm_public void nouveau_drm_del(struct nouveau_drm **pdrm) { free(*pdrm); *pdrm = NULL; } -int +drm_public int nouveau_drm_new(int fd, struct nouveau_drm **pdrm) { struct nouveau_drm *drm; @@ -357,14 +353,14 @@ nouveau_drm_new(int fd, struct nouveau_drm **pdrm) * is kept here to prevent AIGLX from crashing if the DDX is linked against * the new libdrm, but the DRI driver against the old */ -int +drm_public int nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd, drm_context_t ctx) { return -EACCES; } -int +drm_public int nouveau_device_new(struct nouveau_object *parent, int32_t oclass, void *data, uint32_t size, struct nouveau_device **pdev) { @@ -458,7 +454,7 @@ done: return ret; } -int +drm_public int nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) { struct nouveau_drm *drm; @@ -486,7 +482,7 @@ nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) return 0; } -int +drm_public int nouveau_device_open(const char *busid, struct nouveau_device **pdev) { int ret = -ENODEV, fd = drmOpen("nouveau", busid); @@ -498,7 +494,7 @@ nouveau_device_open(const char *busid, struct nouveau_device **pdev) return ret; } -void +drm_public void nouveau_device_del(struct nouveau_device **pdev) { struct nouveau_device_priv *nvdev = nouveau_device(*pdev); @@ -517,7 +513,7 @@ nouveau_device_del(struct nouveau_device **pdev) } } -int +drm_public int nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value) { struct nouveau_drm *drm = nouveau_drm(&dev->object); @@ -528,7 +524,7 @@ nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value) return ret; } -int +drm_public int nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value) { struct nouveau_drm *drm = nouveau_drm(&dev->object); @@ -536,7 +532,7 @@ nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value) return drmCommandWrite(drm->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r)); } -int +drm_public int nouveau_client_new(struct nouveau_device *dev, struct nouveau_client **pclient) { struct nouveau_device_priv *nvdev = nouveau_device(dev); @@ -575,7 +571,7 @@ unlock: return ret; } -void +drm_public void nouveau_client_del(struct nouveau_client **pclient) { struct nouveau_client_priv *pcli = nouveau_client(*pclient); @@ -622,7 +618,7 @@ nouveau_bo_del(struct nouveau_bo *bo) free(nvbo); } -int +drm_public int nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, uint32_t align, uint64_t size, union nouveau_bo_config *config, struct nouveau_bo **pbo) @@ -713,7 +709,7 @@ nouveau_bo_make_global(struct nouveau_bo_priv *nvbo) } } -int +drm_public int nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle, struct nouveau_bo **pbo) { @@ -725,7 +721,7 @@ nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle, return ret; } -int +drm_public int nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name, struct nouveau_bo **pbo) { @@ -754,7 +750,7 @@ nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name, return ret; } -int +drm_public int nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name) { struct drm_gem_flink req = { .handle = bo->handle }; @@ -776,7 +772,7 @@ nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name) return 0; } -void +drm_public void nouveau_bo_ref(struct nouveau_bo *bo, struct nouveau_bo **pref) { struct nouveau_bo *ref = *pref; @@ -790,7 +786,7 @@ nouveau_bo_ref(struct nouveau_bo *bo, struct nouveau_bo **pref) *pref = bo; } -int +drm_public int nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd, struct nouveau_bo **bo) { @@ -810,7 +806,7 @@ nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd, return ret; } -int +drm_public int nouveau_bo_set_prime(struct nouveau_bo *bo, int *prime_fd) { struct nouveau_drm *drm = nouveau_drm(&bo->device->object); @@ -825,7 +821,7 @@ nouveau_bo_set_prime(struct nouveau_bo *bo, int *prime_fd) return 0; } -int +drm_public int nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) { @@ -860,7 +856,7 @@ nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access, return ret; } -int +drm_public int nouveau_bo_map(struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client) { diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c index 035e3019..e5f73f0d 100644 --- a/nouveau/pushbuf.c +++ b/nouveau/pushbuf.c @@ -22,10 +22,6 @@ * Authors: Ben Skeggs */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -532,7 +528,7 @@ pushbuf_validate(struct nouveau_pushbuf *push, bool retry) return ret; } -int +drm_public int nouveau_pushbuf_new(struct nouveau_client *client, struct nouveau_object *chan, int nr, uint32_t size, bool immediate, struct nouveau_pushbuf **ppush) @@ -603,7 +599,7 @@ nouveau_pushbuf_new(struct nouveau_client *client, struct nouveau_object *chan, return 0; } -void +drm_public void nouveau_pushbuf_del(struct nouveau_pushbuf **ppush) { struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(*ppush); @@ -629,7 +625,7 @@ nouveau_pushbuf_del(struct nouveau_pushbuf **ppush) *ppush = NULL; } -struct nouveau_bufctx * +drm_public struct nouveau_bufctx * nouveau_pushbuf_bufctx(struct nouveau_pushbuf *push, struct nouveau_bufctx *ctx) { struct nouveau_bufctx *prev = push->bufctx; @@ -637,7 +633,7 @@ nouveau_pushbuf_bufctx(struct nouveau_pushbuf *push, struct nouveau_bufctx *ctx) return prev; } -int +drm_public int nouveau_pushbuf_space(struct nouveau_pushbuf *push, uint32_t dwords, uint32_t relocs, uint32_t pushes) { @@ -701,7 +697,7 @@ nouveau_pushbuf_space(struct nouveau_pushbuf *push, return flushed ? pushbuf_validate(push, false) : 0; } -void +drm_public void nouveau_pushbuf_data(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint64_t offset, uint64_t length) { @@ -732,14 +728,14 @@ nouveau_pushbuf_data(struct nouveau_pushbuf *push, struct nouveau_bo *bo, } } -int +drm_public int nouveau_pushbuf_refn(struct nouveau_pushbuf *push, struct nouveau_pushbuf_refn *refs, int nr) { return pushbuf_refn(push, true, refs, nr); } -void +drm_public void nouveau_pushbuf_reloc(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor) { @@ -747,13 +743,13 @@ nouveau_pushbuf_reloc(struct nouveau_pushbuf *push, struct nouveau_bo *bo, push->cur++; } -int +drm_public int nouveau_pushbuf_validate(struct nouveau_pushbuf *push) { return pushbuf_validate(push, true); } -uint32_t +drm_public uint32_t nouveau_pushbuf_refd(struct nouveau_pushbuf *push, struct nouveau_bo *bo) { struct drm_nouveau_gem_pushbuf_bo *kref; @@ -771,7 +767,7 @@ nouveau_pushbuf_refd(struct nouveau_pushbuf *push, struct nouveau_bo *bo) return flags; } -int +drm_public int nouveau_pushbuf_kick(struct nouveau_pushbuf *push, struct nouveau_object *chan) { if (!push->channel) diff --git a/omap/Android.bp b/omap/Android.bp new file mode 100644 index 00000000..05ca7d2d --- /dev/null +++ b/omap/Android.bp @@ -0,0 +1,12 @@ +build = ["Android.sources.bp"] + +cc_library_shared { + name: "libdrm_omap", + defaults: [ + "libdrm_defaults", + "libdrm_omap_sources", + ], + vendor: true, + + shared_libs: ["libdrm"], +} diff --git a/omap/Android.sources.bp b/omap/Android.sources.bp new file mode 100644 index 00000000..3c7da94a --- /dev/null +++ b/omap/Android.sources.bp @@ -0,0 +1,8 @@ +// Autogenerated with Android.sources.bp.mk + +cc_defaults { + name: "libdrm_omap_sources", + srcs: [ + "omap_drm.c", + ], +} diff --git a/omap/Makefile.am b/omap/Makefile.am index 599bb9de..38a1007b 100644 --- a/omap/Makefile.am +++ b/omap/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ -I$(top_srcdir)/include/drm @@ -20,5 +21,6 @@ libdrm_omapinclude_HEADERS = omap_drmif.h pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_omap.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = omap-symbol-check EXTRA_DIST = $(TESTS) diff --git a/omap/meson.build b/omap/meson.build new file mode 100644 index 00000000..54698c6a --- /dev/null +++ b/omap/meson.build @@ -0,0 +1,54 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libdrm_omap = shared_library( + 'drm_omap', + [files('omap_drm.c'), config_file], + include_directories : [inc_root, inc_drm], + c_args : libdrm_c_args, + link_with : libdrm, + dependencies : [dep_pthread_stubs, dep_atomic_ops], + version : '1.0.0', + install : true, +) + +ext_libdrm_omap = declare_dependency( + link_with : [libdrm, libdrm_omap], + include_directories : [inc_drm, include_directories('.')], +) + +install_headers('omap_drmif.h', subdir : 'libdrm') +install_headers('omap_drm.h', subdir : 'omap') + +pkg.generate( + name : 'libdrm_omap', + libraries : libdrm_omap, + subdirs : ['.', 'libdrm', 'omap'], + version : '0.6', + requires_private : 'libdrm', + description : 'Userspace interface to omap kernel DRM services', +) + +test( + 'omap-symbol-check', + prog_bash, + env : env_test, + args : [files('omap-symbol-check'), libdrm_omap] +) diff --git a/omap/omap-symbol-check b/omap/omap-symbol-check index 759c84bd..16da3c40 100755 --- a/omap/omap-symbol-check +++ b/omap/omap-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.am/libdrm_omap*HEADERS -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_omap.so} | awk '{print $3}'| while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_omap.so} | awk '{print $3}'| while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata diff --git a/omap/omap_drm.c b/omap/omap_drm.c index 08ba64eb..ffacea69 100644 --- a/omap/omap_drm.c +++ b/omap/omap_drm.c @@ -26,10 +26,6 @@ * Rob Clark <rob@ti.com> */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <linux/stddef.h> #include <linux/types.h> @@ -92,7 +88,7 @@ static struct omap_device * omap_device_new_impl(int fd) return dev; } -struct omap_device * omap_device_new(int fd) +drm_public struct omap_device * omap_device_new(int fd) { struct omap_device *dev = NULL; @@ -115,13 +111,13 @@ struct omap_device * omap_device_new(int fd) return dev; } -struct omap_device * omap_device_ref(struct omap_device *dev) +drm_public struct omap_device * omap_device_ref(struct omap_device *dev) { atomic_inc(&dev->refcnt); return dev; } -void omap_device_del(struct omap_device *dev) +drm_public void omap_device_del(struct omap_device *dev) { if (!atomic_dec_and_test(&dev->refcnt)) return; @@ -132,7 +128,7 @@ void omap_device_del(struct omap_device *dev) free(dev); } -int +drm_public int omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value) { struct drm_omap_param req = { @@ -150,7 +146,7 @@ omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value) return 0; } -int +drm_public int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value) { struct drm_omap_param req = { @@ -230,7 +226,7 @@ fail: /* allocate a new (un-tiled) buffer object */ -struct omap_bo * +drm_public struct omap_bo * omap_bo_new(struct omap_device *dev, uint32_t size, uint32_t flags) { union omap_gem_size gsize = { @@ -243,7 +239,7 @@ omap_bo_new(struct omap_device *dev, uint32_t size, uint32_t flags) } /* allocate a new buffer object */ -struct omap_bo * +drm_public struct omap_bo * omap_bo_new_tiled(struct omap_device *dev, uint32_t width, uint32_t height, uint32_t flags) { @@ -259,7 +255,7 @@ omap_bo_new_tiled(struct omap_device *dev, uint32_t width, return omap_bo_new_impl(dev, gsize, flags); } -struct omap_bo *omap_bo_ref(struct omap_bo *bo) +drm_public struct omap_bo *omap_bo_ref(struct omap_bo *bo) { atomic_inc(&bo->refcnt); return bo; @@ -285,7 +281,7 @@ static int get_buffer_info(struct omap_bo *bo) } /* import a buffer object from DRI2 name */ -struct omap_bo * +drm_public struct omap_bo * omap_bo_from_name(struct omap_device *dev, uint32_t name) { struct omap_bo *bo = NULL; @@ -319,7 +315,7 @@ fail: * fd so caller should close() the fd when it is otherwise done * with it (even if it is still using the 'struct omap_bo *') */ -struct omap_bo * +drm_public struct omap_bo * omap_bo_from_dmabuf(struct omap_device *dev, int fd) { struct omap_bo *bo = NULL; @@ -351,7 +347,7 @@ fail: } /* destroy a buffer object */ -void omap_bo_del(struct omap_bo *bo) +drm_public void omap_bo_del(struct omap_bo *bo) { if (!bo) { return; @@ -384,7 +380,7 @@ void omap_bo_del(struct omap_bo *bo) } /* get the global flink/DRI2 buffer name */ -int omap_bo_get_name(struct omap_bo *bo, uint32_t *name) +drm_public int omap_bo_get_name(struct omap_bo *bo, uint32_t *name) { if (!bo->name) { struct drm_gem_flink req = { @@ -405,7 +401,7 @@ int omap_bo_get_name(struct omap_bo *bo, uint32_t *name) return 0; } -uint32_t omap_bo_handle(struct omap_bo *bo) +drm_public uint32_t omap_bo_handle(struct omap_bo *bo) { return bo->handle; } @@ -413,12 +409,12 @@ uint32_t omap_bo_handle(struct omap_bo *bo) /* caller owns the dmabuf fd that is returned and is responsible * to close() it when done */ -int omap_bo_dmabuf(struct omap_bo *bo) +drm_public int omap_bo_dmabuf(struct omap_bo *bo) { if (bo->fd < 0) { struct drm_prime_handle req = { .handle = bo->handle, - .flags = DRM_CLOEXEC, + .flags = DRM_CLOEXEC | DRM_RDWR, }; int ret; @@ -432,7 +428,7 @@ int omap_bo_dmabuf(struct omap_bo *bo) return dup(bo->fd); } -uint32_t omap_bo_size(struct omap_bo *bo) +drm_public uint32_t omap_bo_size(struct omap_bo *bo) { if (!bo->size) { get_buffer_info(bo); @@ -440,7 +436,7 @@ uint32_t omap_bo_size(struct omap_bo *bo) return bo->size; } -void *omap_bo_map(struct omap_bo *bo) +drm_public void *omap_bo_map(struct omap_bo *bo) { if (!bo->map) { if (!bo->offset) { @@ -456,7 +452,7 @@ void *omap_bo_map(struct omap_bo *bo) return bo->map; } -int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op) +drm_public int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op) { struct drm_omap_gem_cpu_prep req = { .handle = bo->handle, @@ -466,7 +462,7 @@ int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op) DRM_OMAP_GEM_CPU_PREP, &req, sizeof(req)); } -int omap_bo_cpu_fini(struct omap_bo *bo, enum omap_gem_op op) +drm_public int omap_bo_cpu_fini(struct omap_bo *bo, enum omap_gem_op op) { struct drm_omap_gem_cpu_fini req = { .handle = bo->handle, diff --git a/radeon/Makefile.am b/radeon/Makefile.am index e2415314..e712a4ac 100644 --- a/radeon/Makefile.am +++ b/radeon/Makefile.am @@ -26,6 +26,7 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ -I$(top_srcdir)/include/drm @@ -43,5 +44,6 @@ libdrm_radeoninclude_HEADERS = $(LIBDRM_RADEON_H_FILES) pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_radeon.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = radeon-symbol-check EXTRA_DIST = $(LIBDRM_RADEON_BOF_FILES) $(TESTS) diff --git a/radeon/meson.build b/radeon/meson.build new file mode 100644 index 00000000..1fc5282c --- /dev/null +++ b/radeon/meson.build @@ -0,0 +1,64 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +libdrm_radeon = shared_library( + 'drm_radeon', + [ + files( + 'radeon_bo_gem.c', 'radeon_cs_gem.c', 'radeon_cs_space.c', 'radeon_bo.c', + 'radeon_cs.c', 'radeon_surface.c', + ), + config_file, + ], + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm], + link_with : libdrm, + dependencies : [dep_pthread_stubs, dep_atomic_ops], + version : '1.0.1', + install : true, +) + +ext_libdrm_radeon = declare_dependency( + link_with : [libdrm, libdrm_radeon], + include_directories : [inc_drm, include_directories('.')], +) + +install_headers( + 'radeon_bo.h', 'radeon_cs.h', 'radeon_surface.h', 'radeon_bo_gem.h', + 'radeon_cs_gem.h', 'radeon_bo_int.h', 'radeon_cs_int.h', 'r600_pci_ids.h', + subdir : 'libdrm' +) + +pkg.generate( + name : 'libdrm_radeon', + libraries : libdrm_radeon, + subdirs : ['.', 'libdrm'], + version : meson.project_version(), + requires_private : 'libdrm', + description : 'Userspace interface to kernel DRM services for radeon', +) + +test( + 'radeon-symbol-check', + prog_bash, + env : env_test, + args : [files('radeon-symbol-check'), libdrm_radeon] +) diff --git a/radeon/radeon-symbol-check b/radeon/radeon-symbol-check index 0bf2ffcb..da605bb8 100755 --- a/radeon/radeon-symbol-check +++ b/radeon/radeon-symbol-check @@ -1,9 +1,11 @@ #!/bin/bash +set -u + # The following symbols (past the first five) are taken from the public headers. # A list of the latter should be available Makefile.sources/LIBDRM_RADEON_H_FILES -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_radeon.so} | awk '{print $3}'| while read func; do +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_radeon.so} | awk '{print $3}'| while read func; do ( grep -q "^$func$" || echo $func ) <<EOF __bss_start _edata diff --git a/radeon/radeon_bo.c b/radeon/radeon_bo.c index 447f9280..91929532 100644 --- a/radeon/radeon_bo.c +++ b/radeon/radeon_bo.c @@ -29,14 +29,11 @@ * Dave Airlie * Jérôme Glisse <glisse@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif #include <libdrm_macros.h> #include <radeon_bo.h> #include <radeon_bo_int.h> -void radeon_bo_debug(struct radeon_bo *bo, const char *op) +drm_public void radeon_bo_debug(struct radeon_bo *bo, const char *op) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; @@ -44,7 +41,7 @@ void radeon_bo_debug(struct radeon_bo *bo, const char *op) op, bo, bo->handle, boi->size, boi->cref); } -struct radeon_bo * +drm_public struct radeon_bo * radeon_bo_open(struct radeon_bo_manager *bom, uint32_t handle, uint32_t size, uint32_t alignment, uint32_t domains, uint32_t flags) { @@ -53,14 +50,14 @@ radeon_bo_open(struct radeon_bo_manager *bom, uint32_t handle, uint32_t size, return bo; } -void radeon_bo_ref(struct radeon_bo *bo) +drm_public void radeon_bo_ref(struct radeon_bo *bo) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; boi->cref++; boi->bom->funcs->bo_ref(boi); } -struct radeon_bo *radeon_bo_unref(struct radeon_bo *bo) +drm_public struct radeon_bo *radeon_bo_unref(struct radeon_bo *bo) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; if (bo == NULL) @@ -70,19 +67,19 @@ struct radeon_bo *radeon_bo_unref(struct radeon_bo *bo) return boi->bom->funcs->bo_unref(boi); } -int radeon_bo_map(struct radeon_bo *bo, int write) +drm_public int radeon_bo_map(struct radeon_bo *bo, int write) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; return boi->bom->funcs->bo_map(boi, write); } -int radeon_bo_unmap(struct radeon_bo *bo) +drm_public int radeon_bo_unmap(struct radeon_bo *bo) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; return boi->bom->funcs->bo_unmap(boi); } -int radeon_bo_wait(struct radeon_bo *bo) +drm_public int radeon_bo_wait(struct radeon_bo *bo) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; if (!boi->bom->funcs->bo_wait) @@ -90,13 +87,13 @@ int radeon_bo_wait(struct radeon_bo *bo) return boi->bom->funcs->bo_wait(boi); } -int radeon_bo_is_busy(struct radeon_bo *bo, uint32_t *domain) +drm_public int radeon_bo_is_busy(struct radeon_bo *bo, uint32_t *domain) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; return boi->bom->funcs->bo_is_busy(boi, domain); } -int +drm_public int radeon_bo_set_tiling(struct radeon_bo *bo, uint32_t tiling_flags, uint32_t pitch) { @@ -104,7 +101,7 @@ radeon_bo_set_tiling(struct radeon_bo *bo, return boi->bom->funcs->bo_set_tiling(boi, tiling_flags, pitch); } -int +drm_public int radeon_bo_get_tiling(struct radeon_bo *bo, uint32_t *tiling_flags, uint32_t *pitch) { @@ -112,7 +109,7 @@ radeon_bo_get_tiling(struct radeon_bo *bo, return boi->bom->funcs->bo_get_tiling(boi, tiling_flags, pitch); } -int radeon_bo_is_static(struct radeon_bo *bo) +drm_public int radeon_bo_is_static(struct radeon_bo *bo) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; if (boi->bom->funcs->bo_is_static) @@ -120,19 +117,19 @@ int radeon_bo_is_static(struct radeon_bo *bo) return 0; } -int +drm_public int radeon_bo_is_referenced_by_cs(struct radeon_bo *bo, struct radeon_cs *cs) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; return boi->cref > 1; } -uint32_t radeon_bo_get_handle(struct radeon_bo *bo) +drm_public uint32_t radeon_bo_get_handle(struct radeon_bo *bo) { return bo->handle; } -uint32_t radeon_bo_get_src_domain(struct radeon_bo *bo) +drm_public uint32_t radeon_bo_get_src_domain(struct radeon_bo *bo) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; uint32_t src_domain; diff --git a/radeon/radeon_bo_gem.c b/radeon/radeon_bo_gem.c index fbd453d9..86f7c007 100644 --- a/radeon/radeon_bo_gem.c +++ b/radeon/radeon_bo_gem.c @@ -29,9 +29,6 @@ * Dave Airlie * Jérôme Glisse <glisse@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif #include <stdio.h> #include <stdint.h> #include <stdlib.h> @@ -284,7 +281,7 @@ static const struct radeon_bo_funcs bo_gem_funcs = { .bo_is_referenced_by_cs = NULL, }; -struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd) +drm_public struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd) { struct bo_manager_gem *bomg; @@ -297,7 +294,7 @@ struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd) return (struct radeon_bo_manager*)bomg; } -void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom) +drm_public void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom) { struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom; @@ -307,21 +304,21 @@ void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom) free(bomg); } -uint32_t +drm_public uint32_t radeon_gem_name_bo(struct radeon_bo *bo) { struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; return bo_gem->name; } -void * +drm_public void * radeon_gem_get_reloc_in_cs(struct radeon_bo *bo) { struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; return &bo_gem->reloc_in_cs; } -int +drm_public int radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name) { struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; @@ -343,7 +340,7 @@ radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name) return 0; } -int +drm_public int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain) { struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; @@ -361,7 +358,7 @@ radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t writ return r; } -int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle) +drm_public int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle) { struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; int ret; @@ -370,7 +367,7 @@ int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle) return ret; } -struct radeon_bo * +drm_public struct radeon_bo * radeon_gem_bo_open_prime(struct radeon_bo_manager *bom, int fd_handle, uint32_t size) { struct radeon_bo_gem *bo; diff --git a/radeon/radeon_cs.c b/radeon/radeon_cs.c index dffb869f..1132d069 100644 --- a/radeon/radeon_cs.c +++ b/radeon/radeon_cs.c @@ -1,19 +1,16 @@ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif #include "libdrm_macros.h" #include <stdio.h> #include "radeon_cs.h" #include "radeon_cs_int.h" -struct radeon_cs * +drm_public struct radeon_cs * radeon_cs_create(struct radeon_cs_manager *csm, uint32_t ndw) { struct radeon_cs_int *csi = csm->funcs->cs_create(csm, ndw); return (struct radeon_cs *)csi; } -int +drm_public int radeon_cs_write_reloc(struct radeon_cs *cs, struct radeon_bo *bo, uint32_t read_domain, uint32_t write_domain, uint32_t flags) @@ -27,7 +24,7 @@ radeon_cs_write_reloc(struct radeon_cs *cs, struct radeon_bo *bo, flags); } -int +drm_public int radeon_cs_begin(struct radeon_cs *cs, uint32_t ndw, const char *file, const char *func, int line) { @@ -35,7 +32,7 @@ radeon_cs_begin(struct radeon_cs *cs, uint32_t ndw, return csi->csm->funcs->cs_begin(csi, ndw, file, func, line); } -int +drm_public int radeon_cs_end(struct radeon_cs *cs, const char *file, const char *func, int line) { @@ -43,37 +40,37 @@ radeon_cs_end(struct radeon_cs *cs, return csi->csm->funcs->cs_end(csi, file, func, line); } -int radeon_cs_emit(struct radeon_cs *cs) +drm_public int radeon_cs_emit(struct radeon_cs *cs) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; return csi->csm->funcs->cs_emit(csi); } -int radeon_cs_destroy(struct radeon_cs *cs) +drm_public int radeon_cs_destroy(struct radeon_cs *cs) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; return csi->csm->funcs->cs_destroy(csi); } -int radeon_cs_erase(struct radeon_cs *cs) +drm_public int radeon_cs_erase(struct radeon_cs *cs) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; return csi->csm->funcs->cs_erase(csi); } -int radeon_cs_need_flush(struct radeon_cs *cs) +drm_public int radeon_cs_need_flush(struct radeon_cs *cs) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; return csi->csm->funcs->cs_need_flush(csi); } -void radeon_cs_print(struct radeon_cs *cs, FILE *file) +drm_public void radeon_cs_print(struct radeon_cs *cs, FILE *file) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; csi->csm->funcs->cs_print(csi, file); } -void +drm_public void radeon_cs_set_limit(struct radeon_cs *cs, uint32_t domain, uint32_t limit) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; @@ -83,7 +80,7 @@ radeon_cs_set_limit(struct radeon_cs *cs, uint32_t domain, uint32_t limit) csi->csm->gart_limit = limit; } -void radeon_cs_space_set_flush(struct radeon_cs *cs, +drm_public void radeon_cs_space_set_flush(struct radeon_cs *cs, void (*fn)(void *), void *data) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; @@ -91,7 +88,7 @@ void radeon_cs_space_set_flush(struct radeon_cs *cs, csi->space_flush_data = data; } -uint32_t radeon_cs_get_id(struct radeon_cs *cs) +drm_public uint32_t radeon_cs_get_id(struct radeon_cs *cs) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; return csi->id; diff --git a/radeon/radeon_cs_gem.c b/radeon/radeon_cs_gem.c index f3dccb6c..ef070c60 100644 --- a/radeon/radeon_cs_gem.c +++ b/radeon/radeon_cs_gem.c @@ -29,9 +29,6 @@ * Nicolai Haehnle <prefect_@gmx.net> * Jérôme Glisse <glisse@freedesktop.org> */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif #include <assert.h> #include <errno.h> #include <stdlib.h> @@ -539,7 +536,7 @@ static int radeon_get_device_id(int fd, uint32_t *device_id) return r; } -struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd) +drm_public struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd) { struct radeon_cs_manager_gem *csm; @@ -553,7 +550,7 @@ struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd) return &csm->base; } -void radeon_cs_manager_gem_dtor(struct radeon_cs_manager *csm) +drm_public void radeon_cs_manager_gem_dtor(struct radeon_cs_manager *csm) { free(csm); } diff --git a/radeon/radeon_cs_space.c b/radeon/radeon_cs_space.c index 69287be5..039b0414 100644 --- a/radeon/radeon_cs_space.c +++ b/radeon/radeon_cs_space.c @@ -25,9 +25,6 @@ */ /* */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif #include <assert.h> #include <errno.h> #include <stdlib.h> @@ -165,7 +162,7 @@ static int radeon_cs_do_space_check(struct radeon_cs_int *cs, struct radeon_cs_s return RADEON_CS_SPACE_OK; } -void +drm_public void radeon_cs_space_add_persistent_bo(struct radeon_cs *cs, struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain) { @@ -209,7 +206,7 @@ again: return 0; } -int +drm_public int radeon_cs_space_check_with_bo(struct radeon_cs *cs, struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain) { @@ -230,13 +227,13 @@ radeon_cs_space_check_with_bo(struct radeon_cs *cs, struct radeon_bo *bo, return ret; } -int radeon_cs_space_check(struct radeon_cs *cs) +drm_public int radeon_cs_space_check(struct radeon_cs *cs) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; return radeon_cs_check_space_internal(csi, NULL); } -void radeon_cs_space_reset_bos(struct radeon_cs *cs) +drm_public void radeon_cs_space_reset_bos(struct radeon_cs *cs) { struct radeon_cs_int *csi = (struct radeon_cs_int *)cs; int i; diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c index 965be24c..ea0a27a9 100644 --- a/radeon/radeon_surface.c +++ b/radeon/radeon_surface.c @@ -26,9 +26,6 @@ * Authors: * Jérôme Glisse <jglisse@redhat.com> */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif #include <stdbool.h> #include <assert.h> #include <errno.h> @@ -2411,7 +2408,7 @@ static int cik_surface_best(struct radeon_surface_manager *surf_man, /* =========================================================================== * public API */ -struct radeon_surface_manager * +drm_public struct radeon_surface_manager * radeon_surface_manager_new(int fd) { struct radeon_surface_manager *surf_man; @@ -2460,7 +2457,7 @@ out_err: return NULL; } -void +drm_public void radeon_surface_manager_free(struct radeon_surface_manager *surf_man) { free(surf_man); @@ -2503,6 +2500,7 @@ static int radeon_surface_sanity(struct radeon_surface_manager *surf_man, if (surf->npix_y > 1) { return -EINVAL; } + /* fallthrough */ case RADEON_SURF_TYPE_2D: if (surf->npix_z > 1) { return -EINVAL; @@ -2533,7 +2531,7 @@ static int radeon_surface_sanity(struct radeon_surface_manager *surf_man, return 0; } -int +drm_public int radeon_surface_init(struct radeon_surface_manager *surf_man, struct radeon_surface *surf) { @@ -2550,7 +2548,7 @@ radeon_surface_init(struct radeon_surface_manager *surf_man, return surf_man->surface_init(surf_man, surf); } -int +drm_public int radeon_surface_best(struct radeon_surface_manager *surf_man, struct radeon_surface *surf) { diff --git a/rockchip/Android.bp b/rockchip/Android.bp deleted file mode 100644 index daceacca..00000000 --- a/rockchip/Android.bp +++ /dev/null @@ -1,13 +0,0 @@ -cc_library_shared { - name: "libdrm_rockchip", - vendor: true, - shared_libs: ["libdrm"], - - srcs: ["rockchip_drm.c"], - - cflags: [ - "-DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1", - "-Wall", - "-Werror", - ], -} diff --git a/rockchip/Makefile.am b/rockchip/Makefile.am deleted file mode 100644 index 2ebb82f1..00000000 --- a/rockchip/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -AM_CFLAGS = \ - $(WARN_CFLAGS) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/rockchip \ - $(PTHREADSTUBS_CFLAGS) \ - -I$(top_srcdir)/include/drm - -libdrm_rockchip_la_LTLIBRARIES = libdrm_rockchip.la -libdrm_rockchip_ladir = $(libdir) -libdrm_rockchip_la_LDFLAGS = -version-number 1:0:0 -no-undefined -libdrm_rockchip_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ - -libdrm_rockchip_la_SOURCES = \ - rockchip_drm.c - -libdrm_rockchipincludedir = ${includedir}/libdrm -libdrm_rockchipinclude_HEADERS = rockchip_drmif.h rockchip_drm.h - -pkgconfigdir = @pkgconfigdir@ -pkgconfig_DATA = libdrm_rockchip.pc diff --git a/rockchip/libdrm_rockchip.pc.in b/rockchip/libdrm_rockchip.pc.in deleted file mode 100644 index 13f22ac7..00000000 --- a/rockchip/libdrm_rockchip.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libdrm_rockchip -Description: Userspace interface to rockchip kernel DRM services -Version: 0.1 -Libs: -L${libdir} -ldrm_rockchip -Cflags: -I${includedir} -I${includedir}/libdrm -Requires.private: libdrm diff --git a/rockchip/rockchip_drm.c b/rockchip/rockchip_drm.c deleted file mode 100644 index 44a78be8..00000000 --- a/rockchip/rockchip_drm.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) ROCKCHIP, Inc. - * Author:yzq<yzq@rock-chips.com> - * - * based on exynos_drm.c - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <sys/mman.h> -#include <linux/stddef.h> - -#include <xf86drm.h> - -#include "rockchip_drm.h" -#include "rockchip_drmif.h" - -/* - * Create rockchip drm device object. - * - * @fd: file descriptor to rockchip drm driver opened. - * - * if true, return the device object else NULL. - */ -struct rockchip_device *rockchip_device_create(int fd) -{ - struct rockchip_device *dev; - - dev = calloc(1, sizeof(*dev)); - if (!dev) { - fprintf(stderr, "failed to create device[%s].\n", - strerror(errno)); - return NULL; - } - - dev->fd = fd; - - return dev; -} - -/* - * Destroy rockchip drm device object - * - * @dev: rockchip drm device object. - */ -void rockchip_device_destroy(struct rockchip_device *dev) -{ - free(dev); -} - -/* - * Create a rockchip buffer object to rockchip drm device. - * - * @dev: rockchip drm device object. - * @size: user-desired size. - * flags: user-desired memory type. - * user can set one or more types among several types to memory - * allocation and cache attribute types. and as default, - * ROCKCHIP_BO_NONCONTIG and ROCKCHIP-BO_NONCACHABLE types would - * be used. - * - * if true, return a rockchip buffer object else NULL. - */ -struct rockchip_bo *rockchip_bo_create(struct rockchip_device *dev, - size_t size, uint32_t flags) -{ - struct rockchip_bo *bo; - struct drm_rockchip_gem_create req = { - .size = size, - .flags = flags, - }; - - if (size == 0) { - fprintf(stderr, "invalid size.\n"); - return NULL; - } - - bo = calloc(1, sizeof(*bo)); - if (!bo) { - fprintf(stderr, "failed to create bo[%s].\n", - strerror(errno)); - goto fail; - } - - bo->dev = dev; - - if (drmIoctl(dev->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &req)){ - fprintf(stderr, "failed to create gem object[%s].\n", - strerror(errno)); - goto err_free_bo; - } - - bo->handle = req.handle; - bo->size = size; - bo->flags = flags; - - return bo; - -err_free_bo: - free(bo); -fail: - return NULL; -} - -struct rockchip_bo *rockchip_bo_from_handle(struct rockchip_device *dev, - uint32_t handle, uint32_t flags, uint32_t size) -{ - struct rockchip_bo *bo; - - if (size == 0) { - fprintf(stderr, "invalid size.\n"); - return NULL; - } - - bo = calloc(1, sizeof(*bo)); - if (!bo) { - fprintf(stderr, "failed to create bo[%s].\n", - strerror(errno)); - return NULL; - } - - bo->dev = dev; - bo->handle = handle; - bo->size = size; - bo->flags = flags; - - return bo; -} - -/* - * Destroy a rockchip buffer object. - * - * @bo: a rockchip buffer object to be destroyed. - */ -void rockchip_bo_destroy(struct rockchip_bo *bo) -{ - if (!bo) - return; - - if (bo->vaddr) - munmap(bo->vaddr, bo->size); - - if (bo->handle) { - struct drm_gem_close req = { - .handle = bo->handle, - }; - - drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); - } - - free(bo); -} - - -/* - * Get a rockchip buffer object from a gem global object name. - * - * @dev: a rockchip device object. - * @name: a gem global object name exported by another process. - * - * this interface is used to get a rockchip buffer object from a gem - * global object name sent by another process for buffer sharing. - * - * if true, return a rockchip buffer object else NULL. - * - */ -struct rockchip_bo *rockchip_bo_from_name(struct rockchip_device *dev, - uint32_t name) -{ - struct rockchip_bo *bo; - struct drm_gem_open req = { - .name = name, - }; - - bo = calloc(1, sizeof(*bo)); - if (!bo) { - fprintf(stderr, "failed to allocate bo[%s].\n", - strerror(errno)); - return NULL; - } - - if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { - fprintf(stderr, "failed to open gem object[%s].\n", - strerror(errno)); - goto err_free_bo; - } - - bo->dev = dev; - bo->name = name; - bo->handle = req.handle; - - return bo; - -err_free_bo: - free(bo); - return NULL; -} - -/* - * Get a gem global object name from a gem object handle. - * - * @bo: a rockchip buffer object including gem handle. - * @name: a gem global object name to be got by kernel driver. - * - * this interface is used to get a gem global object name from a gem object - * handle to a buffer that wants to share it with another process. - * - * if true, return 0 else negative. - */ -int rockchip_bo_get_name(struct rockchip_bo *bo, uint32_t *name) -{ - if (!bo->name) { - struct drm_gem_flink req = { - .handle = bo->handle, - }; - int ret; - - ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); - if (ret) { - fprintf(stderr, "failed to get gem global name[%s].\n", - strerror(errno)); - return ret; - } - - bo->name = req.name; - } - - *name = bo->name; - - return 0; -} - -uint32_t rockchip_bo_handle(struct rockchip_bo *bo) -{ - return bo->handle; -} - -/* - * Mmap a buffer to user space. - * - * @bo: a rockchip buffer object including a gem object handle to be mmapped - * to user space. - * - * if true, user pointer mmaped else NULL. - */ -void *rockchip_bo_map(struct rockchip_bo *bo) -{ - if (!bo->vaddr) { - struct rockchip_device *dev = bo->dev; - struct drm_rockchip_gem_map_off req = { - .handle = bo->handle, - }; - int ret; - - ret = drmIoctl(dev->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &req); - if (ret) { - fprintf(stderr, "failed to ioctl gem map offset[%s].\n", - strerror(errno)); - return NULL; - } - - bo->vaddr = mmap(0, bo->size, PROT_READ | PROT_WRITE, - MAP_SHARED, dev->fd, req.offset); - if (bo->vaddr == MAP_FAILED) { - fprintf(stderr, "failed to mmap buffer[%s].\n", - strerror(errno)); - return NULL; - } - } - - return bo->vaddr; -} diff --git a/rockchip/rockchip_drm.h b/rockchip/rockchip_drm.h deleted file mode 100644 index 13977d59..00000000 --- a/rockchip/rockchip_drm.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) Fuzhou Rockchip Electronics Co.Ltd - * Authors: - * Mark Yao <yzq@rock-chips.com> - * - * based on exynos_drm.h - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef _ROCKCHIP_DRM_H_ -#define _ROCKCHIP_DRM_H_ - -#include <stdint.h> -#include "drm.h" - -/** - * User-desired buffer creation information structure. - * - * @size: user-desired memory allocation size. - * - this size value would be page-aligned internally. - * @flags: user request for setting memory type or cache attributes. - * @handle: returned a handle to created gem object. - * - this handle will be set by gem module of kernel side. - */ -struct drm_rockchip_gem_create { - uint64_t size; - uint32_t flags; - uint32_t handle; -}; - -/** - * A structure for getting buffer offset. - * - * @handle: a pointer to gem object created. - * @pad: just padding to be 64-bit aligned. - * @offset: relatived offset value of the memory region allocated. - * - this value should be set by user. - */ -struct drm_rockchip_gem_map_off { - uint32_t handle; - uint32_t pad; - uint64_t offset; -}; - -#define DRM_ROCKCHIP_GEM_CREATE 0x00 -#define DRM_ROCKCHIP_GEM_MAP_OFFSET 0x01 - -#define DRM_IOCTL_ROCKCHIP_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ - DRM_ROCKCHIP_GEM_CREATE, struct drm_rockchip_gem_create) - -#define DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + \ - DRM_ROCKCHIP_GEM_MAP_OFFSET, struct drm_rockchip_gem_map_off) - -#endif diff --git a/rockchip/rockchip_drmif.h b/rockchip/rockchip_drmif.h deleted file mode 100644 index 5c549a05..00000000 --- a/rockchip/rockchip_drmif.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) ROCKCHIP, Inc. - * Author:yzq<yzq@rock-chips.com> - * - * based on exynos_drmif.h - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef ROCKCHIP_DRMIF_H_ -#define ROCKCHIP_DRMIF_H_ - -#include <xf86drm.h> -#include <stdint.h> -#include "rockchip_drm.h" - -struct rockchip_device { - int fd; -}; - -/* - * Rockchip Buffer Object structure. - * - * @dev: rockchip device object allocated. - * @handle: a gem handle to gem object created. - * @flags: indicate memory allocation and cache attribute types. - * @size: size to the buffer created. - * @vaddr: user space address to a gem buffer mmaped. - * @name: a gem global handle from flink request. - */ -struct rockchip_bo { - struct rockchip_device *dev; - uint32_t handle; - uint32_t flags; - size_t size; - void *vaddr; - uint32_t name; -}; - -/* - * device related functions: - */ -struct rockchip_device *rockchip_device_create(int fd); -void rockchip_device_destroy(struct rockchip_device *dev); - -/* - * buffer-object related functions: - */ -struct rockchip_bo *rockchip_bo_create(struct rockchip_device *dev, - size_t size, uint32_t flags); -int rockchip_bo_get_info(struct rockchip_device *dev, uint32_t handle, - size_t *size, uint32_t *flags); -void rockchip_bo_destroy(struct rockchip_bo *bo); -struct rockchip_bo *rockchip_bo_from_name(struct rockchip_device *dev, - uint32_t name); -int rockchip_bo_get_name(struct rockchip_bo *bo, uint32_t *name); -uint32_t rockchip_bo_handle(struct rockchip_bo *bo); -struct rockchip_bo *rockchip_bo_from_handle(struct rockchip_device *dev, - uint32_t handle, uint32_t flags, uint32_t size); -void *rockchip_bo_map(struct rockchip_bo *bo); -#endif /* ROCKCHIP_DRMIF_H_ */ diff --git a/tegra/Makefile.am b/tegra/Makefile.am index fb40be55..53119970 100644 --- a/tegra/Makefile.am +++ b/tegra/Makefile.am @@ -4,7 +4,8 @@ AM_CPPFLAGS = \ AM_CFLAGS = \ @PTHREADSTUBS_CFLAGS@ \ - $(WARN_CFLAGS) + $(WARN_CFLAGS) \ + -fvisibility=hidden libdrm_tegra_ladir = $(libdir) libdrm_tegra_la_LTLIBRARIES = libdrm_tegra.la @@ -21,5 +22,6 @@ libdrm_tegrainclude_HEADERS = tegra.h pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm_tegra.pc +AM_TESTS_ENVIRONMENT = NM='$(NM)' TESTS = tegra-symbol-check EXTRA_DIST = $(TESTS) diff --git a/tegra/meson.build b/tegra/meson.build new file mode 100644 index 00000000..4bc454b6 --- /dev/null +++ b/tegra/meson.build @@ -0,0 +1,53 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libdrm_tegra = shared_library( + 'drm_tegra', + [files('tegra.c'), config_file], + include_directories : [inc_root, inc_drm], + link_with : libdrm, + dependencies : [dep_pthread_stubs, dep_atomic_ops], + c_args : libdrm_c_args, + version : '0.0.0', + install : true, +) + +ext_libdrm_tegra = declare_dependency( + link_with : [libdrm, libdrm_tegra], + include_directories : [inc_drm, include_directories('.')], +) + +install_headers('tegra.h', subdir : 'libdrm') + +pkg.generate( + name : 'libdrm_tegra', + libraries : libdrm_tegra, + subdirs : ['.', 'libdrm'], + version : meson.project_version(), + requires_private : 'libdrm', + description : 'Userspace interface to Tegra kernel DRM services', +) + +test( + 'tegra-symbol-check', + prog_bash, + env : env_test, + args : [files('tegra-symbol-check'), libdrm_tegra] +) diff --git a/tegra/private.h b/tegra/private.h index 571caa56..bb6c1a51 100644 --- a/tegra/private.h +++ b/tegra/private.h @@ -41,10 +41,9 @@ struct drm_tegra { struct drm_tegra_bo { struct drm_tegra *drm; uint32_t handle; - uint64_t offset; + uint32_t offset; uint32_t flags; uint32_t size; - uint32_t name; atomic_t ref; void *map; }; diff --git a/tegra/tegra-symbol-check b/tegra/tegra-symbol-check index 40208311..8539b95b 100755 --- a/tegra/tegra-symbol-check +++ b/tegra/tegra-symbol-check @@ -1,11 +1,16 @@ #!/bin/bash -# The following symbols (past the first five) are taken from the public headers. -# A list of the latter should be available Makefile.sources/LIBDRM_FREEDRENO_H_FILES +set -u -FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_tegra.so} | awk '{print $3}'| while read func; do +# The following symbols (past the first nine) are taken from tegra.h. + +FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_tegra.so} | awk '{print $3}'| while read func; do ( grep -q "^$func$" || echo $func ) <<EOF +__bss_end__ +__bss_start__ __bss_start +__end__ +_bss_end__ _edata _end _fini diff --git a/tegra/tegra.c b/tegra/tegra.c index 66f19e96..cf00a3ca 100644 --- a/tegra/tegra.c +++ b/tegra/tegra.c @@ -22,10 +22,6 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include <errno.h> #include <fcntl.h> #include <string.h> @@ -74,7 +70,7 @@ static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close) return 0; } -int drm_tegra_new(struct drm_tegra **drmp, int fd) +drm_public int drm_tegra_new(struct drm_tegra **drmp, int fd) { bool supported = false; drmVersionPtr version; @@ -94,7 +90,7 @@ int drm_tegra_new(struct drm_tegra **drmp, int fd) return drm_tegra_wrap(drmp, fd, false); } -void drm_tegra_close(struct drm_tegra *drm) +drm_public void drm_tegra_close(struct drm_tegra *drm) { if (!drm) return; @@ -105,7 +101,7 @@ void drm_tegra_close(struct drm_tegra *drm) free(drm); } -int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, +drm_public int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, uint32_t flags, uint32_t size) { struct drm_tegra_gem_create args; @@ -143,7 +139,7 @@ int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, return 0; } -int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, +drm_public int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, uint32_t handle, uint32_t flags, uint32_t size) { struct drm_tegra_bo *bo; @@ -166,62 +162,7 @@ int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, return 0; } -int drm_tegra_bo_name_ref(struct drm_tegra *drm, uint32_t name, uint32_t size, - struct drm_tegra_bo **bop) -{ - struct drm_tegra_bo *bo; - struct drm_gem_open open_args; - struct drm_gem_close close_args; - int ret; - - memset(&open_args, 0, sizeof(open_args)); - - open_args.name = name; - - ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &open_args); - if (ret) - return ret; - - ret = drm_tegra_bo_wrap(bop, drm, open_args.handle, 0, size); - if (ret) - goto err; - - (*bop)->name = name; - - return 0; - -err: - memset(&close_args, 0, sizeof(close_args)); - close_args.handle = open_args.handle; - drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &close_args); - - return ret; -} - -int drm_tegra_bo_name_get(struct drm_tegra_bo *bo, uint32_t *name) -{ - struct drm_gem_flink args; - int ret; - - args.handle = bo->handle; - - *name = bo->name; - if (*name && *name != ~0U) - return 0; - - ret = drmIoctl(bo->drm->fd, DRM_IOCTL_GEM_FLINK, &args); - if (ret) { - *name = 0; - return ret; - } - - bo->name = args.name; - *name = bo->name; - - return 0; -} - -struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo) +drm_public struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo) { if (bo) atomic_inc(&bo->ref); @@ -229,13 +170,13 @@ struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo) return bo; } -void drm_tegra_bo_unref(struct drm_tegra_bo *bo) +drm_public void drm_tegra_bo_unref(struct drm_tegra_bo *bo) { if (bo && atomic_dec_and_test(&bo->ref)) drm_tegra_bo_free(bo); } -int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle) +drm_public int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle) { if (!bo || !handle) return -EINVAL; @@ -245,7 +186,7 @@ int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle) return 0; } -int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr) +drm_public int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr) { struct drm_tegra *drm = bo->drm; @@ -277,7 +218,7 @@ int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr) return 0; } -int drm_tegra_bo_unmap(struct drm_tegra_bo *bo) +drm_public int drm_tegra_bo_unmap(struct drm_tegra_bo *bo) { if (!bo) return -EINVAL; @@ -293,7 +234,7 @@ int drm_tegra_bo_unmap(struct drm_tegra_bo *bo) return 0; } -int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags) +drm_public int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags) { struct drm_tegra_gem_get_flags args; struct drm_tegra *drm = bo->drm; @@ -316,7 +257,7 @@ int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags) return 0; } -int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags) +drm_public int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags) { struct drm_tegra_gem_get_flags args; struct drm_tegra *drm = bo->drm; @@ -337,7 +278,7 @@ int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags) return 0; } -int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo, +drm_public int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo, struct drm_tegra_bo_tiling *tiling) { struct drm_tegra_gem_get_tiling args; @@ -363,7 +304,7 @@ int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo, return 0; } -int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo, +drm_public int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo, const struct drm_tegra_bo_tiling *tiling) { struct drm_tegra_gem_set_tiling args; diff --git a/tegra/tegra.h b/tegra/tegra.h index e10eab71..31b0995a 100644 --- a/tegra/tegra.h +++ b/tegra/tegra.h @@ -38,11 +38,6 @@ int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, uint32_t flags, uint32_t size); int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, uint32_t handle, uint32_t flags, uint32_t size); - -int drm_tegra_bo_name_ref(struct drm_tegra *drm, uint32_t name, uint32_t size, - struct drm_tegra_bo **bop); -int drm_tegra_bo_name_get(struct drm_tegra_bo *bo, uint32_t *name); - struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo); void drm_tegra_bo_unref(struct drm_tegra_bo *bo); int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle); diff --git a/tests/Makefile.am b/tests/Makefile.am index f2bb4d44..d274a3e9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS = util kms modeprint proptest modetest vbltest if HAVE_LIBKMS -SUBDIRS += kmstest planetest +SUBDIRS += kmstest endif if HAVE_RADEON @@ -32,6 +32,7 @@ endif AM_CFLAGS = \ $(WARN_CFLAGS)\ + -fvisibility=hidden \ -I $(top_srcdir)/include/drm \ -I $(top_srcdir) @@ -43,5 +44,10 @@ TESTS = \ random check_PROGRAMS = \ - $(TESTS) \ - drmdevice + $(TESTS) + +if HAVE_INSTALL_TESTS +bin_PROGRAMS = drmdevice +else +check_PROGRAMS += drmdevice +endif diff --git a/tests/amdgpu/.editorconfig b/tests/amdgpu/.editorconfig new file mode 120000 index 00000000..70734e42 --- /dev/null +++ b/tests/amdgpu/.editorconfig @@ -0,0 +1 @@ +../../amdgpu/.editorconfig
\ No newline at end of file diff --git a/tests/amdgpu/Makefile.am b/tests/amdgpu/Makefile.am index c1c3a32e..447ff217 100644 --- a/tests/amdgpu/Makefile.am +++ b/tests/amdgpu/Makefile.am @@ -1,7 +1,9 @@ AM_CFLAGS = \ + -fvisibility=hidden \ -I $(top_srcdir)/include/drm \ -I $(top_srcdir)/amdgpu \ - -I $(top_srcdir) + -I $(top_srcdir) \ + -pthread LDADD = $(top_builddir)/libdrm.la \ $(top_builddir)/amdgpu/libdrm_amdgpu.la \ @@ -23,7 +25,12 @@ amdgpu_test_SOURCES = \ basic_tests.c \ bo_tests.c \ cs_tests.c \ - uvd_messages.h \ + decode_messages.h \ vce_tests.c \ vce_ib.h \ - frame.h + frame.h \ + uvd_enc_tests.c \ + vcn_tests.c \ + uve_ib.h \ + deadlock_tests.c \ + vm_tests.c diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c index 3fd6820a..ebf44098 100644 --- a/tests/amdgpu/amdgpu_test.c +++ b/tests/amdgpu/amdgpu_test.c @@ -21,10 +21,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -49,6 +45,17 @@ #include "CUnit/Basic.h" #include "amdgpu_test.h" +#include "amdgpu_internal.h" + +/* Test suite names */ +#define BASIC_TESTS_STR "Basic Tests" +#define BO_TESTS_STR "BO Tests" +#define CS_TESTS_STR "CS Tests" +#define VCE_TESTS_STR "VCE Tests" +#define VCN_TESTS_STR "VCN Tests" +#define UVD_ENC_TESTS_STR "UVD ENC Tests" +#define DEADLOCK_TESTS_STR "Deadlock Tests" +#define VM_TESTS_STR "VM Tests" /** * Open handles for amdgpu devices @@ -62,49 +69,150 @@ int open_render_node = 0; /* By default run most tests on primary node */ /** The table of all known test suites to run */ static CU_SuiteInfo suites[] = { { - .pName = "Basic Tests", + .pName = BASIC_TESTS_STR, .pInitFunc = suite_basic_tests_init, .pCleanupFunc = suite_basic_tests_clean, .pTests = basic_tests, }, { - .pName = "BO Tests", + .pName = BO_TESTS_STR, .pInitFunc = suite_bo_tests_init, .pCleanupFunc = suite_bo_tests_clean, .pTests = bo_tests, }, { - .pName = "CS Tests", + .pName = CS_TESTS_STR, .pInitFunc = suite_cs_tests_init, .pCleanupFunc = suite_cs_tests_clean, .pTests = cs_tests, }, { - .pName = "VCE Tests", + .pName = VCE_TESTS_STR, .pInitFunc = suite_vce_tests_init, .pCleanupFunc = suite_vce_tests_clean, .pTests = vce_tests, }, + { + .pName = VCN_TESTS_STR, + .pInitFunc = suite_vcn_tests_init, + .pCleanupFunc = suite_vcn_tests_clean, + .pTests = vcn_tests, + }, + { + .pName = UVD_ENC_TESTS_STR, + .pInitFunc = suite_uvd_enc_tests_init, + .pCleanupFunc = suite_uvd_enc_tests_clean, + .pTests = uvd_enc_tests, + }, + { + .pName = DEADLOCK_TESTS_STR, + .pInitFunc = suite_deadlock_tests_init, + .pCleanupFunc = suite_deadlock_tests_clean, + .pTests = deadlock_tests, + }, + { + .pName = VM_TESTS_STR, + .pInitFunc = suite_vm_tests_init, + .pCleanupFunc = suite_vm_tests_clean, + .pTests = vm_tests, + }, + CU_SUITE_INFO_NULL, }; +typedef CU_BOOL (*active__stat_func)(void); -/** Display information about all suites and their tests */ +typedef struct Suites_Active_Status { + char* pName; + active__stat_func pActive; +}Suites_Active_Status; + +static CU_BOOL always_active() +{ + return CU_TRUE; +} + +static Suites_Active_Status suites_active_stat[] = { + { + .pName = BASIC_TESTS_STR, + .pActive = always_active, + }, + { + .pName = BO_TESTS_STR, + .pActive = always_active, + }, + { + .pName = CS_TESTS_STR, + .pActive = suite_cs_tests_enable, + }, + { + .pName = VCE_TESTS_STR, + .pActive = suite_vce_tests_enable, + }, + { + .pName = VCN_TESTS_STR, + .pActive = suite_vcn_tests_enable, + }, + { + .pName = UVD_ENC_TESTS_STR, + .pActive = suite_uvd_enc_tests_enable, + }, + { + .pName = DEADLOCK_TESTS_STR, + .pActive = suite_deadlock_tests_enable, + }, + { + .pName = VM_TESTS_STR, + .pActive = suite_vm_tests_enable, + }, +}; + + +/* + * Display information about all suites and their tests + * + * NOTE: Must be run after registry is initialized and suites registered. + */ static void display_test_suites(void) { int iSuite; int iTest; + CU_pSuite pSuite = NULL; + CU_pTest pTest = NULL; printf("Suites\n"); for (iSuite = 0; suites[iSuite].pName != NULL; iSuite++) { - printf("Suite id = %d: Name '%s'\n", - iSuite + 1, suites[iSuite].pName); + + pSuite = CU_get_suite_by_index((unsigned int) iSuite + 1, + CU_get_registry()); + + if (!pSuite) { + fprintf(stderr, "Invalid suite id : %d\n", iSuite + 1); + continue; + } + + printf("Suite id = %d: Name '%s status: %s'\n", + iSuite + 1, suites[iSuite].pName, + pSuite->fActive ? "ENABLED" : "DISABLED"); + + for (iTest = 0; suites[iSuite].pTests[iTest].pName != NULL; iTest++) { - printf(" Test id %d: Name: '%s'\n", iTest + 1, - suites[iSuite].pTests[iTest].pName); + + pTest = CU_get_test_by_index((unsigned int) iTest + 1, + pSuite); + + if (!pTest) { + fprintf(stderr, "Invalid test id : %d\n", iTest + 1); + continue; + } + + printf("Test id %d: Name: '%s status: %s'\n", iTest + 1, + suites[iSuite].pTests[iTest].pName, + pSuite->fActive && pTest->fActive ? + "ENABLED" : "DISABLED"); } } } @@ -112,7 +220,7 @@ static void display_test_suites(void) /** Help string for command line parameters */ static const char usage[] = - "Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>]] " + "Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>] [-f]] " "[-b <pci_bus_id> [-d <pci_device_id>]]\n" "where:\n" " l - Display all suites and their tests\n" @@ -120,9 +228,10 @@ static const char usage[] = " b - Specify device's PCI bus id to run tests\n" " d - Specify device's PCI device id to run tests (optional)\n" " p - Display information of AMDGPU devices in system\n" + " f - Force executing inactive suite or test\n" " h - Display this help\n"; /** Specified options strings for getopt */ -static const char options[] = "hlrps:t:b:d:"; +static const char options[] = "hlrps:t:b:d:f"; /* Open AMD devices. * Return the number of AMD device openned. @@ -130,7 +239,6 @@ static const char options[] = "hlrps:t:b:d:"; static int amdgpu_open_devices(int open_render_node) { drmDevicePtr devices[MAX_CARDS_SUPPORTED]; - int ret; int i; int drm_node; int amd_index = 0; @@ -264,29 +372,72 @@ static void amdgpu_print_devices() /* Find a match AMD device in PCI bus * Return the index of the device or -1 if not found */ -static int amdgpu_find_device(uint8_t bus, uint8_t dev) +static int amdgpu_find_device(uint8_t bus, uint16_t dev) { int i; drmDevicePtr device; - for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++) + for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) { if (drmGetDevice2(drm_amdgpu[i], DRM_DEVICE_GET_PCI_REVISION, &device) == 0) { if (device->bustype == DRM_BUS_PCI) - if (device->businfo.pci->bus == bus && - device->businfo.pci->dev == dev) { - + if ((bus == 0xFF || device->businfo.pci->bus == bus) && + device->deviceinfo.pci->device_id == dev) { drmFreeDevice(&device); return i; } drmFreeDevice(&device); } + } return -1; } +static void amdgpu_disable_suites() +{ + amdgpu_device_handle device_handle; + uint32_t major_version, minor_version, family_id; + int i; + int size = sizeof(suites_active_stat) / sizeof(suites_active_stat[0]); + + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return; + + family_id = device_handle->info.family_id; + + if (amdgpu_device_deinitialize(device_handle)) + return; + + /* Set active status for suites based on their policies */ + for (i = 0; i < size; ++i) + if (amdgpu_set_suite_active(suites_active_stat[i].pName, + suites_active_stat[i].pActive())) + fprintf(stderr, "suite deactivation failed - %s\n", CU_get_error_msg()); + + /* Explicitly disable specific tests due to known bugs or preferences */ + /* + * BUG: Compute ring stalls and never recovers when the address is + * written after the command already submitted + */ + if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, + "compute ring block test (set amdgpu.lockup_timeout=50)", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + if (amdgpu_set_test_active(BASIC_TESTS_STR, "bo eviction Test", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); + + /* This test was ran on GFX8 and GFX9 only */ + if (family_id < AMDGPU_FAMILY_VI || family_id > AMDGPU_FAMILY_RV) + if (amdgpu_set_test_active(BASIC_TESTS_STR, "Sync dependency Test", CU_FALSE)) + fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); +} + /* The main() function for setting up and running the tests. * Returns a CUE_SUCCESS on successful running, another * CUnit error code on failure. @@ -303,6 +454,8 @@ int main(int argc, char **argv) CU_pSuite pSuite = NULL; CU_pTest pTest = NULL; int test_device_index; + int display_list = 0; + int force_run = 0; for (i = 0; i < MAX_CARDS_SUPPORTED; i++) drm_amdgpu[i] = -1; @@ -313,8 +466,8 @@ int main(int argc, char **argv) while ((c = getopt(argc, argv, options)) != -1) { switch (c) { case 'l': - display_test_suites(); - exit(EXIT_SUCCESS); + display_list = 1; + break; case 's': suite_id = atoi(optarg); break; @@ -325,7 +478,7 @@ int main(int argc, char **argv) pci_bus_id = atoi(optarg); break; case 'd': - pci_device_id = atoi(optarg); + sscanf(optarg, "%x", &pci_device_id); break; case 'p': display_devices = 1; @@ -333,6 +486,9 @@ int main(int argc, char **argv) case 'r': open_render_node = 1; break; + case 'f': + force_run = 1; + break; case '?': case 'h': fprintf(stderr, usage, argv[0]); @@ -359,10 +515,10 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); } - if (pci_bus_id > 0) { + if (pci_bus_id > 0 || pci_device_id) { /* A device was specified to run the test */ - test_device_index = amdgpu_find_device((uint8_t)pci_bus_id, - (uint8_t)pci_device_id); + test_device_index = amdgpu_find_device(pci_bus_id, + pci_device_id); if (test_device_index >= 0) { /* Most tests run on device of drm_amdgpu[0]. @@ -398,17 +554,33 @@ int main(int argc, char **argv) /* Run tests using the CUnit Basic interface */ CU_basic_set_mode(CU_BRM_VERBOSE); + /* Disable suites and individual tests based on misc. conditions */ + amdgpu_disable_suites(); + + if (display_list) { + display_test_suites(); + goto end; + } + if (suite_id != -1) { /* If user specify particular suite? */ pSuite = CU_get_suite_by_index((unsigned int) suite_id, CU_get_registry()); if (pSuite) { + + if (force_run) + CU_set_suite_active(pSuite, CU_TRUE); + if (test_id != -1) { /* If user specify test id */ pTest = CU_get_test_by_index( (unsigned int) test_id, pSuite); - if (pTest) + if (pTest) { + if (force_run) + CU_set_test_active(pTest, CU_TRUE); + CU_basic_run_test(pSuite, pTest); + } else { fprintf(stderr, "Invalid test id: %d\n", test_id); @@ -428,6 +600,7 @@ int main(int argc, char **argv) } else CU_basic_run_tests(); +end: CU_cleanup_registry(); amdgpu_close_devices(); return CU_get_error(); diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h index e30e2312..af81eea8 100644 --- a/tests/amdgpu/amdgpu_test.h +++ b/tests/amdgpu/amdgpu_test.h @@ -30,7 +30,7 @@ /** * Define max. number of card in system which we are able to handle */ -#define MAX_CARDS_SUPPORTED 4 +#define MAX_CARDS_SUPPORTED 128 /* Forward reference for array to keep "drm" handles */ extern int drm_amdgpu[MAX_CARDS_SUPPORTED]; @@ -85,6 +85,11 @@ int suite_cs_tests_init(); int suite_cs_tests_clean(); /** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_cs_tests_enable(void); + +/** * Tests in cs test suite */ extern CU_TestInfo cs_tests[]; @@ -100,11 +105,96 @@ int suite_vce_tests_init(); int suite_vce_tests_clean(); /** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_vce_tests_enable(void); + +/** * Tests in vce test suite */ extern CU_TestInfo vce_tests[]; /** ++ * Initialize vcn test suite ++ */ +int suite_vcn_tests_init(); + +/** ++ * Deinitialize vcn test suite ++ */ +int suite_vcn_tests_clean(); + +/** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_vcn_tests_enable(void); + +/** ++ * Tests in vcn test suite ++ */ +extern CU_TestInfo vcn_tests[]; + +/** + * Initialize uvd enc test suite + */ +int suite_uvd_enc_tests_init(); + +/** + * Deinitialize uvd enc test suite + */ +int suite_uvd_enc_tests_clean(); + +/** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_uvd_enc_tests_enable(void); + +/** + * Tests in uvd enc test suite + */ +extern CU_TestInfo uvd_enc_tests[]; + +/** + * Initialize deadlock test suite + */ +int suite_deadlock_tests_init(); + +/** + * Deinitialize deadlock test suite + */ +int suite_deadlock_tests_clean(); + +/** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_deadlock_tests_enable(void); + +/** + * Tests in uvd enc test suite + */ +extern CU_TestInfo deadlock_tests[]; + +/** + * Initialize vm test suite + */ +int suite_vm_tests_init(); + +/** + * Deinitialize deadlock test suite + */ +int suite_vm_tests_clean(); + +/** + * Decide if the suite is enabled by default or not. + */ +CU_BOOL suite_vm_tests_enable(void); + +/** + * Tests in vm test suite + */ +extern CU_TestInfo vm_tests[]; + +/** * Helper functions */ static inline amdgpu_bo_handle gpu_mem_alloc( @@ -117,11 +207,9 @@ static inline amdgpu_bo_handle gpu_mem_alloc( amdgpu_va_handle *va_handle) { struct amdgpu_bo_alloc_request req = {0}; - amdgpu_bo_handle buf_handle; + amdgpu_bo_handle buf_handle = NULL; int r; - CU_ASSERT_NOT_EQUAL(vmc_addr, NULL); - req.alloc_size = size; req.phys_alignment = alignment; req.preferred_heap = type; @@ -129,17 +217,36 @@ static inline amdgpu_bo_handle gpu_mem_alloc( r = amdgpu_bo_alloc(device_handle, &req, &buf_handle); CU_ASSERT_EQUAL(r, 0); + if (r) + return NULL; + + if (vmc_addr && va_handle) { + r = amdgpu_va_range_alloc(device_handle, + amdgpu_gpu_va_range_general, + size, alignment, 0, vmc_addr, + va_handle, 0); + CU_ASSERT_EQUAL(r, 0); + if (r) + goto error_free_bo; + + r = amdgpu_bo_va_op(buf_handle, 0, size, *vmc_addr, 0, + AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + if (r) + goto error_free_va; + } + + return buf_handle; - r = amdgpu_va_range_alloc(device_handle, - amdgpu_gpu_va_range_general, - size, alignment, 0, vmc_addr, - va_handle, 0); +error_free_va: + r = amdgpu_va_range_free(*va_handle); CU_ASSERT_EQUAL(r, 0); - r = amdgpu_bo_va_op(buf_handle, 0, size, *vmc_addr, 0, AMDGPU_VA_OP_MAP); +error_free_bo: + r = amdgpu_bo_free(buf_handle); CU_ASSERT_EQUAL(r, 0); - return buf_handle; + return NULL; } static inline int gpu_mem_free(amdgpu_bo_handle bo, @@ -149,28 +256,35 @@ static inline int gpu_mem_free(amdgpu_bo_handle bo, { int r; - r = amdgpu_bo_va_op(bo, 0, size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP); - CU_ASSERT_EQUAL(r, 0); + if (!bo) + return 0; - r = amdgpu_va_range_free(va_handle); - CU_ASSERT_EQUAL(r, 0); + if (va_handle) { + r = amdgpu_bo_va_op(bo, 0, size, vmc_addr, 0, + AMDGPU_VA_OP_UNMAP); + CU_ASSERT_EQUAL(r, 0); + if (r) + return r; + + r = amdgpu_va_range_free(va_handle); + CU_ASSERT_EQUAL(r, 0); + if (r) + return r; + } r = amdgpu_bo_free(bo); CU_ASSERT_EQUAL(r, 0); - return 0; + return r; } static inline int -amdgpu_bo_alloc_and_map(amdgpu_device_handle dev, unsigned size, - unsigned alignment, unsigned heap, uint64_t flags, - amdgpu_bo_handle *bo, void **cpu, uint64_t *mc_address, - amdgpu_va_handle *va_handle) +amdgpu_bo_alloc_wrap(amdgpu_device_handle dev, unsigned size, + unsigned alignment, unsigned heap, uint64_t flags, + amdgpu_bo_handle *bo) { struct amdgpu_bo_alloc_request request = {}; amdgpu_bo_handle buf_handle; - amdgpu_va_handle handle; - uint64_t vmc_addr; int r; request.alloc_size = size; @@ -182,36 +296,25 @@ amdgpu_bo_alloc_and_map(amdgpu_device_handle dev, unsigned size, if (r) return r; - r = amdgpu_va_range_alloc(dev, - amdgpu_gpu_va_range_general, - size, alignment, 0, &vmc_addr, - &handle, 0); - if (r) - goto error_va_alloc; - - r = amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr, 0, AMDGPU_VA_OP_MAP); - if (r) - goto error_va_map; - - r = amdgpu_bo_cpu_map(buf_handle, cpu); - if (r) - goto error_cpu_map; - *bo = buf_handle; - *mc_address = vmc_addr; - *va_handle = handle; return 0; +} -error_cpu_map: - amdgpu_bo_cpu_unmap(buf_handle); - -error_va_map: - amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP); +int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, + unsigned alignment, unsigned heap, uint64_t alloc_flags, + uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu, + uint64_t *mc_address, + amdgpu_va_handle *va_handle); -error_va_alloc: - amdgpu_bo_free(buf_handle); - return r; +static inline int +amdgpu_bo_alloc_and_map(amdgpu_device_handle dev, unsigned size, + unsigned alignment, unsigned heap, uint64_t alloc_flags, + amdgpu_bo_handle *bo, void **cpu, uint64_t *mc_address, + amdgpu_va_handle *va_handle) +{ + return amdgpu_bo_alloc_and_map_raw(dev, size, alignment, heap, + alloc_flags, 0, bo, cpu, mc_address, va_handle); } static inline int @@ -236,4 +339,35 @@ amdgpu_get_bo_list(amdgpu_device_handle dev, amdgpu_bo_handle bo1, return amdgpu_bo_list_create(dev, bo2 ? 2 : 1, resources, NULL, list); } + +static inline CU_ErrorCode amdgpu_set_suite_active(const char *suite_name, + CU_BOOL active) +{ + CU_ErrorCode r = CU_set_suite_active(CU_get_suite(suite_name), active); + + if (r != CUE_SUCCESS) + fprintf(stderr, "Failed to obtain suite %s\n", suite_name); + + return r; +} + +static inline CU_ErrorCode amdgpu_set_test_active(const char *suite_name, + const char *test_name, CU_BOOL active) +{ + CU_ErrorCode r; + CU_pSuite pSuite = CU_get_suite(suite_name); + + if (!pSuite) { + fprintf(stderr, "Failed to obtain suite %s\n", + suite_name); + return CUE_NOSUITE; + } + + r = CU_set_test_active(CU_get_test(pSuite, test_name), active); + if (r != CUE_SUCCESS) + fprintf(stderr, "Failed to obtain test %s\n", test_name); + + return r; +} + #endif /* #ifdef _AMDGPU_TEST_H_ */ diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c index bfda21b1..dbae4d53 100644 --- a/tests/amdgpu/basic_tests.c +++ b/tests/amdgpu/basic_tests.c @@ -21,46 +21,55 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdio.h> #include <stdlib.h> #include <unistd.h> #ifdef HAVE_ALLOCA_H # include <alloca.h> #endif +#include <sys/wait.h> #include "CUnit/Basic.h" #include "amdgpu_test.h" #include "amdgpu_drm.h" +#include "util_math.h" static amdgpu_device_handle device_handle; static uint32_t major_version; static uint32_t minor_version; +static uint32_t family_id; static void amdgpu_query_info_test(void); -static void amdgpu_memory_alloc(void); static void amdgpu_command_submission_gfx(void); static void amdgpu_command_submission_compute(void); +static void amdgpu_command_submission_multi_fence(void); static void amdgpu_command_submission_sdma(void); static void amdgpu_userptr_test(void); static void amdgpu_semaphore_test(void); +static void amdgpu_sync_dependency_test(void); +static void amdgpu_bo_eviction_test(void); static void amdgpu_command_submission_write_linear_helper(unsigned ip_type); static void amdgpu_command_submission_const_fill_helper(unsigned ip_type); static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type); - +static void amdgpu_test_exec_cs_helper(amdgpu_context_handle context_handle, + unsigned ip_type, + int instance, int pm4_dw, uint32_t *pm4_src, + int res_cnt, amdgpu_bo_handle *resources, + struct amdgpu_cs_ib_info *ib_info, + struct amdgpu_cs_request *ibs_request); + CU_TestInfo basic_tests[] = { { "Query Info Test", amdgpu_query_info_test }, - { "Memory alloc Test", amdgpu_memory_alloc }, { "Userptr Test", amdgpu_userptr_test }, + { "bo eviction Test", amdgpu_bo_eviction_test }, { "Command submission Test (GFX)", amdgpu_command_submission_gfx }, { "Command submission Test (Compute)", amdgpu_command_submission_compute }, + { "Command submission Test (Multi-Fence)", amdgpu_command_submission_multi_fence }, { "Command submission Test (SDMA)", amdgpu_command_submission_sdma }, { "SW semaphore Test", amdgpu_semaphore_test }, + { "Sync dependency Test", amdgpu_sync_dependency_test }, CU_TEST_INFO_NULL, }; #define BUFFER_SIZE (8 * 1024) @@ -197,22 +206,170 @@ CU_TestInfo basic_tests[] = { # define PACKET3_DMA_DATA_CMD_DAIC (1 << 29) # define PACKET3_DMA_DATA_CMD_RAW_WAIT (1 << 30) +#define SDMA_PACKET_SI(op, b, t, s, cnt) ((((op) & 0xF) << 28) | \ + (((b) & 0x1) << 26) | \ + (((t) & 0x1) << 23) | \ + (((s) & 0x1) << 22) | \ + (((cnt) & 0xFFFFF) << 0)) +#define SDMA_OPCODE_COPY_SI 3 +#define SDMA_OPCODE_CONSTANT_FILL_SI 13 +#define SDMA_NOP_SI 0xf +#define GFX_COMPUTE_NOP_SI 0x80000000 +#define PACKET3_DMA_DATA_SI 0x41 +# define PACKET3_DMA_DATA_SI_ENGINE(x) ((x) << 27) + /* 0 - ME + * 1 - PFP + */ +# define PACKET3_DMA_DATA_SI_DST_SEL(x) ((x) << 20) + /* 0 - DST_ADDR using DAS + * 1 - GDS + * 3 - DST_ADDR using L2 + */ +# define PACKET3_DMA_DATA_SI_SRC_SEL(x) ((x) << 29) + /* 0 - SRC_ADDR using SAS + * 1 - GDS + * 2 - DATA + * 3 - SRC_ADDR using L2 + */ +# define PACKET3_DMA_DATA_SI_CP_SYNC (1 << 31) + + +#define PKT3_CONTEXT_CONTROL 0x28 +#define CONTEXT_CONTROL_LOAD_ENABLE(x) (((unsigned)(x) & 0x1) << 31) +#define CONTEXT_CONTROL_LOAD_CE_RAM(x) (((unsigned)(x) & 0x1) << 28) +#define CONTEXT_CONTROL_SHADOW_ENABLE(x) (((unsigned)(x) & 0x1) << 31) + +#define PKT3_CLEAR_STATE 0x12 + +#define PKT3_SET_SH_REG 0x76 +#define PACKET3_SET_SH_REG_START 0x00002c00 + +#define PACKET3_DISPATCH_DIRECT 0x15 + + +/* gfx 8 */ +#define mmCOMPUTE_PGM_LO 0x2e0c +#define mmCOMPUTE_PGM_RSRC1 0x2e12 +#define mmCOMPUTE_TMPRING_SIZE 0x2e18 +#define mmCOMPUTE_USER_DATA_0 0x2e40 +#define mmCOMPUTE_USER_DATA_1 0x2e41 +#define mmCOMPUTE_RESOURCE_LIMITS 0x2e15 +#define mmCOMPUTE_NUM_THREAD_X 0x2e07 + + + +#define SWAP_32(num) (((num & 0xff000000) >> 24) | \ + ((num & 0x0000ff00) << 8) | \ + ((num & 0x00ff0000) >> 8) | \ + ((num & 0x000000ff) << 24)) + + +/* Shader code + * void main() +{ + + float x = some_input; + for (unsigned i = 0; i < 1000000; i++) + x = sin(x); + + u[0] = 42u; +} +*/ + +static uint32_t shader_bin[] = { + SWAP_32(0x800082be), SWAP_32(0x02ff08bf), SWAP_32(0x7f969800), SWAP_32(0x040085bf), + SWAP_32(0x02810281), SWAP_32(0x02ff08bf), SWAP_32(0x7f969800), SWAP_32(0xfcff84bf), + SWAP_32(0xff0083be), SWAP_32(0x00f00000), SWAP_32(0xc10082be), SWAP_32(0xaa02007e), + SWAP_32(0x000070e0), SWAP_32(0x00000080), SWAP_32(0x000081bf) +}; + +#define CODE_OFFSET 512 +#define DATA_OFFSET 1024 + + +int amdgpu_bo_alloc_and_map_raw(amdgpu_device_handle dev, unsigned size, + unsigned alignment, unsigned heap, uint64_t alloc_flags, + uint64_t mapping_flags, amdgpu_bo_handle *bo, void **cpu, + uint64_t *mc_address, + amdgpu_va_handle *va_handle) +{ + struct amdgpu_bo_alloc_request request = {}; + amdgpu_bo_handle buf_handle; + amdgpu_va_handle handle; + uint64_t vmc_addr; + int r; + + request.alloc_size = size; + request.phys_alignment = alignment; + request.preferred_heap = heap; + request.flags = alloc_flags; + + r = amdgpu_bo_alloc(dev, &request, &buf_handle); + if (r) + return r; + + r = amdgpu_va_range_alloc(dev, + amdgpu_gpu_va_range_general, + size, alignment, 0, &vmc_addr, + &handle, 0); + if (r) + goto error_va_alloc; + + r = amdgpu_bo_va_op_raw(dev, buf_handle, 0, ALIGN(size, getpagesize()), vmc_addr, + AMDGPU_VM_PAGE_READABLE | + AMDGPU_VM_PAGE_WRITEABLE | + AMDGPU_VM_PAGE_EXECUTABLE | + mapping_flags, + AMDGPU_VA_OP_MAP); + if (r) + goto error_va_map; + + r = amdgpu_bo_cpu_map(buf_handle, cpu); + if (r) + goto error_cpu_map; + + *bo = buf_handle; + *mc_address = vmc_addr; + *va_handle = handle; + + return 0; + + error_cpu_map: + amdgpu_bo_cpu_unmap(buf_handle); + + error_va_map: + amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP); + + error_va_alloc: + amdgpu_bo_free(buf_handle); + return r; +} + + + int suite_basic_tests_init(void) { + struct amdgpu_gpu_info gpu_info = {0}; int r; r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, &minor_version, &device_handle); - if (r == 0) - return CUE_SUCCESS; - else { + if (r) { if ((r == -EACCES) && (errno == EACCES)) printf("\n\nError:%s. " "Hint:Try to run this test program as root.", strerror(errno)); return CUE_SINIT_FAILED; } + + r = amdgpu_query_gpu_info(device_handle, &gpu_info); + if (r) + return CUE_SINIT_FAILED; + + family_id = gpu_info.family_id; + + return CUE_SUCCESS; } int suite_basic_tests_clean(void) @@ -239,53 +396,6 @@ static void amdgpu_query_info_test(void) CU_ASSERT_EQUAL(r, 0); } -static void amdgpu_memory_alloc(void) -{ - amdgpu_bo_handle bo; - amdgpu_va_handle va_handle; - uint64_t bo_mc; - int r; - - /* Test visible VRAM */ - bo = gpu_mem_alloc(device_handle, - 4096, 4096, - AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, - &bo_mc, &va_handle); - - r = gpu_mem_free(bo, va_handle, bo_mc, 4096); - CU_ASSERT_EQUAL(r, 0); - - /* Test invisible VRAM */ - bo = gpu_mem_alloc(device_handle, - 4096, 4096, - AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_NO_CPU_ACCESS, - &bo_mc, &va_handle); - - r = gpu_mem_free(bo, va_handle, bo_mc, 4096); - CU_ASSERT_EQUAL(r, 0); - - /* Test GART Cacheable */ - bo = gpu_mem_alloc(device_handle, - 4096, 4096, - AMDGPU_GEM_DOMAIN_GTT, - 0, &bo_mc, &va_handle); - - r = gpu_mem_free(bo, va_handle, bo_mc, 4096); - CU_ASSERT_EQUAL(r, 0); - - /* Test GART USWC */ - bo = gpu_mem_alloc(device_handle, - 4096, 4096, - AMDGPU_GEM_DOMAIN_GTT, - AMDGPU_GEM_CREATE_CPU_GTT_USWC, - &bo_mc, &va_handle); - - r = gpu_mem_free(bo, va_handle, bo_mc, 4096); - CU_ASSERT_EQUAL(r, 0); -} - static void amdgpu_command_submission_gfx_separate_ibs(void) { amdgpu_context_handle context_handle; @@ -299,7 +409,7 @@ static void amdgpu_command_submission_gfx_separate_ibs(void) uint32_t expired; amdgpu_bo_list_handle bo_list; amdgpu_va_handle va_handle, va_handle_ce; - int r; + int r, i = 0; r = amdgpu_cs_ctx_create(device_handle, &context_handle); CU_ASSERT_EQUAL(r, 0); @@ -324,12 +434,14 @@ static void amdgpu_command_submission_gfx_separate_ibs(void) /* IT_SET_CE_DE_COUNTERS */ ptr = ib_result_ce_cpu; - ptr[0] = 0xc0008900; - ptr[1] = 0; - ptr[2] = 0xc0008400; - ptr[3] = 1; + if (family_id != AMDGPU_FAMILY_SI) { + ptr[i++] = 0xc0008900; + ptr[i++] = 0; + } + ptr[i++] = 0xc0008400; + ptr[i++] = 1; ib_info[0].ib_mc_address = ib_result_ce_mc_address; - ib_info[0].size = 4; + ib_info[0].size = i; ib_info[0].flags = AMDGPU_IB_FLAG_CE; /* IT_WAIT_ON_CE_COUNTER */ @@ -388,7 +500,7 @@ static void amdgpu_command_submission_gfx_shared_ib(void) uint32_t expired; amdgpu_bo_list_handle bo_list; amdgpu_va_handle va_handle; - int r; + int r, i = 0; r = amdgpu_cs_ctx_create(device_handle, &context_handle); CU_ASSERT_EQUAL(r, 0); @@ -407,12 +519,14 @@ static void amdgpu_command_submission_gfx_shared_ib(void) /* IT_SET_CE_DE_COUNTERS */ ptr = ib_result_cpu; - ptr[0] = 0xc0008900; - ptr[1] = 0; - ptr[2] = 0xc0008400; - ptr[3] = 1; + if (family_id != AMDGPU_FAMILY_SI) { + ptr[i++] = 0xc0008900; + ptr[i++] = 0; + } + ptr[i++] = 0xc0008400; + ptr[i++] = 1; ib_info[0].ib_mc_address = ib_result_mc_address; - ib_info[0].size = 4; + ib_info[0].size = i; ib_info[0].flags = AMDGPU_IB_FLAG_CE; ptr = (uint32_t *)ib_result_cpu + 4; @@ -467,6 +581,156 @@ static void amdgpu_command_submission_gfx_cp_copy_data(void) amdgpu_command_submission_copy_linear_helper(AMDGPU_HW_IP_GFX); } +static void amdgpu_bo_eviction_test(void) +{ + const int sdma_write_length = 1024; + const int pm4_dw = 256; + amdgpu_context_handle context_handle; + amdgpu_bo_handle bo1, bo2, vram_max[2], gtt_max[2]; + amdgpu_bo_handle *resources; + uint32_t *pm4; + struct amdgpu_cs_ib_info *ib_info; + struct amdgpu_cs_request *ibs_request; + uint64_t bo1_mc, bo2_mc; + volatile unsigned char *bo1_cpu, *bo2_cpu; + int i, j, r, loop1, loop2; + uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC}; + amdgpu_va_handle bo1_va_handle, bo2_va_handle; + struct amdgpu_heap_info vram_info, gtt_info; + + pm4 = calloc(pm4_dw, sizeof(*pm4)); + CU_ASSERT_NOT_EQUAL(pm4, NULL); + + ib_info = calloc(1, sizeof(*ib_info)); + CU_ASSERT_NOT_EQUAL(ib_info, NULL); + + ibs_request = calloc(1, sizeof(*ibs_request)); + CU_ASSERT_NOT_EQUAL(ibs_request, NULL); + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + /* prepare resource */ + resources = calloc(4, sizeof(amdgpu_bo_handle)); + CU_ASSERT_NOT_EQUAL(resources, NULL); + + r = amdgpu_query_heap_info(device_handle, AMDGPU_GEM_DOMAIN_VRAM, + 0, &vram_info); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_wrap(device_handle, vram_info.max_allocation, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, &vram_max[0]); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_alloc_wrap(device_handle, vram_info.max_allocation, 4096, + AMDGPU_GEM_DOMAIN_VRAM, 0, &vram_max[1]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_query_heap_info(device_handle, AMDGPU_GEM_DOMAIN_GTT, + 0, >t_info); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_wrap(device_handle, gtt_info.max_allocation, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, >t_max[0]); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_alloc_wrap(device_handle, gtt_info.max_allocation, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, >t_max[1]); + CU_ASSERT_EQUAL(r, 0); + + + + loop1 = loop2 = 0; + /* run 9 circle to test all mapping combination */ + while(loop1 < 2) { + while(loop2 < 2) { + /* allocate UC bo1for sDMA use */ + r = amdgpu_bo_alloc_and_map(device_handle, + sdma_write_length, 4096, + AMDGPU_GEM_DOMAIN_GTT, + gtt_flags[loop1], &bo1, + (void**)&bo1_cpu, &bo1_mc, + &bo1_va_handle); + CU_ASSERT_EQUAL(r, 0); + + /* set bo1 */ + memset((void*)bo1_cpu, 0xaa, sdma_write_length); + + /* allocate UC bo2 for sDMA use */ + r = amdgpu_bo_alloc_and_map(device_handle, + sdma_write_length, 4096, + AMDGPU_GEM_DOMAIN_GTT, + gtt_flags[loop2], &bo2, + (void**)&bo2_cpu, &bo2_mc, + &bo2_va_handle); + CU_ASSERT_EQUAL(r, 0); + + /* clear bo2 */ + memset((void*)bo2_cpu, 0, sdma_write_length); + + resources[0] = bo1; + resources[1] = bo2; + resources[2] = vram_max[loop2]; + resources[3] = gtt_max[loop2]; + + /* fulfill PM4: test DMA copy linear */ + i = j = 0; + if (family_id == AMDGPU_FAMILY_SI) { + pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI, 0, 0, 0, + sdma_write_length); + pm4[i++] = 0xffffffff & bo2_mc; + pm4[i++] = 0xffffffff & bo1_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; + } else { + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0); + if (family_id >= AMDGPU_FAMILY_AI) + pm4[i++] = sdma_write_length - 1; + else + pm4[i++] = sdma_write_length; + pm4[i++] = 0; + pm4[i++] = 0xffffffff & bo1_mc; + pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; + pm4[i++] = 0xffffffff & bo2_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + } + + amdgpu_test_exec_cs_helper(context_handle, + AMDGPU_HW_IP_DMA, 0, + i, pm4, + 4, resources, + ib_info, ibs_request); + + /* verify if SDMA test result meets with expected */ + i = 0; + while(i < sdma_write_length) { + CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa); + } + r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc, + sdma_write_length); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc, + sdma_write_length); + CU_ASSERT_EQUAL(r, 0); + loop2++; + } + loop2 = 0; + loop1++; + } + amdgpu_bo_free(vram_max[0]); + amdgpu_bo_free(vram_max[1]); + amdgpu_bo_free(gtt_max[0]); + amdgpu_bo_free(gtt_max[1]); + /* clean resources */ + free(resources); + free(ibs_request); + free(ib_info); + free(pm4); + + /* end of test */ + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + + static void amdgpu_command_submission_gfx(void) { /* write data using the CP */ @@ -493,10 +757,19 @@ static void amdgpu_semaphore_test(void) struct amdgpu_cs_fence fence_status = {0}; uint32_t *ptr; uint32_t expired; + uint32_t sdma_nop, gfx_nop; amdgpu_bo_list_handle bo_list[2]; amdgpu_va_handle va_handle[2]; int r, i; + if (family_id == AMDGPU_FAMILY_SI) { + sdma_nop = SDMA_PACKET_SI(SDMA_NOP_SI, 0, 0, 0, 0); + gfx_nop = GFX_COMPUTE_NOP_SI; + } else { + sdma_nop = SDMA_PKT_HEADER_OP(SDMA_NOP); + gfx_nop = GFX_COMPUTE_NOP; + } + r = amdgpu_cs_create_semaphore(&sem); CU_ASSERT_EQUAL(r, 0); for (i = 0; i < 2; i++) { @@ -516,7 +789,7 @@ static void amdgpu_semaphore_test(void) /* 1. same context different engine */ ptr = ib_result_cpu[0]; - ptr[0] = SDMA_NOP; + ptr[0] = sdma_nop; ib_info[0].ib_mc_address = ib_result_mc_address[0]; ib_info[0].size = 1; @@ -533,7 +806,7 @@ static void amdgpu_semaphore_test(void) r = amdgpu_cs_wait_semaphore(context_handle[0], AMDGPU_HW_IP_GFX, 0, 0, sem); CU_ASSERT_EQUAL(r, 0); ptr = ib_result_cpu[1]; - ptr[0] = GFX_COMPUTE_NOP; + ptr[0] = gfx_nop; ib_info[1].ib_mc_address = ib_result_mc_address[1]; ib_info[1].size = 1; @@ -557,7 +830,7 @@ static void amdgpu_semaphore_test(void) /* 2. same engine different context */ ptr = ib_result_cpu[0]; - ptr[0] = GFX_COMPUTE_NOP; + ptr[0] = gfx_nop; ib_info[0].ib_mc_address = ib_result_mc_address[0]; ib_info[0].size = 1; @@ -574,7 +847,7 @@ static void amdgpu_semaphore_test(void) r = amdgpu_cs_wait_semaphore(context_handle[1], AMDGPU_HW_IP_GFX, 0, 0, sem); CU_ASSERT_EQUAL(r, 0); ptr = ib_result_cpu[1]; - ptr[0] = GFX_COMPUTE_NOP; + ptr[0] = gfx_nop; ib_info[1].ib_mc_address = ib_result_mc_address[1]; ib_info[1].size = 1; @@ -595,6 +868,7 @@ static void amdgpu_semaphore_test(void) 500000000, 0, &expired); CU_ASSERT_EQUAL(r, 0); CU_ASSERT_EQUAL(expired, true); + for (i = 0; i < 2; i++) { r = amdgpu_bo_unmap_and_free(ib_result_handle[i], va_handle[i], ib_result_mc_address[i], 4096); @@ -622,14 +896,18 @@ static void amdgpu_command_submission_compute_nop(void) struct amdgpu_cs_fence fence_status; uint32_t *ptr; uint32_t expired; - int i, r, instance; + int r, instance; amdgpu_bo_list_handle bo_list; amdgpu_va_handle va_handle; + struct drm_amdgpu_info_hw_ip info; + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_COMPUTE, 0, &info); + CU_ASSERT_EQUAL(r, 0); r = amdgpu_cs_ctx_create(device_handle, &context_handle); CU_ASSERT_EQUAL(r, 0); - for (instance = 0; instance < 8; instance++) { + for (instance = 0; (1 << instance) & info.available_rings; instance++) { r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, AMDGPU_GEM_DOMAIN_GTT, 0, &ib_result_handle, &ib_result_cpu, @@ -641,8 +919,8 @@ static void amdgpu_command_submission_compute_nop(void) CU_ASSERT_EQUAL(r, 0); ptr = ib_result_cpu; - for (i = 0; i < 16; ++i) - ptr[i] = 0xffff1000; + memset(ptr, 0, 16); + ptr[0]=PACKET3(PACKET3_NOP, 14); memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); ib_info.ib_mc_address = ib_result_mc_address; @@ -805,9 +1083,10 @@ static void amdgpu_command_submission_write_linear_helper(unsigned ip_type) struct amdgpu_cs_request *ibs_request; uint64_t bo_mc; volatile uint32_t *bo_cpu; - int i, j, r, loop; + int i, j, r, loop, ring_id; uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC}; amdgpu_va_handle va_handle; + struct drm_amdgpu_info_hw_ip hw_ip_info; pm4 = calloc(pm4_dw, sizeof(*pm4)); CU_ASSERT_NOT_EQUAL(pm4, NULL); @@ -818,6 +1097,9 @@ static void amdgpu_command_submission_write_linear_helper(unsigned ip_type) ibs_request = calloc(1, sizeof(*ibs_request)); CU_ASSERT_NOT_EQUAL(ibs_request, NULL); + r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_ctx_create(device_handle, &context_handle); CU_ASSERT_EQUAL(r, 0); @@ -825,58 +1107,66 @@ static void amdgpu_command_submission_write_linear_helper(unsigned ip_type) resources = calloc(1, sizeof(amdgpu_bo_handle)); CU_ASSERT_NOT_EQUAL(resources, NULL); - loop = 0; - while(loop < 2) { - /* allocate UC bo for sDMA use */ - r = amdgpu_bo_alloc_and_map(device_handle, - sdma_write_length * sizeof(uint32_t), - 4096, AMDGPU_GEM_DOMAIN_GTT, - gtt_flags[loop], &bo, (void**)&bo_cpu, - &bo_mc, &va_handle); - CU_ASSERT_EQUAL(r, 0); + for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) { + loop = 0; + while(loop < 2) { + /* allocate UC bo for sDMA use */ + r = amdgpu_bo_alloc_and_map(device_handle, + sdma_write_length * sizeof(uint32_t), + 4096, AMDGPU_GEM_DOMAIN_GTT, + gtt_flags[loop], &bo, (void**)&bo_cpu, + &bo_mc, &va_handle); + CU_ASSERT_EQUAL(r, 0); - /* clear bo */ - memset((void*)bo_cpu, 0, sdma_write_length * sizeof(uint32_t)); - - - resources[0] = bo; - - /* fulfill PM4: test DMA write-linear */ - i = j = 0; - if (ip_type == AMDGPU_HW_IP_DMA) { - pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE, - SDMA_WRITE_SUB_OPCODE_LINEAR, 0); - pm4[i++] = 0xffffffff & bo_mc; - pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; - pm4[i++] = sdma_write_length; - while(j++ < sdma_write_length) - pm4[i++] = 0xdeadbeaf; - } else if ((ip_type == AMDGPU_HW_IP_GFX) || - (ip_type == AMDGPU_HW_IP_COMPUTE)) { - pm4[i++] = PACKET3(PACKET3_WRITE_DATA, 2 + sdma_write_length); - pm4[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM; - pm4[i++] = 0xfffffffc & bo_mc; - pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; - while(j++ < sdma_write_length) - pm4[i++] = 0xdeadbeaf; - } + /* clear bo */ + memset((void*)bo_cpu, 0, sdma_write_length * sizeof(uint32_t)); - amdgpu_test_exec_cs_helper(context_handle, - ip_type, 0, - i, pm4, - 1, resources, - ib_info, ibs_request); + resources[0] = bo; - /* verify if SDMA test result meets with expected */ - i = 0; - while(i < sdma_write_length) { - CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf); - } + /* fulfill PM4: test DMA write-linear */ + i = j = 0; + if (ip_type == AMDGPU_HW_IP_DMA) { + if (family_id == AMDGPU_FAMILY_SI) + pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_WRITE, 0, 0, 0, + sdma_write_length); + else + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE, + SDMA_WRITE_SUB_OPCODE_LINEAR, 0); + pm4[i++] = 0xffffffff & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + if (family_id >= AMDGPU_FAMILY_AI) + pm4[i++] = sdma_write_length - 1; + else if (family_id != AMDGPU_FAMILY_SI) + pm4[i++] = sdma_write_length; + while(j++ < sdma_write_length) + pm4[i++] = 0xdeadbeaf; + } else if ((ip_type == AMDGPU_HW_IP_GFX) || + (ip_type == AMDGPU_HW_IP_COMPUTE)) { + pm4[i++] = PACKET3(PACKET3_WRITE_DATA, 2 + sdma_write_length); + pm4[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM; + pm4[i++] = 0xfffffffc & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + while(j++ < sdma_write_length) + pm4[i++] = 0xdeadbeaf; + } - r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc, - sdma_write_length * sizeof(uint32_t)); - CU_ASSERT_EQUAL(r, 0); - loop++; + amdgpu_test_exec_cs_helper(context_handle, + ip_type, ring_id, + i, pm4, + 1, resources, + ib_info, ibs_request); + + /* verify if SDMA test result meets with expected */ + i = 0; + while(i < sdma_write_length) { + CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf); + } + + r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc, + sdma_write_length * sizeof(uint32_t)); + CU_ASSERT_EQUAL(r, 0); + loop++; + } } /* clean resources */ free(resources); @@ -906,9 +1196,10 @@ static void amdgpu_command_submission_const_fill_helper(unsigned ip_type) struct amdgpu_cs_request *ibs_request; uint64_t bo_mc; volatile uint32_t *bo_cpu; - int i, j, r, loop; + int i, j, r, loop, ring_id; uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC}; amdgpu_va_handle va_handle; + struct drm_amdgpu_info_hw_ip hw_ip_info; pm4 = calloc(pm4_dw, sizeof(*pm4)); CU_ASSERT_NOT_EQUAL(pm4, NULL); @@ -919,6 +1210,9 @@ static void amdgpu_command_submission_const_fill_helper(unsigned ip_type) ibs_request = calloc(1, sizeof(*ibs_request)); CU_ASSERT_NOT_EQUAL(ibs_request, NULL); + r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_ctx_create(device_handle, &context_handle); CU_ASSERT_EQUAL(r, 0); @@ -926,60 +1220,86 @@ static void amdgpu_command_submission_const_fill_helper(unsigned ip_type) resources = calloc(1, sizeof(amdgpu_bo_handle)); CU_ASSERT_NOT_EQUAL(resources, NULL); - loop = 0; - while(loop < 2) { - /* allocate UC bo for sDMA use */ - r = amdgpu_bo_alloc_and_map(device_handle, - sdma_write_length, 4096, - AMDGPU_GEM_DOMAIN_GTT, - gtt_flags[loop], &bo, (void**)&bo_cpu, - &bo_mc, &va_handle); - CU_ASSERT_EQUAL(r, 0); + for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) { + loop = 0; + while(loop < 2) { + /* allocate UC bo for sDMA use */ + r = amdgpu_bo_alloc_and_map(device_handle, + sdma_write_length, 4096, + AMDGPU_GEM_DOMAIN_GTT, + gtt_flags[loop], &bo, (void**)&bo_cpu, + &bo_mc, &va_handle); + CU_ASSERT_EQUAL(r, 0); - /* clear bo */ - memset((void*)bo_cpu, 0, sdma_write_length); - - resources[0] = bo; - - /* fulfill PM4: test DMA const fill */ - i = j = 0; - if (ip_type == AMDGPU_HW_IP_DMA) { - pm4[i++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, - SDMA_CONSTANT_FILL_EXTRA_SIZE(2)); - pm4[i++] = 0xffffffff & bo_mc; - pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; - pm4[i++] = 0xdeadbeaf; - pm4[i++] = sdma_write_length; - } else if ((ip_type == AMDGPU_HW_IP_GFX) || - (ip_type == AMDGPU_HW_IP_COMPUTE)) { - pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5); - pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) | - PACKET3_DMA_DATA_DST_SEL(0) | - PACKET3_DMA_DATA_SRC_SEL(2) | - PACKET3_DMA_DATA_CP_SYNC; - pm4[i++] = 0xdeadbeaf; - pm4[i++] = 0; - pm4[i++] = 0xfffffffc & bo_mc; - pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; - pm4[i++] = sdma_write_length; - } + /* clear bo */ + memset((void*)bo_cpu, 0, sdma_write_length); - amdgpu_test_exec_cs_helper(context_handle, - ip_type, 0, - i, pm4, - 1, resources, - ib_info, ibs_request); + resources[0] = bo; - /* verify if SDMA test result meets with expected */ - i = 0; - while(i < (sdma_write_length / 4)) { - CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf); - } + /* fulfill PM4: test DMA const fill */ + i = j = 0; + if (ip_type == AMDGPU_HW_IP_DMA) { + if (family_id == AMDGPU_FAMILY_SI) { + pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_CONSTANT_FILL_SI, + 0, 0, 0, + sdma_write_length / 4); + pm4[i++] = 0xfffffffc & bo_mc; + pm4[i++] = 0xdeadbeaf; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 16; + } else { + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, + SDMA_CONSTANT_FILL_EXTRA_SIZE(2)); + pm4[i++] = 0xffffffff & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + pm4[i++] = 0xdeadbeaf; + if (family_id >= AMDGPU_FAMILY_AI) + pm4[i++] = sdma_write_length - 1; + else + pm4[i++] = sdma_write_length; + } + } else if ((ip_type == AMDGPU_HW_IP_GFX) || + (ip_type == AMDGPU_HW_IP_COMPUTE)) { + if (family_id == AMDGPU_FAMILY_SI) { + pm4[i++] = PACKET3(PACKET3_DMA_DATA_SI, 4); + pm4[i++] = 0xdeadbeaf; + pm4[i++] = PACKET3_DMA_DATA_SI_ENGINE(0) | + PACKET3_DMA_DATA_SI_DST_SEL(0) | + PACKET3_DMA_DATA_SI_SRC_SEL(2) | + PACKET3_DMA_DATA_SI_CP_SYNC; + pm4[i++] = 0xffffffff & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + pm4[i++] = sdma_write_length; + } else { + pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5); + pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) | + PACKET3_DMA_DATA_DST_SEL(0) | + PACKET3_DMA_DATA_SRC_SEL(2) | + PACKET3_DMA_DATA_CP_SYNC; + pm4[i++] = 0xdeadbeaf; + pm4[i++] = 0; + pm4[i++] = 0xfffffffc & bo_mc; + pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; + pm4[i++] = sdma_write_length; + } + } - r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc, - sdma_write_length); - CU_ASSERT_EQUAL(r, 0); - loop++; + amdgpu_test_exec_cs_helper(context_handle, + ip_type, ring_id, + i, pm4, + 1, resources, + ib_info, ibs_request); + + /* verify if SDMA test result meets with expected */ + i = 0; + while(i < (sdma_write_length / 4)) { + CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf); + } + + r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc, + sdma_write_length); + CU_ASSERT_EQUAL(r, 0); + loop++; + } } /* clean resources */ free(resources); @@ -1009,9 +1329,10 @@ static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type) struct amdgpu_cs_request *ibs_request; uint64_t bo1_mc, bo2_mc; volatile unsigned char *bo1_cpu, *bo2_cpu; - int i, j, r, loop1, loop2; + int i, j, r, loop1, loop2, ring_id; uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC}; amdgpu_va_handle bo1_va_handle, bo2_va_handle; + struct drm_amdgpu_info_hw_ip hw_ip_info; pm4 = calloc(pm4_dw, sizeof(*pm4)); CU_ASSERT_NOT_EQUAL(pm4, NULL); @@ -1022,6 +1343,9 @@ static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type) ibs_request = calloc(1, sizeof(*ibs_request)); CU_ASSERT_NOT_EQUAL(ibs_request, NULL); + r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_ctx_create(device_handle, &context_handle); CU_ASSERT_EQUAL(r, 0); @@ -1029,81 +1353,111 @@ static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type) resources = calloc(2, sizeof(amdgpu_bo_handle)); CU_ASSERT_NOT_EQUAL(resources, NULL); - loop1 = loop2 = 0; - /* run 9 circle to test all mapping combination */ - while(loop1 < 2) { - while(loop2 < 2) { - /* allocate UC bo1for sDMA use */ - r = amdgpu_bo_alloc_and_map(device_handle, - sdma_write_length, 4096, - AMDGPU_GEM_DOMAIN_GTT, - gtt_flags[loop1], &bo1, - (void**)&bo1_cpu, &bo1_mc, - &bo1_va_handle); - CU_ASSERT_EQUAL(r, 0); - - /* set bo1 */ - memset((void*)bo1_cpu, 0xaa, sdma_write_length); - - /* allocate UC bo2 for sDMA use */ - r = amdgpu_bo_alloc_and_map(device_handle, - sdma_write_length, 4096, - AMDGPU_GEM_DOMAIN_GTT, - gtt_flags[loop2], &bo2, - (void**)&bo2_cpu, &bo2_mc, - &bo2_va_handle); - CU_ASSERT_EQUAL(r, 0); - - /* clear bo2 */ - memset((void*)bo2_cpu, 0, sdma_write_length); - - resources[0] = bo1; - resources[1] = bo2; - - /* fulfill PM4: test DMA copy linear */ - i = j = 0; - if (ip_type == AMDGPU_HW_IP_DMA) { - pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0); - pm4[i++] = sdma_write_length; - pm4[i++] = 0; - pm4[i++] = 0xffffffff & bo1_mc; - pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; - pm4[i++] = 0xffffffff & bo2_mc; - pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; - } else if ((ip_type == AMDGPU_HW_IP_GFX) || - (ip_type == AMDGPU_HW_IP_COMPUTE)) { - pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5); - pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) | - PACKET3_DMA_DATA_DST_SEL(0) | - PACKET3_DMA_DATA_SRC_SEL(0) | - PACKET3_DMA_DATA_CP_SYNC; - pm4[i++] = 0xfffffffc & bo1_mc; - pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; - pm4[i++] = 0xfffffffc & bo2_mc; - pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; - pm4[i++] = sdma_write_length; - } - - amdgpu_test_exec_cs_helper(context_handle, - ip_type, 0, - i, pm4, - 2, resources, - ib_info, ibs_request); - - /* verify if SDMA test result meets with expected */ - i = 0; - while(i < sdma_write_length) { - CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa); + for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) { + loop1 = loop2 = 0; + /* run 9 circle to test all mapping combination */ + while(loop1 < 2) { + while(loop2 < 2) { + /* allocate UC bo1for sDMA use */ + r = amdgpu_bo_alloc_and_map(device_handle, + sdma_write_length, 4096, + AMDGPU_GEM_DOMAIN_GTT, + gtt_flags[loop1], &bo1, + (void**)&bo1_cpu, &bo1_mc, + &bo1_va_handle); + CU_ASSERT_EQUAL(r, 0); + + /* set bo1 */ + memset((void*)bo1_cpu, 0xaa, sdma_write_length); + + /* allocate UC bo2 for sDMA use */ + r = amdgpu_bo_alloc_and_map(device_handle, + sdma_write_length, 4096, + AMDGPU_GEM_DOMAIN_GTT, + gtt_flags[loop2], &bo2, + (void**)&bo2_cpu, &bo2_mc, + &bo2_va_handle); + CU_ASSERT_EQUAL(r, 0); + + /* clear bo2 */ + memset((void*)bo2_cpu, 0, sdma_write_length); + + resources[0] = bo1; + resources[1] = bo2; + + /* fulfill PM4: test DMA copy linear */ + i = j = 0; + if (ip_type == AMDGPU_HW_IP_DMA) { + if (family_id == AMDGPU_FAMILY_SI) { + pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI, + 0, 0, 0, + sdma_write_length); + pm4[i++] = 0xffffffff & bo2_mc; + pm4[i++] = 0xffffffff & bo1_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; + } else { + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, + SDMA_COPY_SUB_OPCODE_LINEAR, + 0); + if (family_id >= AMDGPU_FAMILY_AI) + pm4[i++] = sdma_write_length - 1; + else + pm4[i++] = sdma_write_length; + pm4[i++] = 0; + pm4[i++] = 0xffffffff & bo1_mc; + pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; + pm4[i++] = 0xffffffff & bo2_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + } + } else if ((ip_type == AMDGPU_HW_IP_GFX) || + (ip_type == AMDGPU_HW_IP_COMPUTE)) { + if (family_id == AMDGPU_FAMILY_SI) { + pm4[i++] = PACKET3(PACKET3_DMA_DATA_SI, 4); + pm4[i++] = 0xfffffffc & bo1_mc; + pm4[i++] = PACKET3_DMA_DATA_SI_ENGINE(0) | + PACKET3_DMA_DATA_SI_DST_SEL(0) | + PACKET3_DMA_DATA_SI_SRC_SEL(0) | + PACKET3_DMA_DATA_SI_CP_SYNC | + (0xffff00000000 & bo1_mc) >> 32; + pm4[i++] = 0xfffffffc & bo2_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + pm4[i++] = sdma_write_length; + } else { + pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5); + pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) | + PACKET3_DMA_DATA_DST_SEL(0) | + PACKET3_DMA_DATA_SRC_SEL(0) | + PACKET3_DMA_DATA_CP_SYNC; + pm4[i++] = 0xfffffffc & bo1_mc; + pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32; + pm4[i++] = 0xfffffffc & bo2_mc; + pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32; + pm4[i++] = sdma_write_length; + } + } + + amdgpu_test_exec_cs_helper(context_handle, + ip_type, ring_id, + i, pm4, + 2, resources, + ib_info, ibs_request); + + /* verify if SDMA test result meets with expected */ + i = 0; + while(i < sdma_write_length) { + CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa); + } + r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc, + sdma_write_length); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc, + sdma_write_length); + CU_ASSERT_EQUAL(r, 0); + loop2++; } - r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc, - sdma_write_length); - CU_ASSERT_EQUAL(r, 0); - r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc, - sdma_write_length); - CU_ASSERT_EQUAL(r, 0); - loop2++; + loop1++; } - loop1++; } /* clean resources */ free(resources); @@ -1128,6 +1482,106 @@ static void amdgpu_command_submission_sdma(void) amdgpu_command_submission_sdma_copy_linear(); } +static void amdgpu_command_submission_multi_fence_wait_all(bool wait_all) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle ib_result_handle, ib_result_ce_handle; + void *ib_result_cpu, *ib_result_ce_cpu; + uint64_t ib_result_mc_address, ib_result_ce_mc_address; + struct amdgpu_cs_request ibs_request[2] = {0}; + struct amdgpu_cs_ib_info ib_info[2]; + struct amdgpu_cs_fence fence_status[2] = {0}; + uint32_t *ptr; + uint32_t expired; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle, va_handle_ce; + int r; + int i = 0, ib_cs_num = 2; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_ce_handle, &ib_result_ce_cpu, + &ib_result_ce_mc_address, &va_handle_ce); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle, + ib_result_ce_handle, &bo_list); + CU_ASSERT_EQUAL(r, 0); + + memset(ib_info, 0, 2 * sizeof(struct amdgpu_cs_ib_info)); + + /* IT_SET_CE_DE_COUNTERS */ + ptr = ib_result_ce_cpu; + if (family_id != AMDGPU_FAMILY_SI) { + ptr[i++] = 0xc0008900; + ptr[i++] = 0; + } + ptr[i++] = 0xc0008400; + ptr[i++] = 1; + ib_info[0].ib_mc_address = ib_result_ce_mc_address; + ib_info[0].size = i; + ib_info[0].flags = AMDGPU_IB_FLAG_CE; + + /* IT_WAIT_ON_CE_COUNTER */ + ptr = ib_result_cpu; + ptr[0] = 0xc0008600; + ptr[1] = 0x00000001; + ib_info[1].ib_mc_address = ib_result_mc_address; + ib_info[1].size = 2; + + for (i = 0; i < ib_cs_num; i++) { + ibs_request[i].ip_type = AMDGPU_HW_IP_GFX; + ibs_request[i].number_of_ibs = 2; + ibs_request[i].ibs = ib_info; + ibs_request[i].resources = bo_list; + ibs_request[i].fence_info.handle = NULL; + } + + r = amdgpu_cs_submit(context_handle, 0,ibs_request, ib_cs_num); + + CU_ASSERT_EQUAL(r, 0); + + for (i = 0; i < ib_cs_num; i++) { + fence_status[i].context = context_handle; + fence_status[i].ip_type = AMDGPU_HW_IP_GFX; + fence_status[i].fence = ibs_request[i].seq_no; + } + + r = amdgpu_cs_wait_fences(fence_status, ib_cs_num, wait_all, + AMDGPU_TIMEOUT_INFINITE, + &expired, NULL); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(ib_result_ce_handle, va_handle_ce, + ib_result_ce_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_command_submission_multi_fence(void) +{ + amdgpu_command_submission_multi_fence_wait_all(true); + amdgpu_command_submission_multi_fence_wait_all(false); +} + static void amdgpu_userptr_test(void) { int i, r, j; @@ -1175,15 +1629,28 @@ static void amdgpu_userptr_test(void) handle = buf_handle; j = i = 0; - pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE, - SDMA_WRITE_SUB_OPCODE_LINEAR, 0); + + if (family_id == AMDGPU_FAMILY_SI) + pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_WRITE, 0, 0, 0, + sdma_write_length); + else + pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE, + SDMA_WRITE_SUB_OPCODE_LINEAR, 0); pm4[i++] = 0xffffffff & bo_mc; pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32; - pm4[i++] = sdma_write_length; + if (family_id >= AMDGPU_FAMILY_AI) + pm4[i++] = sdma_write_length - 1; + else if (family_id != AMDGPU_FAMILY_SI) + pm4[i++] = sdma_write_length; while (j++ < sdma_write_length) pm4[i++] = 0xdeadbeaf; + if (!fork()) { + pm4[0] = 0x0; + exit(0); + } + amdgpu_test_exec_cs_helper(context_handle, AMDGPU_HW_IP_DMA, 0, i, pm4, @@ -1207,4 +1674,212 @@ static void amdgpu_userptr_test(void) r = amdgpu_cs_ctx_free(context_handle); CU_ASSERT_EQUAL(r, 0); + + wait(NULL); +} + +static void amdgpu_sync_dependency_test(void) +{ + amdgpu_context_handle context_handle[2]; + amdgpu_bo_handle ib_result_handle; + void *ib_result_cpu; + uint64_t ib_result_mc_address; + struct amdgpu_cs_request ibs_request; + struct amdgpu_cs_ib_info ib_info; + struct amdgpu_cs_fence fence_status; + uint32_t expired; + int i, j, r; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle; + static uint32_t *ptr; + uint64_t seq_no; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle[0]); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_ctx_create(device_handle, &context_handle[1]); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map(device_handle, 8192, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL, + &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ptr = ib_result_cpu; + i = 0; + + memcpy(ptr + CODE_OFFSET , shader_bin, sizeof(shader_bin)); + + /* Dispatch minimal init config and verify it's executed */ + ptr[i++] = PACKET3(PKT3_CONTEXT_CONTROL, 1); + ptr[i++] = 0x80000000; + ptr[i++] = 0x80000000; + + ptr[i++] = PACKET3(PKT3_CLEAR_STATE, 0); + ptr[i++] = 0x80000000; + + + /* Program compute regs */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2); + ptr[i++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START; + ptr[i++] = (ib_result_mc_address + CODE_OFFSET * 4) >> 8; + ptr[i++] = (ib_result_mc_address + CODE_OFFSET * 4) >> 40; + + + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2); + ptr[i++] = mmCOMPUTE_PGM_RSRC1 - PACKET3_SET_SH_REG_START; + /* + * 002c0040 COMPUTE_PGM_RSRC1 <- VGPRS = 0 + SGPRS = 1 + PRIORITY = 0 + FLOAT_MODE = 192 (0xc0) + PRIV = 0 + DX10_CLAMP = 1 + DEBUG_MODE = 0 + IEEE_MODE = 0 + BULKY = 0 + CDBG_USER = 0 + * + */ + ptr[i++] = 0x002c0040; + + + /* + * 00000010 COMPUTE_PGM_RSRC2 <- SCRATCH_EN = 0 + USER_SGPR = 8 + TRAP_PRESENT = 0 + TGID_X_EN = 0 + TGID_Y_EN = 0 + TGID_Z_EN = 0 + TG_SIZE_EN = 0 + TIDIG_COMP_CNT = 0 + EXCP_EN_MSB = 0 + LDS_SIZE = 0 + EXCP_EN = 0 + * + */ + ptr[i++] = 0x00000010; + + +/* + * 00000100 COMPUTE_TMPRING_SIZE <- WAVES = 256 (0x100) + WAVESIZE = 0 + * + */ + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr[i++] = mmCOMPUTE_TMPRING_SIZE - PACKET3_SET_SH_REG_START; + ptr[i++] = 0x00000100; + + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2); + ptr[i++] = mmCOMPUTE_USER_DATA_0 - PACKET3_SET_SH_REG_START; + ptr[i++] = 0xffffffff & (ib_result_mc_address + DATA_OFFSET * 4); + ptr[i++] = (0xffffffff00000000 & (ib_result_mc_address + DATA_OFFSET * 4)) >> 32; + + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1); + ptr[i++] = mmCOMPUTE_RESOURCE_LIMITS - PACKET3_SET_SH_REG_START; + ptr[i++] = 0; + + ptr[i++] = PACKET3(PKT3_SET_SH_REG, 3); + ptr[i++] = mmCOMPUTE_NUM_THREAD_X - PACKET3_SET_SH_REG_START; + ptr[i++] = 1; + ptr[i++] = 1; + ptr[i++] = 1; + + + /* Dispatch */ + ptr[i++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3); + ptr[i++] = 1; + ptr[i++] = 1; + ptr[i++] = 1; + ptr[i++] = 0x00000045; /* DISPATCH DIRECT field */ + + + while (i & 7) + ptr[i++] = 0xffff1000; /* type3 nop packet */ + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address; + ib_info.size = i; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = 0; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + ibs_request.fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle[1], 0,&ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + seq_no = ibs_request.seq_no; + + + + /* Prepare second command with dependency on the first */ + j = i; + ptr[i++] = PACKET3(PACKET3_WRITE_DATA, 3); + ptr[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM; + ptr[i++] = 0xfffffffc & (ib_result_mc_address + DATA_OFFSET * 4); + ptr[i++] = (0xffffffff00000000 & (ib_result_mc_address + DATA_OFFSET * 4)) >> 32; + ptr[i++] = 99; + + while (i & 7) + ptr[i++] = 0xffff1000; /* type3 nop packet */ + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address + j * 4; + ib_info.size = i - j; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = 0; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + ibs_request.fence_info.handle = NULL; + + ibs_request.number_of_dependencies = 1; + + ibs_request.dependencies = calloc(1, sizeof(*ibs_request.dependencies)); + ibs_request.dependencies[0].context = context_handle[1]; + ibs_request.dependencies[0].ip_instance = 0; + ibs_request.dependencies[0].ring = 0; + ibs_request.dependencies[0].fence = seq_no; + + + r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + + memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence)); + fence_status.context = context_handle[0]; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.ip_instance = 0; + fence_status.ring = 0; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE,0, &expired); + CU_ASSERT_EQUAL(r, 0); + + /* Expect the second command to wait for shader to complete */ + CU_ASSERT_EQUAL(ptr[DATA_OFFSET], 99); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle[0]); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_cs_ctx_free(context_handle[1]); + CU_ASSERT_EQUAL(r, 0); + + free(ibs_request.dependencies); } diff --git a/tests/amdgpu/bo_tests.c b/tests/amdgpu/bo_tests.c index 74b5e77b..7cff4cf7 100644 --- a/tests/amdgpu/bo_tests.c +++ b/tests/amdgpu/bo_tests.c @@ -21,16 +21,13 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdio.h> #include "CUnit/Basic.h" #include "amdgpu_test.h" #include "amdgpu_drm.h" +#include "amdgpu_internal.h" #define BUFFER_SIZE (4*1024) #define BUFFER_ALIGN (4*1024) @@ -46,13 +43,17 @@ static amdgpu_va_handle va_handle; static void amdgpu_bo_export_import(void); static void amdgpu_bo_metadata(void); static void amdgpu_bo_map_unmap(void); +static void amdgpu_memory_alloc(void); +static void amdgpu_mem_fail_alloc(void); +static void amdgpu_bo_find_by_cpu_mapping(void); CU_TestInfo bo_tests[] = { { "Export/Import", amdgpu_bo_export_import }, -#if 0 { "Metadata", amdgpu_bo_metadata }, -#endif { "CPU map/unmap", amdgpu_bo_map_unmap }, + { "Memory alloc Test", amdgpu_memory_alloc }, + { "Memory fail alloc Test", amdgpu_mem_fail_alloc }, + { "Find bo by CPU mapping", amdgpu_bo_find_by_cpu_mapping }, CU_TEST_INFO_NULL, }; @@ -195,3 +196,123 @@ static void amdgpu_bo_map_unmap(void) r = amdgpu_bo_cpu_unmap(buffer_handle); CU_ASSERT_EQUAL(r, 0); } + +static void amdgpu_memory_alloc(void) +{ + amdgpu_bo_handle bo; + amdgpu_va_handle va_handle; + uint64_t bo_mc; + int r; + + /* Test visible VRAM */ + bo = gpu_mem_alloc(device_handle, + 4096, 4096, + AMDGPU_GEM_DOMAIN_VRAM, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + &bo_mc, &va_handle); + + r = gpu_mem_free(bo, va_handle, bo_mc, 4096); + CU_ASSERT_EQUAL(r, 0); + + /* Test invisible VRAM */ + bo = gpu_mem_alloc(device_handle, + 4096, 4096, + AMDGPU_GEM_DOMAIN_VRAM, + AMDGPU_GEM_CREATE_NO_CPU_ACCESS, + &bo_mc, &va_handle); + + r = gpu_mem_free(bo, va_handle, bo_mc, 4096); + CU_ASSERT_EQUAL(r, 0); + + /* Test GART Cacheable */ + bo = gpu_mem_alloc(device_handle, + 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, + 0, &bo_mc, &va_handle); + + r = gpu_mem_free(bo, va_handle, bo_mc, 4096); + CU_ASSERT_EQUAL(r, 0); + + /* Test GART USWC */ + bo = gpu_mem_alloc(device_handle, + 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, + AMDGPU_GEM_CREATE_CPU_GTT_USWC, + &bo_mc, &va_handle); + + r = gpu_mem_free(bo, va_handle, bo_mc, 4096); + CU_ASSERT_EQUAL(r, 0); + + /* Test GDS */ + bo = gpu_mem_alloc(device_handle, 1024, 0, + AMDGPU_GEM_DOMAIN_GDS, 0, + NULL, NULL); + r = gpu_mem_free(bo, NULL, 0, 4096); + CU_ASSERT_EQUAL(r, 0); + + /* Test GWS */ + bo = gpu_mem_alloc(device_handle, 1, 0, + AMDGPU_GEM_DOMAIN_GWS, 0, + NULL, NULL); + r = gpu_mem_free(bo, NULL, 0, 4096); + CU_ASSERT_EQUAL(r, 0); + + /* Test OA */ + bo = gpu_mem_alloc(device_handle, 1, 0, + AMDGPU_GEM_DOMAIN_OA, 0, + NULL, NULL); + r = gpu_mem_free(bo, NULL, 0, 4096); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_mem_fail_alloc(void) +{ + amdgpu_bo_handle bo; + int r; + struct amdgpu_bo_alloc_request req = {0}; + amdgpu_bo_handle buf_handle; + + /* Test impossible mem allocation, 1TB */ + req.alloc_size = 0xE8D4A51000; + req.phys_alignment = 4096; + req.preferred_heap = AMDGPU_GEM_DOMAIN_VRAM; + req.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS; + + r = amdgpu_bo_alloc(device_handle, &req, &buf_handle); + CU_ASSERT_EQUAL(r, -ENOMEM); + + if (!r) { + r = amdgpu_bo_free(bo); + CU_ASSERT_EQUAL(r, 0); + } +} + +static void amdgpu_bo_find_by_cpu_mapping(void) +{ + amdgpu_bo_handle bo_handle, find_bo_handle; + amdgpu_va_handle va_handle; + void *bo_cpu; + uint64_t bo_mc_address; + uint64_t offset; + int r; + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &bo_handle, &bo_cpu, + &bo_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_find_bo_by_cpu_mapping(device_handle, + bo_cpu, + 4096, + &find_bo_handle, + &offset); + CU_ASSERT_EQUAL(r, 0); + CU_ASSERT_EQUAL(offset, 0); + CU_ASSERT_EQUAL(bo_handle->handle, find_bo_handle->handle); + + atomic_dec(&find_bo_handle->refcount, 1); + r = amdgpu_bo_unmap_and_free(bo_handle, va_handle, + bo_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); +} diff --git a/tests/amdgpu/cs_tests.c b/tests/amdgpu/cs_tests.c index 82c55aa8..7ad0f0dc 100644 --- a/tests/amdgpu/cs_tests.c +++ b/tests/amdgpu/cs_tests.c @@ -21,10 +21,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdio.h> #include "CUnit/Basic.h" @@ -32,7 +28,7 @@ #include "util_math.h" #include "amdgpu_test.h" -#include "uvd_messages.h" +#include "decode_messages.h" #include "amdgpu_drm.h" #include "amdgpu_internal.h" @@ -66,6 +62,26 @@ CU_TestInfo cs_tests[] = { CU_TEST_INFO_NULL, }; +CU_BOOL suite_cs_tests_enable(void) +{ + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return CU_FALSE; + + family_id = device_handle->info.family_id; + + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + + + if (family_id >= AMDGPU_FAMILY_RV || family_id == AMDGPU_FAMILY_SI) { + printf("\n\nThe ASIC NOT support UVD, suite disabled\n"); + return CU_FALSE; + } + + return CU_TRUE; +} + int suite_cs_tests_init(void) { amdgpu_bo_handle ib_result_handle; @@ -175,11 +191,11 @@ static int submit(unsigned ndw, unsigned ip) static void uvd_cmd(uint64_t addr, unsigned cmd, int *idx) { - ib_cpu[(*idx)++] = 0x3BC4; + ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC4 : 0x81C4; ib_cpu[(*idx)++] = addr; - ib_cpu[(*idx)++] = 0x3BC5; + ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC5 : 0x81C5; ib_cpu[(*idx)++] = addr >> 32; - ib_cpu[(*idx)++] = 0x3BC3; + ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC3 : 0x81C3; ib_cpu[(*idx)++] = cmd << 1; } @@ -211,10 +227,13 @@ static void amdgpu_cs_uvd_create(void) CU_ASSERT_EQUAL(r, 0); memcpy(msg, uvd_create_msg, sizeof(uvd_create_msg)); + if (family_id >= AMDGPU_FAMILY_VI) { ((uint8_t*)msg)[0x10] = 7; - /* chip polaris 10/11 */ - if (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A) { + /* chip beyond polaris 10/11 */ + if ((family_id == AMDGPU_FAMILY_AI) || + (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A || + chip_id == chip_rev+0x64)) { /* dpb size */ ((uint8_t*)msg)[0x28] = 0x00; ((uint8_t*)msg)[0x29] = 0x94; @@ -250,7 +269,7 @@ static void amdgpu_cs_uvd_create(void) static void amdgpu_cs_uvd_decode(void) { - const unsigned dpb_size = 15923584, ctx_size = 5287680, dt_size = 737280; + const unsigned dpb_size = 15923584, dt_size = 737280; uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, ctx_addr, dt_addr, it_addr; struct amdgpu_bo_alloc_request req = {0}; amdgpu_bo_handle buf_handle; @@ -286,14 +305,18 @@ static void amdgpu_cs_uvd_decode(void) r = amdgpu_bo_cpu_map(buf_handle, (void **)&ptr); CU_ASSERT_EQUAL(r, 0); - memcpy(ptr, uvd_decode_msg, sizeof(uvd_create_msg)); + memcpy(ptr, uvd_decode_msg, sizeof(uvd_decode_msg)); + memcpy(ptr + sizeof(uvd_decode_msg), avc_decode_msg, sizeof(avc_decode_msg)); + if (family_id >= AMDGPU_FAMILY_VI) { ptr[0x10] = 7; ptr[0x98] = 0x00; ptr[0x99] = 0x02; - /* chip polaris10/11 */ - if (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A) { - /*dpb size */ + /* chip beyond polaris10/11 */ + if ((family_id == AMDGPU_FAMILY_AI) || + (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A || + chip_id == chip_rev+0x64)) { + /* dpb size */ ptr[0x24] = 0x00; ptr[0x25] = 0x94; ptr[0x26] = 0x6B; @@ -335,9 +358,12 @@ static void amdgpu_cs_uvd_decode(void) bs_addr = fb_addr + 4*1024; dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024); - if ((family_id >= AMDGPU_FAMILY_VI) && - (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A)) { - ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024); + if (family_id >= AMDGPU_FAMILY_VI) { + if ((family_id == AMDGPU_FAMILY_AI) || + (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A || + chip_id == chip_rev+0x64)) { + ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024); + } } dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024); @@ -348,12 +374,16 @@ static void amdgpu_cs_uvd_decode(void) uvd_cmd(dt_addr, 0x2, &i); uvd_cmd(fb_addr, 0x3, &i); uvd_cmd(bs_addr, 0x100, &i); + if (family_id >= AMDGPU_FAMILY_VI) { uvd_cmd(it_addr, 0x204, &i); - if (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A) + if ((family_id == AMDGPU_FAMILY_AI) || + (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A || + chip_id == chip_rev+0x64)) uvd_cmd(ctx_addr, 0x206, &i); -} - ib_cpu[i++] = 0x3BC6; + } + + ib_cpu[i++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC6 : 0x81C6; ib_cpu[i++] = 0x1; for (; i % 16; ++i) ib_cpu[i] = 0x80000000; @@ -364,7 +394,7 @@ static void amdgpu_cs_uvd_decode(void) /* TODO: use a real CRC32 */ for (i = 0, sum = 0; i < dt_size; ++i) sum += ptr[i]; - CU_ASSERT_EQUAL(sum, 0x20345d8); + CU_ASSERT_EQUAL(sum, SUM_DECODE); r = amdgpu_bo_cpu_unmap(buf_handle); CU_ASSERT_EQUAL(r, 0); diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c new file mode 100644 index 00000000..a6c2635d --- /dev/null +++ b/tests/amdgpu/deadlock_tests.c @@ -0,0 +1,379 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#endif + +#include "CUnit/Basic.h" + +#include "amdgpu_test.h" +#include "amdgpu_drm.h" +#include "amdgpu_internal.h" + +#include <pthread.h> + + +/* + * This defines the delay in MS after which memory location designated for + * compression against reference value is written to, unblocking command + * processor + */ +#define WRITE_MEM_ADDRESS_DELAY_MS 100 + +#define PACKET_TYPE3 3 + +#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ + (((op) & 0xFF) << 8) | \ + ((n) & 0x3FFF) << 16) + +#define PACKET3_WAIT_REG_MEM 0x3C +#define WAIT_REG_MEM_FUNCTION(x) ((x) << 0) + /* 0 - always + * 1 - < + * 2 - <= + * 3 - == + * 4 - != + * 5 - >= + * 6 - > + */ +#define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4) + /* 0 - reg + * 1 - mem + */ +#define WAIT_REG_MEM_OPERATION(x) ((x) << 6) + /* 0 - wait_reg_mem + * 1 - wr_wait_wr_reg + */ +#define WAIT_REG_MEM_ENGINE(x) ((x) << 8) + /* 0 - me + * 1 - pfp + */ + +#define PACKET3_WRITE_DATA 0x37 +#define WRITE_DATA_DST_SEL(x) ((x) << 8) + /* 0 - register + * 1 - memory (sync - via GRBM) + * 2 - gl2 + * 3 - gds + * 4 - reserved + * 5 - memory (async - direct) + */ +#define WR_ONE_ADDR (1 << 16) +#define WR_CONFIRM (1 << 20) +#define WRITE_DATA_CACHE_POLICY(x) ((x) << 25) + /* 0 - LRU + * 1 - Stream + */ +#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30) + /* 0 - me + * 1 - pfp + * 2 - ce + */ + +#define mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x54f + +static amdgpu_device_handle device_handle; +static uint32_t major_version; +static uint32_t minor_version; + +static pthread_t stress_thread; +static uint32_t *ptr; + +int use_uc_mtype = 0; + +static void amdgpu_deadlock_helper(unsigned ip_type); +static void amdgpu_deadlock_gfx(void); +static void amdgpu_deadlock_compute(void); +static void amdgpu_illegal_reg_access(); +static void amdgpu_illegal_mem_access(); + +CU_BOOL suite_deadlock_tests_enable(void) +{ + CU_BOOL enable = CU_TRUE; + + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return CU_FALSE; + + /* + * Only enable for ASICs supporting GPU reset and for which it's enabled + * by default (currently GFX8/9 dGPUS) + */ + if (device_handle->info.family_id != AMDGPU_FAMILY_VI && + device_handle->info.family_id != AMDGPU_FAMILY_AI && + device_handle->info.family_id != AMDGPU_FAMILY_CI) { + printf("\n\nGPU reset is not enabled for the ASIC, deadlock suite disabled\n"); + enable = CU_FALSE; + } + + if (device_handle->info.family_id >= AMDGPU_FAMILY_AI) + use_uc_mtype = 1; + + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + + return enable; +} + +int suite_deadlock_tests_init(void) +{ + int r; + + r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle); + + if (r) { + if ((r == -EACCES) && (errno == EACCES)) + printf("\n\nError:%s. " + "Hint:Try to run this test program as root.", + strerror(errno)); + return CUE_SINIT_FAILED; + } + + return CUE_SUCCESS; +} + +int suite_deadlock_tests_clean(void) +{ + int r = amdgpu_device_deinitialize(device_handle); + + if (r == 0) + return CUE_SUCCESS; + else + return CUE_SCLEAN_FAILED; +} + + +CU_TestInfo deadlock_tests[] = { + { "gfx ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_gfx }, + { "compute ring block test (set amdgpu.lockup_timeout=50)", amdgpu_deadlock_compute }, + { "illegal reg access test", amdgpu_illegal_reg_access }, + { "illegal mem access test (set amdgpu.vm_fault_stop=2)", amdgpu_illegal_mem_access }, + CU_TEST_INFO_NULL, +}; + +static void *write_mem_address(void *data) +{ + int i; + + /* useconds_t range is [0, 1,000,000] so use loop for waits > 1s */ + for (i = 0; i < WRITE_MEM_ADDRESS_DELAY_MS; i++) + usleep(1000); + + ptr[256] = 0x1; + + return 0; +} + +static void amdgpu_deadlock_gfx(void) +{ + amdgpu_deadlock_helper(AMDGPU_HW_IP_GFX); +} + +static void amdgpu_deadlock_compute(void) +{ + amdgpu_deadlock_helper(AMDGPU_HW_IP_COMPUTE); +} + +static void amdgpu_deadlock_helper(unsigned ip_type) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle ib_result_handle; + void *ib_result_cpu; + uint64_t ib_result_mc_address; + struct amdgpu_cs_request ibs_request; + struct amdgpu_cs_ib_info ib_info; + struct amdgpu_cs_fence fence_status; + uint32_t expired; + int i, r; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle; + + r = pthread_create(&stress_thread, NULL, write_mem_address, NULL); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map_raw(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, use_uc_mtype ? AMDGPU_VM_MTYPE_UC : 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL, + &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ptr = ib_result_cpu; + + ptr[0] = PACKET3(PACKET3_WAIT_REG_MEM, 5); + ptr[1] = (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */ + WAIT_REG_MEM_FUNCTION(4) | /* != */ + WAIT_REG_MEM_ENGINE(0)); /* me */ + ptr[2] = (ib_result_mc_address + 256*4) & 0xfffffffc; + ptr[3] = ((ib_result_mc_address + 256*4) >> 32) & 0xffffffff; + ptr[4] = 0x00000000; /* reference value */ + ptr[5] = 0xffffffff; /* and mask */ + ptr[6] = 0x00000004; /* poll interval */ + + for (i = 7; i < 16; ++i) + ptr[i] = 0xffff1000; + + + ptr[256] = 0x0; /* the memory we wait on to change */ + + + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address; + ib_info.size = 16; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = ip_type; + ibs_request.ring = 0; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + ibs_request.fence_info.handle = NULL; + + for (i = 0; i < 200; i++) { + r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1); + CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); + + } + + memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence)); + fence_status.context = context_handle; + fence_status.ip_type = ip_type; + fence_status.ip_instance = 0; + fence_status.ring = 0; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE,0, &expired); + CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); + + pthread_join(stress_thread, NULL); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void bad_access_helper(int reg_access) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle ib_result_handle; + void *ib_result_cpu; + uint64_t ib_result_mc_address; + struct amdgpu_cs_request ibs_request; + struct amdgpu_cs_ib_info ib_info; + struct amdgpu_cs_fence fence_status; + uint32_t expired; + int i, r; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_alloc_and_map_raw(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL, + &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ptr = ib_result_cpu; + i = 0; + + ptr[i++] = PACKET3(PACKET3_WRITE_DATA, 3); + ptr[i++] = (reg_access ? WRITE_DATA_DST_SEL(0) : WRITE_DATA_DST_SEL(5))| WR_CONFIRM; + ptr[i++] = reg_access ? mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR : 0xdeadbee0; + ptr[i++] = 0; + ptr[i++] = 0xdeadbeef; + + for (; i < 16; ++i) + ptr[i] = 0xffff1000; + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address; + ib_info.size = 16; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = 0; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + ibs_request.fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1); + CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); + + + memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence)); + fence_status.context = context_handle; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.ip_instance = 0; + fence_status.ring = 0; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE,0, &expired); + CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_illegal_reg_access() +{ + bad_access_helper(1); +} + +static void amdgpu_illegal_mem_access() +{ + bad_access_helper(0); +} diff --git a/tests/amdgpu/uvd_messages.h b/tests/amdgpu/decode_messages.h index 00235cbb..bd6fe4b6 100644 --- a/tests/amdgpu/uvd_messages.h +++ b/tests/amdgpu/decode_messages.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Advanced Micro Devices, Inc. + * Copyright 2017 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,8 +21,10 @@ * */ -#ifndef _UVD_MESSAGES_H_ -#define _UVD_MESSAGES_H_ +#ifndef _DECODE_MESSAGES_H_ +#define _DECODE_MESSAGES_H_ + +#define SUM_DECODE 0x20345d8 static const uint8_t uvd_create_msg[] = { 0xe4,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00, @@ -356,6 +358,9 @@ static const uint8_t uvd_decode_msg[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +static const uint8_t avc_decode_msg[] = { 0x02,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x88,0x00,0x00,0x00, 0x01,0x00,0x00,0x01,0x00,0x03,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, @@ -810,4 +815,34 @@ static const uint8_t uvd_it_scaling_table[] = { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, }; -#endif /* _UVD_MESSAGES_H_ */ +static const uint8_t vcn_dec_create_msg[] = { + 0x28,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00, + 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x60,0x03,0x00,0x00,0xe0,0x01,0x00,0x00, +}; + +static const uint8_t vcn_dec_decode_msg[] = { + 0x28,0x00,0x00,0x00,0x90,0x06,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x03,0x00,0x44,0x40,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x38,0x00,0x00,0x00, + 0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0xec,0x00,0x00,0x00, + 0x5c,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x60,0x03,0x00,0x00,0xe0,0x01,0x00,0x00,0x80,0x05,0x00,0x00,0x00,0x94,0x6b,0x00, + 0x96,0x4e,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x50,0x00, + 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x80,0x07,0x00,0x00,0x60,0x09,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +static const uint8_t vcn_dec_destroy_msg[] = { + 0x28,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00, +}; + +#endif /* _DECODE_MESSAGES_H_ */ diff --git a/tests/amdgpu/frame.h b/tests/amdgpu/frame.h index 4c946c27..335401c1 100644 --- a/tests/amdgpu/frame.h +++ b/tests/amdgpu/frame.h @@ -24,7 +24,7 @@ #ifndef _frame_h_ #define _frame_h_ -const uint8_t frame[] = { +static const uint8_t frame[] = { 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa, diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build new file mode 100644 index 00000000..4c1237c6 --- /dev/null +++ b/tests/amdgpu/meson.build @@ -0,0 +1,34 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if dep_cunit.found() + amdgpu_test = executable( + 'amdgpu_test', + files( + 'amdgpu_test.c', 'basic_tests.c', 'bo_tests.c', 'cs_tests.c', + 'vce_tests.c', 'uvd_enc_tests.c', 'vcn_tests.c', 'deadlock_tests.c', + 'vm_tests.c', + ), + dependencies : [dep_cunit, dep_threads], + include_directories : [inc_root, inc_drm, include_directories('../../amdgpu')], + link_with : [libdrm, libdrm_amdgpu], + install : with_install_tests, + ) +endif diff --git a/tests/amdgpu/uvd_enc_tests.c b/tests/amdgpu/uvd_enc_tests.c new file mode 100644 index 00000000..b4251bcf --- /dev/null +++ b/tests/amdgpu/uvd_enc_tests.c @@ -0,0 +1,491 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include <stdio.h> +#include <inttypes.h> + +#include "CUnit/Basic.h" + +#include "util_math.h" + +#include "amdgpu_test.h" +#include "amdgpu_drm.h" +#include "amdgpu_internal.h" +#include "frame.h" +#include "uve_ib.h" + +#define IB_SIZE 4096 +#define MAX_RESOURCES 16 + +struct amdgpu_uvd_enc_bo { + amdgpu_bo_handle handle; + amdgpu_va_handle va_handle; + uint64_t addr; + uint64_t size; + uint8_t *ptr; +}; + +struct amdgpu_uvd_enc { + unsigned width; + unsigned height; + struct amdgpu_uvd_enc_bo session; + struct amdgpu_uvd_enc_bo vbuf; + struct amdgpu_uvd_enc_bo bs; + struct amdgpu_uvd_enc_bo fb; + struct amdgpu_uvd_enc_bo cpb; +}; + +static amdgpu_device_handle device_handle; +static uint32_t major_version; +static uint32_t minor_version; +static uint32_t family_id; + +static amdgpu_context_handle context_handle; +static amdgpu_bo_handle ib_handle; +static amdgpu_va_handle ib_va_handle; +static uint64_t ib_mc_address; +static uint32_t *ib_cpu; + +static struct amdgpu_uvd_enc enc; +static amdgpu_bo_handle resources[MAX_RESOURCES]; +static unsigned num_resources; + +static void amdgpu_cs_uvd_enc_create(void); +static void amdgpu_cs_uvd_enc_session_init(void); +static void amdgpu_cs_uvd_enc_encode(void); +static void amdgpu_cs_uvd_enc_destroy(void); + + +CU_TestInfo uvd_enc_tests[] = { + { "UVD ENC create", amdgpu_cs_uvd_enc_create }, + { "UVD ENC session init", amdgpu_cs_uvd_enc_session_init }, + { "UVD ENC encode", amdgpu_cs_uvd_enc_encode }, + { "UVD ENC destroy", amdgpu_cs_uvd_enc_destroy }, + CU_TEST_INFO_NULL, +}; + +CU_BOOL suite_uvd_enc_tests_enable(void) +{ + int r; + struct drm_amdgpu_info_hw_ip info; + + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return CU_FALSE; + + r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_UVD_ENC, 0, &info); + + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + + if (!info.available_rings) + printf("\n\nThe ASIC NOT support UVD ENC, suite disabled.\n"); + + return (r == 0 && (info.available_rings ? CU_TRUE : CU_FALSE)); +} + + +int suite_uvd_enc_tests_init(void) +{ + int r; + + r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle); + if (r) + return CUE_SINIT_FAILED; + + family_id = device_handle->info.family_id; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + if (r) + return CUE_SINIT_FAILED; + + r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_handle, (void**)&ib_cpu, + &ib_mc_address, &ib_va_handle); + if (r) + return CUE_SINIT_FAILED; + + return CUE_SUCCESS; +} + +int suite_uvd_enc_tests_clean(void) +{ + int r; + + r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle, + ib_mc_address, IB_SIZE); + if (r) + return CUE_SCLEAN_FAILED; + + r = amdgpu_cs_ctx_free(context_handle); + if (r) + return CUE_SCLEAN_FAILED; + + r = amdgpu_device_deinitialize(device_handle); + if (r) + return CUE_SCLEAN_FAILED; + + return CUE_SUCCESS; +} + +static int submit(unsigned ndw, unsigned ip) +{ + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info = {0}; + struct amdgpu_cs_fence fence_status = {0}; + uint32_t expired; + int r; + + ib_info.ib_mc_address = ib_mc_address; + ib_info.size = ndw; + + ibs_request.ip_type = ip; + + r = amdgpu_bo_list_create(device_handle, num_resources, resources, + NULL, &ibs_request.resources); + if (r) + return r; + + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + if (r) + return r; + + r = amdgpu_bo_list_destroy(ibs_request.resources); + if (r) + return r; + + fence_status.context = context_handle; + fence_status.ip_type = ip; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + if (r) + return r; + + return 0; +} + +static void alloc_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo, + unsigned size, unsigned domain) +{ + struct amdgpu_bo_alloc_request req = {0}; + amdgpu_bo_handle buf_handle; + amdgpu_va_handle va_handle; + uint64_t va = 0; + int r; + + req.alloc_size = ALIGN(size, 4096); + req.preferred_heap = domain; + r = amdgpu_bo_alloc(device_handle, &req, &buf_handle); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_va_range_alloc(device_handle, + amdgpu_gpu_va_range_general, + req.alloc_size, 1, 0, &va, + &va_handle, 0); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, + AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + uvd_enc_bo->addr = va; + uvd_enc_bo->handle = buf_handle; + uvd_enc_bo->size = req.alloc_size; + uvd_enc_bo->va_handle = va_handle; + r = amdgpu_bo_cpu_map(uvd_enc_bo->handle, (void **)&uvd_enc_bo->ptr); + CU_ASSERT_EQUAL(r, 0); + memset(uvd_enc_bo->ptr, 0, size); + r = amdgpu_bo_cpu_unmap(uvd_enc_bo->handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void free_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo) +{ + int r; + + r = amdgpu_bo_va_op(uvd_enc_bo->handle, 0, uvd_enc_bo->size, + uvd_enc_bo->addr, 0, AMDGPU_VA_OP_UNMAP); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_va_range_free(uvd_enc_bo->va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_free(uvd_enc_bo->handle); + CU_ASSERT_EQUAL(r, 0); + memset(uvd_enc_bo, 0, sizeof(*uvd_enc_bo)); +} + +static void amdgpu_cs_uvd_enc_create(void) +{ + enc.width = 160; + enc.height = 128; + + num_resources = 0; + alloc_resource(&enc.session, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT); + resources[num_resources++] = enc.session.handle; + resources[num_resources++] = ib_handle; +} + +static void check_result(struct amdgpu_uvd_enc *enc) +{ + uint64_t sum; + uint32_t s = 175602; + uint32_t *ptr, size; + int j, r; + + r = amdgpu_bo_cpu_map(enc->fb.handle, (void **)&enc->fb.ptr); + CU_ASSERT_EQUAL(r, 0); + ptr = (uint32_t *)enc->fb.ptr; + size = ptr[6]; + r = amdgpu_bo_cpu_unmap(enc->fb.handle); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_cpu_map(enc->bs.handle, (void **)&enc->bs.ptr); + CU_ASSERT_EQUAL(r, 0); + for (j = 0, sum = 0; j < size; ++j) + sum += enc->bs.ptr[j]; + CU_ASSERT_EQUAL(sum, s); + r = amdgpu_bo_cpu_unmap(enc->bs.handle); + CU_ASSERT_EQUAL(r, 0); + +} + +static void amdgpu_cs_uvd_enc_session_init(void) +{ + int len, r; + + len = 0; + memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); + len += sizeof(uve_session_info) / 4; + ib_cpu[len++] = enc.session.addr >> 32; + ib_cpu[len++] = enc.session.addr; + + memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); + len += sizeof(uve_task_info) / 4; + ib_cpu[len++] = 0x000000d8; + ib_cpu[len++] = 0x00000000; + ib_cpu[len++] = 0x00000000; + + memcpy((ib_cpu + len), uve_op_init, sizeof(uve_op_init)); + len += sizeof(uve_op_init) / 4; + + memcpy((ib_cpu + len), uve_session_init, sizeof(uve_session_init)); + len += sizeof(uve_session_init) / 4; + + memcpy((ib_cpu + len), uve_layer_ctrl, sizeof(uve_layer_ctrl)); + len += sizeof(uve_layer_ctrl) / 4; + + memcpy((ib_cpu + len), uve_slice_ctrl, sizeof(uve_slice_ctrl)); + len += sizeof(uve_slice_ctrl) / 4; + + memcpy((ib_cpu + len), uve_spec_misc, sizeof(uve_spec_misc)); + len += sizeof(uve_spec_misc) / 4; + + memcpy((ib_cpu + len), uve_rc_session_init, sizeof(uve_rc_session_init)); + len += sizeof(uve_rc_session_init) / 4; + + memcpy((ib_cpu + len), uve_deblocking_filter, sizeof(uve_deblocking_filter)); + len += sizeof(uve_deblocking_filter) / 4; + + memcpy((ib_cpu + len), uve_quality_params, sizeof(uve_quality_params)); + len += sizeof(uve_quality_params) / 4; + + memcpy((ib_cpu + len), uve_op_init_rc, sizeof(uve_op_init_rc)); + len += sizeof(uve_op_init_rc) / 4; + + memcpy((ib_cpu + len), uve_op_init_rc_vbv_level, sizeof(uve_op_init_rc_vbv_level)); + len += sizeof(uve_op_init_rc_vbv_level) / 4; + + r = submit(len, AMDGPU_HW_IP_UVD_ENC); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_cs_uvd_enc_encode(void) +{ + int len, r, i; + uint64_t luma_offset, chroma_offset; + uint32_t vbuf_size, bs_size = 0x003f4800, cpb_size; + unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; + vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5; + cpb_size = vbuf_size * 10; + + + num_resources = 0; + alloc_resource(&enc.fb, 4096, AMDGPU_GEM_DOMAIN_VRAM); + resources[num_resources++] = enc.fb.handle; + alloc_resource(&enc.bs, bs_size, AMDGPU_GEM_DOMAIN_VRAM); + resources[num_resources++] = enc.bs.handle; + alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM); + resources[num_resources++] = enc.vbuf.handle; + alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM); + resources[num_resources++] = enc.cpb.handle; + resources[num_resources++] = ib_handle; + + r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr); + CU_ASSERT_EQUAL(r, 0); + + memset(enc.vbuf.ptr, 0, vbuf_size); + for (i = 0; i < enc.height; ++i) { + memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width); + enc.vbuf.ptr += ALIGN(enc.width, align); + } + for (i = 0; i < enc.height / 2; ++i) { + memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width); + enc.vbuf.ptr += ALIGN(enc.width, align); + } + + r = amdgpu_bo_cpu_unmap(enc.vbuf.handle); + CU_ASSERT_EQUAL(r, 0); + + len = 0; + memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); + len += sizeof(uve_session_info) / 4; + ib_cpu[len++] = enc.session.addr >> 32; + ib_cpu[len++] = enc.session.addr; + + memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); + len += sizeof(uve_task_info) / 4; + ib_cpu[len++] = 0x000005e0; + ib_cpu[len++] = 0x00000001; + ib_cpu[len++] = 0x00000001; + + memcpy((ib_cpu + len), uve_nalu_buffer_1, sizeof(uve_nalu_buffer_1)); + len += sizeof(uve_nalu_buffer_1) / 4; + + memcpy((ib_cpu + len), uve_nalu_buffer_2, sizeof(uve_nalu_buffer_2)); + len += sizeof(uve_nalu_buffer_2) / 4; + + memcpy((ib_cpu + len), uve_nalu_buffer_3, sizeof(uve_nalu_buffer_3)); + len += sizeof(uve_nalu_buffer_3) / 4; + + memcpy((ib_cpu + len), uve_nalu_buffer_4, sizeof(uve_nalu_buffer_4)); + len += sizeof(uve_nalu_buffer_4) / 4; + + memcpy((ib_cpu + len), uve_slice_header, sizeof(uve_slice_header)); + len += sizeof(uve_slice_header) / 4; + + ib_cpu[len++] = 0x00000254; + ib_cpu[len++] = 0x00000010; + ib_cpu[len++] = enc.cpb.addr >> 32; + ib_cpu[len++] = enc.cpb.addr; + memcpy((ib_cpu + len), uve_ctx_buffer, sizeof(uve_ctx_buffer)); + len += sizeof(uve_ctx_buffer) / 4; + + memcpy((ib_cpu + len), uve_bitstream_buffer, sizeof(uve_bitstream_buffer)); + len += sizeof(uve_bitstream_buffer) / 4; + ib_cpu[len++] = 0x00000000; + ib_cpu[len++] = enc.bs.addr >> 32; + ib_cpu[len++] = enc.bs.addr; + ib_cpu[len++] = 0x003f4800; + ib_cpu[len++] = 0x00000000; + + memcpy((ib_cpu + len), uve_feedback_buffer, sizeof(uve_feedback_buffer)); + len += sizeof(uve_feedback_buffer) / 4; + ib_cpu[len++] = enc.fb.addr >> 32; + ib_cpu[len++] = enc.fb.addr; + ib_cpu[len++] = 0x00000010; + ib_cpu[len++] = 0x00000028; + + memcpy((ib_cpu + len), uve_feedback_buffer_additional, sizeof(uve_feedback_buffer_additional)); + len += sizeof(uve_feedback_buffer_additional) / 4; + + memcpy((ib_cpu + len), uve_intra_refresh, sizeof(uve_intra_refresh)); + len += sizeof(uve_intra_refresh) / 4; + + memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select)); + len += sizeof(uve_layer_select) / 4; + + memcpy((ib_cpu + len), uve_rc_layer_init, sizeof(uve_rc_layer_init)); + len += sizeof(uve_rc_layer_init) / 4; + + memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select)); + len += sizeof(uve_layer_select) / 4; + + memcpy((ib_cpu + len), uve_rc_per_pic, sizeof(uve_rc_per_pic)); + len += sizeof(uve_rc_per_pic) / 4; + + unsigned luma_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16); + luma_offset = enc.vbuf.addr; + chroma_offset = luma_offset + luma_size; + ib_cpu[len++] = 0x00000054; + ib_cpu[len++] = 0x0000000c; + ib_cpu[len++] = 0x00000002; + ib_cpu[len++] = 0x003f4800; + ib_cpu[len++] = luma_offset >> 32; + ib_cpu[len++] = luma_offset; + ib_cpu[len++] = chroma_offset >> 32; + ib_cpu[len++] = chroma_offset; + memcpy((ib_cpu + len), uve_encode_param, sizeof(uve_encode_param)); + ib_cpu[len] = ALIGN(enc.width, align); + ib_cpu[len + 1] = ALIGN(enc.width, align); + len += sizeof(uve_encode_param) / 4; + + memcpy((ib_cpu + len), uve_op_speed_enc_mode, sizeof(uve_op_speed_enc_mode)); + len += sizeof(uve_op_speed_enc_mode) / 4; + + memcpy((ib_cpu + len), uve_op_encode, sizeof(uve_op_encode)); + len += sizeof(uve_op_encode) / 4; + + r = submit(len, AMDGPU_HW_IP_UVD_ENC); + CU_ASSERT_EQUAL(r, 0); + + check_result(&enc); + + free_resource(&enc.fb); + free_resource(&enc.bs); + free_resource(&enc.vbuf); + free_resource(&enc.cpb); +} + +static void amdgpu_cs_uvd_enc_destroy(void) +{ + int len, r; + + num_resources = 0; + resources[num_resources++] = ib_handle; + + len = 0; + memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); + len += sizeof(uve_session_info) / 4; + ib_cpu[len++] = enc.session.addr >> 32; + ib_cpu[len++] = enc.session.addr; + + memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); + len += sizeof(uve_task_info) / 4; + ib_cpu[len++] = 0xffffffff; + ib_cpu[len++] = 0x00000002; + ib_cpu[len++] = 0x00000000; + + memcpy((ib_cpu + len), uve_op_close, sizeof(uve_op_close)); + len += sizeof(uve_op_close) / 4; + + r = submit(len, AMDGPU_HW_IP_UVD_ENC); + CU_ASSERT_EQUAL(r, 0); + + free_resource(&enc.session); +} diff --git a/tests/amdgpu/uve_ib.h b/tests/amdgpu/uve_ib.h new file mode 100644 index 00000000..cb72be22 --- /dev/null +++ b/tests/amdgpu/uve_ib.h @@ -0,0 +1,527 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#ifndef _uve_ib_h_ +#define _uve_ib_h_ + +static const uint32_t uve_session_info[] = { + 0x00000018, + 0x00000001, + 0x00000000, + 0x00010000, +}; + +static const uint32_t uve_task_info[] = { + 0x00000014, + 0x00000002, +}; + +static const uint32_t uve_session_init[] = { + 0x00000020, + 0x00000003, + 0x000000c0, + 0x00000080, + 0x00000020, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const uint32_t uve_layer_ctrl[] = { + 0x00000010, + 0x00000004, + 0x00000001, + 0x00000001, +}; + +static const uint32_t uve_layer_select[] = { + 0x0000000c, + 0x00000005, + 0x00000000, +}; + +static const uint32_t uve_slice_ctrl[] = { + 0x00000014, + 0x00000006, + 0x00000000, + 0x00000006, + 0x00000006, +}; + +static const uint32_t uve_spec_misc[] = { + 0x00000024, + 0x00000007, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000001, + 0x00000001, +}; + +static const uint32_t uve_rc_session_init[] = { + 0x00000010, + 0x00000008, + 0x00000000, + 0x00000040, +}; + +static const uint32_t uve_rc_layer_init[] = { + 0x00000028, + 0x00000009, + 0x001e8480, + 0x001e8480, + 0x0000001e, + 0x00000001, + 0x0001046a, + 0x0001046a, + 0x0001046a, + 0xaaaaaaaa, +}; + +static const uint32_t uve_deblocking_filter[] = { + 0x00000020, + 0x0000000e, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const uint32_t uve_quality_params[] = { + 0x00000014, + 0x0000000d, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const uint32_t uve_feedback_buffer[] = { + 0x0000001c, + 0x00000012, + 0x00000000, +}; + +static const uint32_t uve_feedback_buffer_additional[] = { + 0x00000108, + 0x00000014, + 0x00000001, + 0x00000010, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const uint32_t uve_nalu_buffer_1[] = { + 0x00000018, + 0x00000013, + 0x00000001, + 0x00000007, + 0x00000001, + 0x46011000, +}; + +static const uint32_t uve_nalu_buffer_2[] = { + 0x0000002c, + 0x00000013, + 0x00000002, + 0x0000001b, + 0x00000001, + 0x40010c01, + 0xffff0160, + 0x00000300, + 0xb0000003, + 0x00000300, + 0x962c0900, +}; + +static const uint32_t uve_nalu_buffer_3[] = { + 0x00000034, + 0x00000013, + 0x00000003, + 0x00000023, + 0x00000001, + 0x42010101, + 0x60000003, + 0x00b00000, + 0x03000003, + 0x0096a018, + 0x2020708f, + 0xcb924295, + 0x12e08000, +}; + +static const uint32_t uve_nalu_buffer_4[] = { + 0x0000001c, + 0x00000013, + 0x00000004, + 0x0000000b, + 0x00000001, + 0x4401e0f1, + 0x80992000, +}; + +static const uint32_t uve_slice_header[] = { + 0x000000c8, + 0x0000000b, + 0x28010000, + 0x40000000, + 0x60000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000002, + 0x00000010, + 0x00000003, + 0x00000000, + 0x00000002, + 0x00000002, + 0x00000004, + 0x00000000, + 0x00000001, + 0x00000000, + 0x00000002, + 0x00000003, + 0x00000005, + 0x00000000, + 0x00000002, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const uint32_t uve_encode_param[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xffffffff, + 0x00000001, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const uint32_t uve_intra_refresh[] = { + 0x00000014, + 0x0000000f, + 0x00000000, + 0x00000000, + 0x00000001, +}; + +static const uint32_t uve_ctx_buffer[] = { + 0x00000000, + 0x00000000, + 0x000000a0, + 0x000000a0, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +static const uint32_t uve_bitstream_buffer[] = { + 0x0000001c, + 0x00000011, +}; + +static const uint32_t uve_rc_per_pic[] = { + 0x00000024, + 0x0000000a, + 0x0000001a, + 0x00000000, + 0x00000033, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000001, +}; + +static const uint32_t uve_op_init[] = { + 0x00000008, + 0x08000001, +}; + +static const uint32_t uve_op_close[] = { + 0x00000008, + 0x08000002, +}; + +static const uint32_t uve_op_encode[] = { + 0x00000008, + 0x08000003, +}; + +static const uint32_t uve_op_init_rc[] = { + 0x00000008, + 0x08000004, +}; + +static const uint32_t uve_op_init_rc_vbv_level[] = { + 0x00000008, + 0x08000005, +}; + +static const uint32_t uve_op_speed_enc_mode[] = { + 0x00000008, + 0x08000006, +}; + +static const uint32_t uve_op_balance_enc_mode[] = { + 0x00000008, + 0x08000007, +}; + +static const uint32_t uve_op_quality_enc_mode[] = { + 0x00000008, + 0x08000008, +}; +#endif /*_uve_ib_h*/ diff --git a/tests/amdgpu/vce_ib.h b/tests/amdgpu/vce_ib.h index 80ab1795..f3108a04 100644 --- a/tests/amdgpu/vce_ib.h +++ b/tests/amdgpu/vce_ib.h @@ -315,4 +315,21 @@ static const uint32_t vce_destroy[] = { 0x00000008, 0x02000001, }; + +static const uint32_t vce_mv_buffer[] = { + 0x00000038, + 0x0500000d, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; #endif /*_vce_ib_h*/ diff --git a/tests/amdgpu/vce_tests.c b/tests/amdgpu/vce_tests.c index de63aa15..b9e15ee9 100644 --- a/tests/amdgpu/vce_tests.c +++ b/tests/amdgpu/vce_tests.c @@ -21,10 +21,6 @@ * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdio.h> #include <inttypes.h> @@ -41,6 +37,7 @@ #define IB_SIZE 4096 #define MAX_RESOURCES 16 +#define FW_53_0_03 ((53 << 24) | (0 << 16) | (03 << 8)) struct amdgpu_vce_bo { amdgpu_bo_handle handle; @@ -59,6 +56,9 @@ struct amdgpu_vce_encode { struct amdgpu_vce_bo cpb; unsigned ib_len; bool two_instance; + struct amdgpu_vce_bo mvrefbuf; + struct amdgpu_vce_bo mvb; + unsigned mvbuf_size; }; static amdgpu_device_handle device_handle; @@ -66,6 +66,10 @@ static uint32_t major_version; static uint32_t minor_version; static uint32_t family_id; static uint32_t vce_harvest_config; +static uint32_t chip_rev; +static uint32_t chip_id; +static uint32_t ids_flags; +static bool is_mv_supported = true; static amdgpu_context_handle context_handle; static amdgpu_bo_handle ib_handle; @@ -79,15 +83,61 @@ static unsigned num_resources; static void amdgpu_cs_vce_create(void); static void amdgpu_cs_vce_encode(void); +static void amdgpu_cs_vce_encode_mv(void); static void amdgpu_cs_vce_destroy(void); CU_TestInfo vce_tests[] = { { "VCE create", amdgpu_cs_vce_create }, { "VCE encode", amdgpu_cs_vce_encode }, + { "VCE MV dump", amdgpu_cs_vce_encode_mv }, { "VCE destroy", amdgpu_cs_vce_destroy }, CU_TEST_INFO_NULL, }; +CU_BOOL suite_vce_tests_enable(void) +{ + uint32_t version, feature; + CU_BOOL ret_mv = CU_FALSE; + + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return CU_FALSE; + + family_id = device_handle->info.family_id; + chip_rev = device_handle->info.chip_rev; + chip_id = device_handle->info.chip_external_rev; + ids_flags = device_handle->info.ids_flags; + + amdgpu_query_firmware_version(device_handle, AMDGPU_INFO_FW_VCE, 0, + 0, &version, &feature); + + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + + if (family_id >= AMDGPU_FAMILY_RV || family_id == AMDGPU_FAMILY_SI) { + printf("\n\nThe ASIC NOT support VCE, suite disabled\n"); + return CU_FALSE; + } + + if (!(chip_id == (chip_rev + 0x3C) || /* FIJI */ + chip_id == (chip_rev + 0x50) || /* Polaris 10*/ + chip_id == (chip_rev + 0x5A) || /* Polaris 11*/ + chip_id == (chip_rev + 0x64) || /* Polaris 12*/ + (family_id >= AMDGPU_FAMILY_AI && !ids_flags))) /* dGPU > Polaris */ + printf("\n\nThe ASIC NOT support VCE MV, suite disabled\n"); + else if (FW_53_0_03 > version) + printf("\n\nThe ASIC FW version NOT support VCE MV, suite disabled\n"); + else + ret_mv = CU_TRUE; + + if (ret_mv == CU_FALSE) { + amdgpu_set_test_active("VCE Tests", "VCE MV dump", ret_mv); + is_mv_supported = false; + } + + return CU_TRUE; +} + int suite_vce_tests_init(void) { int r; @@ -234,6 +284,7 @@ static void free_resource(struct amdgpu_vce_bo *vce_bo) static void amdgpu_cs_vce_create(void) { + unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; int len, r; enc.width = vce_create[6]; @@ -250,6 +301,14 @@ static void amdgpu_cs_vce_create(void) memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo)); len += sizeof(vce_taskinfo) / 4; memcpy((ib_cpu + len), vce_create, sizeof(vce_create)); + ib_cpu[len + 8] = ALIGN(enc.width, align); + ib_cpu[len + 9] = ALIGN(enc.width, align); + if (is_mv_supported == true) {/* disableTwoInstance */ + if (family_id >= AMDGPU_FAMILY_AI) + ib_cpu[len + 11] = 0x01000001; + else + ib_cpu[len + 11] = 0x01000201; + } len += sizeof(vce_create) / 4; memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback)); ib_cpu[len + 2] = enc.fb[0].addr >> 32; @@ -281,20 +340,24 @@ static void amdgpu_cs_vce_config(void) memcpy((ib_cpu + len), vce_rdo, sizeof(vce_rdo)); len += sizeof(vce_rdo) / 4; memcpy((ib_cpu + len), vce_pic_ctrl, sizeof(vce_pic_ctrl)); + if (is_mv_supported == true) + ib_cpu[len + 27] = 0x00000001; /* encSliceMode */ len += sizeof(vce_pic_ctrl) / 4; r = submit(len, AMDGPU_HW_IP_VCE); CU_ASSERT_EQUAL(r, 0); } -static void amdgpu_cs_vce_encode_idr(struct amdgpu_vce_encode *enc) +static void amdgpu_cs_vce_encode_idr(struct amdgpu_vce_encode *enc) { uint64_t luma_offset, chroma_offset; - int len = 0, r; + unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; + unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16); + int len = 0, i, r; luma_offset = enc->vbuf.addr; - chroma_offset = luma_offset + enc->width * enc->height; + chroma_offset = luma_offset + luma_size; memcpy((ib_cpu + len), vce_session, sizeof(vce_session)); len += sizeof(vce_session) / 4; @@ -309,6 +372,10 @@ static void amdgpu_cs_vce_encode_idr(struct amdgpu_vce_encode *enc) ib_cpu[len + 3] = enc->cpb.addr; len += sizeof(vce_context_buffer) / 4; memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer)); + for (i = 0; i < 8; ++i) + ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2); + for (i = 0; i < 8; ++i) + ib_cpu[len + 10 + i] = luma_size * 1.5; len += sizeof(vce_aux_buffer) / 4; memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback)); ib_cpu[len + 2] = enc->fb[0].addr >> 32; @@ -319,8 +386,10 @@ static void amdgpu_cs_vce_encode_idr(struct amdgpu_vce_encode *enc) ib_cpu[len + 10] = luma_offset; ib_cpu[len + 11] = chroma_offset >> 32; ib_cpu[len + 12] = chroma_offset; - ib_cpu[len + 73] = 0x7800; - ib_cpu[len + 74] = 0x7800 + 0x5000; + ib_cpu[len + 14] = ALIGN(enc->width, align); + ib_cpu[len + 15] = ALIGN(enc->width, align); + ib_cpu[len + 73] = luma_size * 1.5; + ib_cpu[len + 74] = luma_size * 2.5; len += sizeof(vce_encode) / 4; enc->ib_len = len; if (!enc->two_instance) { @@ -332,11 +401,13 @@ static void amdgpu_cs_vce_encode_idr(struct amdgpu_vce_encode *enc) static void amdgpu_cs_vce_encode_p(struct amdgpu_vce_encode *enc) { uint64_t luma_offset, chroma_offset; - int len, r; + int len, i, r; + unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; + unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16); len = (enc->two_instance) ? enc->ib_len : 0; luma_offset = enc->vbuf.addr; - chroma_offset = luma_offset + enc->width * enc->height; + chroma_offset = luma_offset + luma_size; if (!enc->two_instance) { memcpy((ib_cpu + len), vce_session, sizeof(vce_session)); @@ -353,6 +424,10 @@ static void amdgpu_cs_vce_encode_p(struct amdgpu_vce_encode *enc) ib_cpu[len + 3] = enc->cpb.addr; len += sizeof(vce_context_buffer) / 4; memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer)); + for (i = 0; i < 8; ++i) + ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2); + for (i = 0; i < 8; ++i) + ib_cpu[len + 10 + i] = luma_size * 1.5; len += sizeof(vce_aux_buffer) / 4; memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback)); ib_cpu[len + 2] = enc->fb[1].addr >> 32; @@ -364,15 +439,17 @@ static void amdgpu_cs_vce_encode_p(struct amdgpu_vce_encode *enc) ib_cpu[len + 10] = luma_offset; ib_cpu[len + 11] = chroma_offset >> 32; ib_cpu[len + 12] = chroma_offset; + ib_cpu[len + 14] = ALIGN(enc->width, align); + ib_cpu[len + 15] = ALIGN(enc->width, align); ib_cpu[len + 18] = 0; ib_cpu[len + 19] = 0; ib_cpu[len + 56] = 3; ib_cpu[len + 57] = 0; ib_cpu[len + 58] = 0; - ib_cpu[len + 59] = 0x7800; - ib_cpu[len + 60] = 0x7800 + 0x5000; + ib_cpu[len + 59] = luma_size * 1.5; + ib_cpu[len + 60] = luma_size * 2.5; ib_cpu[len + 73] = 0; - ib_cpu[len + 74] = 0x5000; + ib_cpu[len + 74] = luma_size; ib_cpu[len + 81] = 1; ib_cpu[len + 82] = 1; len += sizeof(vce_encode) / 4; @@ -408,9 +485,10 @@ static void check_result(struct amdgpu_vce_encode *enc) static void amdgpu_cs_vce_encode(void) { uint32_t vbuf_size, bs_size = 0x154000, cpb_size; - int r; + unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; + int i, r; - vbuf_size = enc.width * enc.height * 1.5; + vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5; cpb_size = vbuf_size * 10; num_resources = 0; alloc_resource(&enc.fb[0], 4096, AMDGPU_GEM_DOMAIN_GTT); @@ -429,7 +507,17 @@ static void amdgpu_cs_vce_encode(void) r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr); CU_ASSERT_EQUAL(r, 0); - memcpy(enc.vbuf.ptr, frame, sizeof(frame)); + + memset(enc.vbuf.ptr, 0, vbuf_size); + for (i = 0; i < enc.height; ++i) { + memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width); + enc.vbuf.ptr += ALIGN(enc.width, align); + } + for (i = 0; i < enc.height / 2; ++i) { + memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width); + enc.vbuf.ptr += ALIGN(enc.width, align); + } + r = amdgpu_bo_cpu_unmap(enc.vbuf.handle); CU_ASSERT_EQUAL(r, 0); @@ -474,6 +562,180 @@ static void amdgpu_cs_vce_encode(void) free_resource(&enc.cpb); } +static void amdgpu_cs_vce_mv(struct amdgpu_vce_encode *enc) +{ + uint64_t luma_offset, chroma_offset; + uint64_t mv_ref_luma_offset; + unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; + unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16); + int len = 0, i, r; + + luma_offset = enc->vbuf.addr; + chroma_offset = luma_offset + luma_size; + mv_ref_luma_offset = enc->mvrefbuf.addr; + + memcpy((ib_cpu + len), vce_session, sizeof(vce_session)); + len += sizeof(vce_session) / 4; + memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo)); + len += sizeof(vce_taskinfo) / 4; + memcpy((ib_cpu + len), vce_bs_buffer, sizeof(vce_bs_buffer)); + ib_cpu[len + 2] = enc->bs[0].addr >> 32; + ib_cpu[len + 3] = enc->bs[0].addr; + len += sizeof(vce_bs_buffer) / 4; + memcpy((ib_cpu + len), vce_context_buffer, sizeof(vce_context_buffer)); + ib_cpu[len + 2] = enc->cpb.addr >> 32; + ib_cpu[len + 3] = enc->cpb.addr; + len += sizeof(vce_context_buffer) / 4; + memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer)); + for (i = 0; i < 8; ++i) + ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2); + for (i = 0; i < 8; ++i) + ib_cpu[len + 10 + i] = luma_size * 1.5; + len += sizeof(vce_aux_buffer) / 4; + memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback)); + ib_cpu[len + 2] = enc->fb[0].addr >> 32; + ib_cpu[len + 3] = enc->fb[0].addr; + len += sizeof(vce_feedback) / 4; + memcpy((ib_cpu + len), vce_mv_buffer, sizeof(vce_mv_buffer)); + ib_cpu[len + 2] = mv_ref_luma_offset >> 32; + ib_cpu[len + 3] = mv_ref_luma_offset; + ib_cpu[len + 4] = ALIGN(enc->width, align); + ib_cpu[len + 5] = ALIGN(enc->width, align); + ib_cpu[len + 6] = luma_size; + ib_cpu[len + 7] = enc->mvb.addr >> 32; + ib_cpu[len + 8] = enc->mvb.addr; + len += sizeof(vce_mv_buffer) / 4; + memcpy((ib_cpu + len), vce_encode, sizeof(vce_encode)); + ib_cpu[len + 2] = 0; + ib_cpu[len + 3] = 0; + ib_cpu[len + 4] = 0x154000; + ib_cpu[len + 9] = luma_offset >> 32; + ib_cpu[len + 10] = luma_offset; + ib_cpu[len + 11] = chroma_offset >> 32; + ib_cpu[len + 12] = chroma_offset; + ib_cpu[len + 13] = ALIGN(enc->height, 16);; + ib_cpu[len + 14] = ALIGN(enc->width, align); + ib_cpu[len + 15] = ALIGN(enc->width, align); + /* encDisableMBOffloading-encDisableTwoPipeMode-encInputPicArrayMode-encInputPicAddrMode */ + ib_cpu[len + 16] = 0x01010000; + ib_cpu[len + 18] = 0; /* encPicType */ + ib_cpu[len + 19] = 0; /* encIdrFlag */ + ib_cpu[len + 20] = 0; /* encIdrPicId */ + ib_cpu[len + 21] = 0; /* encMGSKeyPic */ + ib_cpu[len + 22] = 0; /* encReferenceFlag */ + ib_cpu[len + 23] = 0; /* encTemporalLayerIndex */ + ib_cpu[len + 55] = 0; /* pictureStructure */ + ib_cpu[len + 56] = 0; /* encPicType -ref[0] */ + ib_cpu[len + 61] = 0; /* pictureStructure */ + ib_cpu[len + 62] = 0; /* encPicType -ref[1] */ + ib_cpu[len + 67] = 0; /* pictureStructure */ + ib_cpu[len + 68] = 0; /* encPicType -ref1 */ + ib_cpu[len + 81] = 1; /* frameNumber */ + ib_cpu[len + 82] = 2; /* pictureOrderCount */ + ib_cpu[len + 83] = 0xffffffff; /* numIPicRemainInRCGOP */ + ib_cpu[len + 84] = 0xffffffff; /* numPPicRemainInRCGOP */ + ib_cpu[len + 85] = 0xffffffff; /* numBPicRemainInRCGOP */ + ib_cpu[len + 86] = 0xffffffff; /* numIRPicRemainInRCGOP */ + ib_cpu[len + 87] = 0; /* remainedIntraRefreshPictures */ + len += sizeof(vce_encode) / 4; + + enc->ib_len = len; + r = submit(len, AMDGPU_HW_IP_VCE); + CU_ASSERT_EQUAL(r, 0); +} + +static void check_mv_result(struct amdgpu_vce_encode *enc) +{ + uint64_t sum; + uint32_t s = 140790; + uint32_t *ptr, size; + int i, j, r; + + r = amdgpu_bo_cpu_map(enc->fb[0].handle, (void **)&enc->fb[0].ptr); + CU_ASSERT_EQUAL(r, 0); + ptr = (uint32_t *)enc->fb[0].ptr; + r = amdgpu_bo_cpu_unmap(enc->fb[0].handle); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_cpu_map(enc->mvb.handle, (void **)&enc->mvb.ptr); + CU_ASSERT_EQUAL(r, 0); + for (j = 0, sum = 0; j < enc->mvbuf_size; ++j) + sum += enc->mvb.ptr[j]; + CU_ASSERT_EQUAL(sum, s); + r = amdgpu_bo_cpu_unmap(enc->mvb.handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_cs_vce_encode_mv(void) +{ + uint32_t vbuf_size, bs_size = 0x154000, cpb_size; + unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; + int i, r; + + vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5; + enc.mvbuf_size = ALIGN(enc.width, 16) * ALIGN(enc.height, 16) / 8; + cpb_size = vbuf_size * 10; + num_resources = 0; + alloc_resource(&enc.fb[0], 4096, AMDGPU_GEM_DOMAIN_GTT); + resources[num_resources++] = enc.fb[0].handle; + alloc_resource(&enc.bs[0], bs_size, AMDGPU_GEM_DOMAIN_GTT); + resources[num_resources++] = enc.bs[0].handle; + alloc_resource(&enc.mvb, enc.mvbuf_size, AMDGPU_GEM_DOMAIN_GTT); + resources[num_resources++] = enc.mvb.handle; + alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM); + resources[num_resources++] = enc.vbuf.handle; + alloc_resource(&enc.mvrefbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM); + resources[num_resources++] = enc.mvrefbuf.handle; + alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM); + resources[num_resources++] = enc.cpb.handle; + resources[num_resources++] = ib_handle; + + r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr); + CU_ASSERT_EQUAL(r, 0); + + memset(enc.vbuf.ptr, 0, vbuf_size); + for (i = 0; i < enc.height; ++i) { + memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width); + enc.vbuf.ptr += ALIGN(enc.width, align); + } + for (i = 0; i < enc.height / 2; ++i) { + memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width); + enc.vbuf.ptr += ALIGN(enc.width, align); + } + + r = amdgpu_bo_cpu_unmap(enc.vbuf.handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_cpu_map(enc.mvrefbuf.handle, (void **)&enc.mvrefbuf.ptr); + CU_ASSERT_EQUAL(r, 0); + + memset(enc.mvrefbuf.ptr, 0, vbuf_size); + for (i = 0; i < enc.height; ++i) { + memcpy(enc.mvrefbuf.ptr, (frame + (enc.height - i -1) * enc.width), enc.width); + enc.mvrefbuf.ptr += ALIGN(enc.width, align); + } + for (i = 0; i < enc.height / 2; ++i) { + memcpy(enc.mvrefbuf.ptr, + ((frame + enc.height * enc.width) + (enc.height / 2 - i -1) * enc.width), enc.width); + enc.mvrefbuf.ptr += ALIGN(enc.width, align); + } + + r = amdgpu_bo_cpu_unmap(enc.mvrefbuf.handle); + CU_ASSERT_EQUAL(r, 0); + + amdgpu_cs_vce_config(); + + vce_taskinfo[3] = 3; + amdgpu_cs_vce_mv(&enc); + check_mv_result(&enc); + + free_resource(&enc.fb[0]); + free_resource(&enc.bs[0]); + free_resource(&enc.vbuf); + free_resource(&enc.cpb); + free_resource(&enc.mvrefbuf); + free_resource(&enc.mvb); +} + static void amdgpu_cs_vce_destroy(void) { int len, r; diff --git a/tests/amdgpu/vcn_tests.c b/tests/amdgpu/vcn_tests.c new file mode 100644 index 00000000..859ec496 --- /dev/null +++ b/tests/amdgpu/vcn_tests.c @@ -0,0 +1,404 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include <stdio.h> +#include <inttypes.h> + +#include "CUnit/Basic.h" + +#include "util_math.h" + +#include "amdgpu_test.h" +#include "amdgpu_drm.h" +#include "amdgpu_internal.h" +#include "decode_messages.h" + +#define IB_SIZE 4096 +#define MAX_RESOURCES 16 + +struct amdgpu_vcn_bo { + amdgpu_bo_handle handle; + amdgpu_va_handle va_handle; + uint64_t addr; + uint64_t size; + uint8_t *ptr; +}; + +static amdgpu_device_handle device_handle; +static uint32_t major_version; +static uint32_t minor_version; +static uint32_t family_id; + +static amdgpu_context_handle context_handle; +static amdgpu_bo_handle ib_handle; +static amdgpu_va_handle ib_va_handle; +static uint64_t ib_mc_address; +static uint32_t *ib_cpu; + +static amdgpu_bo_handle resources[MAX_RESOURCES]; +static unsigned num_resources; + +static void amdgpu_cs_vcn_dec_create(void); +static void amdgpu_cs_vcn_dec_decode(void); +static void amdgpu_cs_vcn_dec_destroy(void); + +static void amdgpu_cs_vcn_enc_create(void); +static void amdgpu_cs_vcn_enc_encode(void); +static void amdgpu_cs_vcn_enc_destroy(void); + +CU_TestInfo vcn_tests[] = { + + { "VCN DEC create", amdgpu_cs_vcn_dec_create }, + { "VCN DEC decode", amdgpu_cs_vcn_dec_decode }, + { "VCN DEC destroy", amdgpu_cs_vcn_dec_destroy }, + + { "VCN ENC create", amdgpu_cs_vcn_enc_create }, + { "VCN ENC decode", amdgpu_cs_vcn_enc_encode }, + { "VCN ENC destroy", amdgpu_cs_vcn_enc_destroy }, + CU_TEST_INFO_NULL, +}; + +CU_BOOL suite_vcn_tests_enable(void) +{ + + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return CU_FALSE; + + family_id = device_handle->info.family_id; + + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + + + if (family_id < AMDGPU_FAMILY_RV) { + printf("\n\nThe ASIC NOT support VCN, suite disabled\n"); + return CU_FALSE; + } + + return CU_TRUE; +} + +int suite_vcn_tests_init(void) +{ + int r; + + r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle); + if (r) + return CUE_SINIT_FAILED; + + family_id = device_handle->info.family_id; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + if (r) + return CUE_SINIT_FAILED; + + r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_handle, (void**)&ib_cpu, + &ib_mc_address, &ib_va_handle); + if (r) + return CUE_SINIT_FAILED; + + return CUE_SUCCESS; +} + +int suite_vcn_tests_clean(void) +{ + int r; + + r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle, + ib_mc_address, IB_SIZE); + if (r) + return CUE_SCLEAN_FAILED; + + r = amdgpu_cs_ctx_free(context_handle); + if (r) + return CUE_SCLEAN_FAILED; + + r = amdgpu_device_deinitialize(device_handle); + if (r) + return CUE_SCLEAN_FAILED; + + return CUE_SUCCESS; +} + +static int submit(unsigned ndw, unsigned ip) +{ + struct amdgpu_cs_request ibs_request = {0}; + struct amdgpu_cs_ib_info ib_info = {0}; + struct amdgpu_cs_fence fence_status = {0}; + uint32_t expired; + int r; + + ib_info.ib_mc_address = ib_mc_address; + ib_info.size = ndw; + + ibs_request.ip_type = ip; + + r = amdgpu_bo_list_create(device_handle, num_resources, resources, + NULL, &ibs_request.resources); + if (r) + return r; + + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); + if (r) + return r; + + r = amdgpu_bo_list_destroy(ibs_request.resources); + if (r) + return r; + + fence_status.context = context_handle; + fence_status.ip_type = ip; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE, + 0, &expired); + if (r) + return r; + + return 0; +} + +static void alloc_resource(struct amdgpu_vcn_bo *vcn_bo, + unsigned size, unsigned domain) +{ + struct amdgpu_bo_alloc_request req = {0}; + amdgpu_bo_handle buf_handle; + amdgpu_va_handle va_handle; + uint64_t va = 0; + int r; + + req.alloc_size = ALIGN(size, 4096); + req.preferred_heap = domain; + r = amdgpu_bo_alloc(device_handle, &req, &buf_handle); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_va_range_alloc(device_handle, + amdgpu_gpu_va_range_general, + req.alloc_size, 1, 0, &va, + &va_handle, 0); + CU_ASSERT_EQUAL(r, 0); + r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, + AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + vcn_bo->addr = va; + vcn_bo->handle = buf_handle; + vcn_bo->size = req.alloc_size; + vcn_bo->va_handle = va_handle; + r = amdgpu_bo_cpu_map(vcn_bo->handle, (void **)&vcn_bo->ptr); + CU_ASSERT_EQUAL(r, 0); + memset(vcn_bo->ptr, 0, size); + r = amdgpu_bo_cpu_unmap(vcn_bo->handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void free_resource(struct amdgpu_vcn_bo *vcn_bo) +{ + int r; + + r = amdgpu_bo_va_op(vcn_bo->handle, 0, vcn_bo->size, + vcn_bo->addr, 0, AMDGPU_VA_OP_UNMAP); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_va_range_free(vcn_bo->va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_free(vcn_bo->handle); + CU_ASSERT_EQUAL(r, 0); + memset(vcn_bo, 0, sizeof(*vcn_bo)); +} + +static void vcn_dec_cmd(uint64_t addr, unsigned cmd, int *idx) +{ + ib_cpu[(*idx)++] = 0x81C4; + ib_cpu[(*idx)++] = addr; + ib_cpu[(*idx)++] = 0x81C5; + ib_cpu[(*idx)++] = addr >> 32; + ib_cpu[(*idx)++] = 0x81C3; + ib_cpu[(*idx)++] = cmd << 1; +} + +static void amdgpu_cs_vcn_dec_create(void) +{ + struct amdgpu_vcn_bo msg_buf; + int len, r; + + num_resources = 0; + alloc_resource(&msg_buf, 4096, AMDGPU_GEM_DOMAIN_GTT); + resources[num_resources++] = msg_buf.handle; + resources[num_resources++] = ib_handle; + + r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr); + CU_ASSERT_EQUAL(r, 0); + + memset(msg_buf.ptr, 0, 4096); + memcpy(msg_buf.ptr, vcn_dec_create_msg, sizeof(vcn_dec_create_msg)); + + len = 0; + ib_cpu[len++] = 0x81C4; + ib_cpu[len++] = msg_buf.addr; + ib_cpu[len++] = 0x81C5; + ib_cpu[len++] = msg_buf.addr >> 32; + ib_cpu[len++] = 0x81C3; + ib_cpu[len++] = 0; + for (; len % 16; ) { + ib_cpu[len++] = 0x81ff; + ib_cpu[len++] = 0; + } + + r = submit(len, AMDGPU_HW_IP_VCN_DEC); + CU_ASSERT_EQUAL(r, 0); + + free_resource(&msg_buf); +} + +static void amdgpu_cs_vcn_dec_decode(void) +{ + const unsigned dpb_size = 15923584, dt_size = 737280; + uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, ctx_addr, dt_addr, it_addr, sum; + struct amdgpu_vcn_bo dec_buf; + int size, len, i, r; + uint8_t *dec; + + size = 4*1024; /* msg */ + size += 4*1024; /* fb */ + size += 4096; /*it_scaling_table*/ + size += ALIGN(sizeof(uvd_bitstream), 4*1024); + size += ALIGN(dpb_size, 4*1024); + size += ALIGN(dt_size, 4*1024); + + num_resources = 0; + alloc_resource(&dec_buf, size, AMDGPU_GEM_DOMAIN_GTT); + resources[num_resources++] = dec_buf.handle; + resources[num_resources++] = ib_handle; + + r = amdgpu_bo_cpu_map(dec_buf.handle, (void **)&dec_buf.ptr); + dec = dec_buf.ptr; + + CU_ASSERT_EQUAL(r, 0); + memset(dec_buf.ptr, 0, size); + memcpy(dec_buf.ptr, vcn_dec_decode_msg, sizeof(vcn_dec_decode_msg)); + memcpy(dec_buf.ptr + sizeof(vcn_dec_decode_msg), + avc_decode_msg, sizeof(avc_decode_msg)); + + dec += 4*1024; + dec += 4*1024; + memcpy(dec, uvd_it_scaling_table, sizeof(uvd_it_scaling_table)); + + dec += 4*1024; + memcpy(dec, uvd_bitstream, sizeof(uvd_bitstream)); + + dec += ALIGN(sizeof(uvd_bitstream), 4*1024); + + dec += ALIGN(dpb_size, 4*1024); + + msg_addr = dec_buf.addr; + fb_addr = msg_addr + 4*1024; + it_addr = fb_addr + 4*1024; + bs_addr = it_addr + 4*1024; + dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024); + ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024); + dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024); + + len = 0; + vcn_dec_cmd(msg_addr, 0x0, &len); + vcn_dec_cmd(dpb_addr, 0x1, &len); + vcn_dec_cmd(dt_addr, 0x2, &len); + vcn_dec_cmd(fb_addr, 0x3, &len); + vcn_dec_cmd(bs_addr, 0x100, &len); + vcn_dec_cmd(it_addr, 0x204, &len); + vcn_dec_cmd(ctx_addr, 0x206, &len); + + ib_cpu[len++] = 0x81C6; + ib_cpu[len++] = 0x1; + for (; len % 16; ) { + ib_cpu[len++] = 0x81ff; + ib_cpu[len++] = 0; + } + + r = submit(len, AMDGPU_HW_IP_VCN_DEC); + CU_ASSERT_EQUAL(r, 0); + + for (i = 0, sum = 0; i < dt_size; ++i) + sum += dec[i]; + + CU_ASSERT_EQUAL(sum, SUM_DECODE); + + free_resource(&dec_buf); +} + +static void amdgpu_cs_vcn_dec_destroy(void) +{ + struct amdgpu_vcn_bo msg_buf; + int len, r; + + num_resources = 0; + alloc_resource(&msg_buf, 1024, AMDGPU_GEM_DOMAIN_GTT); + resources[num_resources++] = msg_buf.handle; + resources[num_resources++] = ib_handle; + + r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr); + CU_ASSERT_EQUAL(r, 0); + + memset(msg_buf.ptr, 0, 1024); + memcpy(msg_buf.ptr, vcn_dec_destroy_msg, sizeof(vcn_dec_destroy_msg)); + + len = 0; + ib_cpu[len++] = 0x81C4; + ib_cpu[len++] = msg_buf.addr; + ib_cpu[len++] = 0x81C5; + ib_cpu[len++] = msg_buf.addr >> 32; + ib_cpu[len++] = 0x81C3; + ib_cpu[len++] = 0; + for (; len % 16; ) { + ib_cpu[len++] = 0x81ff; + ib_cpu[len++] = 0; + } + + r = submit(len, AMDGPU_HW_IP_VCN_DEC); + CU_ASSERT_EQUAL(r, 0); + + free_resource(&msg_buf); +} + +static void amdgpu_cs_vcn_enc_create(void) +{ + /* TODO */ +} + +static void amdgpu_cs_vcn_enc_encode(void) +{ + /* TODO */ +} + +static void amdgpu_cs_vcn_enc_destroy(void) +{ + /* TODO */ +} diff --git a/tests/amdgpu/vm_tests.c b/tests/amdgpu/vm_tests.c new file mode 100644 index 00000000..69bc4683 --- /dev/null +++ b/tests/amdgpu/vm_tests.c @@ -0,0 +1,255 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include "CUnit/Basic.h" + +#include "amdgpu_test.h" +#include "amdgpu_drm.h" +#include "amdgpu_internal.h" + +static amdgpu_device_handle device_handle; +static uint32_t major_version; +static uint32_t minor_version; + +static void amdgpu_vmid_reserve_test(void); +static void amdgpu_vm_unaligned_map(void); +static void amdgpu_vm_mapping_test(void); + +CU_BOOL suite_vm_tests_enable(void) +{ + CU_BOOL enable = CU_TRUE; + + if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle)) + return CU_FALSE; + + if (device_handle->info.family_id == AMDGPU_FAMILY_SI) { + printf("\n\nCurrently hangs the CP on this ASIC, VM suite disabled\n"); + enable = CU_FALSE; + } + + if (amdgpu_device_deinitialize(device_handle)) + return CU_FALSE; + + return enable; +} + +int suite_vm_tests_init(void) +{ + int r; + + r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, + &minor_version, &device_handle); + + if (r) { + if ((r == -EACCES) && (errno == EACCES)) + printf("\n\nError:%s. " + "Hint:Try to run this test program as root.", + strerror(errno)); + return CUE_SINIT_FAILED; + } + + return CUE_SUCCESS; +} + +int suite_vm_tests_clean(void) +{ + int r = amdgpu_device_deinitialize(device_handle); + + if (r == 0) + return CUE_SUCCESS; + else + return CUE_SCLEAN_FAILED; +} + + +CU_TestInfo vm_tests[] = { + { "resere vmid test", amdgpu_vmid_reserve_test }, + { "unaligned map", amdgpu_vm_unaligned_map }, + { "vm mapping test", amdgpu_vm_mapping_test }, + CU_TEST_INFO_NULL, +}; + +static void amdgpu_vmid_reserve_test(void) +{ + amdgpu_context_handle context_handle; + amdgpu_bo_handle ib_result_handle; + void *ib_result_cpu; + uint64_t ib_result_mc_address; + struct amdgpu_cs_request ibs_request; + struct amdgpu_cs_ib_info ib_info; + struct amdgpu_cs_fence fence_status; + uint32_t expired, flags; + int i, r; + amdgpu_bo_list_handle bo_list; + amdgpu_va_handle va_handle; + static uint32_t *ptr; + + r = amdgpu_cs_ctx_create(device_handle, &context_handle); + CU_ASSERT_EQUAL(r, 0); + + flags = 0; + r = amdgpu_vm_reserve_vmid(device_handle, flags); + CU_ASSERT_EQUAL(r, 0); + + + r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096, + AMDGPU_GEM_DOMAIN_GTT, 0, + &ib_result_handle, &ib_result_cpu, + &ib_result_mc_address, &va_handle); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL, + &bo_list); + CU_ASSERT_EQUAL(r, 0); + + ptr = ib_result_cpu; + + for (i = 0; i < 16; ++i) + ptr[i] = 0xffff1000; + + memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); + ib_info.ib_mc_address = ib_result_mc_address; + ib_info.size = 16; + + memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); + ibs_request.ip_type = AMDGPU_HW_IP_GFX; + ibs_request.ring = 0; + ibs_request.number_of_ibs = 1; + ibs_request.ibs = &ib_info; + ibs_request.resources = bo_list; + ibs_request.fence_info.handle = NULL; + + r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1); + CU_ASSERT_EQUAL(r, 0); + + + memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence)); + fence_status.context = context_handle; + fence_status.ip_type = AMDGPU_HW_IP_GFX; + fence_status.ip_instance = 0; + fence_status.ring = 0; + fence_status.fence = ibs_request.seq_no; + + r = amdgpu_cs_query_fence_status(&fence_status, + AMDGPU_TIMEOUT_INFINITE,0, &expired); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_list_destroy(bo_list); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, + ib_result_mc_address, 4096); + CU_ASSERT_EQUAL(r, 0); + + flags = 0; + r = amdgpu_vm_unreserve_vmid(device_handle, flags); + CU_ASSERT_EQUAL(r, 0); + + + r = amdgpu_cs_ctx_free(context_handle); + CU_ASSERT_EQUAL(r, 0); +} + +static void amdgpu_vm_unaligned_map(void) +{ + const uint64_t map_size = (4ULL << 30) - (2 << 12); + struct amdgpu_bo_alloc_request request = {}; + amdgpu_bo_handle buf_handle; + amdgpu_va_handle handle; + uint64_t vmc_addr; + int r; + + request.alloc_size = 4ULL << 30; + request.phys_alignment = 4096; + request.preferred_heap = AMDGPU_GEM_DOMAIN_VRAM; + request.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS; + + r = amdgpu_bo_alloc(device_handle, &request, &buf_handle); + /* Don't let the test fail if the device doesn't have enough VRAM */ + if (r) + return; + + r = amdgpu_va_range_alloc(device_handle, amdgpu_gpu_va_range_general, + 4ULL << 30, 1ULL << 30, 0, &vmc_addr, + &handle, 0); + CU_ASSERT_EQUAL(r, 0); + if (r) + goto error_va_alloc; + + vmc_addr += 1 << 12; + + r = amdgpu_bo_va_op(buf_handle, 0, map_size, vmc_addr, 0, + AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + if (r) + goto error_va_alloc; + + amdgpu_bo_va_op(buf_handle, 0, map_size, vmc_addr, 0, + AMDGPU_VA_OP_UNMAP); + +error_va_alloc: + amdgpu_bo_free(buf_handle); +} + +static void amdgpu_vm_mapping_test(void) +{ + struct amdgpu_bo_alloc_request req = {0}; + struct drm_amdgpu_info_device dev_info; + const uint64_t size = 4096; + amdgpu_bo_handle buf; + uint64_t addr; + int r; + + req.alloc_size = size; + req.phys_alignment = 0; + req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT; + req.flags = 0; + + r = amdgpu_bo_alloc(device_handle, &req, &buf); + CU_ASSERT_EQUAL(r, 0); + + r = amdgpu_query_info(device_handle, AMDGPU_INFO_DEV_INFO, + sizeof(dev_info), &dev_info); + CU_ASSERT_EQUAL(r, 0); + + addr = dev_info.virtual_address_offset; + r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + + addr = dev_info.virtual_address_max - size; + r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + + if (dev_info.high_va_offset) { + addr = dev_info.high_va_offset; + r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + + addr = dev_info.high_va_max - size; + r = amdgpu_bo_va_op(buf, 0, size, addr, 0, AMDGPU_VA_OP_MAP); + CU_ASSERT_EQUAL(r, 0); + } + + amdgpu_bo_free(buf); +} diff --git a/tests/drmdevice.c b/tests/drmdevice.c index 9dd5098a..f1c1cd3a 100644 --- a/tests/drmdevice.c +++ b/tests/drmdevice.c @@ -36,67 +36,66 @@ static void print_device_info(drmDevicePtr device, int i, bool print_revision) { printf("device[%i]\n", i); - printf("\tavailable_nodes %04x\n", device->available_nodes); - printf("\tnodes\n"); + printf("+-> available_nodes %#04x\n", device->available_nodes); + printf("+-> nodes\n"); for (int j = 0; j < DRM_NODE_MAX; j++) if (device->available_nodes & 1 << j) - printf("\t\tnodes[%d] %s\n", j, device->nodes[j]); + printf("| +-> nodes[%d] %s\n", j, device->nodes[j]); - printf("\tbustype %04x\n", device->bustype); - printf("\tbusinfo\n"); + printf("+-> bustype %04x\n", device->bustype); if (device->bustype == DRM_BUS_PCI) { - printf("\t\tpci\n"); - printf("\t\t\tdomain\t%04x\n",device->businfo.pci->domain); - printf("\t\t\tbus\t%02x\n", device->businfo.pci->bus); - printf("\t\t\tdev\t%02x\n", device->businfo.pci->dev); - printf("\t\t\tfunc\t%1u\n", device->businfo.pci->func); - - printf("\tdeviceinfo\n"); - printf("\t\tpci\n"); - printf("\t\t\tvendor_id\t%04x\n", device->deviceinfo.pci->vendor_id); - printf("\t\t\tdevice_id\t%04x\n", device->deviceinfo.pci->device_id); - printf("\t\t\tsubvendor_id\t%04x\n", device->deviceinfo.pci->subvendor_id); - printf("\t\t\tsubdevice_id\t%04x\n", device->deviceinfo.pci->subdevice_id); + printf("| +-> pci\n"); + printf("| +-> domain %04x\n",device->businfo.pci->domain); + printf("| +-> bus %02x\n", device->businfo.pci->bus); + printf("| +-> dev %02x\n", device->businfo.pci->dev); + printf("| +-> func %1u\n", device->businfo.pci->func); + + printf("+-> deviceinfo\n"); + printf(" +-> pci\n"); + printf(" +-> vendor_id %04x\n", device->deviceinfo.pci->vendor_id); + printf(" +-> device_id %04x\n", device->deviceinfo.pci->device_id); + printf(" +-> subvendor_id %04x\n", device->deviceinfo.pci->subvendor_id); + printf(" +-> subdevice_id %04x\n", device->deviceinfo.pci->subdevice_id); if (print_revision) - printf("\t\t\trevision_id\t%02x\n", device->deviceinfo.pci->revision_id); + printf(" +-> revision_id %02x\n", device->deviceinfo.pci->revision_id); else - printf("\t\t\trevision_id\tIGNORED\n"); + printf(" +-> revision_id IGNORED\n"); } else if (device->bustype == DRM_BUS_USB) { - printf("\t\tusb\n"); - printf("\t\t\tbus\t%03u\n", device->businfo.usb->bus); - printf("\t\t\tdev\t%03u\n", device->businfo.usb->dev); - - printf("\tdeviceinfo\n"); - printf("\t\tusb\n"); - printf("\t\t\tvendor\t%04x\n", device->deviceinfo.usb->vendor); - printf("\t\t\tproduct\t%04x\n", device->deviceinfo.usb->product); + printf("| +-> usb\n"); + printf("| +-> bus %03u\n", device->businfo.usb->bus); + printf("| +-> dev %03u\n", device->businfo.usb->dev); + + printf("+-> deviceinfo\n"); + printf(" +-> usb\n"); + printf(" +-> vendor %04x\n", device->deviceinfo.usb->vendor); + printf(" +-> product %04x\n", device->deviceinfo.usb->product); } else if (device->bustype == DRM_BUS_PLATFORM) { char **compatible = device->deviceinfo.platform->compatible; - printf("\t\tplatform\n"); - printf("\t\t\tfullname\t%s\n", device->businfo.platform->fullname); + printf("| +-> platform\n"); + printf("| +-> fullname\t%s\n", device->businfo.platform->fullname); - printf("\tdeviceinfo\n"); - printf("\t\tplatform\n"); - printf("\t\t\tcompatible\n"); + printf("+-> deviceinfo\n"); + printf(" +-> platform\n"); + printf(" +-> compatible\n"); while (*compatible) { - printf("\t\t\t\t%s\n", *compatible); + printf(" %s\n", *compatible); compatible++; } } else if (device->bustype == DRM_BUS_HOST1X) { - char **compatible = device->deviceinfo.platform->compatible; + char **compatible = device->deviceinfo.host1x->compatible; - printf("\t\thost1x\n"); - printf("\t\t\tfullname\t%s\n", device->businfo.host1x->fullname); + printf("| +-> host1x\n"); + printf("| +-> fullname\t%s\n", device->businfo.host1x->fullname); - printf("\tdeviceinfo\n"); - printf("\t\tplatform\n"); - printf("\t\t\tcompatible\n"); + printf("+-> deviceinfo\n"); + printf(" +-> host1x\n"); + printf(" +-> compatible\n"); while (*compatible) { - printf("\t\t\t\t%s\n", *compatible); + printf(" %s\n", *compatible); compatible++; } } else { @@ -112,12 +111,16 @@ main(void) drmDevicePtr device; int fd, ret, max_devices; + printf("--- Checking the number of DRM device available ---\n"); max_devices = drmGetDevices2(0, NULL, 0); if (max_devices <= 0) { - printf("drmGetDevices2() has returned %d\n", max_devices); - return -1; + printf("drmGetDevices2() has not found any devices (errno=%d)\n", + -max_devices); + return 77; } + printf("--- Devices reported %d ---\n", max_devices); + devices = calloc(max_devices, sizeof(drmDevicePtr)); if (devices == NULL) { @@ -125,6 +128,7 @@ main(void) return -1; } + printf("--- Retrieving devices information (PCI device revision is ignored) ---\n"); ret = drmGetDevices2(0, devices, max_devices); if (ret < 0) { printf("drmGetDevices2() returned an error %d\n", ret); @@ -137,13 +141,14 @@ main(void) for (int j = 0; j < DRM_NODE_MAX; j++) { if (devices[i]->available_nodes & 1 << j) { - printf("Opening device %d node %s\n", i, devices[i]->nodes[j]); + printf("--- Opening device node %s ---\n", devices[i]->nodes[j]); fd = open(devices[i]->nodes[j], O_RDONLY | O_CLOEXEC, 0); if (fd < 0) { printf("Failed - %s (%d)\n", strerror(errno), errno); continue; } + printf("--- Retrieving device info, for node %s ---\n", devices[i]->nodes[j]); if (drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, &device) == 0) { print_device_info(device, i, true); drmFreeDevice(&device); diff --git a/tests/drmsl.c b/tests/drmsl.c index d0ac0efa..d1b59a86 100644 --- a/tests/drmsl.c +++ b/tests/drmsl.c @@ -106,7 +106,9 @@ static double do_time(int size, int iter) return usec; } -static void print_neighbors(void *list, unsigned long key) +static void print_neighbors(void *list, unsigned long key, + unsigned long expected_prev, + unsigned long expected_next) { unsigned long prev_key = 0; unsigned long next_key = 0; @@ -119,6 +121,16 @@ static void print_neighbors(void *list, unsigned long key) &next_key, &next_value); printf("Neighbors of %5lu: %d %5lu %5lu\n", key, retval, prev_key, next_key); + if (prev_key != expected_prev) { + fprintf(stderr, "Unexpected neighbor: %5lu. Expected: %5lu\n", + prev_key, expected_prev); + exit(1); + } + if (next_key != expected_next) { + fprintf(stderr, "Unexpected neighbor: %5lu. Expected: %5lu\n", + next_key, expected_next); + exit(1); + } } int main(void) @@ -138,13 +150,13 @@ int main(void) print(list); printf("\n==============================\n\n"); - print_neighbors(list, 0); - print_neighbors(list, 50); - print_neighbors(list, 51); - print_neighbors(list, 123); - print_neighbors(list, 200); - print_neighbors(list, 213); - print_neighbors(list, 256); + print_neighbors(list, 0, 0, 50); + print_neighbors(list, 50, 0, 50); + print_neighbors(list, 51, 50, 123); + print_neighbors(list, 123, 50, 123); + print_neighbors(list, 200, 123, 213); + print_neighbors(list, 213, 123, 213); + print_neighbors(list, 256, 213, 256); printf("\n==============================\n\n"); drmSLDelete(list, 50); diff --git a/tests/drmstat.c b/tests/drmstat.c deleted file mode 100644 index 023aa069..00000000 --- a/tests/drmstat.c +++ /dev/null @@ -1,419 +0,0 @@ -/* drmstat.c -- DRM device status and testing program - * Created: Tue Jan 5 08:19:24 1999 by faith@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: Rickard E. (Rik) Faith <faith@valinux.com> - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/mman.h> -#include <getopt.h> -#include <strings.h> -#include <errno.h> -#include <signal.h> -#include <fcntl.h> -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#endif -#include "xf86drm.h" - -int sigio_fd; - -static double usec(struct timeval *end, struct timeval *start) -{ - double e = end->tv_sec * 1000000 + end->tv_usec; - double s = start->tv_sec * 1000000 + start->tv_usec; - - return e - s; -} - -static void getversion(int fd) -{ - drmVersionPtr version; - - version = drmGetVersion(fd); - if (version) { - printf( "Name: %s\n", version->name ? version->name : "?" ); - printf( " Version: %d.%d.%d\n", - version->version_major, - version->version_minor, - version->version_patchlevel ); - printf( " Date: %s\n", version->date ? version->date : "?" ); - printf( " Desc: %s\n", version->desc ? version->desc : "?" ); - drmFreeVersion(version); - } else { - printf( "No driver available\n" ); - } -} - -static void process_sigio(char *device) -{ - int fd; - - if ((fd = open(device, 0)) < 0) { - drmError(-errno, __func__); - exit(1); - } - - sigio_fd = fd; - for (;;) sleep(60); -} - -int main(int argc, char **argv) -{ - int c; - int r = 0; - int fd = -1; - drm_handle_t handle; - void *address; - char *pt; - unsigned long count; - unsigned long offset; - unsigned long size; - drm_context_t context; - int loops; - char buf[1024]; - int i; - drmBufInfoPtr info; - drmBufMapPtr bufs; - drmLockPtr lock; - int secs; - - while ((c = getopt(argc, argv, - "lc:vo:O:f:s:w:W:b:r:R:P:L:C:XS:B:F:")) != EOF) - switch (c) { - case 'F': - count = strtoul(optarg, NULL, 0); - if (!fork()) { - dup(fd); - sleep(count); - } - close(fd); - break; - case 'v': getversion(fd); break; - case 'X': - if ((r = drmCreateContext(fd, &context))) { - drmError(r, argv[0]); - return 1; - } - printf( "Got %d\n", context); - break; - case 'S': - process_sigio(optarg); - break; - case 'C': - if ((r = drmSwitchToContext(fd, strtoul(optarg, NULL, 0)))) { - drmError(r, argv[0]); - return 1; - } - break; - case 'c': - if ((r = drmSetBusid(fd,optarg))) { - drmError(r, argv[0]); - return 1; - } - break; - case 'o': - if ((fd = drmOpen(optarg, NULL)) < 0) { - drmError(fd, argv[0]); - return 1; - } - break; - case 'O': - if ((fd = drmOpen(NULL, optarg)) < 0) { - drmError(fd, argv[0]); - return 1; - } - break; - case 'B': /* Test buffer allocation */ - count = strtoul(optarg, &pt, 0); - size = strtoul(pt+1, &pt, 0); - secs = strtoul(pt+1, NULL, 0); - { - drmDMAReq dma; - int *indices, *sizes; - - indices = alloca(sizeof(*indices) * count); - sizes = alloca(sizeof(*sizes) * count); - dma.context = context; - dma.send_count = 0; - dma.request_count = count; - dma.request_size = size; - dma.request_list = indices; - dma.request_sizes = sizes; - dma.flags = DRM_DMA_WAIT; - if ((r = drmDMA(fd, &dma))) { - drmError(r, argv[0]); - return 1; - } - for (i = 0; i < dma.granted_count; i++) { - printf("%5d: index = %d, size = %d\n", - i, dma.request_list[i], dma.request_sizes[i]); - } - sleep(secs); - drmFreeBufs(fd, dma.granted_count, indices); - } - break; - case 'b': - count = strtoul(optarg, &pt, 0); - size = strtoul(pt+1, NULL, 0); - if ((r = drmAddBufs(fd, count, size, 0, 65536)) < 0) { - drmError(r, argv[0]); - return 1; - } - if (!(info = drmGetBufInfo(fd))) { - drmError(0, argv[0]); - return 1; - } - for (i = 0; i < info->count; i++) { - printf("%5d buffers of size %6d (low = %d, high = %d)\n", - info->list[i].count, - info->list[i].size, - info->list[i].low_mark, - info->list[i].high_mark); - } - if ((r = drmMarkBufs(fd, 0.50, 0.80))) { - drmError(r, argv[0]); - return 1; - } - if (!(info = drmGetBufInfo(fd))) { - drmError(0, argv[0]); - return 1; - } - for (i = 0; i < info->count; i++) { - printf("%5d buffers of size %6d (low = %d, high = %d)\n", - info->list[i].count, - info->list[i].size, - info->list[i].low_mark, - info->list[i].high_mark); - } - printf("===== /proc/dri/0/mem =====\n"); - sprintf(buf, "cat /proc/dri/0/mem"); - system(buf); -#if 1 - if (!(bufs = drmMapBufs(fd))) { - drmError(0, argv[0]); - return 1; - } - printf("===============================\n"); - printf( "%d bufs\n", bufs->count); - for (i = 0; i < bufs->count; i++) { - printf( " %4d: %8d bytes at %p\n", - i, - bufs->list[i].total, - bufs->list[i].address); - } - printf("===== /proc/dri/0/vma =====\n"); - sprintf(buf, "cat /proc/dri/0/vma"); - system(buf); -#endif - break; - case 'f': - offset = strtoul(optarg, &pt, 0); - size = strtoul(pt+1, NULL, 0); - handle = 0; - if ((r = drmAddMap(fd, offset, size, - DRM_FRAME_BUFFER, 0, &handle))) { - drmError(r, argv[0]); - return 1; - } - printf("0x%08lx:0x%04lx added\n", offset, size); - printf("===== /proc/dri/0/mem =====\n"); - sprintf(buf, "cat /proc/dri/0/mem"); - system(buf); - break; - case 'r': - case 'R': - offset = strtoul(optarg, &pt, 0); - size = strtoul(pt+1, NULL, 0); - handle = 0; - if ((r = drmAddMap(fd, offset, size, - DRM_REGISTERS, - c == 'R' ? DRM_READ_ONLY : 0, - &handle))) { - drmError(r, argv[0]); - return 1; - } - printf("0x%08lx:0x%04lx added\n", offset, size); - printf("===== /proc/dri/0/mem =====\n"); - sprintf(buf, "cat /proc/dri/0/mem"); - system(buf); - break; - case 's': - size = strtoul(optarg, &pt, 0); - handle = 0; - if ((r = drmAddMap(fd, 0, size, - DRM_SHM, DRM_CONTAINS_LOCK, - &handle))) { - drmError(r, argv[0]); - return 1; - } - printf("0x%04lx byte shm added at 0x%08lx\n", size, handle); - sprintf(buf, "cat /proc/dri/0/vm"); - system(buf); - break; - case 'P': - offset = strtoul(optarg, &pt, 0); - size = strtoul(pt+1, NULL, 0); - address = NULL; - if ((r = drmMap(fd, offset, size, &address))) { - drmError(r, argv[0]); - return 1; - } - printf("0x%08lx:0x%04lx mapped at %p for pid %d\n", - offset, size, address, getpid()); - printf("===== /proc/dri/0/vma =====\n"); - sprintf(buf, "cat /proc/dri/0/vma"); - system(buf); - mprotect((void *)offset, size, PROT_READ); - printf("===== /proc/dri/0/vma =====\n"); - sprintf(buf, "cat /proc/dri/0/vma"); - system(buf); - break; - case 'w': - case 'W': - offset = strtoul(optarg, &pt, 0); - size = strtoul(pt+1, NULL, 0); - address = NULL; - if ((r = drmMap(fd, offset, size, &address))) { - drmError(r, argv[0]); - return 1; - } - printf("0x%08lx:0x%04lx mapped at %p for pid %d\n", - offset, size, address, getpid()); - printf("===== /proc/%d/maps =====\n", getpid()); - sprintf(buf, "cat /proc/%d/maps", getpid()); - system(buf); - printf("===== /proc/dri/0/mem =====\n"); - sprintf(buf, "cat /proc/dri/0/mem"); - system(buf); - printf("===== /proc/dri/0/vma =====\n"); - sprintf(buf, "cat /proc/dri/0/vma"); - system(buf); - printf("===== READING =====\n"); - for (i = 0; i < 0x10; i++) - printf("%02x ", (unsigned int)((unsigned char *)address)[i]); - printf("\n"); - if (c == 'w') { - printf("===== WRITING =====\n"); - for (i = 0; i < size; i+=2) { - ((char *)address)[i] = i & 0xff; - ((char *)address)[i+1] = i & 0xff; - } - } - printf("===== READING =====\n"); - for (i = 0; i < 0x10; i++) - printf("%02x ", (unsigned int)((unsigned char *)address)[i]); - printf("\n"); - printf("===== /proc/dri/0/vma =====\n"); - sprintf(buf, "cat /proc/dri/0/vma"); - system(buf); - break; - case 'L': - context = strtoul(optarg, &pt, 0); - offset = strtoul(pt+1, &pt, 0); - size = strtoul(pt+1, &pt, 0); - loops = strtoul(pt+1, NULL, 0); - address = NULL; - if ((r = drmMap(fd, offset, size, &address))) { - drmError(r, argv[0]); - return 1; - } - lock = address; -#if 1 - { - int counter = 0; - struct timeval loop_start, loop_end; - struct timeval lock_start, lock_end; - double wt; -#define HISTOSIZE 9 - int histo[HISTOSIZE]; - int output = 0; - int fast = 0; - - if (loops < 0) { - loops = -loops; - ++output; - } - - for (i = 0; i < HISTOSIZE; i++) histo[i] = 0; - - gettimeofday(&loop_start, NULL); - for (i = 0; i < loops; i++) { - gettimeofday(&lock_start, NULL); - DRM_LIGHT_LOCK_COUNT(fd,lock,context,fast); - gettimeofday(&lock_end, NULL); - DRM_UNLOCK(fd,lock,context); - ++counter; - wt = usec(&lock_end, &lock_start); - if (wt <= 2.5) ++histo[8]; - if (wt < 5.0) ++histo[0]; - else if (wt < 50.0) ++histo[1]; - else if (wt < 500.0) ++histo[2]; - else if (wt < 5000.0) ++histo[3]; - else if (wt < 50000.0) ++histo[4]; - else if (wt < 500000.0) ++histo[5]; - else if (wt < 5000000.0) ++histo[6]; - else ++histo[7]; - if (output) printf( "%.2f uSec, %d fast\n", wt, fast); - } - gettimeofday(&loop_end, NULL); - printf( "Average wait time = %.2f usec, %d fast\n", - usec(&loop_end, &loop_start) / counter, fast); - printf( "%9d <= 2.5 uS\n", histo[8]); - printf( "%9d < 5 uS\n", histo[0]); - printf( "%9d < 50 uS\n", histo[1]); - printf( "%9d < 500 uS\n", histo[2]); - printf( "%9d < 5000 uS\n", histo[3]); - printf( "%9d < 50000 uS\n", histo[4]); - printf( "%9d < 500000 uS\n", histo[5]); - printf( "%9d < 5000000 uS\n", histo[6]); - printf( "%9d >= 5000000 uS\n", histo[7]); - } -#else - printf( "before lock: 0x%08x\n", lock->lock); - printf( "lock: 0x%08x\n", lock->lock); - sleep(5); - printf( "unlock: 0x%08x\n", lock->lock); -#endif - break; - default: - fprintf( stderr, "Usage: drmstat [options]\n" ); - return 1; - } - - return r; -} - -int xf86ConfigDRI[10]; diff --git a/tests/etnaviv/Makefile.am b/tests/etnaviv/Makefile.am index 06318643..3e0c6120 100644 --- a/tests/etnaviv/Makefile.am +++ b/tests/etnaviv/Makefile.am @@ -1,4 +1,5 @@ AM_CFLAGS = \ + -fvisibility=hidden \ -I $(top_srcdir)/include/drm \ -I $(top_srcdir)/etnaviv \ -I $(top_srcdir) @@ -28,6 +29,7 @@ etnaviv_2d_test_SOURCES = \ write_bmp.h etnaviv_cmd_stream_test_LDADD = \ + $(top_builddir)/libdrm.la \ $(top_builddir)/etnaviv/libdrm_etnaviv.la etnaviv_cmd_stream_test_SOURCES = \ diff --git a/tests/etnaviv/etnaviv_2d_test.c b/tests/etnaviv/etnaviv_2d_test.c index 10751c73..8dd77b66 100644 --- a/tests/etnaviv/etnaviv_2d_test.c +++ b/tests/etnaviv/etnaviv_2d_test.c @@ -24,10 +24,6 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include <fcntl.h> #include <stdio.h> #include <string.h> diff --git a/tests/etnaviv/etnaviv_bo_cache_test.c b/tests/etnaviv/etnaviv_bo_cache_test.c index fb01f8d3..7fb06293 100644 --- a/tests/etnaviv/etnaviv_bo_cache_test.c +++ b/tests/etnaviv/etnaviv_bo_cache_test.c @@ -24,10 +24,6 @@ * Christian Gmeiner <christian.gmeiner@gmail.com> */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #undef NDEBUG #include <assert.h> diff --git a/tests/etnaviv/meson.build b/tests/etnaviv/meson.build new file mode 100644 index 00000000..8b4a3cfb --- /dev/null +++ b/tests/etnaviv/meson.build @@ -0,0 +1,45 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +inc_etnaviv_tests = [inc_root, inc_drm, include_directories('../../etnaviv')] + +etnaviv_2d_test = executable( + 'etnaviv_2d_test', + files('etnaviv_2d_test.c', 'write_bmp.c'), + include_directories : inc_etnaviv_tests, + link_with : [libdrm, libdrm_etnaviv], + install : with_install_tests, +) + +etnaviv_cmd_stream_test = executable( + 'etnaviv_cmd_stream_test', + files('etnaviv_cmd_stream_test.c'), + include_directories : inc_etnaviv_tests, + link_with : [libdrm, libdrm_etnaviv], + install : with_install_tests, +) + +etnaviv_bo_cache_test = executable( + 'etnaviv_bo_cache_test', + files('etnaviv_bo_cache_test.c'), + include_directories : inc_etnaviv_tests, + link_with : [libdrm, libdrm_etnaviv], + install : with_install_tests, +) diff --git a/tests/etnaviv/write_bmp.c b/tests/etnaviv/write_bmp.c index 7ae0646c..f7b6bc69 100644 --- a/tests/etnaviv/write_bmp.c +++ b/tests/etnaviv/write_bmp.c @@ -63,7 +63,7 @@ struct dib_header { unsigned int unused[12]; } __attribute__((__packed__)); -static int +static void bmp_header_write(int fd, int width, int height, int bgra, int noflip, int alpha) { struct bmp_header bmp_header = { @@ -98,8 +98,6 @@ bmp_header_write(int fd, int width, int height, int bgra, int noflip, int alpha) write(fd, &bmp_header, sizeof(struct bmp_header)); write(fd, &dib_header, sizeof(struct dib_header)); - - return 0; } void diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am index b6361727..9658fb42 100644 --- a/tests/exynos/Makefile.am +++ b/tests/exynos/Makefile.am @@ -1,6 +1,7 @@ AM_CFLAGS = \ -pthread \ $(WARN_CFLAGS)\ + -fvisibility=hidden \ -I $(top_srcdir)/include/drm \ -I $(top_srcdir)/libkms/ \ -I $(top_srcdir)/exynos \ diff --git a/tests/exynos/exynos_fimg2d_event.c b/tests/exynos/exynos_fimg2d_event.c index 9ed5a307..353e087b 100644 --- a/tests/exynos/exynos_fimg2d_event.c +++ b/tests/exynos/exynos_fimg2d_event.c @@ -1,17 +1,24 @@ /* * Copyright (C) 2015 - Tobias Jakobi * - * This is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 2 of the License, - * or (at your option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * It is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with it. If not, see <http://www.gnu.org/licenses/>. + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include <unistd.h> diff --git a/tests/exynos/exynos_fimg2d_perf.c b/tests/exynos/exynos_fimg2d_perf.c index 1699bba7..97691a71 100644 --- a/tests/exynos/exynos_fimg2d_perf.c +++ b/tests/exynos/exynos_fimg2d_perf.c @@ -1,17 +1,24 @@ /* * Copyright (C) 2015 - Tobias Jakobi * - * This is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 2 of the License, - * or (at your option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * It is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with it. If not, see <http://www.gnu.org/licenses/>. + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include <stdlib.h> @@ -267,13 +274,6 @@ int main(int argc, char **argv) goto out; } - if (bufw == 0 || bufh == 0) { - fprintf(stderr, "error: buffer width/height should be non-zero.\n"); - ret = -1; - - goto out; - } - fd = drmOpen("exynos", NULL); if (fd < 0) { fprintf(stderr, "error: failed to open drm\n"); diff --git a/tests/exynos/exynos_fimg2d_test.c b/tests/exynos/exynos_fimg2d_test.c index 797fb6eb..99bb9233 100644 --- a/tests/exynos/exynos_fimg2d_test.c +++ b/tests/exynos/exynos_fimg2d_test.c @@ -3,17 +3,26 @@ * Authors: * Inki Dae <inki.dae@samsung.com> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -59,7 +68,6 @@ static void connector_find_mode(int fd, struct connector *c, if (!connector) { fprintf(stderr, "could not get connector %i: %s\n", resources->connectors[i], strerror(errno)); - drmModeFreeConnector(connector); continue; } @@ -98,7 +106,6 @@ static void connector_find_mode(int fd, struct connector *c, if (!c->encoder) { fprintf(stderr, "could not get encoder %i: %s\n", resources->encoders[i], strerror(errno)); - drmModeFreeEncoder(c->encoder); continue; } @@ -264,7 +271,8 @@ static int g2d_copy_test(struct exynos_device *dev, struct exynos_bo *src, userptr = (unsigned long)malloc(size); if (!userptr) { fprintf(stderr, "failed to allocate userptr.\n"); - return -EFAULT; + ret = -EFAULT; + goto fail; } src_img.user_ptr[0].userptr = userptr; @@ -469,7 +477,8 @@ static int g2d_copy_with_scale_test(struct exynos_device *dev, userptr = (unsigned long)malloc(size); if (!userptr) { fprintf(stderr, "failed to allocate userptr.\n"); - return -EFAULT; + ret = -EFAULT; + goto fail; } src_img.user_ptr[0].userptr = userptr; @@ -520,9 +529,10 @@ err_free_userptr: fail: g2d_fini(ctx); - return 0; + return ret; } +#ifdef EXYNOS_G2D_USERPTR_TEST static int g2d_blend_test(struct exynos_device *dev, struct exynos_bo *src, struct exynos_bo *dst, @@ -557,7 +567,8 @@ static int g2d_blend_test(struct exynos_device *dev, userptr = (unsigned long)malloc(size); if (!userptr) { fprintf(stderr, "failed to allocate userptr.\n"); - return -EFAULT; + ret = -EFAULT; + goto fail; } src_img.user_ptr[0].userptr = userptr; @@ -619,8 +630,9 @@ err_free_userptr: fail: g2d_fini(ctx); - return 0; + return ret; } +#endif static int g2d_checkerboard_test(struct exynos_device *dev, struct exynos_bo *src, @@ -645,8 +657,8 @@ static int g2d_checkerboard_test(struct exynos_device *dev, dst_y = 0; checkerboard = create_checkerboard_pattern(screen_width / 32, screen_height / 32, 32); - if (checkerboard == NULL) { - ret = -1; + if (!checkerboard) { + ret = -EFAULT; goto fail; } @@ -755,8 +767,8 @@ int main(int argc, char **argv) dev = exynos_device_create(fd); if (!dev) { - drmClose(dev->fd); - return -EFAULT; + ret = -EFAULT; + goto err_drm_close; } resources = drmModeGetResources(dev->fd); @@ -764,7 +776,7 @@ int main(int argc, char **argv) fprintf(stderr, "drmModeGetResources failed: %s\n", strerror(errno)); ret = -EFAULT; - goto err_drm_close; + goto err_dev_destory; } connector_find_mode(dev->fd, &con, resources); @@ -773,7 +785,7 @@ int main(int argc, char **argv) if (!con.mode) { fprintf(stderr, "failed to find usable connector\n"); ret = -EFAULT; - goto err_drm_close; + goto err_dev_destory; } screen_width = con.mode->hdisplay; @@ -782,7 +794,7 @@ int main(int argc, char **argv) if (screen_width == 0 || screen_height == 0) { fprintf(stderr, "failed to find sane resolution on connector\n"); ret = -EFAULT; - goto err_drm_close; + goto err_dev_destory; } printf("screen width = %d, screen height = %d\n", screen_width, @@ -791,7 +803,7 @@ int main(int argc, char **argv) bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0); if (!bo) { ret = -EFAULT; - goto err_drm_close; + goto err_dev_destory; } handles[0] = bo->handle; @@ -864,7 +876,7 @@ int main(int argc, char **argv) * * Disable the test for now, until the kernel code has been sanitized. */ -#if 0 +#ifdef EXYNOS_G2D_USERPTR_TEST ret = g2d_blend_test(dev, src, bo, G2D_IMGBUF_USERPTR); if (ret < 0) fprintf(stderr, "failed to test blend operation.\n"); @@ -882,9 +894,11 @@ err_rm_fb: err_destroy_buffer: exynos_destroy_buffer(bo); -err_drm_close: - drmClose(dev->fd); +err_dev_destory: exynos_device_destroy(dev); - return 0; +err_drm_close: + drmClose(fd); + + return ret; } diff --git a/tests/exynos/meson.build b/tests/exynos/meson.build new file mode 100644 index 00000000..3a048e8a --- /dev/null +++ b/tests/exynos/meson.build @@ -0,0 +1,54 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +inc_exynos = include_directories('../../exynos') + +if with_libkms + exynos_fimg2d_test = executable( + 'exynos_fimg2d_test', + files('exynos_fimg2d_test.c'), + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm, inc_exynos, + include_directories('../../libkms')], + link_with : [libdrm, libkms, libdrm_exynos], + dependencies : dep_threads, + install : with_install_tests, + ) +endif + +exynos_fimg2d_perf = executable( + 'exynos_fimg2d_perf', + files('exynos_fimg2d_perf.c'), + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm, inc_exynos], + link_with : [libdrm, libdrm_exynos], + dependencies : dep_threads, + install : with_install_tests, +) + +exynos_fimg2d_event = executable( + 'exynos_fimg2d_event', + files('exynos_fimg2d_event.c'), + c_args : libdrm_c_args, + include_directories : [inc_root, inc_drm, inc_exynos], + link_with : [libdrm, libdrm_exynos], + dependencies : dep_threads, + install : with_install_tests, +) diff --git a/tests/kms/Makefile.am b/tests/kms/Makefile.am index 6645af7a..42242006 100644 --- a/tests/kms/Makefile.am +++ b/tests/kms/Makefile.am @@ -4,7 +4,8 @@ AM_CPPFLAGS = \ -I$(top_srcdir) AM_CFLAGS = \ - $(WARN_CFLAGS) + $(WARN_CFLAGS) \ + -fvisibility=hidden noinst_LTLIBRARIES = libkms-test.la diff --git a/tests/kms/kms-steal-crtc.c b/tests/kms/kms-steal-crtc.c index 4b830d27..cd40758d 100644 --- a/tests/kms/kms-steal-crtc.c +++ b/tests/kms/kms-steal-crtc.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <fcntl.h> #include <signal.h> diff --git a/tests/kms/kms-universal-planes.c b/tests/kms/kms-universal-planes.c index 89057bb5..2163c987 100644 --- a/tests/kms/kms-universal-planes.c +++ b/tests/kms/kms-universal-planes.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <fcntl.h> #include <getopt.h> #include <stdbool.h> diff --git a/tests/kms/libkms-test-crtc.c b/tests/kms/libkms-test-crtc.c index 3adb4903..2c28face 100644 --- a/tests/kms/libkms-test-crtc.c +++ b/tests/kms/libkms-test-crtc.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include "libkms-test.h" struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id) diff --git a/tests/kms/libkms-test-device.c b/tests/kms/libkms-test-device.c index 53c7349b..d3bb11ce 100644 --- a/tests/kms/libkms-test-device.c +++ b/tests/kms/libkms-test-device.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdio.h> #include <string.h> #include <unistd.h> @@ -67,7 +63,7 @@ static void kms_device_probe_screens(struct kms_device *device) device->screens = calloc(res->count_connectors, sizeof(screen)); if (!device->screens) - return; + goto err_free_resources; for (i = 0; i < res->count_connectors; i++) { unsigned int *count; @@ -97,6 +93,7 @@ static void kms_device_probe_screens(struct kms_device *device) device->num_screens++; } +err_free_resources: drmModeFreeResources(res); } @@ -112,7 +109,7 @@ static void kms_device_probe_crtcs(struct kms_device *device) device->crtcs = calloc(res->count_crtcs, sizeof(crtc)); if (!device->crtcs) - return; + goto err_free_resources; for (i = 0; i < res->count_crtcs; i++) { crtc = kms_crtc_create(device, res->crtcs[i]); @@ -123,6 +120,7 @@ static void kms_device_probe_crtcs(struct kms_device *device) device->num_crtcs++; } +err_free_resources: drmModeFreeResources(res); } @@ -138,7 +136,7 @@ static void kms_device_probe_planes(struct kms_device *device) device->planes = calloc(res->count_planes, sizeof(plane)); if (!device->planes) - return; + goto err_free_resources; for (i = 0; i < res->count_planes; i++) { plane = kms_plane_create(device, res->planes[i]); @@ -149,6 +147,7 @@ static void kms_device_probe_planes(struct kms_device *device) device->num_planes++; } +err_free_resources: drmModeFreePlaneResources(res); } diff --git a/tests/kms/libkms-test-framebuffer.c b/tests/kms/libkms-test-framebuffer.c index c9e5ad3c..9bb2d95b 100644 --- a/tests/kms/libkms-test-framebuffer.c +++ b/tests/kms/libkms-test-framebuffer.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <string.h> diff --git a/tests/kms/libkms-test-plane.c b/tests/kms/libkms-test-plane.c index 8eb78af1..6c40a3c9 100644 --- a/tests/kms/libkms-test-plane.c +++ b/tests/kms/libkms-test-plane.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <string.h> diff --git a/tests/kms/libkms-test-screen.c b/tests/kms/libkms-test-screen.c index 33690222..bbe972a0 100644 --- a/tests/kms/libkms-test-screen.c +++ b/tests/kms/libkms-test-screen.c @@ -21,10 +21,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <string.h> diff --git a/tests/kms/meson.build b/tests/kms/meson.build new file mode 100644 index 00000000..91371aa0 --- /dev/null +++ b/tests/kms/meson.build @@ -0,0 +1,49 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +libkms_test = static_library( + 'kms-test', + files( + 'libkms-test-crtc.c', 'libkms-test-device.c', 'libkms-test-framebuffer.c', + 'libkms-test-plane.c', 'libkms-test-screen.c', + ), + include_directories : [inc_root, inc_tests, inc_drm], + link_with : libdrm, + c_args : libdrm_c_args, +) + +kms_steal_crtc = executable( + 'kms-steal-crtc', + files('kms-steal-crtc.c'), + dependencies : dep_cairo, + include_directories : [inc_root, inc_tests, inc_drm], + link_with : [libkms_test, libutil], + install : with_install_tests, +) + +kms_universal_planes = executable( + 'kms-universal-planes', + files('kms-universal-planes.c'), + dependencies : dep_cairo, + include_directories : [inc_root, inc_tests, inc_drm], + link_with : [libkms_test], + install : with_install_tests, +) diff --git a/tests/kmstest/Makefile.am b/tests/kmstest/Makefile.am index ced541b7..4c993b04 100644 --- a/tests/kmstest/Makefile.am +++ b/tests/kmstest/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ + -fvisibility=hidden \ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/libkms/ \ -I$(top_srcdir)/tests/ \ diff --git a/tests/kmstest/meson.build b/tests/kmstest/meson.build new file mode 100644 index 00000000..4fb870f9 --- /dev/null +++ b/tests/kmstest/meson.build @@ -0,0 +1,30 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +kmstest = executable( + 'kmstest', + files('main.c'), + c_args : libdrm_c_args, + include_directories : [ + inc_root, inc_tests, include_directories('../../libkms'), inc_drm, + ], + link_with : [libutil, libkms, libdrm], + install : with_install_tests, +) diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 00000000..6c8ddd9c --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,86 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +inc_tests = include_directories('.') + +subdir('util') +subdir('kms') +subdir('modeprint') +subdir('proptest') +subdir('modetest') +subdir('vbltest') +if with_libkms + subdir('kmstest') +endif +if with_radeon + subdir('radeon') +endif +if with_amdgpu + subdir('amdgpu') +endif +if with_exynos + subdir('exynos') +endif +if with_tegra + subdir('tegra') +endif +if with_etnaviv + subdir('etnaviv') +endif +if with_nouveau + subdir('nouveau') +endif + +drmsl = executable( + 'drmsl', + files('drmsl.c'), + include_directories : [inc_root, inc_drm], + link_with : libdrm, + c_args : libdrm_c_args, +) + +hash = executable( + 'hash', + files('hash.c'), + include_directories : [inc_root, inc_drm], + link_with : libdrm, + c_args : libdrm_c_args, +) + +random = executable( + 'random', + files('random.c'), + include_directories : [inc_root, inc_drm], + link_with : libdrm, + c_args : libdrm_c_args, +) + +drmdevice = executable( + 'drmdevice', + files('drmdevice.c'), + include_directories : [inc_root, inc_drm], + link_with : libdrm, + c_args : libdrm_c_args, +) + +test('random', random, timeout : 240) +test('hash', hash) +test('drmsl', drmsl) +test('drmdevice', drmdevice) diff --git a/tests/modeprint/Makefile.am b/tests/modeprint/Makefile.am index 601dbc96..568185f0 100644 --- a/tests/modeprint/Makefile.am +++ b/tests/modeprint/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ + -fvisibility=hidden \ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/tests \ -I$(top_srcdir) @@ -15,4 +16,5 @@ endif modeprint_SOURCES = \ modeprint.c modeprint_LDADD = \ + $(top_builddir)/tests/util/libutil.la \ $(top_builddir)/libdrm.la diff --git a/tests/modeprint/meson.build b/tests/modeprint/meson.build new file mode 100644 index 00000000..0801808a --- /dev/null +++ b/tests/modeprint/meson.build @@ -0,0 +1,29 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +modeprint = executable( + 'modeprint', + files('modeprint.c'), + c_args : libdrm_c_args, + include_directories : [inc_root, inc_tests, inc_drm], + link_with : [libdrm, libutil], + dependencies : dep_threads, + install : with_install_tests, +) diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c index 0d854103..ad727e12 100644 --- a/tests/modeprint/modeprint.c +++ b/tests/modeprint/modeprint.c @@ -42,6 +42,7 @@ #include "xf86drmMode.h" #include "util/common.h" +#include "util/kms.h" int current; int connectors; @@ -54,20 +55,6 @@ int crtcs; int fbs; char *module_name; -static const char* getConnectionText(drmModeConnection conn) -{ - switch (conn) { - case DRM_MODE_CONNECTED: - return "connected"; - case DRM_MODE_DISCONNECTED: - return "disconnected"; - case DRM_MODE_UNKNOWNCONNECTION: - default: - return "unknown"; - } - -} - static int printMode(struct drm_mode_modeinfo *mode) { if (full_modes) { @@ -141,40 +128,24 @@ static int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, ui return 0; } -static const char * const output_names[] = { "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "Composite", - "SVIDEO", - "LVDS", - "Component", - "DIN", - "DP", - "HDMI-A", - "HDMI-B", - "TV", - "eDP", - "Virtual", - "DSI", -}; - static int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id) { int i = 0; struct drm_mode_modeinfo *mode = NULL; drmModePropertyPtr props; + const char *connector_type_name = NULL; + + connector_type_name = util_lookup_connector_type_name(connector->connector_type); - if (connector->connector_type < ARRAY_SIZE(output_names)) - printf("Connector: %s-%d\n", output_names[connector->connector_type], + if (connector_type_name) + printf("Connector: %s-%d\n", connector_type_name, connector->connector_type_id); else printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id); printf("\tid : %i\n", id); printf("\tencoder id : %i\n", connector->encoder_id); - printf("\tconn : %s\n", getConnectionText(connector->connection)); + printf("\tconn : %s\n", util_lookup_connector_status_name(connector->connection)); printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight); printf("\tcount_modes : %i\n", connector->count_modes); printf("\tcount_props : %i\n", connector->count_props); @@ -215,7 +186,13 @@ static int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connect static int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id) { - printf("Encoder\n"); + const char *encoder_name; + + encoder_name = util_lookup_encoder_type_name(encoder->encoder_type); + if (encoder_name) + printf("Encoder: %s\n", encoder_name); + else + printf("Encoder\n"); printf("\tid :%i\n", id); printf("\tcrtc_id :%d\n", encoder->crtc_id); printf("\ttype :%d\n", encoder->encoder_type); @@ -244,7 +221,7 @@ static int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb) printf("\thandle : %i\n", fb->handle); printf("\twidth : %i\n", fb->width); printf("\theight : %i\n", fb->height); - printf("\tpitch : %i\n", fb->pitch);; + printf("\tpitch : %i\n", fb->pitch); printf("\tbpp : %i\n", fb->bpp); printf("\tdepth : %i\n", fb->depth); printf("\tbuffer_id : %i\n", fb->handle); diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am index 4b296c83..5eebd960 100644 --- a/tests/modetest/Makefile.am +++ b/tests/modetest/Makefile.am @@ -3,6 +3,7 @@ include Makefile.sources AM_CFLAGS = $(filter-out -Wpointer-arith, $(WARN_CFLAGS)) AM_CFLAGS += \ + -fvisibility=hidden \ -pthread \ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/tests \ diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c index 4fd310b9..9b635c0c 100644 --- a/tests/modetest/buffers.c +++ b/tests/modetest/buffers.c @@ -24,10 +24,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <assert.h> #include <errno.h> #include <stdio.h> diff --git a/tests/modetest/cursor.c b/tests/modetest/cursor.c index 6de82a4a..829bced1 100644 --- a/tests/modetest/cursor.c +++ b/tests/modetest/cursor.c @@ -22,10 +22,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <assert.h> #include <errno.h> #include <stdio.h> diff --git a/tests/modetest/meson.build b/tests/modetest/meson.build new file mode 100644 index 00000000..23d84a1d --- /dev/null +++ b/tests/modetest/meson.build @@ -0,0 +1,29 @@ +# Copyright © 2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +modetest = executable( + 'modetest', + files('buffers.c', 'cursor.c', 'modetest.c'), + c_args : [libdrm_c_args, '-Wno-pointer-arith'], + include_directories : [inc_root, inc_tests, inc_drm], + dependencies : [dep_threads, dep_cairo], + link_with : [libdrm, libutil], + install : with_install_tests, +) diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index cd911193..975dcbcd 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -38,10 +38,6 @@ * the mode has been programmed, along with possible test patterns. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <assert.h> #include <ctype.h> #include <stdbool.h> @@ -123,6 +119,9 @@ struct device { struct bo *bo; struct bo *cursor_bo; } mode; + + int use_atomic; + drmModeAtomicReq *req; }; static inline int64_t U642I64(uint64_t val) @@ -174,6 +173,15 @@ static const char *mode_flag_names[] = { static bit_name_fn(mode_flag) +static void dump_fourcc(uint32_t fourcc) +{ + printf(" %c%c%c%c", + fourcc, + fourcc >> 8, + fourcc >> 16, + fourcc >> 24); +} + static void dump_encoders(struct device *dev) { drmModeEncoder *encoder; @@ -242,6 +250,89 @@ static void dump_blob(struct device *dev, uint32_t blob_id) drmModeFreePropertyBlob(blob); } +static const char *modifier_to_string(uint64_t modifier) +{ + switch (modifier) { + case DRM_FORMAT_MOD_INVALID: + return "INVALID"; + case DRM_FORMAT_MOD_LINEAR: + return "LINEAR"; + case I915_FORMAT_MOD_X_TILED: + return "X_TILED"; + case I915_FORMAT_MOD_Y_TILED: + return "Y_TILED"; + case I915_FORMAT_MOD_Yf_TILED: + return "Yf_TILED"; + case I915_FORMAT_MOD_Y_TILED_CCS: + return "Y_TILED_CCS"; + case I915_FORMAT_MOD_Yf_TILED_CCS: + return "Yf_TILED_CCS"; + case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: + return "SAMSUNG_64_32_TILE"; + case DRM_FORMAT_MOD_VIVANTE_TILED: + return "VIVANTE_TILED"; + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: + return "VIVANTE_SUPER_TILED"; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: + return "VIVANTE_SPLIT_TILED"; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: + return "VIVANTE_SPLIT_SUPER_TILED"; + case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED: + return "NVIDIA_TEGRA_TILED"; + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0): + return "NVIDIA_16BX2_BLOCK(0)"; + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1): + return "NVIDIA_16BX2_BLOCK(1)"; + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2): + return "NVIDIA_16BX2_BLOCK(2)"; + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3): + return "NVIDIA_16BX2_BLOCK(3)"; + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4): + return "NVIDIA_16BX2_BLOCK(4)"; + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5): + return "NVIDIA_16BX2_BLOCK(5)"; + case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: + return "MOD_BROADCOM_VC4_T_TILED"; + default: + return "(UNKNOWN MODIFIER)"; + } +} + +static void dump_in_formats(struct device *dev, uint32_t blob_id) +{ + uint32_t i, j; + drmModePropertyBlobPtr blob; + struct drm_format_modifier_blob *header; + uint32_t *formats; + struct drm_format_modifier *modifiers; + + printf("\t\tin_formats blob decoded:\n"); + blob = drmModeGetPropertyBlob(dev->fd, blob_id); + if (!blob) { + printf("\n"); + return; + } + + header = blob->data; + formats = (uint32_t *) ((char *) header + header->formats_offset); + modifiers = (struct drm_format_modifier *) + ((char *) header + header->modifiers_offset); + + for (i = 0; i < header->count_formats; i++) { + printf("\t\t\t"); + dump_fourcc(formats[i]); + printf(": "); + for (j = 0; j < header->count_modifiers; j++) { + uint64_t mask = 1ULL << i; + if (modifiers[j].formats & mask) + printf(" %s", modifier_to_string(modifiers[j].modifier)); + } + printf("\n"); + } + + drmModeFreePropertyBlob(blob); +} + static void dump_prop(struct device *dev, drmModePropertyPtr prop, uint32_t prop_id, uint64_t value) { @@ -319,6 +410,9 @@ static void dump_prop(struct device *dev, drmModePropertyPtr prop, printf(" %"PRId64"\n", value); else printf(" %"PRIu64"\n", value); + + if (strcmp(prop->name, "IN_FORMATS") == 0) + dump_in_formats(dev, value); } static void dump_connectors(struct device *dev) @@ -443,7 +537,7 @@ static void dump_planes(struct device *dev) printf(" formats:"); for (j = 0; j < ovr->count_formats; j++) - printf(" %4.4s", (char *)&ovr->formats[j]); + dump_fourcc(ovr->formats[j]); printf("\n"); if (plane->props) { @@ -524,7 +618,6 @@ static struct resources *get_resources(struct device *dev) return NULL; drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); - drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1); res->res = drmModeGetResources(dev->fd); if (!res->res) { @@ -562,10 +655,13 @@ static struct resources *get_resources(struct device *dev) for (i = 0; i < res->res->count_connectors; i++) { struct connector *connector = &res->connectors[i]; drmModeConnector *conn = connector->connector; + int num; - asprintf(&connector->name, "%s-%u", + num = asprintf(&connector->name, "%s-%u", util_lookup_connector_type_name(conn->connector_type), conn->connector_type_id); + if (num < 0) + goto error; } #define get_properties(_res, __res, type, Type) \ @@ -712,7 +808,9 @@ struct plane_arg { uint32_t w, h; double scale; unsigned int fb_id; + unsigned int old_fb_id; struct bo *bo; + struct bo *old_bo; char format_str[5]; /* need to leave room for terminating \0 */ unsigned int fourcc; }; @@ -906,8 +1004,12 @@ static void set_property(struct device *dev, struct property_arg *p) p->prop_id = props->props[i]; - ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type, - p->prop_id, p->value); + if (!dev->use_atomic) + ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type, + p->prop_id, p->value); + else + ret = drmModeAtomicAddProperty(dev->req, p->obj_id, p->prop_id, p->value); + if (ret < 0) fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n", obj_type, p->obj_id, p->name, p->value, strerror(errno)); @@ -956,6 +1058,94 @@ static bool format_support(const drmModePlanePtr ovr, uint32_t fmt) return false; } +static void add_property(struct device *dev, uint32_t obj_id, + const char *name, uint64_t value) +{ + struct property_arg p; + + p.obj_id = obj_id; + strcpy(p.name, name); + p.value = value; + + set_property(dev, &p); +} + +static int atomic_set_plane(struct device *dev, struct plane_arg *p, + int pattern, bool update) +{ + uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; + struct bo *plane_bo; + int crtc_x, crtc_y, crtc_w, crtc_h; + struct crtc *crtc = NULL; + unsigned int i; + unsigned int old_fb_id; + + /* Find an unused plane which can be connected to our CRTC. Find the + * CRTC index first, then iterate over available planes. + */ + for (i = 0; i < (unsigned int)dev->resources->res->count_crtcs; i++) { + if (p->crtc_id == dev->resources->res->crtcs[i]) { + crtc = &dev->resources->crtcs[i]; + break; + } + } + + if (!crtc) { + fprintf(stderr, "CRTC %u not found\n", p->crtc_id); + return -1; + } + + if (!update) + fprintf(stderr, "testing %dx%d@%s on plane %u, crtc %u\n", + p->w, p->h, p->format_str, p->plane_id, p->crtc_id); + + plane_bo = p->old_bo; + p->old_bo = p->bo; + + if (!plane_bo) { + plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h, + handles, pitches, offsets, pattern); + + if (plane_bo == NULL) + return -1; + + if (drmModeAddFB2(dev->fd, p->w, p->h, p->fourcc, + handles, pitches, offsets, &p->fb_id, 0)) { + fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); + return -1; + } + } + + p->bo = plane_bo; + + old_fb_id = p->fb_id; + p->old_fb_id = old_fb_id; + + crtc_w = p->w * p->scale; + crtc_h = p->h * p->scale; + if (!p->has_position) { + /* Default to the middle of the screen */ + crtc_x = (crtc->mode->hdisplay - crtc_w) / 2; + crtc_y = (crtc->mode->vdisplay - crtc_h) / 2; + } else { + crtc_x = p->x; + crtc_y = p->y; + } + + add_property(dev, p->plane_id, "FB_ID", p->fb_id); + add_property(dev, p->plane_id, "CRTC_ID", p->crtc_id); + add_property(dev, p->plane_id, "SRC_X", 0); + add_property(dev, p->plane_id, "SRC_Y", 0); + add_property(dev, p->plane_id, "SRC_W", p->w << 16); + add_property(dev, p->plane_id, "SRC_H", p->h << 16); + add_property(dev, p->plane_id, "CRTC_X", crtc_x); + add_property(dev, p->plane_id, "CRTC_Y", crtc_y); + add_property(dev, p->plane_id, "CRTC_W", crtc_w); + add_property(dev, p->plane_id, "CRTC_H", crtc_h); + + return 0; +} + static int set_plane(struct device *dev, struct plane_arg *p) { drmModePlane *ovr; @@ -997,7 +1187,8 @@ static int set_plane(struct device *dev, struct plane_arg *p) if (!format_support(ovr, p->fourcc)) continue; - if ((ovr->possible_crtcs & (1 << pipe)) && !ovr->crtc_id) { + if ((ovr->possible_crtcs & (1 << pipe)) && + (ovr->crtc_id == 0 || ovr->crtc_id == p->crtc_id)) { plane_id = ovr->plane_id; break; } @@ -1051,6 +1242,64 @@ static int set_plane(struct device *dev, struct plane_arg *p) return 0; } +static void atomic_set_planes(struct device *dev, struct plane_arg *p, + unsigned int count, bool update) +{ + unsigned int i, pattern = UTIL_PATTERN_SMPTE; + + /* set up planes */ + for (i = 0; i < count; i++) { + if (i > 0) + pattern = UTIL_PATTERN_TILES; + + if (atomic_set_plane(dev, &p[i], pattern, update)) + return; + } +} + +static void atomic_clear_planes(struct device *dev, struct plane_arg *p, unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) { + add_property(dev, p[i].plane_id, "FB_ID", 0); + add_property(dev, p[i].plane_id, "CRTC_ID", 0); + add_property(dev, p[i].plane_id, "SRC_X", 0); + add_property(dev, p[i].plane_id, "SRC_Y", 0); + add_property(dev, p[i].plane_id, "SRC_W", 0); + add_property(dev, p[i].plane_id, "SRC_H", 0); + add_property(dev, p[i].plane_id, "CRTC_X", 0); + add_property(dev, p[i].plane_id, "CRTC_Y", 0); + add_property(dev, p[i].plane_id, "CRTC_W", 0); + add_property(dev, p[i].plane_id, "CRTC_H", 0); + } +} + +static void atomic_clear_FB(struct device *dev, struct plane_arg *p, unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) { + if (p[i].fb_id) { + drmModeRmFB(dev->fd, p[i].fb_id); + p[i].fb_id = 0; + } + if (p[i].old_fb_id) { + drmModeRmFB(dev->fd, p[i].old_fb_id); + p[i].old_fb_id = 0; + } + if (p[i].bo) { + bo_destroy(p[i].bo); + p[i].bo = NULL; + } + if (p[i].old_bo) { + bo_destroy(p[i].old_bo); + p[i].old_bo = NULL; + } + + } +} + static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int count) { unsigned int i; @@ -1063,6 +1312,59 @@ static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int c } } +static void atomic_set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count) +{ + unsigned int i; + unsigned int j; + int ret; + + for (i = 0; i < count; i++) { + struct pipe_arg *pipe = &pipes[i]; + + ret = pipe_find_crtc_and_mode(dev, pipe); + if (ret < 0) + continue; + } + + for (i = 0; i < count; i++) { + struct pipe_arg *pipe = &pipes[i]; + uint32_t blob_id; + + if (pipe->mode == NULL) + continue; + + printf("setting mode %s-%dHz@%s on connectors ", + pipe->mode_str, pipe->mode->vrefresh, pipe->format_str); + for (j = 0; j < pipe->num_cons; ++j) { + printf("%s, ", pipe->cons[j]); + add_property(dev, pipe->con_ids[j], "CRTC_ID", pipe->crtc->crtc->crtc_id); + } + printf("crtc %d\n", pipe->crtc->crtc->crtc_id); + + drmModeCreatePropertyBlob(dev->fd, pipe->mode, sizeof(*pipe->mode), &blob_id); + add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", blob_id); + add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 1); + } +} + +static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count) +{ + unsigned int i; + unsigned int j; + + for (i = 0; i < count; i++) { + struct pipe_arg *pipe = &pipes[i]; + + if (pipe->mode == NULL) + continue; + + for (j = 0; j < pipe->num_cons; ++j) + add_property(dev, pipe->con_ids[j], "CRTC_ID",0); + + add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", 0); + add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 0); + } +} static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count) { @@ -1438,7 +1740,7 @@ static int parse_property(struct property_arg *p, const char *arg) static void usage(char *name) { - fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name); + fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name); fprintf(stderr, "\n Query options:\n\n"); fprintf(stderr, "\t-c\tlist connectors\n"); @@ -1452,6 +1754,7 @@ static void usage(char *name) fprintf(stderr, "\t-C\ttest hw cursor\n"); fprintf(stderr, "\t-v\ttest vsynced page flipping\n"); fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n"); + fprintf(stderr, "\t-a \tuse atomic API\n"); fprintf(stderr, "\n Generic options:\n\n"); fprintf(stderr, "\t-d\tdrop master after mode set\n"); @@ -1515,7 +1818,7 @@ static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe) return 0; } -static char optstr[] = "cdD:efM:P:ps:Cvw:"; +static char optstr[] = "acdD:efM:P:ps:Cvw:"; int main(int argc, char **argv) { @@ -1526,6 +1829,7 @@ int main(int argc, char **argv) int drop_master = 0; int test_vsync = 0; int test_cursor = 0; + int use_atomic = 0; char *device = NULL; char *module = NULL; unsigned int i; @@ -1544,6 +1848,9 @@ int main(int argc, char **argv) args++; switch (c) { + case 'a': + use_atomic = 1; + break; case 'c': connectors = 1; break; @@ -1623,13 +1930,22 @@ int main(int argc, char **argv) } } - if (!args) + if (!args || (args == 1 && use_atomic)) encoders = connectors = crtcs = planes = framebuffers = 1; dev.fd = util_open(device, module); if (dev.fd < 0) return -1; + ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1); + if (ret && use_atomic) { + fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno)); + drmClose(dev.fd); + return -1; + } + + dev.use_atomic = use_atomic; + if (test_vsync && !page_flipping_supported()) { fprintf(stderr, "page flipping not supported by drm.\n"); return -1; @@ -1670,40 +1986,111 @@ int main(int argc, char **argv) for (i = 0; i < prop_count; ++i) set_property(&dev, &prop_args[i]); - if (count || plane_count) { - uint64_t cap = 0; + if (dev.use_atomic) { + dev.req = drmModeAtomicAlloc(); - ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap); - if (ret || cap == 0) { - fprintf(stderr, "driver doesn't support the dumb buffer API\n"); - return 1; + if (count && plane_count) { + uint64_t cap = 0; + + ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap); + if (ret || cap == 0) { + fprintf(stderr, "driver doesn't support the dumb buffer API\n"); + return 1; + } + + atomic_set_mode(&dev, pipe_args, count); + atomic_set_planes(&dev, plane_args, plane_count, false); + + ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + if (ret) { + fprintf(stderr, "Atomic Commit failed [1]\n"); + return 1; + } + + gettimeofday(&pipe_args->start, NULL); + pipe_args->swap_count = 0; + + while (test_vsync) { + drmModeAtomicFree(dev.req); + dev.req = drmModeAtomicAlloc(); + atomic_set_planes(&dev, plane_args, plane_count, true); + + ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + if (ret) { + fprintf(stderr, "Atomic Commit failed [2]\n"); + return 1; + } + + pipe_args->swap_count++; + if (pipe_args->swap_count == 60) { + struct timeval end; + double t; + + gettimeofday(&end, NULL); + t = end.tv_sec + end.tv_usec * 1e-6 - + (pipe_args->start.tv_sec + pipe_args->start.tv_usec * 1e-6); + fprintf(stderr, "freq: %.02fHz\n", pipe_args->swap_count / t); + pipe_args->swap_count = 0; + pipe_args->start = end; + } + } + + if (drop_master) + drmDropMaster(dev.fd); + + getchar(); + + drmModeAtomicFree(dev.req); + dev.req = drmModeAtomicAlloc(); + + atomic_clear_mode(&dev, pipe_args, count); + atomic_clear_planes(&dev, plane_args, plane_count); + ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + if (ret) { + fprintf(stderr, "Atomic Commit failed\n"); + return 1; + } + + atomic_clear_FB(&dev, plane_args, plane_count); } - if (count) - set_mode(&dev, pipe_args, count); + drmModeAtomicFree(dev.req); + } else { + if (count || plane_count) { + uint64_t cap = 0; - if (plane_count) - set_planes(&dev, plane_args, plane_count); + ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap); + if (ret || cap == 0) { + fprintf(stderr, "driver doesn't support the dumb buffer API\n"); + return 1; + } + + if (count) + set_mode(&dev, pipe_args, count); - if (test_cursor) - set_cursors(&dev, pipe_args, count); + if (plane_count) + set_planes(&dev, plane_args, plane_count); - if (test_vsync) - test_page_flip(&dev, pipe_args, count); + if (test_cursor) + set_cursors(&dev, pipe_args, count); - if (drop_master) - drmDropMaster(dev.fd); + if (test_vsync) + test_page_flip(&dev, pipe_args, count); - getchar(); + if (drop_master) + drmDropMaster(dev.fd); - if (test_cursor) - clear_cursors(&dev); + getchar(); - if (plane_count) - clear_planes(&dev, plane_args, plane_count); + if (test_cursor) + clear_cursors(&dev); - if (count) - clear_mode(&dev); + if (plane_count) + clear_planes(&dev, plane_args, plane_count); + + if (count) + clear_mode(&dev); + } } free_resources(dev.resources); diff --git a/tests/nouveau/Makefile.am b/tests/nouveau/Makefile.am index 3c799a81..554f43ec 100644 --- a/tests/nouveau/Makefile.am +++ b/tests/nouveau/Makefile.am @@ -1,6 +1,7 @@ AM_CFLAGS = \ -pthread \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/nouveau \ -I$(top_srcdir) diff --git a/tests/nouveau/meson.build b/tests/nouveau/meson.build new file mode 100644 index 00000000..ca4d44f0 --- /dev/null +++ b/tests/nouveau/meson.build @@ -0,0 +1,30 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +threaded = executable( + 'threaded', + files('threaded.c'), + dependencies : [dep_dl, dep_threads], + include_directories : [inc_root, inc_drm, include_directories('../../nouveau')], + link_with : [libdrm, libdrm_nouveau], + c_args : libdrm_c_args, +) + +test('threaded', threaded) diff --git a/tests/nouveau/threaded.c b/tests/nouveau/threaded.c index 281af460..3669bcd3 100644 --- a/tests/nouveau/threaded.c +++ b/tests/nouveau/threaded.c @@ -20,10 +20,6 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include <sys/ioctl.h> #include <dlfcn.h> #include <fcntl.h> diff --git a/tests/planetest/Android.bp b/tests/planetest/Android.bp deleted file mode 100644 index 16dfc5b7..00000000 --- a/tests/planetest/Android.bp +++ /dev/null @@ -1,33 +0,0 @@ -build = ["Android.sources.bp"] - -cc_test { - name: "planetest", - defaults: [ - "planetest_common_sources", - "planetest_sources", - ], - shared_libs: ["libdrm"], - - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - "-Wno-pointer-arith", - ], -} - -cc_test { - name: "atomictest", - defaults: [ - "planetest_common_sources", - "atomictest_sources", - ], - shared_libs: ["libdrm"], - - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - "-Wno-pointer-arith", - ], -} diff --git a/tests/planetest/Android.sources.bp b/tests/planetest/Android.sources.bp deleted file mode 100644 index 4a35bb51..00000000 --- a/tests/planetest/Android.sources.bp +++ /dev/null @@ -1,24 +0,0 @@ -// Autogenerated with Android.sources.bp.mk - -cc_defaults { - name: "planetest_common_sources", - srcs: [ - "bo.c", - "dev.c", - "modeset.c", - ], -} - -cc_defaults { - name: "planetest_sources", - srcs: [ - "planetest.c", - ], -} - -cc_defaults { - name: "atomictest_sources", - srcs: [ - "atomictest.c", - ], -} diff --git a/tests/planetest/Makefile.am b/tests/planetest/Makefile.am deleted file mode 100644 index b82d05b8..00000000 --- a/tests/planetest/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -include Makefile.sources - -AM_CFLAGS = $(filter-out -Wpointer-arith, $(WARN_CFLAGS)) - -AM_CFLAGS += \ - -I$(top_srcdir)/include/drm \ - -I$(top_srcdir)/libkms/ \ - -I$(top_srcdir) - -PLANETEST_COMMON_LDADD = \ - $(top_builddir)/libdrm.la \ - $(top_builddir)/libkms/libkms.la \ - -lpthread - -if HAVE_INSTALL_TESTS -bin_PROGRAMS = \ - atomictest \ - planetest -else -noinst_PROGRAMS = \ - atomictest \ - planetest -endif - -atomictest_CFLAGS=-DUSE_ATOMIC_API ${AM_CFLAGS} -atomictest_SOURCES=${PLANETEST_COMMON_FILES} ${ATOMICTEST_FILES} -planetest_SOURCES=${PLANETEST_COMMON_FILES} ${PLANETEST_FILES} - -atomictest_LDADD=${PLANETEST_COMMON_LDADD} -planetest_LDADD=${PLANETEST_COMMON_LDADD} diff --git a/tests/planetest/Makefile.sources b/tests/planetest/Makefile.sources deleted file mode 100644 index 3cbeb2b3..00000000 --- a/tests/planetest/Makefile.sources +++ /dev/null @@ -1,13 +0,0 @@ -PLANETEST_COMMON_FILES := \ - bo.c \ - bo.h \ - dev.c \ - dev.h \ - modeset.c \ - modeset.h - -ATOMICTEST_FILES := \ - atomictest.c - -PLANETEST_FILES := \ - planetest.c diff --git a/tests/planetest/atomictest.c b/tests/planetest/atomictest.c deleted file mode 100644 index 5fec911a..00000000 --- a/tests/planetest/atomictest.c +++ /dev/null @@ -1,151 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/select.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <signal.h> -#include <time.h> -#include <errno.h> - -#include <xf86drm.h> - -#include "dev.h" -#include "bo.h" -#include "modeset.h" - -static int terminate = 0; - -static void sigint_handler(int arg) -{ - terminate = 1; -} - -static void -page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec, - unsigned int tv_usec, void *user_data) -{ -} - -static void incrementor(int *inc, int *val, int increment, int lower, int upper) -{ - if(*inc > 0) - *inc = *val + increment >= upper ? -1 : 1; - else - *inc = *val - increment <= lower ? 1 : -1; - *val += *inc * increment; -} - -int main(int argc, char *argv[]) -{ - int ret, i, j, num_test_planes; - int x_inc = 1, x = 0, y_inc = 1, y = 0; - uint32_t plane_w = 128, plane_h = 128; - struct sp_dev *dev; - struct sp_plane **plane = NULL; - struct sp_crtc *test_crtc; - fd_set fds; - drmModePropertySetPtr pset; - drmEventContext event_context = { - .version = DRM_EVENT_CONTEXT_VERSION, - .page_flip_handler = page_flip_handler, - }; - int card = 0, crtc = 0; - - signal(SIGINT, sigint_handler); - - parse_arguments(argc, argv, &card, &crtc); - - dev = create_sp_dev(card); - if (!dev) { - printf("Failed to create sp_dev\n"); - return -1; - } - - if (crtc >= dev->num_crtcs) { - printf("Invalid crtc %d (num=%d)\n", crtc, dev->num_crtcs); - return -1; - } - - ret = initialize_screens(dev); - if (ret) { - printf("Failed to initialize screens\n"); - goto out; - } - test_crtc = &dev->crtcs[crtc]; - - plane = calloc(dev->num_planes, sizeof(*plane)); - if (!plane) { - printf("Failed to allocate plane array\n"); - goto out; - } - - /* Create our planes */ - num_test_planes = test_crtc->num_planes; - for (i = 0; i < num_test_planes; i++) { - plane[i] = get_sp_plane(dev, test_crtc); - if (!plane[i]) { - printf("no unused planes available\n"); - goto out; - } - - plane[i]->bo = create_sp_bo(dev, plane_w, plane_h, 16, plane[i]->format, 0); - if (!plane[i]->bo) { - printf("failed to create plane bo\n"); - goto out; - } - - fill_bo(plane[i]->bo, 0xFF, 0xFF, 0xFF, 0xFF); - } - - pset = drmModePropertySetAlloc(); - if (!pset) { - printf("Failed to allocate the property set\n"); - goto out; - } - - while (!terminate) { - FD_ZERO(&fds); - FD_SET(dev->fd, &fds); - - incrementor(&x_inc, &x, 5, 0, - test_crtc->crtc->mode.hdisplay - plane_w); - incrementor(&y_inc, &y, 5, 0, test_crtc->crtc->mode.vdisplay - - plane_h * num_test_planes); - - for (j = 0; j < num_test_planes; j++) { - ret = set_sp_plane_pset(dev, plane[j], pset, test_crtc, - x, y + j * plane_h); - if (ret) { - printf("failed to move plane %d\n", ret); - goto out; - } - } - - ret = drmModePropertySetCommit(dev->fd, - DRM_MODE_PAGE_FLIP_EVENT, NULL, pset); - if (ret) { - printf("failed to commit properties ret=%d\n", ret); - goto out; - } - - do { - ret = select(dev->fd + 1, &fds, NULL, NULL, NULL); - } while (ret == -1 && errno == EINTR); - - if (FD_ISSET(dev->fd, &fds)) - drmHandleEvent(dev->fd, &event_context); - } - - drmModePropertySetFree(pset); - - for (i = 0; i < num_test_planes; i++) - put_sp_plane(plane[i]); - -out: - destroy_sp_dev(dev); - free(plane); - return ret; -} diff --git a/tests/planetest/bo.c b/tests/planetest/bo.c deleted file mode 100644 index d4b82c66..00000000 --- a/tests/planetest/bo.c +++ /dev/null @@ -1,234 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <errno.h> - -#include <xf86drm.h> -#include <xf86drmMode.h> -#include <drm_fourcc.h> - -#include "bo.h" -#include "dev.h" - -#define MAKE_YUV_601_Y(r, g, b) \ - ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) -#define MAKE_YUV_601_U(r, g, b) \ - (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) -#define MAKE_YUV_601_V(r, g, b) \ - (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) - -static void draw_rect_yuv(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width, - uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b) -{ - uint32_t i, j, xmax = x + width, ymax = y + height; - - if (xmax > bo->width) - xmax = bo->width; - if (ymax > bo->height) - ymax = bo->height; - - for (i = y; i < ymax; i++) { - uint8_t *luma = bo->map_addr + i * bo->pitch; - - for (j = x; j < xmax; j++) - luma[j] = MAKE_YUV_601_Y(r, g, b); - } - - for (i = y; i < ymax / 2; i++) { - uint8_t *chroma = bo->map_addr + (i + height) * bo->pitch; - - for (j = x; j < xmax / 2; j++) { - chroma[j*2] = MAKE_YUV_601_U(r, g, b); - chroma[j*2 + 1] = MAKE_YUV_601_V(r, g, b); - } - } -} - -void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b) -{ - if (bo->format == DRM_FORMAT_NV12) - draw_rect_yuv(bo, 0, 0, bo->width, bo->height, a, r, g, b); - else - draw_rect(bo, 0, 0, bo->width, bo->height, a, r, g, b); -} - -void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width, - uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b) -{ - uint32_t i, j, xmax = x + width, ymax = y + height; - - if (xmax > bo->width) - xmax = bo->width; - if (ymax > bo->height) - ymax = bo->height; - - for (i = y; i < ymax; i++) { - uint8_t *row = bo->map_addr + i * bo->pitch; - - for (j = x; j < xmax; j++) { - uint8_t *pixel = row + j * 4; - - if (bo->format == DRM_FORMAT_ARGB8888 || - bo->format == DRM_FORMAT_XRGB8888) - { - pixel[0] = b; - pixel[1] = g; - pixel[2] = r; - pixel[3] = a; - } else if (bo->format == DRM_FORMAT_RGBA8888) { - pixel[0] = r; - pixel[1] = g; - pixel[2] = b; - pixel[3] = a; - } - } - } -} - -static int add_fb_sp_bo(struct sp_bo *bo, uint32_t format) -{ - int ret; - uint32_t handles[4], pitches[4], offsets[4]; - - handles[0] = bo->handle; - pitches[0] = bo->pitch; - offsets[0] = 0; - if (bo->format == DRM_FORMAT_NV12) { - handles[1] = bo->handle; - pitches[1] = pitches[0]; - offsets[1] = pitches[0] * bo->height; - } - - ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height, - format, handles, pitches, offsets, - &bo->fb_id, bo->flags); - if (ret) { - printf("failed to create fb ret=%d\n", ret); - return ret; - } - return 0; -} - -static int map_sp_bo(struct sp_bo *bo) -{ - int ret; - struct drm_mode_map_dumb md; - - if (bo->map_addr) - return 0; - - md.handle = bo->handle; - ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &md); - if (ret) { - printf("failed to map sp_bo ret=%d\n", ret); - return ret; - } - - bo->map_addr = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, - bo->dev->fd, md.offset); - if (bo->map_addr == MAP_FAILED) { - printf("failed to map bo ret=%d\n", -errno); - return -errno; - } - return 0; -} - -static int format_to_bpp(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_NV12: - return 8; - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_RGBA8888: - default: - return 32; - } -} - -struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t height, - uint32_t depth, uint32_t format, uint32_t flags) -{ - int ret; - struct drm_mode_create_dumb cd; - struct sp_bo *bo; - - bo = calloc(1, sizeof(*bo)); - if (!bo) - return NULL; - - if (format == DRM_FORMAT_NV12) - cd.height = height * 3 / 2; - else - cd.height = height; - - cd.width = width; - cd.bpp = format_to_bpp(format); - cd.flags = flags; - - ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &cd); - if (ret) { - printf("failed to create sp_bo %d\n", ret); - goto err; - } - - bo->dev = dev; - bo->width = width; - bo->height = height; - bo->depth = depth; - bo->bpp = format_to_bpp(format); - bo->format = format; - bo->flags = flags; - - bo->handle = cd.handle; - bo->pitch = cd.pitch; - bo->size = cd.size; - - ret = add_fb_sp_bo(bo, format); - if (ret) { - printf("failed to add fb ret=%d\n", ret); - goto err; - } - - ret = map_sp_bo(bo); - if (ret) { - printf("failed to map bo ret=%d\n", ret); - goto err; - } - - return bo; - -err: - free_sp_bo(bo); - return NULL; -} - -void free_sp_bo(struct sp_bo *bo) -{ - int ret; - struct drm_mode_destroy_dumb dd; - - if (!bo) - return; - - if (bo->map_addr) - munmap(bo->map_addr, bo->size); - - if (bo->fb_id) { - ret = drmModeRmFB(bo->dev->fd, bo->fb_id); - if (ret) - printf("Failed to rmfb ret=%d!\n", ret); - } - - if (bo->handle) { - dd.handle = bo->handle; - ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dd); - if (ret) - printf("Failed to destroy buffer ret=%d\n", ret); - } - - free(bo); -} diff --git a/tests/planetest/bo.h b/tests/planetest/bo.h deleted file mode 100644 index 7471e126..00000000 --- a/tests/planetest/bo.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __BO_H_INCLUDED__ -#define __BO_H_INCLUDED__ - -#include <stdint.h> - -struct sp_dev; - -struct sp_bo { - struct sp_dev *dev; - - uint32_t width; - uint32_t height; - uint32_t depth; - uint32_t bpp; - uint32_t format; - uint32_t flags; - - uint32_t fb_id; - uint32_t handle; - void *map_addr; - uint32_t pitch; - uint32_t size; -}; - -struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t height, - uint32_t depth, uint32_t format, uint32_t flags); - -void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b); -void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width, - uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b); - -void free_sp_bo(struct sp_bo *bo); - -#endif /* __BO_H_INCLUDED__ */ diff --git a/tests/planetest/dev.c b/tests/planetest/dev.c deleted file mode 100644 index bd0968c6..00000000 --- a/tests/planetest/dev.c +++ /dev/null @@ -1,367 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <getopt.h> - -#include <drm.h> -#include <drm_fourcc.h> -#include <errno.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "bo.h" -#include "dev.h" -#include "modeset.h" - -static void show_usage(char *name) -{ - printf("Usage: %s [OPTION]\n", name); - printf(" -c, --card Index of dri card (ie: /dev/dri/cardN)\n"); - printf(" -r, --crtc Index of crtc to use for test\n"); - printf("\n\n"); -} - -void parse_arguments(int argc, char *argv[], int *card, int *crtc) -{ - static struct option options[] = { - { "card", required_argument, NULL, 'c' }, - { "crtc", required_argument, NULL, 'r' }, - { "help", no_argument, NULL, 'h' }, - }; - int option_index = 0; - int c; - - *card = -1; - *crtc = -1; - do { - c = getopt_long(argc, argv, "c:r:h", options, &option_index); - switch (c) { - case 0: - case 'h': - show_usage(argv[0]); - exit(0); - case -1: - break; - case 'c': - if (optarg[0] < '0' || optarg[0] > '9') { - printf("Invalid card value '%s'!\n", optarg); - show_usage(argv[0]); - exit(-1); - } - *card = optarg[0] - '0'; - break; - case 'r': - if (optarg[0] < '0' || optarg[0] > '9') { - printf("Invalid crtc value '%s'!\n", optarg); - show_usage(argv[0]); - exit(-1); - } - *crtc = optarg[0] - '0'; - break; - } - } while (c != -1); - - if (*card < 0 || *crtc < 0) { - show_usage(argv[0]); - exit(-1); - } -} - -static uint32_t get_prop_id(struct sp_dev *dev, - drmModeObjectPropertiesPtr props, const char *name) -{ - drmModePropertyPtr p; - uint32_t i, prop_id = 0; /* Property ID should always be > 0 */ - - for (i = 0; !prop_id && i < props->count_props; i++) { - p = drmModeGetProperty(dev->fd, props->props[i]); - if (!strcmp(p->name, name)) - prop_id = p->prop_id; - drmModeFreeProperty(p); - } - if (!prop_id) - printf("Could not find %s property\n", name); - return prop_id; -} - -static int get_supported_format(struct sp_plane *plane, uint32_t *format) -{ - uint32_t i; - - for (i = 0; i < plane->plane->count_formats; i++) { - if (plane->plane->formats[i] == DRM_FORMAT_XRGB8888 || - plane->plane->formats[i] == DRM_FORMAT_ARGB8888 || - plane->plane->formats[i] == DRM_FORMAT_RGBA8888 || - plane->plane->formats[i] == DRM_FORMAT_NV12) { - *format = plane->plane->formats[i]; - return 0; - } - } - printf("No suitable formats found!\n"); - return -ENOENT; -} - -struct sp_dev *create_sp_dev(int card) -{ - struct sp_dev *dev; - int ret, fd, i, j; - drmModeRes *r = NULL; - drmModePlaneRes *pr = NULL; - char card_path[256]; - - snprintf(card_path, sizeof(card_path), "/dev/dri/card%d", card); - - fd = open(card_path, O_RDWR); - if (fd < 0) { - printf("failed to open card0\n"); - return NULL; - } - - dev = calloc(1, sizeof(*dev)); - if (!dev) { - printf("failed to allocate dev\n"); - return NULL; - } - - dev->fd = fd; - - ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); - if (ret) { - printf("failed to set client cap\n"); - goto err; - } - - ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1); - if (ret) { - printf("Failed to set atomic cap %d", ret); - goto err; - } - - r = drmModeGetResources(dev->fd); - if (!r) { - printf("failed to get r\n"); - goto err; - } - - dev->num_connectors = r->count_connectors; - dev->connectors = calloc(dev->num_connectors, - sizeof(struct sp_connector)); - if (!dev->connectors) { - printf("failed to allocate connectors\n"); - goto err; - } - for (i = 0; i < dev->num_connectors; i++) { - drmModeObjectPropertiesPtr props; - dev->connectors[i].conn = drmModeGetConnector(dev->fd, - r->connectors[i]); - if (!dev->connectors[i].conn) { - printf("failed to get connector %d\n", i); - goto err; - } - - props = drmModeObjectGetProperties(dev->fd, r->connectors[i], - DRM_MODE_OBJECT_CONNECTOR); - if (!props) { - printf("failed to get connector properties\n"); - goto err; - } - - dev->connectors[i].crtc_id_pid = get_prop_id(dev, props, - "CRTC_ID"); - drmModeFreeObjectProperties(props); - if (!dev->connectors[i].crtc_id_pid) - goto err; - } - - dev->num_encoders = r->count_encoders; - dev->encoders = calloc(dev->num_encoders, sizeof(*dev->encoders)); - if (!dev->encoders) { - printf("failed to allocate encoders\n"); - goto err; - } - for (i = 0; i < dev->num_encoders; i++) { - dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]); - if (!dev->encoders[i]) { - printf("failed to get encoder %d\n", i); - goto err; - } - } - - dev->num_crtcs = r->count_crtcs; - dev->crtcs = calloc(dev->num_crtcs, sizeof(struct sp_crtc)); - if (!dev->crtcs) { - printf("failed to allocate crtcs\n"); - goto err; - } - for (i = 0; i < dev->num_crtcs; i++) { - drmModeObjectPropertiesPtr props; - - dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]); - if (!dev->crtcs[i].crtc) { - printf("failed to get crtc %d\n", i); - goto err; - } - dev->crtcs[i].pipe = i; - dev->crtcs[i].num_planes = 0; - - props = drmModeObjectGetProperties(dev->fd, r->crtcs[i], - DRM_MODE_OBJECT_CRTC); - if (!props) { - printf("failed to get crtc properties\n"); - goto err; - } - - dev->crtcs[i].mode_pid = get_prop_id(dev, props, "MODE_ID"); - dev->crtcs[i].active_pid = get_prop_id(dev, props, "ACTIVE"); - drmModeFreeObjectProperties(props); - if (!dev->crtcs[i].mode_pid || !dev->crtcs[i].active_pid) - goto err; - } - - pr = drmModeGetPlaneResources(dev->fd); - if (!pr) { - printf("failed to get plane resources\n"); - goto err; - } - dev->num_planes = pr->count_planes; - dev->planes = calloc(dev->num_planes, sizeof(struct sp_plane)); - for(i = 0; i < dev->num_planes; i++) { - drmModeObjectPropertiesPtr props; - struct sp_plane *plane = &dev->planes[i]; - - plane->dev = dev; - plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]); - if (!plane->plane) { - printf("failed to get plane %d\n", i); - goto err; - } - plane->bo = NULL; - plane->in_use = 0; - - ret = get_supported_format(plane, &plane->format); - if (ret) { - printf("failed to get supported format: %d\n", ret); - goto err; - } - - for (j = 0; j < dev->num_crtcs; j++) { - if (plane->plane->possible_crtcs & (1 << j)) - dev->crtcs[j].num_planes++; - } - - props = drmModeObjectGetProperties(dev->fd, pr->planes[i], - DRM_MODE_OBJECT_PLANE); - if (!props) { - printf("failed to get plane properties\n"); - goto err; - } - plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID"); - if (!plane->crtc_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->fb_pid = get_prop_id(dev, props, "FB_ID"); - if (!plane->fb_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X"); - if (!plane->crtc_x_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y"); - if (!plane->crtc_y_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W"); - if (!plane->crtc_w_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H"); - if (!plane->crtc_h_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->src_x_pid = get_prop_id(dev, props, "SRC_X"); - if (!plane->src_x_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->src_y_pid = get_prop_id(dev, props, "SRC_Y"); - if (!plane->src_y_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->src_w_pid = get_prop_id(dev, props, "SRC_W"); - if (!plane->src_w_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - plane->src_h_pid = get_prop_id(dev, props, "SRC_H"); - if (!plane->src_h_pid) { - drmModeFreeObjectProperties(props); - goto err; - } - drmModeFreeObjectProperties(props); - } - - if (pr) - drmModeFreePlaneResources(pr); - if (r) - drmModeFreeResources(r); - - return dev; -err: - if (pr) - drmModeFreePlaneResources(pr); - if (r) - drmModeFreeResources(r); - destroy_sp_dev(dev); - return NULL; -} - -void destroy_sp_dev(struct sp_dev *dev) -{ - int i; - - if (dev->planes) { - for (i = 0; i< dev->num_planes; i++) { - if (dev->planes[i].in_use) - put_sp_plane(&dev->planes[i]); - if (dev->planes[i].plane) - drmModeFreePlane(dev->planes[i].plane); - if (dev->planes[i].bo) - free_sp_bo(dev->planes[i].bo); - } - free(dev->planes); - } - if (dev->crtcs) { - for (i = 0; i< dev->num_crtcs; i++) { - if (dev->crtcs[i].crtc) - drmModeFreeCrtc(dev->crtcs[i].crtc); - } - free(dev->crtcs); - } - if (dev->encoders) { - for (i = 0; i< dev->num_encoders; i++) { - if (dev->encoders[i]) - drmModeFreeEncoder(dev->encoders[i]); - } - free(dev->encoders); - } - if (dev->connectors) { - for (i = 0; i< dev->num_connectors; i++) { - if (dev->connectors[i].conn) - drmModeFreeConnector(dev->connectors[i].conn); - } - free(dev->connectors); - } - - close(dev->fd); - free(dev); -} diff --git a/tests/planetest/dev.h b/tests/planetest/dev.h deleted file mode 100644 index 04dec794..00000000 --- a/tests/planetest/dev.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __DEV_H_INCLUDED__ -#define __DEV_H_INCLUDED__ - -#include <stdint.h> -#include <xf86drmMode.h> - -struct sp_bo; -struct sp_dev; - -struct sp_plane { - struct sp_dev *dev; - drmModePlanePtr plane; - struct sp_bo *bo; - int in_use; - uint32_t format; - - /* Property ID's */ - uint32_t crtc_pid; - uint32_t fb_pid; - uint32_t zpos_pid; - uint32_t crtc_x_pid; - uint32_t crtc_y_pid; - uint32_t crtc_w_pid; - uint32_t crtc_h_pid; - uint32_t src_x_pid; - uint32_t src_y_pid; - uint32_t src_w_pid; - uint32_t src_h_pid; -}; - -struct sp_connector { - drmModeConnectorPtr conn; - uint32_t crtc_id_pid; -}; - -struct sp_crtc { - drmModeCrtcPtr crtc; - int pipe; - int num_planes; - uint32_t mode_pid; - uint32_t active_pid; -}; - -struct sp_dev { - int fd; - - int num_connectors; - struct sp_connector *connectors; - - int num_encoders; - drmModeEncoderPtr *encoders; - - int num_crtcs; - struct sp_crtc *crtcs; - - int num_planes; - struct sp_plane *planes; -}; - -void parse_arguments(int argc, char *argv[], int *card, int *crtc); - -struct sp_dev *create_sp_dev(int card); -void destroy_sp_dev(struct sp_dev *dev); - -#endif /* __DEV_H_INCLUDED__ */ diff --git a/tests/planetest/modeset.c b/tests/planetest/modeset.c deleted file mode 100644 index 037814ec..00000000 --- a/tests/planetest/modeset.c +++ /dev/null @@ -1,232 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <xf86drm.h> -#include <xf86drmMode.h> -#include <drm_fourcc.h> - -#include "modeset.h" -#include "bo.h" -#include "dev.h" - -static int set_crtc_mode(struct sp_dev *dev, struct sp_crtc *crtc, - struct sp_connector *conn, drmModeModeInfoPtr mode) -{ - int ret; - struct drm_mode_create_blob create_blob; - drmModePropertySetPtr pset; - - memset(&create_blob, 0, sizeof(create_blob)); - create_blob.length = sizeof(struct drm_mode_modeinfo); - create_blob.data = (__u64)(uintptr_t)mode; - - ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob); - if (ret) { - printf("Failed to create mode property blob %d", ret); - return ret; - } - - pset = drmModePropertySetAlloc(); - if (!pset) { - printf("Failed to allocate property set"); - return -1; - } - - ret = drmModePropertySetAdd(pset, crtc->crtc->crtc_id, - crtc->mode_pid, create_blob.blob_id) || - drmModePropertySetAdd(pset, crtc->crtc->crtc_id, - crtc->active_pid, 1) || - drmModePropertySetAdd(pset, conn->conn->connector_id, - conn->crtc_id_pid, crtc->crtc->crtc_id); - if (ret) { - printf("Failed to add blob %d to pset", create_blob.blob_id); - drmModePropertySetFree(pset); - return ret; - } - - ret = drmModePropertySetCommit(dev->fd, DRM_MODE_ATOMIC_ALLOW_MODESET, - NULL, pset); - - drmModePropertySetFree(pset); - - if (ret) { - printf("Failed to commit pset ret=%d\n", ret); - return ret; - } - - memcpy(&crtc->crtc->mode, mode, sizeof(struct drm_mode_modeinfo)); - crtc->crtc->mode_valid = 1; - return 0; -} - -int initialize_screens(struct sp_dev *dev) -{ - int ret, i, j; - unsigned crtc_mask = 0; - - for (i = 0; i < dev->num_connectors; i++) { - struct sp_connector *c = &dev->connectors[i]; - drmModeModeInfoPtr m = NULL; - drmModeEncoderPtr e = NULL; - struct sp_crtc *cr = NULL; - - if (c->conn->connection != DRM_MODE_CONNECTED) - continue; - - if (!c->conn->count_modes) { - printf("connector has no modes, skipping\n"); - continue; - } - - /* Take the first unless there's a preferred mode */ - m = &c->conn->modes[0]; - for (j = 0; j < c->conn->count_modes; j++) { - drmModeModeInfoPtr tmp_m = &c->conn->modes[j]; - - if (!(tmp_m->type & DRM_MODE_TYPE_PREFERRED)) - continue; - - m = tmp_m; - break; - } - - if (!c->conn->count_encoders) { - printf("no possible encoders for connector\n"); - continue; - } - - for (j = 0; j < dev->num_encoders; j++) { - e = dev->encoders[j]; - if (e->encoder_id == c->conn->encoders[0]) - break; - } - if (j == dev->num_encoders) { - printf("could not find encoder for the connector\n"); - continue; - } - - for (j = 0; j < dev->num_crtcs; j++) { - if ((1 << j) & crtc_mask) - continue; - - cr = &dev->crtcs[j]; - - if ((1 << j) & e->possible_crtcs) - break; - } - if (j == dev->num_crtcs) { - printf("could not find crtc for the encoder\n"); - continue; - } - - ret = set_crtc_mode(dev, cr, c, m); - if (ret) { - printf("failed to set mode!\n"); - continue; - } - crtc_mask |= 1 << j; - } - return 0; -} - -struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc) -{ - int i; - - for(i = 0; i < dev->num_planes; i++) { - struct sp_plane *p = &dev->planes[i]; - - if (p->in_use) - continue; - - if (!(p->plane->possible_crtcs & (1 << crtc->pipe))) - continue; - - p->in_use = 1; - return p; - } - return NULL; -} - -void put_sp_plane(struct sp_plane *plane) -{ - drmModePlanePtr p; - - /* Get the latest plane information (most notably the crtc_id) */ - p = drmModeGetPlane(plane->dev->fd, plane->plane->plane_id); - if (p) - plane->plane = p; - - if (plane->bo) { - free_sp_bo(plane->bo); - plane->bo = NULL; - } - plane->in_use = 0; -} - -int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane, - struct sp_crtc *crtc, int x, int y) -{ - int ret; - uint32_t w, h; - - w = plane->bo->width; - h = plane->bo->height; - - if ((w + x) > crtc->crtc->mode.hdisplay) - w = crtc->crtc->mode.hdisplay - x; - if ((h + y) > crtc->crtc->mode.vdisplay) - h = crtc->crtc->mode.vdisplay - y; - - ret = drmModeSetPlane(dev->fd, plane->plane->plane_id, - crtc->crtc->crtc_id, plane->bo->fb_id, 0, x, y, w, h, - 0, 0, w << 16, h << 16); - if (ret) { - printf("failed to set plane to crtc ret=%d\n", ret); - return ret; - } - - return ret; -} -int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane, - drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y) -{ - int ret; - uint32_t w, h; - - w = plane->bo->width; - h = plane->bo->height; - - if ((w + x) > crtc->crtc->mode.hdisplay) - w = crtc->crtc->mode.hdisplay - x; - if ((h + y) > crtc->crtc->mode.vdisplay) - h = crtc->crtc->mode.vdisplay - y; - - ret = drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->crtc_pid, crtc->crtc->crtc_id) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->fb_pid, plane->bo->fb_id) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->crtc_x_pid, x) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->crtc_y_pid, y) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->crtc_w_pid, w) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->crtc_h_pid, h) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->src_x_pid, 0) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->src_y_pid, 0) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->src_w_pid, w << 16) - || drmModePropertySetAdd(pset, plane->plane->plane_id, - plane->src_h_pid, h << 16); - if (ret) { - printf("failed to add properties to the set\n"); - return -1; - } - - return ret; -} diff --git a/tests/planetest/modeset.h b/tests/planetest/modeset.h deleted file mode 100644 index 7e965743..00000000 --- a/tests/planetest/modeset.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __MODESET_H_INCLUDED__ -#define __MODESET_H_INCLUDED__ - -struct sp_dev; -struct sp_crtc; - -int initialize_screens(struct sp_dev *dev); - - -struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc); -void put_sp_plane(struct sp_plane *plane); - -int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane, - struct sp_crtc *crtc, int x, int y); - -int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane, - drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y); - -#endif /* __MODESET_H_INCLUDED__ */ diff --git a/tests/planetest/planetest.c b/tests/planetest/planetest.c deleted file mode 100644 index 5e187c99..00000000 --- a/tests/planetest/planetest.c +++ /dev/null @@ -1,116 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/select.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <signal.h> -#include <time.h> -#include <errno.h> - -#include <xf86drm.h> - -#include "dev.h" -#include "bo.h" -#include "modeset.h" - -static int terminate = 0; - -static void sigint_handler(int arg) -{ - terminate = 1; -} - -static void incrementor(int *inc, int *val, int increment, int lower, int upper) -{ - if(*inc > 0) - *inc = *val + increment >= upper ? -1 : 1; - else - *inc = *val - increment <= lower ? 1 : -1; - *val += *inc * increment; -} - -int main(int argc, char *argv[]) -{ - int ret, i, j, num_test_planes; - int x_inc = 1, x = 0, y_inc = 1, y = 0; - uint32_t plane_w = 128, plane_h = 128; - struct sp_dev *dev; - struct sp_plane **plane = NULL; - struct sp_crtc *test_crtc; - int card = 0, crtc = 0; - - signal(SIGINT, sigint_handler); - - parse_arguments(argc, argv, &card, &crtc); - - dev = create_sp_dev(card); - if (!dev) { - printf("Failed to create sp_dev\n"); - return -1; - } - - if (crtc >= dev->num_crtcs) { - printf("Invalid crtc %d (num=%d)\n", crtc, dev->num_crtcs); - return -1; - } - - ret = initialize_screens(dev); - if (ret) { - printf("Failed to initialize screens\n"); - goto out; - } - test_crtc = &dev->crtcs[crtc]; - - plane = calloc(dev->num_planes, sizeof(*plane)); - if (!plane) { - printf("Failed to allocate plane array\n"); - goto out; - } - - /* Create our planes */ - num_test_planes = test_crtc->num_planes; - for (i = 0; i < num_test_planes; i++) { - plane[i] = get_sp_plane(dev, test_crtc); - if (!plane[i]) { - printf("no unused planes available\n"); - goto out; - } - - plane[i]->bo = create_sp_bo(dev, plane_w, plane_h, 16, - plane[i]->format, 0); - if (!plane[i]->bo) { - printf("failed to create plane bo\n"); - goto out; - } - - fill_bo(plane[i]->bo, 0xFF, 0xFF, 0xFF, 0xFF); - } - - while (!terminate) { - incrementor(&x_inc, &x, 5, 0, - test_crtc->crtc->mode.hdisplay - plane_w); - incrementor(&y_inc, &y, 5, 0, test_crtc->crtc->mode.vdisplay - - plane_h * num_test_planes); - - for (j = 0; j < num_test_planes; j++) { - ret = set_sp_plane(dev, plane[j], test_crtc, - x, y + j * plane_h); - if (ret) { - printf("failed to set plane %d %d\n", j, ret); - goto out; - } - } - usleep(15 * 1000); - } - - for (i = 0; i < num_test_planes; i++) - put_sp_plane(plane[i]); - -out: - destroy_sp_dev(dev); - free(plane); - return ret; -} diff --git a/tests/proptest/Makefile.am b/tests/proptest/Makefile.am index 3fde46be..33b8705b 100644 --- a/tests/proptest/Makefile.am +++ b/tests/proptest/Makefile.am @@ -2,6 +2,7 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS)\ + -fvisibility=hidden \ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/tests \ -I$(top_srcdir) diff --git a/tests/proptest/meson.build b/tests/proptest/meson.build new file mode 100644 index 00000000..9c87965a --- /dev/null +++ b/tests/proptest/meson.build @@ -0,0 +1,28 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +proptest = executable( + 'proptest', + files('proptest.c'), + c_args : libdrm_c_args, + include_directories : [inc_root, inc_tests, inc_drm], + link_with : [libdrm, libutil], + install : with_install_tests, +) diff --git a/tests/radeon/Makefile.am b/tests/radeon/Makefile.am index 9da76259..3d173e31 100644 --- a/tests/radeon/Makefile.am +++ b/tests/radeon/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ + -fvisibility=hidden \ -I $(top_srcdir)/include/drm \ -I $(top_srcdir) diff --git a/tests/radeon/meson.build b/tests/radeon/meson.build new file mode 100644 index 00000000..bb345b73 --- /dev/null +++ b/tests/radeon/meson.build @@ -0,0 +1,27 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +radeon_ttm = executable( + 'radeon_ttm', + files('rbo.c', 'radeon_ttm.c'), + include_directories : [inc_root, inc_drm], + link_with : libdrm, + c_args : libdrm_c_args, +) diff --git a/tests/tegra/Makefile.am b/tests/tegra/Makefile.am index 8e625c8f..b462a30c 100644 --- a/tests/tegra/Makefile.am +++ b/tests/tegra/Makefile.am @@ -3,7 +3,9 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/tegra \ -I$(top_srcdir) -AM_CFLAGS = $(WARN_CFLAGS) +AM_CFLAGS = \ + $(WARN_CFLAGS) \ + -fvisibility=hidden LDADD = \ ../../tegra/libdrm_tegra.la \ diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build new file mode 100644 index 00000000..4f8c54f4 --- /dev/null +++ b/tests/tegra/meson.build @@ -0,0 +1,27 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +openclose = executable( + 'openclose', + files('openclose.c'), + include_directories : [inc_root, inc_drm, include_directories('../../tegra')], + c_args : libdrm_c_args, + link_with : [libdrm, libdrm_tegra], +) diff --git a/tests/tegra/openclose.c b/tests/tegra/openclose.c index 881d8aa4..f80f52d4 100644 --- a/tests/tegra/openclose.c +++ b/tests/tegra/openclose.c @@ -20,10 +20,6 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include <fcntl.h> #include <stdio.h> #include <unistd.h> diff --git a/tests/util/format.c b/tests/util/format.c index 043cfe7f..15ac5e1e 100644 --- a/tests/util/format.c +++ b/tests/util/format.c @@ -23,10 +23,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdint.h> #include <stdlib.h> #include <string.h> diff --git a/tests/util/kms.c b/tests/util/kms.c index 959b6881..5af8bf20 100644 --- a/tests/util/kms.c +++ b/tests/util/kms.c @@ -37,10 +37,6 @@ * the mode has been programmed, along with possible test patterns. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <errno.h> #include <stdint.h> #include <stdio.h> @@ -79,6 +75,7 @@ static const struct type_name encoder_type_names[] = { { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, { DRM_MODE_ENCODER_DSI, "DSI" }, { DRM_MODE_ENCODER_DPMST, "DPMST" }, + { DRM_MODE_ENCODER_DPI, "DPI" }, }; const char *util_lookup_encoder_type_name(unsigned int type) @@ -117,6 +114,7 @@ static const struct type_name connector_type_names[] = { { DRM_MODE_CONNECTOR_eDP, "eDP" }, { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, { DRM_MODE_CONNECTOR_DSI, "DSI" }, + { DRM_MODE_CONNECTOR_DPI, "DPI" }, }; const char *util_lookup_connector_type_name(unsigned int type) @@ -145,6 +143,9 @@ static const char * const modules[] = { "virtio_gpu", "mediatek", "meson", + "pl111", + "stm", + "sun4i-drm", }; int util_open(const char *device, const char *module) diff --git a/tests/util/meson.build b/tests/util/meson.build new file mode 100644 index 00000000..7fa1a4b7 --- /dev/null +++ b/tests/util/meson.build @@ -0,0 +1,28 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +libutil = static_library( + 'util', + [files('format.c', 'kms.c', 'pattern.c'), config_file], + include_directories : [inc_root, inc_drm], + link_with : libdrm, + dependencies : dep_cairo +) diff --git a/tests/util/pattern.c b/tests/util/pattern.c index 00b08a8c..9fa0a417 100644 --- a/tests/util/pattern.c +++ b/tests/util/pattern.c @@ -23,10 +23,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -34,7 +30,7 @@ #include <drm_fourcc.h> -#ifdef HAVE_CAIRO +#if HAVE_CAIRO #include <cairo.h> #include <math.h> #endif @@ -546,10 +542,9 @@ static void fill_smpte(const struct util_format_info *info, void *planes[3], static void make_pwetty(void *data, unsigned int width, unsigned int height, unsigned int stride, uint32_t format) { -#ifdef HAVE_CAIRO +#if HAVE_CAIRO cairo_surface_t *surface; cairo_t *cr; - int x, y; cairo_format_t cairo_format; /* we can ignore the order of R,G,B channels */ @@ -576,8 +571,8 @@ static void make_pwetty(void *data, unsigned int width, unsigned int height, cairo_surface_destroy(surface); cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); - for (x = 0; x < width; x += 250) - for (y = 0; y < height; y += 250) { + for (unsigned x = 0; x < width; x += 250) + for (unsigned y = 0; y < height; y += 250) { char buf[64]; cairo_move_to(cr, x, y - 20); @@ -824,8 +819,8 @@ static void fill_tiles(const struct util_format_info *info, void *planes[3], } } -static void fill_plain(const struct util_format_info *info, void *planes[3], - unsigned int width, unsigned int height, +static void fill_plain(void *planes[3], + unsigned int height, unsigned int stride) { memset(planes[0], 0x77, stride * height); @@ -861,7 +856,7 @@ void util_fill_pattern(uint32_t format, enum util_fill_pattern pattern, return fill_smpte(info, planes, width, height, stride); case UTIL_PATTERN_PLAIN: - return fill_plain(info, planes, width, height, stride); + return fill_plain(planes, height, stride); default: printf("Error: unsupported test pattern %u.\n", pattern); diff --git a/tests/vbltest/Makefile.am b/tests/vbltest/Makefile.am index 276afad5..b6cd7a4d 100644 --- a/tests/vbltest/Makefile.am +++ b/tests/vbltest/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ $(WARN_CFLAGS)\ + -fvisibility=hidden \ -I$(top_srcdir)/include/drm \ -I$(top_srcdir)/tests \ -I$(top_srcdir) diff --git a/tests/vbltest/meson.build b/tests/vbltest/meson.build new file mode 100644 index 00000000..6339feba --- /dev/null +++ b/tests/vbltest/meson.build @@ -0,0 +1,28 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +vbltest = executable( + 'vbltest', + files('vbltest.c'), + c_args : libdrm_c_args, + include_directories : [inc_root, inc_tests, inc_drm], + link_with : [libdrm, libutil], + install : with_install_tests, +) diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c index 3f6b803a..48708d20 100644 --- a/tests/vbltest/vbltest.c +++ b/tests/vbltest/vbltest.c @@ -24,10 +24,6 @@ * IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <assert.h> #include <stdio.h> #include <stdlib.h> diff --git a/util_math.h b/util_math.h index 02b15a8e..35bf4512 100644 --- a/util_math.h +++ b/util_math.h @@ -29,6 +29,6 @@ #define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) #define __align_mask(value, mask) (((value) + (mask)) & ~(mask)) -#define ALIGN(value, alignment) __align_mask(value, (typeof(value))((alignment) - 1)) +#define ALIGN(value, alignment) __align_mask(value, (__typeof__(value))((alignment) - 1)) #endif /*_UTIL_MATH_H_*/ diff --git a/vc4/Makefile.am b/vc4/Makefile.am index 7e486b4d..5f82d04e 100644 --- a/vc4/Makefile.am +++ b/vc4/Makefile.am @@ -23,6 +23,7 @@ include Makefile.sources AM_CFLAGS = \ $(WARN_CFLAGS) \ + -fvisibility=hidden \ -I$(top_srcdir) \ $(PTHREADSTUBS_CFLAGS) \ $(VALGRIND_CFLAGS) \ diff --git a/vc4/meson.build b/vc4/meson.build new file mode 100644 index 00000000..0136987b --- /dev/null +++ b/vc4/meson.build @@ -0,0 +1,28 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +install_headers('vc4_packet.h', 'vc4_qpu_defines.h', subdir : 'libdrm') + +pkg.generate( + name : 'libdrm_vc4', + version : meson.project_version(), + requires_private : 'libdrm', + description : 'Userspace interface to vc4 kernel DRM services', +) diff --git a/xf86atomic.h b/xf86atomic.h index 922b37da..2d733bd5 100644 --- a/xf86atomic.h +++ b/xf86atomic.h @@ -34,10 +34,6 @@ #ifndef LIBDRM_ATOMICS_H #define LIBDRM_ATOMICS_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #if HAVE_LIBDRM_ATOMIC_PRIMITIVES #define HAS_ATOMIC_OPS 1 @@ -101,7 +97,7 @@ typedef struct { LIBDRM_ATOMIC_TYPE atomic; } atomic_t; #endif -#if ! HAS_ATOMIC_OPS +#if !defined(HAS_ATOMIC_OPS) #error libdrm requires atomic operations, please define them for your CPU/compiler. #endif @@ -31,9 +31,6 @@ * DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif #include <stdio.h> #include <stdlib.h> #include <stdbool.h> @@ -62,6 +59,8 @@ #endif #include <math.h> +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + /* Not all systems have MAP_FAILED defined */ #ifndef MAP_FAILED #define MAP_FAILED ((void *)-1) @@ -102,7 +101,7 @@ #define DRM_MAJOR 226 /* Linux */ #endif -#ifdef __OpenBSD__ +#if defined(__OpenBSD__) || defined(__DragonFly__) struct drm_pciinfo { uint16_t domain; uint8_t bus; @@ -124,7 +123,7 @@ struct drm_pciinfo { static drmServerInfoPtr drm_server_info; -void drmSetServerInfo(drmServerInfoPtr info) +drm_public void drmSetServerInfo(drmServerInfoPtr info) { drm_server_info = info; } @@ -144,7 +143,7 @@ drmDebugPrint(const char *format, va_list ap) return vfprintf(stderr, format, ap); } -void +drm_public void drmMsg(const char *format, ...) { va_list ap; @@ -164,17 +163,17 @@ drmMsg(const char *format, ...) static void *drmHashTable = NULL; /* Context switch callbacks */ -void *drmGetHashTable(void) +drm_public void *drmGetHashTable(void) { return drmHashTable; } -void *drmMalloc(int size) +drm_public void *drmMalloc(int size) { return calloc(1, size); } -void drmFree(void *pt) +drm_public void drmFree(void *pt) { free(pt); } @@ -182,7 +181,7 @@ void drmFree(void *pt) /** * Call ioctl, restarting if it is interupted */ -int +drm_public int drmIoctl(int fd, unsigned long request, void *arg) { int ret; @@ -202,7 +201,7 @@ static unsigned long drmGetKeyFromFd(int fd) return st.st_rdev; } -drmHashEntry *drmGetEntry(int fd) +drm_public drmHashEntry *drmGetEntry(int fd) { unsigned long key = drmGetKeyFromFd(fd); void *value; @@ -293,7 +292,7 @@ static int drmMatchBusID(const char *id1, const char *id2, int pci_domain_ok) * If any other failure happened then it will output error mesage using * drmMsg() call. */ -#if !defined(UDEV) +#if !UDEV static int chown_check_return(const char *path, uid_t owner, gid_t group) { int rv; @@ -332,7 +331,7 @@ static int drmOpenDevice(dev_t dev, int minor, int type) int fd; mode_t devmode = DRM_DEV_MODE, serv_mode; gid_t serv_group; -#if !defined(UDEV) +#if !UDEV int isroot = !geteuid(); uid_t user = DRM_DEV_UID; gid_t group = DRM_DEV_GID; @@ -361,7 +360,7 @@ static int drmOpenDevice(dev_t dev, int minor, int type) devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); } -#if !defined(UDEV) +#if !UDEV if (stat(DRM_DIR_NAME, &st)) { if (!isroot) return DRM_ERR_NOT_ROOT; @@ -408,13 +407,13 @@ wait_for_udev: } #endif - fd = open(buf, O_RDWR, 0); + fd = open(buf, O_RDWR | O_CLOEXEC, 0); drmMsg("drmOpenDevice: open result is %d, (%s)\n", fd, fd < 0 ? strerror(errno) : "OK"); if (fd >= 0) return fd; -#if !defined(UDEV) +#if !UDEV /* Check if the device node is not what we expect it to be, and recreate it * and try again if so. */ @@ -428,7 +427,7 @@ wait_for_udev: chmod(buf, devmode); } } - fd = open(buf, O_RDWR, 0); + fd = open(buf, O_RDWR | O_CLOEXEC, 0); drmMsg("drmOpenDevice: open result is %d, (%s)\n", fd, fd < 0 ? strerror(errno) : "OK"); if (fd >= 0) @@ -477,7 +476,7 @@ static int drmOpenMinor(int minor, int create, int type) }; sprintf(buf, dev_name, DRM_DIR_NAME, minor); - if ((fd = open(buf, O_RDWR, 0)) >= 0) + if ((fd = open(buf, O_RDWR | O_CLOEXEC, 0)) >= 0) return fd; return -errno; } @@ -493,7 +492,7 @@ static int drmOpenMinor(int minor, int create, int type) * minor and get version information. For backward compatibility with older * Linux implementations, /proc/dri is also checked. */ -int drmAvailable(void) +drm_public int drmAvailable(void) { drmVersionPtr version; int retval = 0; @@ -728,7 +727,7 @@ static int drmOpenByName(const char *name, int type) * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() * otherwise. */ -int drmOpen(const char *name, const char *busid) +drm_public int drmOpen(const char *name, const char *busid) { return drmOpenWithType(name, busid, DRM_NODE_PRIMARY); } @@ -749,7 +748,7 @@ int drmOpen(const char *name, const char *busid) * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() * otherwise. */ -int drmOpenWithType(const char *name, const char *busid, int type) +drm_public int drmOpenWithType(const char *name, const char *busid, int type) { if (name != NULL && drm_server_info && drm_server_info->load_module && !drmAvailable()) { @@ -772,12 +771,12 @@ int drmOpenWithType(const char *name, const char *busid, int type) return -1; } -int drmOpenControl(int minor) +drm_public int drmOpenControl(int minor) { return drmOpenMinor(minor, 0, DRM_NODE_CONTROL); } -int drmOpenRender(int minor) +drm_public int drmOpenRender(int minor) { return drmOpenMinor(minor, 0, DRM_NODE_RENDER); } @@ -791,7 +790,7 @@ int drmOpenRender(int minor) * It frees the memory pointed by \p %v as well as all the non-null strings * pointers in it. */ -void drmFreeVersion(drmVersionPtr v) +drm_public void drmFreeVersion(drmVersionPtr v) { if (!v) return; @@ -861,13 +860,11 @@ static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) * first with zeros to get the string lengths, and then the actually strings. * It also null-terminates them since they might not be already. */ -drmVersionPtr drmGetVersion(int fd) +drm_public drmVersionPtr drmGetVersion(int fd) { drmVersionPtr retval; drm_version_t *version = drmMalloc(sizeof(*version)); - memclear(*version); - if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) { drmFreeKernelVersion(version); return NULL; @@ -911,7 +908,7 @@ drmVersionPtr drmGetVersion(int fd) * This function allocates and fills a drm_version structure with a hard coded * version number. */ -drmVersionPtr drmGetLibVersion(int fd) +drm_public drmVersionPtr drmGetLibVersion(int fd) { drm_version_t *version = drmMalloc(sizeof(*version)); @@ -932,7 +929,7 @@ drmVersionPtr drmGetLibVersion(int fd) return (drmVersionPtr)version; } -int drmGetCap(int fd, uint64_t capability, uint64_t *value) +drm_public int drmGetCap(int fd, uint64_t capability, uint64_t *value) { struct drm_get_cap cap; int ret; @@ -948,7 +945,7 @@ int drmGetCap(int fd, uint64_t capability, uint64_t *value) return 0; } -int drmSetClientCap(int fd, uint64_t capability, uint64_t value) +drm_public int drmSetClientCap(int fd, uint64_t capability, uint64_t value) { struct drm_set_client_cap cap; @@ -967,7 +964,7 @@ int drmSetClientCap(int fd, uint64_t capability, uint64_t value) * \internal * This function is just frees the memory pointed by \p busid. */ -void drmFreeBusid(const char *busid) +drm_public void drmFreeBusid(const char *busid) { drmFree((void *)busid); } @@ -985,7 +982,7 @@ void drmFreeBusid(const char *busid) * get the string length and data, passing the arguments in a drm_unique * structure. */ -char *drmGetBusid(int fd) +drm_public char *drmGetBusid(int fd) { drm_unique_t u; @@ -994,8 +991,10 @@ char *drmGetBusid(int fd) if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; u.unique = drmMalloc(u.unique_len + 1); - if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) + if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) { + drmFree(u.unique); return NULL; + } u.unique[u.unique_len] = '\0'; return u.unique; @@ -1014,7 +1013,7 @@ char *drmGetBusid(int fd) * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing * the arguments in a drm_unique structure. */ -int drmSetBusid(int fd, const char *busid) +drm_public int drmSetBusid(int fd, const char *busid) { drm_unique_t u; @@ -1028,7 +1027,7 @@ int drmSetBusid(int fd, const char *busid) return 0; } -int drmGetMagic(int fd, drm_magic_t * magic) +drm_public int drmGetMagic(int fd, drm_magic_t * magic) { drm_auth_t auth; @@ -1041,7 +1040,7 @@ int drmGetMagic(int fd, drm_magic_t * magic) return 0; } -int drmAuthMagic(int fd, drm_magic_t magic) +drm_public int drmAuthMagic(int fd, drm_magic_t magic) { drm_auth_t auth; @@ -1102,8 +1101,8 @@ int drmAuthMagic(int fd, drm_magic_t magic) * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing * the arguments in a drm_map structure. */ -int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, - drmMapFlags flags, drm_handle_t *handle) +drm_public int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, + drmMapFlags flags, drm_handle_t *handle) { drm_map_t map; @@ -1119,7 +1118,7 @@ int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type, return 0; } -int drmRmMap(int fd, drm_handle_t handle) +drm_public int drmRmMap(int fd, drm_handle_t handle) { drm_map_t map; @@ -1147,8 +1146,8 @@ int drmRmMap(int fd, drm_handle_t handle) * * \sa drm_buf_desc. */ -int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, - int agp_offset) +drm_public int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, + int agp_offset) { drm_buf_desc_t request; @@ -1163,7 +1162,7 @@ int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, return request.count; } -int drmMarkBufs(int fd, double low, double high) +drm_public int drmMarkBufs(int fd, double low, double high) { drm_buf_info_t info; int i; @@ -1214,7 +1213,7 @@ int drmMarkBufs(int fd, double low, double high) * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing * the arguments in a drm_buf_free structure. */ -int drmFreeBufs(int fd, int count, int *list) +drm_public int drmFreeBufs(int fd, int count, int *list) { drm_buf_free_t request; @@ -1235,7 +1234,7 @@ int drmFreeBufs(int fd, int count, int *list) * \internal * This function closes the file descriptor. */ -int drmClose(int fd) +drm_public int drmClose(int fd) { unsigned long key = drmGetKeyFromFd(fd); drmHashEntry *entry = drmGetEntry(fd); @@ -1266,7 +1265,8 @@ int drmClose(int fd) * \internal * This function is a wrapper for mmap(). */ -int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address) +drm_public int drmMap(int fd, drm_handle_t handle, drmSize size, + drmAddressPtr address) { static unsigned long pagesize_mask = 0; @@ -1296,12 +1296,12 @@ int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address) * \internal * This function is a wrapper for munmap(). */ -int drmUnmap(drmAddress address, drmSize size) +drm_public int drmUnmap(drmAddress address, drmSize size) { return drm_munmap(address, size); } -drmBufInfoPtr drmGetBufInfo(int fd) +drm_public drmBufInfoPtr drmGetBufInfo(int fd) { drm_buf_info_t info; drmBufInfoPtr retval; @@ -1351,7 +1351,7 @@ drmBufInfoPtr drmGetBufInfo(int fd) * information about the buffers in a drm_buf_map structure into the * client-visible data structures. */ -drmBufMapPtr drmMapBufs(int fd) +drm_public drmBufMapPtr drmMapBufs(int fd) { drm_buf_map_t bufs; drmBufMapPtr retval; @@ -1396,7 +1396,7 @@ drmBufMapPtr drmMapBufs(int fd) * Calls munmap() for every buffer stored in \p bufs and frees the * memory allocated by drmMapBufs(). */ -int drmUnmapBufs(drmBufMapPtr bufs) +drm_public int drmUnmapBufs(drmBufMapPtr bufs) { int i; @@ -1424,7 +1424,7 @@ int drmUnmapBufs(drmBufMapPtr bufs) * Assemble the arguments into a drm_dma structure and keeps issuing the * DRM_IOCTL_DMA ioctl until success or until maximum number of retries. */ -int drmDMA(int fd, drmDMAReqPtr request) +drm_public int drmDMA(int fd, drmDMAReqPtr request) { drm_dma_t dma; int ret, i = 0; @@ -1467,7 +1467,7 @@ int drmDMA(int fd, drmDMAReqPtr request) * This function translates the arguments into a drm_lock structure and issue * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. */ -int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) +drm_public int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) { drm_lock_t lock; @@ -1498,7 +1498,7 @@ int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the * argument in a drm_lock structure. */ -int drmUnlock(int fd, drm_context_t context) +drm_public int drmUnlock(int fd, drm_context_t context) { drm_lock_t lock; @@ -1507,7 +1507,7 @@ int drmUnlock(int fd, drm_context_t context) return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock); } -drm_context_t *drmGetReservedContextList(int fd, int *count) +drm_public drm_context_t *drmGetReservedContextList(int fd, int *count) { drm_ctx_res_t res; drm_ctx_t *list; @@ -1523,14 +1523,12 @@ drm_context_t *drmGetReservedContextList(int fd, int *count) if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL; - if (!(retval = drmMalloc(res.count * sizeof(*retval)))) { - drmFree(list); - return NULL; - } + if (!(retval = drmMalloc(res.count * sizeof(*retval)))) + goto err_free_list; res.contexts = list; if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res)) - return NULL; + goto err_free_context; for (i = 0; i < res.count; i++) retval[i] = list[i].handle; @@ -1538,9 +1536,15 @@ drm_context_t *drmGetReservedContextList(int fd, int *count) *count = res.count; return retval; + +err_free_list: + drmFree(list); +err_free_context: + drmFree(retval); + return NULL; } -void drmFreeReservedContextList(drm_context_t *pt) +drm_public void drmFreeReservedContextList(drm_context_t *pt) { drmFree(pt); } @@ -1563,7 +1567,7 @@ void drmFreeReservedContextList(drm_context_t *pt) * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the * argument in a drm_ctx structure. */ -int drmCreateContext(int fd, drm_context_t *handle) +drm_public int drmCreateContext(int fd, drm_context_t *handle) { drm_ctx_t ctx; @@ -1574,7 +1578,7 @@ int drmCreateContext(int fd, drm_context_t *handle) return 0; } -int drmSwitchToContext(int fd, drm_context_t context) +drm_public int drmSwitchToContext(int fd, drm_context_t context) { drm_ctx_t ctx; @@ -1585,7 +1589,8 @@ int drmSwitchToContext(int fd, drm_context_t context) return 0; } -int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags) +drm_public int drmSetContextFlags(int fd, drm_context_t context, + drm_context_tFlags flags) { drm_ctx_t ctx; @@ -1606,8 +1611,8 @@ int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags) return 0; } -int drmGetContextFlags(int fd, drm_context_t context, - drm_context_tFlagsPtr flags) +drm_public int drmGetContextFlags(int fd, drm_context_t context, + drm_context_tFlagsPtr flags) { drm_ctx_t ctx; @@ -1640,7 +1645,7 @@ int drmGetContextFlags(int fd, drm_context_t context, * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the * argument in a drm_ctx structure. */ -int drmDestroyContext(int fd, drm_context_t handle) +drm_public int drmDestroyContext(int fd, drm_context_t handle) { drm_ctx_t ctx; @@ -1651,7 +1656,7 @@ int drmDestroyContext(int fd, drm_context_t handle) return 0; } -int drmCreateDrawable(int fd, drm_drawable_t *handle) +drm_public int drmCreateDrawable(int fd, drm_drawable_t *handle) { drm_draw_t draw; @@ -1662,7 +1667,7 @@ int drmCreateDrawable(int fd, drm_drawable_t *handle) return 0; } -int drmDestroyDrawable(int fd, drm_drawable_t handle) +drm_public int drmDestroyDrawable(int fd, drm_drawable_t handle) { drm_draw_t draw; @@ -1673,9 +1678,9 @@ int drmDestroyDrawable(int fd, drm_drawable_t handle) return 0; } -int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, - drm_drawable_info_type_t type, unsigned int num, - void *data) +drm_public int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, + drm_drawable_info_type_t type, + unsigned int num, void *data) { drm_update_draw_t update; @@ -1691,6 +1696,46 @@ int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, return 0; } +drm_public int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence, + uint64_t *ns) +{ + struct drm_crtc_get_sequence get_seq; + int ret; + + memclear(get_seq); + get_seq.crtc_id = crtcId; + ret = drmIoctl(fd, DRM_IOCTL_CRTC_GET_SEQUENCE, &get_seq); + if (ret) + return ret; + + if (sequence) + *sequence = get_seq.sequence; + if (ns) + *ns = get_seq.sequence_ns; + return 0; +} + +drm_public int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags, + uint64_t sequence, + uint64_t *sequence_queued, + uint64_t user_data) +{ + struct drm_crtc_queue_sequence queue_seq; + int ret; + + memclear(queue_seq); + queue_seq.crtc_id = crtcId; + queue_seq.flags = flags; + queue_seq.sequence = sequence; + queue_seq.user_data = user_data; + + ret = drmIoctl(fd, DRM_IOCTL_CRTC_QUEUE_SEQUENCE, &queue_seq); + if (ret == 0 && sequence_queued) + *sequence_queued = queue_seq.sequence; + + return ret; +} + /** * Acquire the AGP device. * @@ -1703,7 +1748,7 @@ int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, * \internal * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl. */ -int drmAgpAcquire(int fd) +drm_public int drmAgpAcquire(int fd) { if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno; @@ -1721,7 +1766,7 @@ int drmAgpAcquire(int fd) * \internal * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl. */ -int drmAgpRelease(int fd) +drm_public int drmAgpRelease(int fd) { if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno; @@ -1741,7 +1786,7 @@ int drmAgpRelease(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the * argument in a drm_agp_mode structure. */ -int drmAgpEnable(int fd, unsigned long mode) +drm_public int drmAgpEnable(int fd, unsigned long mode) { drm_agp_mode_t m; @@ -1769,8 +1814,8 @@ int drmAgpEnable(int fd, unsigned long mode) * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the * arguments in a drm_agp_buffer structure. */ -int drmAgpAlloc(int fd, unsigned long size, unsigned long type, - unsigned long *address, drm_handle_t *handle) +drm_public int drmAgpAlloc(int fd, unsigned long size, unsigned long type, + unsigned long *address, drm_handle_t *handle) { drm_agp_buffer_t b; @@ -1799,7 +1844,7 @@ int drmAgpAlloc(int fd, unsigned long size, unsigned long type, * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the * argument in a drm_agp_buffer structure. */ -int drmAgpFree(int fd, drm_handle_t handle) +drm_public int drmAgpFree(int fd, drm_handle_t handle) { drm_agp_buffer_t b; @@ -1824,7 +1869,7 @@ int drmAgpFree(int fd, drm_handle_t handle) * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the * argument in a drm_agp_binding structure. */ -int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) +drm_public int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) { drm_agp_binding_t b; @@ -1849,7 +1894,7 @@ int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset) * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing * the argument in a drm_agp_binding structure. */ -int drmAgpUnbind(int fd, drm_handle_t handle) +drm_public int drmAgpUnbind(int fd, drm_handle_t handle) { drm_agp_binding_t b; @@ -1872,7 +1917,7 @@ int drmAgpUnbind(int fd, drm_handle_t handle) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -int drmAgpVersionMajor(int fd) +drm_public int drmAgpVersionMajor(int fd) { drm_agp_info_t i; @@ -1895,7 +1940,7 @@ int drmAgpVersionMajor(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -int drmAgpVersionMinor(int fd) +drm_public int drmAgpVersionMinor(int fd) { drm_agp_info_t i; @@ -1918,7 +1963,7 @@ int drmAgpVersionMinor(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -unsigned long drmAgpGetMode(int fd) +drm_public unsigned long drmAgpGetMode(int fd) { drm_agp_info_t i; @@ -1941,7 +1986,7 @@ unsigned long drmAgpGetMode(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -unsigned long drmAgpBase(int fd) +drm_public unsigned long drmAgpBase(int fd) { drm_agp_info_t i; @@ -1964,7 +2009,7 @@ unsigned long drmAgpBase(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -unsigned long drmAgpSize(int fd) +drm_public unsigned long drmAgpSize(int fd) { drm_agp_info_t i; @@ -1987,7 +2032,7 @@ unsigned long drmAgpSize(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -unsigned long drmAgpMemoryUsed(int fd) +drm_public unsigned long drmAgpMemoryUsed(int fd) { drm_agp_info_t i; @@ -2010,7 +2055,7 @@ unsigned long drmAgpMemoryUsed(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -unsigned long drmAgpMemoryAvail(int fd) +drm_public unsigned long drmAgpMemoryAvail(int fd) { drm_agp_info_t i; @@ -2033,7 +2078,7 @@ unsigned long drmAgpMemoryAvail(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -unsigned int drmAgpVendorId(int fd) +drm_public unsigned int drmAgpVendorId(int fd) { drm_agp_info_t i; @@ -2056,7 +2101,7 @@ unsigned int drmAgpVendorId(int fd) * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the * necessary information in a drm_agp_info structure. */ -unsigned int drmAgpDeviceId(int fd) +drm_public unsigned int drmAgpDeviceId(int fd) { drm_agp_info_t i; @@ -2067,7 +2112,8 @@ unsigned int drmAgpDeviceId(int fd) return i.id_device; } -int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle) +drm_public int drmScatterGatherAlloc(int fd, unsigned long size, + drm_handle_t *handle) { drm_scatter_gather_t sg; @@ -2081,7 +2127,7 @@ int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle) return 0; } -int drmScatterGatherFree(int fd, drm_handle_t handle) +drm_public int drmScatterGatherFree(int fd, drm_handle_t handle) { drm_scatter_gather_t sg; @@ -2103,7 +2149,7 @@ int drmScatterGatherFree(int fd, drm_handle_t handle) * \internal * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl. */ -int drmWaitVBlank(int fd, drmVBlankPtr vbl) +drm_public int drmWaitVBlank(int fd, drmVBlankPtr vbl) { struct timespec timeout, cur; int ret; @@ -2135,7 +2181,7 @@ out: return ret; } -int drmError(int err, const char *label) +drm_public int drmError(int err, const char *label) { switch (err) { case DRM_ERR_NO_DEVICE: @@ -2172,7 +2218,7 @@ int drmError(int err, const char *label) * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the * argument in a drm_control structure. */ -int drmCtlInstHandler(int fd, int irq) +drm_public int drmCtlInstHandler(int fd, int irq) { drm_control_t ctl; @@ -2196,7 +2242,7 @@ int drmCtlInstHandler(int fd, int irq) * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the * argument in a drm_control structure. */ -int drmCtlUninstHandler(int fd) +drm_public int drmCtlUninstHandler(int fd) { drm_control_t ctl; @@ -2208,7 +2254,7 @@ int drmCtlUninstHandler(int fd) return 0; } -int drmFinish(int fd, int context, drmLockFlags flags) +drm_public int drmFinish(int fd, int context, drmLockFlags flags) { drm_lock_t lock; @@ -2239,7 +2285,8 @@ int drmFinish(int fd, int context, drmLockFlags flags) * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the * arguments in a drm_irq_busid structure. */ -int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) +drm_public int drmGetInterruptFromBusID(int fd, int busnum, int devnum, + int funcnum) { drm_irq_busid_t p; @@ -2252,7 +2299,7 @@ int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) return p.irq; } -int drmAddContextTag(int fd, drm_context_t context, void *tag) +drm_public int drmAddContextTag(int fd, drm_context_t context, void *tag) { drmHashEntry *entry = drmGetEntry(fd); @@ -2263,14 +2310,14 @@ int drmAddContextTag(int fd, drm_context_t context, void *tag) return 0; } -int drmDelContextTag(int fd, drm_context_t context) +drm_public int drmDelContextTag(int fd, drm_context_t context) { drmHashEntry *entry = drmGetEntry(fd); return drmHashDelete(entry->tagTable, context); } -void *drmGetContextTag(int fd, drm_context_t context) +drm_public void *drmGetContextTag(int fd, drm_context_t context) { drmHashEntry *entry = drmGetEntry(fd); void *value; @@ -2281,8 +2328,8 @@ void *drmGetContextTag(int fd, drm_context_t context) return value; } -int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, - drm_handle_t handle) +drm_public int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t handle) { drm_ctx_priv_map_t map; @@ -2295,8 +2342,8 @@ int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, return 0; } -int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, - drm_handle_t *handle) +drm_public int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t *handle) { drm_ctx_priv_map_t map; @@ -2311,9 +2358,9 @@ int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, return 0; } -int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, - drmMapType *type, drmMapFlags *flags, drm_handle_t *handle, - int *mtrr) +drm_public int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, + drmMapType *type, drmMapFlags *flags, + drm_handle_t *handle, int *mtrr) { drm_map_t map; @@ -2330,8 +2377,8 @@ int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, return 0; } -int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, - unsigned long *magic, unsigned long *iocs) +drm_public int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, + unsigned long *magic, unsigned long *iocs) { drm_client_t client; @@ -2347,7 +2394,7 @@ int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, return 0; } -int drmGetStats(int fd, drmStatsT *stats) +drm_public int drmGetStats(int fd, drmStatsT *stats) { drm_stats_t s; unsigned i; @@ -2485,7 +2532,7 @@ int drmGetStats(int fd, drmStatsT *stats) * It issues a read-write ioctl given by * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. */ -int drmSetInterfaceVersion(int fd, drmSetVersion *version) +drm_public int drmSetInterfaceVersion(int fd, drmSetVersion *version) { int retcode = 0; drm_set_version_t sv; @@ -2520,7 +2567,7 @@ int drmSetInterfaceVersion(int fd, drmSetVersion *version) * It issues a ioctl given by * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. */ -int drmCommandNone(int fd, unsigned long drmCommandIndex) +drm_public int drmCommandNone(int fd, unsigned long drmCommandIndex) { unsigned long request; @@ -2547,8 +2594,8 @@ int drmCommandNone(int fd, unsigned long drmCommandIndex) * It issues a read ioctl given by * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. */ -int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data, - unsigned long size) +drm_public int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size) { unsigned long request; @@ -2576,8 +2623,8 @@ int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data, * It issues a write ioctl given by * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. */ -int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data, - unsigned long size) +drm_public int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size) { unsigned long request; @@ -2605,8 +2652,8 @@ int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data, * It issues a read-write ioctl given by * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. */ -int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data, - unsigned long size) +drm_public int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size) { unsigned long request; @@ -2628,14 +2675,13 @@ static struct { static int nr_fds = 0; -int drmOpenOnce(void *unused, - const char *BusID, - int *newlyopened) +drm_public int drmOpenOnce(void *unused, const char *BusID, int *newlyopened) { return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY); } -int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type) +drm_public int drmOpenOnceWithType(const char *BusID, int *newlyopened, + int type) { int i; int fd; @@ -2668,7 +2714,7 @@ int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type) return fd; } -void drmCloseOnce(int fd) +drm_public void drmCloseOnce(int fd) { int i; @@ -2687,17 +2733,17 @@ void drmCloseOnce(int fd) } } -int drmSetMaster(int fd) +drm_public int drmSetMaster(int fd) { return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL); } -int drmDropMaster(int fd) +drm_public int drmDropMaster(int fd) { return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL); } -char *drmGetDeviceNameFromFd(int fd) +drm_public char *drmGetDeviceNameFromFd(int fd) { char name[128]; struct stat sbuf; @@ -2723,7 +2769,21 @@ char *drmGetDeviceNameFromFd(int fd) return strdup(name); } -int drmGetNodeTypeFromFd(int fd) +static bool drmNodeIsDRM(int maj, int min) +{ +#ifdef __linux__ + char path[64]; + struct stat sbuf; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm", + maj, min); + return stat(path, &sbuf) == 0; +#else + return maj == DRM_MAJOR; +#endif +} + +drm_public int drmGetNodeTypeFromFd(int fd) { struct stat sbuf; int maj, min, type; @@ -2734,7 +2794,7 @@ int drmGetNodeTypeFromFd(int fd) maj = major(sbuf.st_rdev); min = minor(sbuf.st_rdev); - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) { + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) { errno = EINVAL; return -1; } @@ -2745,7 +2805,8 @@ int drmGetNodeTypeFromFd(int fd) return type; } -int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd) +drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, + int *prime_fd) { struct drm_prime_handle args; int ret; @@ -2762,7 +2823,7 @@ int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd) return 0; } -int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) +drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) { struct drm_prime_handle args; int ret; @@ -2781,12 +2842,11 @@ static char *drmGetMinorNameForFD(int fd, int type) { #ifdef __linux__ DIR *sysdir; - struct dirent *pent, *ent; + struct dirent *ent; struct stat sbuf; const char *name = drmGetMinorName(type); int len; char dev_name[64], buf[64]; - long name_max; int maj, min; if (!name) @@ -2800,7 +2860,7 @@ static char *drmGetMinorNameForFD(int fd, int type) maj = major(sbuf.st_rdev); min = minor(sbuf.st_rdev); - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) return NULL; snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min); @@ -2809,30 +2869,18 @@ static char *drmGetMinorNameForFD(int fd, int type) if (!sysdir) return NULL; - name_max = fpathconf(dirfd(sysdir), _PC_NAME_MAX); - if (name_max == -1) - goto out_close_dir; - - pent = malloc(offsetof(struct dirent, d_name) + name_max + 1); - if (pent == NULL) - goto out_close_dir; - - while (readdir_r(sysdir, pent, &ent) == 0 && ent != NULL) { + while ((ent = readdir(sysdir))) { if (strncmp(ent->d_name, name, len) == 0) { snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s", ent->d_name); - free(pent); closedir(sysdir); - return strdup(dev_name); } } - free(pent); - -out_close_dir: closedir(sysdir); + return NULL; #else struct stat sbuf; char buf[PATH_MAX + 1]; @@ -2846,7 +2894,7 @@ out_close_dir: maj = major(sbuf.st_rdev); min = minor(sbuf.st_rdev); - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) return NULL; switch (type) { @@ -2873,15 +2921,14 @@ out_close_dir: return strdup(buf); #endif - return NULL; } -char *drmGetPrimaryDeviceNameFromFd(int fd) +drm_public char *drmGetPrimaryDeviceNameFromFd(int fd) { return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY); } -char *drmGetRenderDeviceNameFromFd(int fd) +drm_public char *drmGetRenderDeviceNameFromFd(int fd) { return drmGetMinorNameForFD(fd, DRM_NODE_RENDER); } @@ -2930,12 +2977,26 @@ sysfs_uevent_get(const char *path, const char *fmt, ...) } #endif +/* Little white lie to avoid major rework of the existing code */ +#define DRM_BUS_VIRTIO 0x10 + static int drmParseSubsystemType(int maj, int min) { #ifdef __linux__ char path[PATH_MAX + 1]; char link[PATH_MAX + 1] = ""; char *name; + struct { + const char *name; + int bus_type; + } bus_types[] = { + { "/pci", DRM_BUS_PCI }, + { "/usb", DRM_BUS_USB }, + { "/platform", DRM_BUS_PLATFORM }, + { "/spi", DRM_BUS_PLATFORM }, + { "/host1x", DRM_BUS_HOST1X }, + { "/virtio", DRM_BUS_VIRTIO }, + }; snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem", maj, min); @@ -2947,20 +3008,13 @@ static int drmParseSubsystemType(int maj, int min) if (!name) return -EINVAL; - if (strncmp(name, "/pci", 4) == 0) - return DRM_BUS_PCI; - - if (strncmp(name, "/usb", 4) == 0) - return DRM_BUS_USB; - - if (strncmp(name, "/platform", 9) == 0) - return DRM_BUS_PLATFORM; - - if (strncmp(name, "/host1x", 7) == 0) - return DRM_BUS_HOST1X; + for (unsigned i = 0; i < ARRAY_SIZE(bus_types); i++) { + if (strncmp(name, bus_types[i].name, strlen(bus_types[i].name)) == 0) + return bus_types[i].bus_type; + } return -EINVAL; -#elif defined(__OpenBSD__) +#elif defined(__OpenBSD__) || defined(__DragonFly__) return DRM_BUS_PCI; #else #warning "Missing implementation of drmParseSubsystemType" @@ -2968,16 +3022,32 @@ static int drmParseSubsystemType(int maj, int min) #endif } +static void +get_pci_path(int maj, int min, char *pci_path) +{ + char path[PATH_MAX + 1], *term; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + if (!realpath(path, pci_path)) { + strcpy(pci_path, path); + return; + } + + term = strrchr(pci_path, '/'); + if (term && strncmp(term, "/virtio", 7) == 0) + *term = 0; +} + static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) { #ifdef __linux__ unsigned int domain, bus, dev, func; - char path[PATH_MAX + 1], *value; + char pci_path[PATH_MAX + 1], *value; int num; - snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + get_pci_path(maj, min, pci_path); - value = sysfs_uevent_get(path, "PCI_SLOT_NAME"); + value = sysfs_uevent_get(pci_path, "PCI_SLOT_NAME"); if (!value) return -ENOENT; @@ -2993,7 +3063,7 @@ static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) info->func = func; return 0; -#elif defined(__OpenBSD__) +#elif defined(__OpenBSD__) || defined(__DragonFly__) struct drm_pciinfo pinfo; int fd, type; @@ -3023,32 +3093,32 @@ static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info) #endif } -static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b) +drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b) { if (a == NULL || b == NULL) - return -1; + return 0; if (a->bustype != b->bustype) - return -1; + return 0; switch (a->bustype) { case DRM_BUS_PCI: - return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)); + return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0; case DRM_BUS_USB: - return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)); + return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0; case DRM_BUS_PLATFORM: - return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)); + return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0; case DRM_BUS_HOST1X: - return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)); + return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0; default: break; } - return -1; + return 0; } static int drmGetNodeType(const char *name) @@ -3082,7 +3152,6 @@ static int parse_separate_sysfs_files(int maj, int min, drmPciDeviceInfoPtr device, bool ignore_revision) { -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static const char *attrs[] = { "revision", /* Older kernels are missing the file, so check for it first */ "vendor", @@ -3090,14 +3159,15 @@ static int parse_separate_sysfs_files(int maj, int min, "subsystem_vendor", "subsystem_device", }; - char path[PATH_MAX + 1]; + char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; unsigned int data[ARRAY_SIZE(attrs)]; FILE *fp; int ret; + get_pci_path(maj, min, pci_path); + for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) { - snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/%s", maj, min, - attrs[i]); + snprintf(path, PATH_MAX, "%s/%s", pci_path, attrs[i]); fp = fopen(path, "r"); if (!fp) return -errno; @@ -3121,11 +3191,13 @@ static int parse_separate_sysfs_files(int maj, int min, static int parse_config_sysfs_file(int maj, int min, drmPciDeviceInfoPtr device) { - char path[PATH_MAX + 1]; + char path[PATH_MAX + 1], pci_path[PATH_MAX + 1]; unsigned char config[64]; int fd, ret; - snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/config", maj, min); + get_pci_path(maj, min, pci_path); + + snprintf(path, PATH_MAX, "%s/config", pci_path); fd = open(path, O_RDONLY); if (fd < 0) return -errno; @@ -3157,7 +3229,7 @@ static int drmParsePciDeviceInfo(int maj, int min, return parse_config_sysfs_file(maj, min, device); return 0; -#elif defined(__OpenBSD__) +#elif defined(__OpenBSD__) || defined(__DragonFly__) struct drm_pciinfo pinfo; int fd, type; @@ -3220,7 +3292,7 @@ static void drmFreeHost1xDevice(drmDevicePtr device) } } -void drmFreeDevice(drmDevicePtr *device) +drm_public void drmFreeDevice(drmDevicePtr *device) { if (device == NULL) return; @@ -3241,7 +3313,7 @@ void drmFreeDevice(drmDevicePtr *device) *device = NULL; } -void drmFreeDevices(drmDevicePtr devices[], int count) +drm_public void drmFreeDevices(drmDevicePtr devices[], int count) { int i; @@ -3652,6 +3724,53 @@ free_device: return ret; } +static int +process_device(drmDevicePtr *device, const char *d_name, + int req_subsystem_type, + bool fetch_deviceinfo, uint32_t flags) +{ + struct stat sbuf; + char node[PATH_MAX + 1]; + int node_type, subsystem_type; + unsigned int maj, min; + + node_type = drmGetNodeType(d_name); + if (node_type < 0) + return -1; + + snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name); + if (stat(node, &sbuf)) + return -1; + + maj = major(sbuf.st_rdev); + min = minor(sbuf.st_rdev); + + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) + return -1; + + subsystem_type = drmParseSubsystemType(maj, min); + if (req_subsystem_type != -1 && req_subsystem_type != subsystem_type) + return -1; + + switch (subsystem_type) { + case DRM_BUS_PCI: + case DRM_BUS_VIRTIO: + return drmProcessPciDevice(device, node, node_type, maj, min, + fetch_deviceinfo, flags); + case DRM_BUS_USB: + return drmProcessUsbDevice(device, node, node_type, maj, min, + fetch_deviceinfo, flags); + case DRM_BUS_PLATFORM: + return drmProcessPlatformDevice(device, node, node_type, maj, min, + fetch_deviceinfo, flags); + case DRM_BUS_HOST1X: + return drmProcessHost1xDevice(device, node, node_type, maj, min, + fetch_deviceinfo, flags); + default: + return -1; + } +} + /* Consider devices located on the same bus as duplicate and fold the respective * entries into a single one. * @@ -3663,7 +3782,7 @@ static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count) for (i = 0; i < count; i++) { for (j = i + 1; j < count; j++) { - if (drmCompareBusInfo(local_devices[i], local_devices[j]) == 0) { + if (drmDevicesEqual(local_devices[i], local_devices[j])) { local_devices[i]->available_nodes |= local_devices[j]->available_nodes; node_type = log2(local_devices[j]->available_nodes); memcpy(local_devices[i]->nodes[node_type], @@ -3681,6 +3800,28 @@ drm_device_validate_flags(uint32_t flags) return (flags & ~DRM_DEVICE_GET_PCI_REVISION); } +static bool +drm_device_has_rdev(drmDevicePtr device, dev_t find_rdev) +{ + struct stat sbuf; + + for (int i = 0; i < DRM_NODE_MAX; i++) { + if (device->available_nodes & 1 << i) { + if (stat(device->nodes[i], &sbuf) == 0 && + sbuf.st_rdev == find_rdev) + return true; + } + } + return false; +} + +/* + * The kernel drm core has a number of places that assume maximum of + * 3x64 devices nodes. That's 64 for each of primary, control and + * render nodes. Rounded it up to 256 for simplicity. + */ +#define MAX_DRM_NODES 256 + /** * Get information about the opened drm device * @@ -3694,7 +3835,7 @@ drm_device_validate_flags(uint32_t flags) * \note Unlike drmGetDevice it does not retrieve the pci device revision field * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. */ -int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) +drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) { #ifdef __OpenBSD__ /* @@ -3718,7 +3859,7 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) maj = major(sbuf.st_rdev); min = minor(sbuf.st_rdev); - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) return -EINVAL; node_type = drmGetMinorType(min); @@ -3761,16 +3902,14 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) return 0; #else - drmDevicePtr *local_devices; + drmDevicePtr local_devices[MAX_DRM_NODES]; drmDevicePtr d; DIR *sysdir; struct dirent *dent; struct stat sbuf; - char node[PATH_MAX + 1]; - int node_type, subsystem_type; + int subsystem_type; int maj, min; int ret, i, node_count; - int max_count = 16; dev_t find_rdev; if (drm_device_validate_flags(flags)) @@ -3786,112 +3925,52 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) maj = major(sbuf.st_rdev); min = minor(sbuf.st_rdev); - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) return -EINVAL; subsystem_type = drmParseSubsystemType(maj, min); - - local_devices = calloc(max_count, sizeof(drmDevicePtr)); - if (local_devices == NULL) - return -ENOMEM; + if (subsystem_type < 0) + return subsystem_type; sysdir = opendir(DRM_DIR_NAME); - if (!sysdir) { - ret = -errno; - goto free_locals; - } + if (!sysdir) + return -errno; i = 0; while ((dent = readdir(sysdir))) { - node_type = drmGetNodeType(dent->d_name); - if (node_type < 0) - continue; - - snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name); - if (stat(node, &sbuf)) - continue; - - maj = major(sbuf.st_rdev); - min = minor(sbuf.st_rdev); - - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) - continue; - - if (drmParseSubsystemType(maj, min) != subsystem_type) + ret = process_device(&d, dent->d_name, subsystem_type, true, flags); + if (ret) continue; - switch (subsystem_type) { - case DRM_BUS_PCI: - ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags); - if (ret) - continue; - + if (i >= MAX_DRM_NODES) { + fprintf(stderr, "More than %d drm nodes detected. " + "Please report a bug - that should not happen.\n" + "Skipping extra nodes\n", MAX_DRM_NODES); break; - - case DRM_BUS_USB: - ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags); - if (ret) - continue; - - break; - - case DRM_BUS_PLATFORM: - ret = drmProcessPlatformDevice(&d, node, node_type, maj, min, true, flags); - if (ret) - continue; - - break; - - case DRM_BUS_HOST1X: - ret = drmProcessHost1xDevice(&d, node, node_type, maj, min, true, flags); - if (ret) - continue; - - break; - - default: - continue; } - - if (i >= max_count) { - drmDevicePtr *temp; - - max_count += 16; - temp = realloc(local_devices, max_count * sizeof(drmDevicePtr)); - if (!temp) - goto free_devices; - local_devices = temp; - } - - /* store target at local_devices[0] for ease to use below */ - if (find_rdev == sbuf.st_rdev && i) { - local_devices[i] = local_devices[0]; - local_devices[0] = d; - } - else - local_devices[i] = d; + local_devices[i] = d; i++; } node_count = i; drmFoldDuplicatedDevices(local_devices, node_count); - *device = local_devices[0]; - drmFreeDevices(&local_devices[1], node_count - 1); + *device = NULL; + + for (i = 0; i < node_count; i++) { + if (!local_devices[i]) + continue; + + if (drm_device_has_rdev(local_devices[i], find_rdev)) + *device = local_devices[i]; + else + drmFreeDevice(&local_devices[i]); + } closedir(sysdir); - free(local_devices); if (*device == NULL) return -ENODEV; return 0; - -free_devices: - drmFreeDevices(local_devices, i); - closedir(sysdir); - -free_locals: - free(local_devices); - return ret; #endif } @@ -3904,7 +3983,7 @@ free_locals: * * \return zero on success, negative error code otherwise. */ -int drmGetDevice(int fd, drmDevicePtr *device) +drm_public int drmGetDevice(int fd, drmDevicePtr *device) { return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device); } @@ -3925,100 +4004,34 @@ int drmGetDevice(int fd, drmDevicePtr *device) * \note Unlike drmGetDevices it does not retrieve the pci device revision field * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set. */ -int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices) +drm_public int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], + int max_devices) { - drmDevicePtr *local_devices; + drmDevicePtr local_devices[MAX_DRM_NODES]; drmDevicePtr device; DIR *sysdir; struct dirent *dent; - struct stat sbuf; - char node[PATH_MAX + 1]; - int node_type, subsystem_type; - int maj, min; int ret, i, node_count, device_count; - int max_count = 16; if (drm_device_validate_flags(flags)) return -EINVAL; - local_devices = calloc(max_count, sizeof(drmDevicePtr)); - if (local_devices == NULL) - return -ENOMEM; - sysdir = opendir(DRM_DIR_NAME); - if (!sysdir) { - ret = -errno; - goto free_locals; - } + if (!sysdir) + return -errno; i = 0; while ((dent = readdir(sysdir))) { - node_type = drmGetNodeType(dent->d_name); - if (node_type < 0) - continue; - - snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name); - if (stat(node, &sbuf)) - continue; - - maj = major(sbuf.st_rdev); - min = minor(sbuf.st_rdev); - - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) - continue; - - subsystem_type = drmParseSubsystemType(maj, min); - - if (subsystem_type < 0) + ret = process_device(&device, dent->d_name, -1, devices != NULL, flags); + if (ret) continue; - switch (subsystem_type) { - case DRM_BUS_PCI: - ret = drmProcessPciDevice(&device, node, node_type, - maj, min, devices != NULL, flags); - if (ret) - continue; - + if (i >= MAX_DRM_NODES) { + fprintf(stderr, "More than %d drm nodes detected. " + "Please report a bug - that should not happen.\n" + "Skipping extra nodes\n", MAX_DRM_NODES); break; - - case DRM_BUS_USB: - ret = drmProcessUsbDevice(&device, node, node_type, maj, min, - devices != NULL, flags); - if (ret) - goto free_devices; - - break; - - case DRM_BUS_PLATFORM: - ret = drmProcessPlatformDevice(&device, node, node_type, maj, min, - devices != NULL, flags); - if (ret) - goto free_devices; - - break; - - case DRM_BUS_HOST1X: - ret = drmProcessHost1xDevice(&device, node, node_type, maj, min, - devices != NULL, flags); - if (ret) - goto free_devices; - - break; - - default: - continue; } - - if (i >= max_count) { - drmDevicePtr *temp; - - max_count += 16; - temp = realloc(local_devices, max_count * sizeof(drmDevicePtr)); - if (!temp) - goto free_devices; - local_devices = temp; - } - local_devices[i] = device; i++; } @@ -4040,16 +4053,7 @@ int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices) } closedir(sysdir); - free(local_devices); return device_count; - -free_devices: - drmFreeDevices(local_devices, i); - closedir(sysdir); - -free_locals: - free(local_devices); - return ret; } /** @@ -4064,12 +4068,12 @@ free_locals: * alternatively the number of devices stored in devices[], which is * capped by the max_devices. */ -int drmGetDevices(drmDevicePtr devices[], int max_devices) +drm_public int drmGetDevices(drmDevicePtr devices[], int max_devices) { return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices); } -char *drmGetDeviceNameFromFd2(int fd) +drm_public char *drmGetDeviceNameFromFd2(int fd) { #ifdef __linux__ struct stat sbuf; @@ -4082,7 +4086,7 @@ char *drmGetDeviceNameFromFd2(int fd) maj = major(sbuf.st_rdev); min = minor(sbuf.st_rdev); - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) return NULL; snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min); @@ -4108,7 +4112,7 @@ char *drmGetDeviceNameFromFd2(int fd) maj = major(sbuf.st_rdev); min = minor(sbuf.st_rdev); - if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) + if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) return NULL; node_type = drmGetMinorType(min); @@ -4140,3 +4144,136 @@ char *drmGetDeviceNameFromFd2(int fd) return strdup(node); #endif } + +drm_public int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle) +{ + struct drm_syncobj_create args; + int ret; + + memclear(args); + args.flags = flags; + args.handle = 0; + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args); + if (ret) + return ret; + *handle = args.handle; + return 0; +} + +drm_public int drmSyncobjDestroy(int fd, uint32_t handle) +{ + struct drm_syncobj_destroy args; + + memclear(args); + args.handle = handle; + return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args); +} + +drm_public int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd) +{ + struct drm_syncobj_handle args; + int ret; + + memclear(args); + args.fd = -1; + args.handle = handle; + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); + if (ret) + return ret; + *obj_fd = args.fd; + return 0; +} + +drm_public int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle) +{ + struct drm_syncobj_handle args; + int ret; + + memclear(args); + args.fd = obj_fd; + args.handle = 0; + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); + if (ret) + return ret; + *handle = args.handle; + return 0; +} + +drm_public int drmSyncobjImportSyncFile(int fd, uint32_t handle, + int sync_file_fd) +{ + struct drm_syncobj_handle args; + + memclear(args); + args.fd = sync_file_fd; + args.handle = handle; + args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE; + return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); +} + +drm_public int drmSyncobjExportSyncFile(int fd, uint32_t handle, + int *sync_file_fd) +{ + struct drm_syncobj_handle args; + int ret; + + memclear(args); + args.fd = -1; + args.handle = handle; + args.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE; + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); + if (ret) + return ret; + *sync_file_fd = args.fd; + return 0; +} + +drm_public int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled) +{ + struct drm_syncobj_wait args; + int ret; + + memclear(args); + args.handles = (uintptr_t)handles; + args.timeout_nsec = timeout_nsec; + args.count_handles = num_handles; + args.flags = flags; + + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); + if (ret < 0) + return -errno; + + if (first_signaled) + *first_signaled = args.first_signaled; + return ret; +} + +drm_public int drmSyncobjReset(int fd, const uint32_t *handles, + uint32_t handle_count) +{ + struct drm_syncobj_array args; + int ret; + + memclear(args); + args.handles = (uintptr_t)handles; + args.count_handles = handle_count; + + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &args); + return ret; +} + +drm_public int drmSyncobjSignal(int fd, const uint32_t *handles, + uint32_t handle_count) +{ + struct drm_syncobj_array args; + int ret; + + memclear(args); + args.handles = (uintptr_t)handles; + args.count_handles = handle_count; + + ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args); + return ret; +} @@ -636,6 +636,12 @@ extern int drmCtlUninstHandler(int fd); extern int drmSetClientCap(int fd, uint64_t capability, uint64_t value); +extern int drmCrtcGetSequence(int fd, uint32_t crtcId, + uint64_t *sequence, uint64_t *ns); +extern int drmCrtcQueueSequence(int fd, uint32_t crtcId, + uint32_t flags, uint64_t sequence, + uint64_t *sequence_queued, + uint64_t user_data); /* General user-level programmer's API: authenticated client and/or X */ extern int drmMap(int fd, drm_handle_t handle, @@ -728,7 +734,7 @@ extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2); extern int drmSetMaster(int fd); extern int drmDropMaster(int fd); -#define DRM_EVENT_CONTEXT_VERSION 2 +#define DRM_EVENT_CONTEXT_VERSION 4 typedef struct _drmEventContext { @@ -748,6 +754,17 @@ typedef struct _drmEventContext { unsigned int tv_usec, void *user_data); + void (*page_flip_handler2)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + unsigned int crtc_id, + void *user_data); + + void (*sequence_handler)(int fd, + uint64_t sequence, + uint64_t ns, + uint64_t user_data); } drmEventContext, *drmEventContextPtr; extern int drmHandleEvent(int fd, drmEventContextPtr evctx); @@ -844,6 +861,21 @@ extern void drmFreeDevices(drmDevicePtr devices[], int count); extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device); extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices); +extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); + +extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); +extern int drmSyncobjDestroy(int fd, uint32_t handle); +extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd); +extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle); + +extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd); +extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd); +extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, + int64_t timeout_nsec, unsigned flags, + uint32_t *first_signaled); +extern int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count); +extern int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count); + #if defined(__cplusplus) } #endif diff --git a/xf86drmHash.c b/xf86drmHash.c index f287e61f..2cf2b80e 100644 --- a/xf86drmHash.c +++ b/xf86drmHash.c @@ -71,6 +71,7 @@ #include <stdio.h> #include <stdlib.h> +#include "libdrm_macros.h" #include "xf86drm.h" #include "xf86drmHash.h" @@ -98,30 +99,21 @@ static unsigned long HashHash(unsigned long key) } hash %= HASH_SIZE; -#if DEBUG - printf( "Hash(%lu) = %lu\n", key, hash); -#endif return hash; } -void *drmHashCreate(void) +drm_public void *drmHashCreate(void) { HashTablePtr table; - int i; table = drmMalloc(sizeof(*table)); if (!table) return NULL; table->magic = HASH_MAGIC; - table->entries = 0; - table->hits = 0; - table->partials = 0; - table->misses = 0; - for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL; return table; } -int drmHashDestroy(void *t) +drm_public int drmHashDestroy(void *t) { HashTablePtr table = (HashTablePtr)t; HashBucketPtr bucket; @@ -172,7 +164,7 @@ static HashBucketPtr HashFind(HashTablePtr table, return NULL; } -int drmHashLookup(void *t, unsigned long key, void **value) +drm_public int drmHashLookup(void *t, unsigned long key, void **value) { HashTablePtr table = (HashTablePtr)t; HashBucketPtr bucket; @@ -185,7 +177,7 @@ int drmHashLookup(void *t, unsigned long key, void **value) return 0; /* Found */ } -int drmHashInsert(void *t, unsigned long key, void *value) +drm_public int drmHashInsert(void *t, unsigned long key, void *value) { HashTablePtr table = (HashTablePtr)t; HashBucketPtr bucket; @@ -201,13 +193,10 @@ int drmHashInsert(void *t, unsigned long key, void *value) bucket->value = value; bucket->next = table->buckets[hash]; table->buckets[hash] = bucket; -#if DEBUG - printf("Inserted %lu at %lu/%p\n", key, hash, bucket); -#endif return 0; /* Added to table */ } -int drmHashDelete(void *t, unsigned long key) +drm_public int drmHashDelete(void *t, unsigned long key) { HashTablePtr table = (HashTablePtr)t; unsigned long hash; @@ -224,7 +213,7 @@ int drmHashDelete(void *t, unsigned long key) return 0; } -int drmHashNext(void *t, unsigned long *key, void **value) +drm_public int drmHashNext(void *t, unsigned long *key, void **value) { HashTablePtr table = (HashTablePtr)t; @@ -241,7 +230,7 @@ int drmHashNext(void *t, unsigned long *key, void **value) return 0; } -int drmHashFirst(void *t, unsigned long *key, void **value) +drm_public int drmHashFirst(void *t, unsigned long *key, void **value) { HashTablePtr table = (HashTablePtr)t; diff --git a/xf86drmMode.c b/xf86drmMode.c index 2876b422..c878d9ea 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -38,10 +38,6 @@ * platforms find which headers to include to get uint32_t */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <limits.h> #include <stdint.h> #include <stdlib.h> @@ -52,6 +48,7 @@ #include <stdio.h> #include <stdbool.h> +#include "libdrm_macros.h" #include "xf86drmMode.h" #include "xf86drm.h" #include <drm.h> @@ -96,7 +93,7 @@ static void* drmAllocCpy(char *array, int count, int entry_size) * A couple of free functions. */ -void drmModeFreeModeInfo(drmModeModeInfoPtr ptr) +drm_public void drmModeFreeModeInfo(drmModeModeInfoPtr ptr) { if (!ptr) return; @@ -104,7 +101,7 @@ void drmModeFreeModeInfo(drmModeModeInfoPtr ptr) drmFree(ptr); } -void drmModeFreeResources(drmModeResPtr ptr) +drm_public void drmModeFreeResources(drmModeResPtr ptr) { if (!ptr) return; @@ -116,7 +113,7 @@ void drmModeFreeResources(drmModeResPtr ptr) drmFree(ptr); } -void drmModeFreeFB(drmModeFBPtr ptr) +drm_public void drmModeFreeFB(drmModeFBPtr ptr) { if (!ptr) return; @@ -125,7 +122,7 @@ void drmModeFreeFB(drmModeFBPtr ptr) drmFree(ptr); } -void drmModeFreeCrtc(drmModeCrtcPtr ptr) +drm_public void drmModeFreeCrtc(drmModeCrtcPtr ptr) { if (!ptr) return; @@ -133,7 +130,7 @@ void drmModeFreeCrtc(drmModeCrtcPtr ptr) drmFree(ptr); } -void drmModeFreeConnector(drmModeConnectorPtr ptr) +drm_public void drmModeFreeConnector(drmModeConnectorPtr ptr) { if (!ptr) return; @@ -145,7 +142,7 @@ void drmModeFreeConnector(drmModeConnectorPtr ptr) drmFree(ptr); } -void drmModeFreeEncoder(drmModeEncoderPtr ptr) +drm_public void drmModeFreeEncoder(drmModeEncoderPtr ptr) { drmFree(ptr); } @@ -154,7 +151,7 @@ void drmModeFreeEncoder(drmModeEncoderPtr ptr) * ModeSetting functions. */ -drmModeResPtr drmModeGetResources(int fd) +drm_public drmModeResPtr drmModeGetResources(int fd) { struct drm_mode_card_res res, counts; drmModeResPtr r = 0; @@ -248,9 +245,10 @@ err_allocs: return r; } -int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, - uint8_t bpp, uint32_t pitch, uint32_t bo_handle, - uint32_t *buf_id) + +drm_public int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, + uint32_t *buf_id) { struct drm_mode_fb_cmd f; int ret; @@ -270,10 +268,10 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, return 0; } -int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height, - uint32_t pixel_format, uint32_t bo_handles[4], - uint32_t pitches[4], uint32_t offsets[4], - uint64_t modifier[4], uint32_t *buf_id, uint32_t flags) +drm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width, + uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags) { struct drm_mode_fb_cmd2 f; int ret; @@ -296,10 +294,10 @@ int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height, return 0; } -int drmModeAddFB2(int fd, uint32_t width, uint32_t height, - uint32_t pixel_format, uint32_t bo_handles[4], - uint32_t pitches[4], uint32_t offsets[4], - uint32_t *buf_id, uint32_t flags) +drm_public int drmModeAddFB2(int fd, uint32_t width, uint32_t height, + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + uint32_t *buf_id, uint32_t flags) { return drmModeAddFB2WithModifiers(fd, width, height, pixel_format, bo_handles, @@ -307,12 +305,12 @@ int drmModeAddFB2(int fd, uint32_t width, uint32_t height, buf_id, flags); } -int drmModeRmFB(int fd, uint32_t bufferId) +drm_public int drmModeRmFB(int fd, uint32_t bufferId) { return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); } -drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) +drm_public drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) { struct drm_mode_fb_cmd info; drmModeFBPtr r; @@ -337,7 +335,7 @@ drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) return r; } -int drmModeDirtyFB(int fd, uint32_t bufferId, +drm_public int drmModeDirtyFB(int fd, uint32_t bufferId, drmModeClipPtr clips, uint32_t num_clips) { struct drm_mode_fb_dirty_cmd dirty; @@ -354,7 +352,7 @@ int drmModeDirtyFB(int fd, uint32_t bufferId, * Crtc functions */ -drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) +drm_public drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) { struct drm_mode_crtc crtc; drmModeCrtcPtr r; @@ -386,7 +384,7 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) return r; } -int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, +drm_public int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode) { @@ -411,7 +409,8 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, * Cursor manipulation */ -int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height) +drm_public int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, + uint32_t width, uint32_t height) { struct drm_mode_cursor arg; @@ -425,7 +424,9 @@ int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); } -int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y) +drm_public int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, + uint32_t width, uint32_t height, int32_t hot_x, + int32_t hot_y) { struct drm_mode_cursor2 arg; @@ -441,7 +442,7 @@ int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t widt return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR2, &arg); } -int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) +drm_public int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) { struct drm_mode_cursor arg; @@ -457,7 +458,7 @@ int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) /* * Encoder get */ -drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) +drm_public drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) { struct drm_mode_get_encoder enc; drmModeEncoderPtr r = NULL; @@ -589,17 +590,17 @@ err_allocs: return r; } -drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) +drm_public drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) { return _drmModeGetConnector(fd, connector_id, 1); } -drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id) +drm_public drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id) { return _drmModeGetConnector(fd, connector_id, 0); } -int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) +drm_public int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) { struct drm_mode_mode_cmd res; @@ -610,7 +611,7 @@ int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); } -int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) +drm_public int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) { struct drm_mode_mode_cmd res; @@ -621,7 +622,7 @@ int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); } -drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) +drm_public drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) { struct drm_mode_get_property prop; drmModePropertyPtr r; @@ -675,7 +676,7 @@ err_allocs: return r; } -void drmModeFreeProperty(drmModePropertyPtr ptr) +drm_public void drmModeFreeProperty(drmModePropertyPtr ptr) { if (!ptr) return; @@ -685,7 +686,8 @@ void drmModeFreeProperty(drmModePropertyPtr ptr) drmFree(ptr); } -drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) +drm_public drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, + uint32_t blob_id) { struct drm_mode_get_blob blob; drmModePropertyBlobPtr r; @@ -716,7 +718,7 @@ err_allocs: return r; } -void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) +drm_public void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) { if (!ptr) return; @@ -725,8 +727,9 @@ void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) drmFree(ptr); } -int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, - uint64_t value) +drm_public int drmModeConnectorSetProperty(int fd, uint32_t connector_id, + uint32_t property_id, + uint64_t value) { struct drm_mode_connector_set_property osp; @@ -744,7 +747,7 @@ int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property * -EINVAL or invalid bus id * -ENOSYS if no modesetting support */ -int drmCheckModesettingSupported(const char *busid) +drm_public int drmCheckModesettingSupported(const char *busid) { #if defined (__linux__) char pci_dev_dir[1024]; @@ -831,8 +834,7 @@ int drmCheckModesettingSupported(const char *busid) } #elif defined(__DragonFly__) return 0; -#endif -#ifdef __OpenBSD__ +#elif defined(__OpenBSD__) int fd; struct drm_mode_card_res res; drmModeResPtr r = 0; @@ -853,8 +855,9 @@ int drmCheckModesettingSupported(const char *busid) return -ENOSYS; } -int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, - uint16_t *red, uint16_t *green, uint16_t *blue) +drm_public int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, + uint16_t *blue) { struct drm_mode_crtc_lut l; @@ -868,8 +871,9 @@ int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); } -int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, - uint16_t *red, uint16_t *green, uint16_t *blue) +drm_public int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, + uint16_t *red, uint16_t *green, + uint16_t *blue) { struct drm_mode_crtc_lut l; @@ -883,12 +887,14 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); } -int drmHandleEvent(int fd, drmEventContextPtr evctx) +drm_public int drmHandleEvent(int fd, drmEventContextPtr evctx) { char buffer[1024]; int len, i; struct drm_event *e; struct drm_event_vblank *vblank; + struct drm_event_crtc_sequence *seq; + void *user_data; /* The DRM read semantics guarantees that we always get only * complete events. */ @@ -915,15 +921,30 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx) U642VOID (vblank->user_data)); break; case DRM_EVENT_FLIP_COMPLETE: - if (evctx->version < 2 || - evctx->page_flip_handler == NULL) - break; vblank = (struct drm_event_vblank *) e; - evctx->page_flip_handler(fd, - vblank->sequence, - vblank->tv_sec, - vblank->tv_usec, - U642VOID (vblank->user_data)); + user_data = U642VOID (vblank->user_data); + + if (evctx->version >= 3 && evctx->page_flip_handler2) + evctx->page_flip_handler2(fd, + vblank->sequence, + vblank->tv_sec, + vblank->tv_usec, + vblank->crtc_id, + user_data); + else if (evctx->version >= 2 && evctx->page_flip_handler) + evctx->page_flip_handler(fd, + vblank->sequence, + vblank->tv_sec, + vblank->tv_usec, + user_data); + break; + case DRM_EVENT_CRTC_SEQUENCE: + seq = (struct drm_event_crtc_sequence *) e; + if (evctx->version >= 4 && evctx->sequence_handler) + evctx->sequence_handler(fd, + seq->sequence, + seq->time_ns, + seq->user_data); break; default: break; @@ -934,7 +955,7 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx) return 0; } -int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, +drm_public int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data) { struct drm_mode_crtc_page_flip flip; @@ -948,7 +969,7 @@ int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); } -int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, +drm_public int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data, uint32_t target_vblank) { @@ -964,7 +985,7 @@ int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip_target); } -int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, +drm_public int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, int32_t crtc_x, int32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h, @@ -990,7 +1011,7 @@ int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s); } -drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) +drm_public drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) { struct drm_mode_get_plane ovr, counts; drmModePlanePtr r = 0; @@ -1041,7 +1062,7 @@ err_allocs: return r; } -void drmModeFreePlane(drmModePlanePtr ptr) +drm_public void drmModeFreePlane(drmModePlanePtr ptr) { if (!ptr) return; @@ -1050,7 +1071,7 @@ void drmModeFreePlane(drmModePlanePtr ptr) drmFree(ptr); } -drmModePlaneResPtr drmModeGetPlaneResources(int fd) +drm_public drmModePlaneResPtr drmModeGetPlaneResources(int fd) { struct drm_mode_get_plane_res res, counts; drmModePlaneResPtr r = 0; @@ -1095,7 +1116,7 @@ err_allocs: return r; } -void drmModeFreePlaneResources(drmModePlaneResPtr ptr) +drm_public void drmModeFreePlaneResources(drmModePlaneResPtr ptr) { if (!ptr) return; @@ -1104,7 +1125,7 @@ void drmModeFreePlaneResources(drmModePlaneResPtr ptr) drmFree(ptr); } -drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, +drm_public drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, uint32_t object_id, uint32_t object_type) { @@ -1165,7 +1186,7 @@ err_allocs: return ret; } -void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) +drm_public void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) { if (!ptr) return; @@ -1174,7 +1195,7 @@ void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) drmFree(ptr); } -int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, +drm_public int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, uint32_t property_id, uint64_t value) { struct drm_mode_obj_set_property prop; @@ -1188,275 +1209,6 @@ int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); } -typedef struct _drmModePropertySetItem drmModePropertySetItem, *drmModePropertySetItemPtr; - -struct _drmModePropertySetItem { - uint32_t object_id; - uint32_t property_id; - bool is_blob; - uint64_t value; - void *blob; - drmModePropertySetItemPtr next; -}; - -struct _drmModePropertySet { - unsigned int count_objs; - unsigned int count_props; - unsigned int count_blobs; - drmModePropertySetItem list; -}; - -drmModePropertySetPtr drmModePropertySetAlloc(void) -{ - drmModePropertySetPtr set; - - set = drmMalloc(sizeof *set); - if (!set) - return NULL; - - set->list.next = NULL; - set->count_props = 0; - set->count_objs = 0; - - return set; -} - -int drmModePropertySetAdd(drmModePropertySetPtr set, - uint32_t object_id, - uint32_t property_id, - uint64_t value) -{ - drmModePropertySetItemPtr prev = &set->list; - bool new_obj = false; - - /* keep it sorted by object_id and property_id */ - while (prev->next) { - if (prev->next->object_id > object_id) - break; - - if (prev->next->object_id == object_id && - prev->next->property_id >= property_id) - break; - - prev = prev->next; - } - - if ((prev == &set->list || prev->object_id != object_id) && - (!prev->next || prev->next->object_id != object_id)) - new_obj = true; - - /* replace or add? */ - if (prev->next && - prev->next->object_id == object_id && - prev->next->property_id == property_id) { - drmModePropertySetItemPtr item = prev->next; - - if (item->is_blob) - return -EINVAL; - - item->value = value; - } else { - drmModePropertySetItemPtr item; - - item = drmMalloc(sizeof *item); - if (!item) - return -1; - - item->object_id = object_id; - item->property_id = property_id; - item->value = value; - item->is_blob = false; - item->blob = NULL; - - item->next = prev->next; - prev->next = item; - - set->count_props++; - } - - if (new_obj) - set->count_objs++; - - return 0; -} - -int drmModePropertySetAddBlob(drmModePropertySetPtr set, - uint32_t object_id, - uint32_t property_id, - uint64_t length, - void *data) -{ - drmModePropertySetItemPtr prev = &set->list; - bool new_obj = false; - - /* keep it sorted by object_id and property_id */ - while (prev->next) { - if (prev->next->object_id > object_id) - break; - - if (prev->next->object_id == object_id && - prev->next->property_id >= property_id) - break; - - prev = prev->next; - } - - if ((prev == &set->list || prev->object_id != object_id) && - (!prev->next || prev->next->object_id != object_id)) - new_obj = true; - - /* replace or add? */ - if (prev->next && - prev->next->object_id == object_id && - prev->next->property_id == property_id) { - drmModePropertySetItemPtr item = prev->next; - - if (!item->is_blob) - return -EINVAL; - - item->value = length; - item->blob = data; - } else { - drmModePropertySetItemPtr item; - - item = drmMalloc(sizeof *item); - if (!item) - return -1; - - item->object_id = object_id; - item->property_id = property_id; - item->is_blob = true; - item->value = length; - item->blob = data; - - item->next = prev->next; - prev->next = item; - - set->count_props++; - set->count_blobs++; - } - - if (new_obj) - set->count_objs++; - - return 0; -} - -void drmModePropertySetFree(drmModePropertySetPtr set) -{ - drmModePropertySetItemPtr item; - - if (!set) - return; - - item = set->list.next; - - while (item) { - drmModePropertySetItemPtr next = item->next; - - drmFree(item); - - item = next; - } - - drmFree(set); -} - -int drmModePropertySetCommit(int fd, uint32_t flags, void *user_data, - drmModePropertySetPtr set) -{ - drmModePropertySetItemPtr item; - uint32_t *objs_ptr = NULL; - uint32_t *count_props_ptr = NULL; - uint32_t *props_ptr = NULL; - uint64_t *prop_values_ptr = NULL; - uint64_t *blob_values_ptr = NULL; - struct drm_mode_atomic atomic = { 0 }; - unsigned int obj_idx = 0; - unsigned int prop_idx = 0; - unsigned int blob_idx = 0; - int ret = -1; - - if (!set) - return -1; - - objs_ptr = drmMalloc(set->count_objs * sizeof objs_ptr[0]); - if (!objs_ptr) { - errno = ENOMEM; - goto out; - } - - count_props_ptr = drmMalloc(set->count_objs * sizeof count_props_ptr[0]); - if (!count_props_ptr) { - errno = ENOMEM; - goto out; - } - - props_ptr = drmMalloc(set->count_props * sizeof props_ptr[0]); - if (!props_ptr) { - errno = ENOMEM; - goto out; - } - - prop_values_ptr = drmMalloc(set->count_props * sizeof prop_values_ptr[0]); - if (!prop_values_ptr) { - errno = ENOMEM; - goto out; - } - - blob_values_ptr = drmMalloc(set->count_blobs * sizeof blob_values_ptr[0]); - if (!blob_values_ptr) { - errno = ENOMEM; - goto out; - } - - item = set->list.next; - - while (item) { - int count_props = 0; - drmModePropertySetItemPtr next = item; - - objs_ptr[obj_idx] = item->object_id; - - while (next && next->object_id == item->object_id) { - props_ptr[prop_idx] = next->property_id; - prop_values_ptr[prop_idx] = next->value; - prop_idx++; - - if (next->is_blob) - blob_values_ptr[blob_idx++] = VOID2U64(next->blob); - - count_props++; - - next = next->next; - } - - count_props_ptr[obj_idx++] = count_props; - - item = next; - } - - atomic.count_objs = set->count_objs; - atomic.flags = flags; - atomic.objs_ptr = VOID2U64(objs_ptr); - atomic.count_props_ptr = VOID2U64(count_props_ptr); - atomic.props_ptr = VOID2U64(props_ptr); - atomic.prop_values_ptr = VOID2U64(prop_values_ptr); -// TODO: -// atomic.blob_values_ptr = VOID2U64(blob_values_ptr); - atomic.user_data = VOID2U64(user_data); - - ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic); - -out: - drmFree(objs_ptr); - drmFree(count_props_ptr); - drmFree(props_ptr); - drmFree(prop_values_ptr); - - return ret; -} - typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr; struct _drmModeAtomicReqItem { @@ -1471,7 +1223,7 @@ struct _drmModeAtomicReq { drmModeAtomicReqItemPtr items; }; -drmModeAtomicReqPtr drmModeAtomicAlloc(void) +drm_public drmModeAtomicReqPtr drmModeAtomicAlloc(void) { drmModeAtomicReqPtr req; @@ -1486,7 +1238,7 @@ drmModeAtomicReqPtr drmModeAtomicAlloc(void) return req; } -drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr old) +drm_public drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr old) { drmModeAtomicReqPtr new; @@ -1515,7 +1267,8 @@ drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr old) return new; } -int drmModeAtomicMerge(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment) +drm_public int drmModeAtomicMerge(drmModeAtomicReqPtr base, + drmModeAtomicReqPtr augment) { if (!base) return -EINVAL; @@ -1544,27 +1297,30 @@ int drmModeAtomicMerge(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment) return 0; } -int drmModeAtomicGetCursor(drmModeAtomicReqPtr req) +drm_public int drmModeAtomicGetCursor(drmModeAtomicReqPtr req) { if (!req) return -EINVAL; return req->cursor; } -void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor) +drm_public void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor) { if (req) req->cursor = cursor; } -int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, - uint32_t object_id, - uint32_t property_id, - uint64_t value) +drm_public int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, + uint32_t object_id, + uint32_t property_id, + uint64_t value) { if (!req) return -EINVAL; + if (object_id == 0 || property_id == 0) + return -EINVAL; + if (req->cursor >= req->size_items) { const uint32_t item_size_inc = getpagesize() / sizeof(*req->items); drmModeAtomicReqItemPtr new; @@ -1586,7 +1342,7 @@ int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, return req->cursor; } -void drmModeAtomicFree(drmModeAtomicReqPtr req) +drm_public void drmModeAtomicFree(drmModeAtomicReqPtr req) { if (!req) return; @@ -1609,8 +1365,8 @@ static int sort_req_list(const void *misc, const void *other) return second->property_id - first->property_id; } -int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req, uint32_t flags, - void *user_data) +drm_public int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req, + uint32_t flags, void *user_data) { drmModeAtomicReqPtr sorted; struct drm_mode_atomic atomic; @@ -1714,8 +1470,9 @@ out: return ret; } -int -drmModeCreatePropertyBlob(int fd, const void *data, size_t length, uint32_t *id) +drm_public int +drmModeCreatePropertyBlob(int fd, const void *data, size_t length, + uint32_t *id) { struct drm_mode_create_blob create; int ret; @@ -1738,7 +1495,7 @@ drmModeCreatePropertyBlob(int fd, const void *data, size_t length, uint32_t *id) return 0; } -int +drm_public int drmModeDestroyPropertyBlob(int fd, uint32_t id) { struct drm_mode_destroy_blob destroy; @@ -1747,3 +1504,93 @@ drmModeDestroyPropertyBlob(int fd, uint32_t id) destroy.blob_id = id; return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy); } + +drm_public int +drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, + uint32_t *lessee_id) +{ + struct drm_mode_create_lease create; + int ret; + + memclear(create); + create.object_ids = (uintptr_t) objects; + create.object_count = num_objects; + create.flags = flags; + + ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATE_LEASE, &create); + if (ret == 0) { + *lessee_id = create.lessee_id; + return create.fd; + } + return -errno; +} + +drm_public drmModeLesseeListPtr +drmModeListLessees(int fd) +{ + struct drm_mode_list_lessees list; + uint32_t count; + drmModeLesseeListPtr ret; + + memclear(list); + + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) + return NULL; + + count = list.count_lessees; + ret = drmMalloc(sizeof (drmModeLesseeListRes) + count * sizeof (ret->lessees[0])); + if (!ret) + return NULL; + + list.lessees_ptr = VOID2U64(&ret->lessees[0]); + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) { + drmFree(ret); + return NULL; + } + + ret->count = count; + return ret; +} + +drm_public drmModeObjectListPtr +drmModeGetLease(int fd) +{ + struct drm_mode_get_lease get; + uint32_t count; + drmModeObjectListPtr ret; + + memclear(get); + + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) + return NULL; + + count = get.count_objects; + ret = drmMalloc(sizeof (drmModeObjectListRes) + count * sizeof (ret->objects[0])); + if (!ret) + return NULL; + + get.objects_ptr = VOID2U64(&ret->objects[0]); + if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) { + drmFree(ret); + return NULL; + } + + ret->count = count; + return ret; +} + +drm_public int +drmModeRevokeLease(int fd, uint32_t lessee_id) +{ + struct drm_mode_revoke_lease revoke; + int ret; + + memclear(revoke); + + revoke.lessee_id = lessee_id; + + ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_REVOKE_LEASE, &revoke); + if (ret == 0) + return 0; + return -errno; +} diff --git a/xf86drmMode.h b/xf86drmMode.h index 9d73be95..3cd27aee 100644 --- a/xf86drmMode.h +++ b/xf86drmMode.h @@ -369,15 +369,16 @@ extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, uint32_t *buf_id); /* ...with a specific pixel format */ extern int drmModeAddFB2(int fd, uint32_t width, uint32_t height, - uint32_t pixel_format, uint32_t bo_handles[4], - uint32_t pitches[4], uint32_t offsets[4], + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], uint32_t *buf_id, uint32_t flags); /* ...with format modifiers */ int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height, - uint32_t pixel_format, uint32_t bo_handles[4], - uint32_t pitches[4], uint32_t offsets[4], - uint64_t modifier[4], uint32_t *buf_id, uint32_t flags); + uint32_t pixel_format, const uint32_t bo_handles[4], + const uint32_t pitches[4], const uint32_t offsets[4], + const uint64_t modifier[4], uint32_t *buf_id, + uint32_t flags); /** * Destroies the given framebuffer. @@ -498,25 +499,6 @@ extern int drmModeObjectSetProperty(int fd, uint32_t object_id, uint64_t value); -typedef struct _drmModePropertySet drmModePropertySet, *drmModePropertySetPtr; - -extern drmModePropertySetPtr drmModePropertySetAlloc(void); - -extern int drmModePropertySetAdd(drmModePropertySetPtr set, - uint32_t object_id, - uint32_t property_id, - uint64_t value); -extern int drmModePropertySetAddBlob(drmModePropertySetPtr set, - uint32_t object_id, - uint32_t property_id, - uint64_t length, - void *blob); - -extern int drmModePropertySetCommit(int fd, uint32_t flags, - void *user_data, drmModePropertySetPtr set); - -extern void drmModePropertySetFree(drmModePropertySetPtr set); - typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr; extern drmModeAtomicReqPtr drmModeAtomicAlloc(void); @@ -539,6 +521,28 @@ extern int drmModeCreatePropertyBlob(int fd, const void *data, size_t size, uint32_t *id); extern int drmModeDestroyPropertyBlob(int fd, uint32_t id); +/* + * DRM mode lease APIs. These create and manage new drm_masters with + * access to a subset of the available DRM resources + */ + +extern int drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id); + +typedef struct drmModeLesseeList { + uint32_t count; + uint32_t lessees[0]; +} drmModeLesseeListRes, *drmModeLesseeListPtr; + +extern drmModeLesseeListPtr drmModeListLessees(int fd); + +typedef struct drmModeObjectList { + uint32_t count; + uint32_t objects[0]; +} drmModeObjectListRes, *drmModeObjectListPtr; + +extern drmModeObjectListPtr drmModeGetLease(int fd); + +extern int drmModeRevokeLease(int fd, uint32_t lessee_id); #if defined(__cplusplus) } diff --git a/xf86drmRandom.c b/xf86drmRandom.c index 81f03014..51e9676f 100644 --- a/xf86drmRandom.c +++ b/xf86drmRandom.c @@ -74,12 +74,13 @@ #include <stdio.h> #include <stdlib.h> +#include "libdrm_macros.h" #include "xf86drm.h" #include "xf86drmRandom.h" #define RANDOM_MAGIC 0xfeedbeef -void *drmRandomCreate(unsigned long seed) +drm_public void *drmRandomCreate(unsigned long seed) { RandomState *state; @@ -109,13 +110,13 @@ void *drmRandomCreate(unsigned long seed) return state; } -int drmRandomDestroy(void *state) +drm_public int drmRandomDestroy(void *state) { drmFree(state); return 0; } -unsigned long drmRandom(void *state) +drm_public unsigned long drmRandom(void *state) { RandomState *s = (RandomState *)state; unsigned long hi; @@ -129,7 +130,7 @@ unsigned long drmRandom(void *state) return s->seed; } -double drmRandomDouble(void *state) +drm_public double drmRandomDouble(void *state) { RandomState *s = (RandomState *)state; diff --git a/xf86drmSL.c b/xf86drmSL.c index a12fa1d0..3826df97 100644 --- a/xf86drmSL.c +++ b/xf86drmSL.c @@ -41,6 +41,7 @@ #include <stdio.h> #include <stdlib.h> +#include "libdrm_macros.h" #include "xf86drm.h" #define SL_LIST_MAGIC 0xfacade00LU @@ -97,7 +98,7 @@ static int SLRandomLevel(void) return level; } -void *drmSLCreate(void) +drm_public void *drmSLCreate(void) { SkipListPtr list; int i; @@ -114,7 +115,7 @@ void *drmSLCreate(void) return list; } -int drmSLDestroy(void *l) +drm_public int drmSLDestroy(void *l) { SkipListPtr list = (SkipListPtr)l; SLEntryPtr entry; @@ -151,7 +152,7 @@ static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update) return entry->forward[0]; } -int drmSLInsert(void *l, unsigned long key, void *value) +drm_public int drmSLInsert(void *l, unsigned long key, void *value) { SkipListPtr list = (SkipListPtr)l; SLEntryPtr entry; @@ -184,7 +185,7 @@ int drmSLInsert(void *l, unsigned long key, void *value) return 0; /* Added to table */ } -int drmSLDelete(void *l, unsigned long key) +drm_public int drmSLDelete(void *l, unsigned long key) { SkipListPtr list = (SkipListPtr)l; SLEntryPtr update[SL_MAX_LEVEL + 1]; @@ -211,7 +212,7 @@ int drmSLDelete(void *l, unsigned long key) return 0; } -int drmSLLookup(void *l, unsigned long key, void **value) +drm_public int drmSLLookup(void *l, unsigned long key, void **value) { SkipListPtr list = (SkipListPtr)l; SLEntryPtr update[SL_MAX_LEVEL + 1]; @@ -227,9 +228,9 @@ int drmSLLookup(void *l, unsigned long key, void **value) return -1; } -int drmSLLookupNeighbors(void *l, unsigned long key, - unsigned long *prev_key, void **prev_value, - unsigned long *next_key, void **next_value) +drm_public int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value) { SkipListPtr list = (SkipListPtr)l; SLEntryPtr update[SL_MAX_LEVEL + 1] = {0}; @@ -253,7 +254,7 @@ int drmSLLookupNeighbors(void *l, unsigned long key, return retcode; } -int drmSLNext(void *l, unsigned long *key, void **value) +drm_public int drmSLNext(void *l, unsigned long *key, void **value) { SkipListPtr list = (SkipListPtr)l; SLEntryPtr entry; @@ -272,7 +273,7 @@ int drmSLNext(void *l, unsigned long *key, void **value) return 0; } -int drmSLFirst(void *l, unsigned long *key, void **value) +drm_public int drmSLFirst(void *l, unsigned long *key, void **value) { SkipListPtr list = (SkipListPtr)l; @@ -283,7 +284,7 @@ int drmSLFirst(void *l, unsigned long *key, void **value) } /* Dump internal data structures for debugging. */ -void drmSLDump(void *l) +drm_public void drmSLDump(void *l) { SkipListPtr list = (SkipListPtr)l; SLEntryPtr entry; |