Hi Alex, On 21/04/15 16:39, Alex Deucher wrote: > This is the new ioctl wrapper used by the new admgpu driver. > It's primarily used by xf86-video-amdgpu and mesa. > Glad to see amdgpu finally out :-) Can we annotate the private symbols with drm_private, in both declaration and definition ? It will hide the symbols, plus will make the leap towards Solaris support a bit smaller. > Signed-off-by: Alex Deucher <alexander.deucher@xxxxxxx> > --- > Makefile.am | 5 + > amdgpu/Makefile.am | 55 ++ > amdgpu/amdgpu.h | 1278 ++++++++++++++++++++++++++++++++++++++++++++ > amdgpu/amdgpu_bo.c | 622 +++++++++++++++++++++ > amdgpu/amdgpu_cs.c | 981 ++++++++++++++++++++++++++++++++++ > amdgpu/amdgpu_device.c | 242 +++++++++ > amdgpu/amdgpu_gpu_info.c | 275 ++++++++++ > amdgpu/amdgpu_internal.h | 210 ++++++++ > amdgpu/amdgpu_vamgr.c | 169 ++++++ > amdgpu/libdrm_amdgpu.pc.in | 10 + > amdgpu/util_double_list.h | 146 +++++ > amdgpu/util_hash.c | 382 +++++++++++++ > amdgpu/util_hash.h | 99 ++++ > amdgpu/util_hash_table.c | 257 +++++++++ > amdgpu/util_hash_table.h | 65 +++ > amdgpu/util_math.h | 32 ++ > configure.ac | 20 + > include/drm/amdgpu_drm.h | 600 +++++++++++++++++++++ > 18 files changed, 5448 insertions(+) > create mode 100644 amdgpu/Makefile.am > create mode 100644 amdgpu/amdgpu.h > create mode 100644 amdgpu/amdgpu_bo.c > create mode 100644 amdgpu/amdgpu_cs.c > create mode 100644 amdgpu/amdgpu_device.c > create mode 100644 amdgpu/amdgpu_gpu_info.c > create mode 100644 amdgpu/amdgpu_internal.h > create mode 100644 amdgpu/amdgpu_vamgr.c > create mode 100644 amdgpu/libdrm_amdgpu.pc.in > create mode 100644 amdgpu/util_double_list.h > create mode 100644 amdgpu/util_hash.c > create mode 100644 amdgpu/util_hash.h > create mode 100644 amdgpu/util_hash_table.c > create mode 100644 amdgpu/util_hash_table.h > create mode 100644 amdgpu/util_math.h > create mode 100644 include/drm/amdgpu_drm.h > > --- /dev/null > +++ b/amdgpu/Makefile.am > +AM_CFLAGS = \ > + $(WARN_CFLAGS) > -Wno-switch-enum \ >From a quick look you should be OK without this. If that's not the case, it might be worth looking into ? > + -I$(top_srcdir) \ > + -I$(top_srcdir)/amdgpu \ You can drop this line. > + $(PTHREADSTUBS_CFLAGS) \ > + -I$(top_srcdir)/include/drm > + > +libdrm_amdgpu_la_LTLIBRARIES = libdrm_amdgpu.la > +libdrm_amdgpu_ladir = $(libdir) > +libdrm_amdgpu_la_LDFLAGS = -version-number 1:0:1 -no-undefined Considering that this is the first public version shouldn't this be 1:0:0 ? > +libdrm_amdgpu_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ > + > +libdrm_amdgpu_la_SOURCES = \ > + amdgpu_gpu_info.c \ > + amdgpu_device.c \ > + amdgpu_bo.c \ > + util_hash.c \ > + util_hash_table.c \ > + amdgpu_vamgr.c \ > + amdgpu_cs.c > + Please include all files, and sort them alphabetically, something like: amdgpu_bo.c amdgpu_cs.c amdgpu_device.c amdgpu_gpu_info.c amdgpu_internal.h amdgpu_vamgr.c util_double_list.h util_hash.c util_hash.h util_hash_table.c util_hash_table.h util_math.h One might want to drop util_double_list.h if you go for my suggestion below. > +nodist_EXTRA_libdrm_amdgpu_la_SOURCES = dummy.cxx > + There are no C++ sources or static libs based on such so you can drop this. > +EXTRA_DIST = libdrm_amdgpu.pc.in You don't need this. > --- /dev/null > +++ b/amdgpu/amdgpu.h > +#ifndef _amdgpu_h_ > +#define _amdgpu_h_ > + Capitalise the header guard name ? > +#include <stdint.h> > +#include <stdbool.h> > + Albeit not so common in libdrm, you can add make the header C++ safe. #if defined(__cplusplus) extern "C" { #endif > +struct amdgpu_bo_alloc_request { > + /** Allocation request. It must be aligned correctly. */ > + uint64_t alloc_size; > + > + /** > + * It may be required to have some specific alignment requirements > + * for physical back-up storage (e.g. for displayable surface). > + * If 0 there is no special alignment requirement > + */ > + uint64_t phys_alignment; > + > + /** > + * UMD should specify where to allocate memory and how it > + * will be accessed by the CPU. > + */ > + uint32_t preferred_heap; > + Worth adding a pad ? > + /** Additional flags passed on allocation */ > + uint64_t flags; > +}; > +struct amdgpu_bo_info { > + /** Allocated memory size */ > + uint64_t alloc_size; > + > + /** > + * It may be required to have some specific alignment requirements > + * for physical back-up storage. > + */ > + uint64_t phys_alignment; > + > + /** > + * Assigned virtual MC Base Address. > + * \note This information will be returned only if this buffer was > + * allocated in the same process otherwise 0 will be returned. > + */ > + uint64_t virtual_mc_base_address; > + > + /** Heap where to allocate memory. */ > + uint32_t preferred_heap; > + Ditto. > + /** Additional allocation flags. */ > + uint64_t alloc_flags; > + > + /** Metadata associated with buffer if any. */ > + struct amdgpu_bo_metadata metadata; > +}; > +struct amdgpu_gds_alloc_info { > + /** Handle assigned to gds allocation */ > + amdgpu_bo_handle resource_handle; > + > + /** How much was really allocated */ > + uint32_t gds_memory_size; > + > + /** Number of GWS resources allocated */ > + uint32_t gws; > + > + /** Number of OA resources allocated */ > + uint32_t oa; Ditto. > +struct amdgpu_cs_ib_info { > + /** Special flags */ > + uint64_t flags; > + > + /** Handle of command buffer */ > + amdgpu_ib_handle ib_handle; > + > + /** > + * Size of Command Buffer to be submitted. > + * - The size is in units of dwords (4 bytes). > + * - Must be less or equal to the size of allocated IB > + * - Could be 0 > + */ > + uint32_t size; Ditto. > +struct amdgpu_cs_request { > + /** Specify flags with additional information */ > + uint64_t flags; > + > + /** Specify HW IP block type to which to send the IB. */ > + unsigned ip_type; > + > + /** IP instance index if there are several IPs of the same type. */ > + unsigned ip_instance; > + > + /** > + * Specify ring index of the IP. We could have several rings > + * in the same IP. E.g. 0 for SDMA0 and 1 for SDMA1. > + */ > + uint32_t ring; > + > + /** > + * Specify number of resource handles passed. > + * Size of 'handles' array > + * > + */ > + uint32_t number_of_resources; > + > + /** Array of resources used by submission. */ > + amdgpu_bo_handle *resources; > + > + /** Array of resources flags. This is optional and can be NULL. */ > + uint8_t *resource_flags; > + > + /** Number of IBs to submit in the field ibs. */ > + uint32_t number_of_ibs; > + Ditto. > + /** > + * IBs to submit. Those IBs will be submit together as single entity > + */ > + struct amdgpu_cs_ib_info *ibs; > +}; > + > +/** > + * Structure describing request to check submission state using fence > + * > + * \sa amdgpu_cs_query_fence_status() > + * > +*/ > +struct amdgpu_cs_query_fence { > + > + /** In which context IB was sent to execution */ > + amdgpu_context_handle context; > + > + /** Timeout in nanoseconds. */ > + uint64_t timeout_ns; > + > + /** To which HW IP type the fence belongs */ > + unsigned ip_type; > + > + /** IP instance index if there are several IPs of the same type. */ > + unsigned ip_instance; > + > + /** Ring index of the HW IP */ > + uint32_t ring; > + Ditto. > + /** Flags */ > + uint64_t flags; > + > + /** Specify fence for which we need to check > + * submission status.*/ > + uint64_t fence; > --- /dev/null > +++ b/amdgpu/amdgpu_bo.c > +#define _FILE_OFFSET_BITS 64 How about #ifdef HAVE_CONFIG_H #include "config.h" #endif If you feel against poluting all the C sources with it, you should ensure that amdgpu_internal.h is included before any other header in every source and header file. > +int amdgpu_bo_cpu_map(amdgpu_bo_handle bo, void **cpu) > +{ > + union drm_amdgpu_gem_mmap args; > + void *ptr; > + int r; > + > + pthread_mutex_lock(&bo->cpu_access_mutex); > + > + if (bo->cpu_ptr) { > + /* already mapped */ > + assert(bo->cpu_map_count > 0); > + bo->cpu_map_count++; > + *cpu = bo->cpu_ptr; > + pthread_mutex_unlock(&bo->cpu_access_mutex); > + return 0; > + } > + > + assert(bo->cpu_map_count == 0); > + > + memset(&args, 0, sizeof(args)); > + > + /* Query the buffer address (args.addr_ptr). > + * The kernel driver ignores the offset and size parameters. */ > + args.in.handle = bo->handle; > + > + r = drmCommandWriteRead(bo->dev->fd, DRM_AMDGPU_GEM_MMAP, &args, > + sizeof(args)); > + if (r) { > + pthread_mutex_unlock(&bo->cpu_access_mutex); > + return r; > + } > + > + /* Map the buffer. */ > + ptr = mmap(NULL, bo->alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED, Please use drm_mmap/drm_munmap. > --- /dev/null > +++ b/amdgpu/amdgpu_cs.c > +static int amdgpu_cs_create_ib(amdgpu_device_handle dev, > + amdgpu_context_handle context, > + enum amdgpu_cs_ib_size ib_size, > + amdgpu_ib_handle *ib) > +{ > + new_ib = malloc(sizeof(struct amdgpu_ib)); > + if (NULL == new_ib) { Use new_ib == NULL or !new_ib ? There are a few other places that can do so. > --- /dev/null > +++ b/amdgpu/amdgpu_device.c > +static unsigned fd_hash(void *key) > +{ > + int fd = PTR_TO_UINT(key); > + struct stat stat; > + fstat(fd, &stat); > + > + if (!S_ISCHR(stat.st_mode)) > + return stat.st_dev ^ stat.st_ino; I'm a bit puzzled, how is this possible ? > + else > + return stat.st_dev ^ (stat.st_rdev & RENDERNODE_MINOR_MASK); I'm not 100% sure that there won't be any side-effects with the idea of using primary and render node interchangeably. Plus one cannot mask out to get from the primary device to the render one, or vice-versa. The minor number is not reliable (rightfully so), thus one can use drmGet(Primary|Render)DeviceNameFromFd or introduce their fd counterpart. > +} > + > +static int fd_compare(void *key1, void *key2) > +{ > + int fd1 = PTR_TO_UINT(key1); > + int fd2 = PTR_TO_UINT(key2); > + struct stat stat1, stat2; > + fstat(fd1, &stat1); > + fstat(fd2, &stat2); > + > + if (!S_ISCHR(stat1.st_mode) || !S_ISCHR(stat2.st_mode)) > + return stat1.st_dev != stat2.st_dev || > + stat1.st_ino != stat2.st_ino; > + else > + return major(stat1.st_rdev) != major(stat2.st_rdev) || > + (minor(stat1.st_rdev) & RENDERNODE_MINOR_MASK) != > + (minor(stat2.st_rdev) & RENDERNODE_MINOR_MASK); Same comments apply. > +} > + > +/** > +* Get the authenticated form fd, > +* > +* \param fd - \c [in] File descriptor for AMD GPU device > +* \param auth - \c [out] Pointer to output the fd is authenticated or not > +* A render node fd, output auth = 0 > +* A legacy fd, get the authenticated for compatibility root > +* > +* \return 0 on success\n > +* >0 - AMD specific error code\n > +* <0 - Negative POSIX Error code > +*/ > +static int amdgpu_get_auth(int fd, int *auth) > +{ > + int r = 0; > + drm_client_t client; > + struct stat stat1; > + fstat(fd,&stat1); > + if (minor(stat1.st_rdev) & ~RENDERNODE_MINOR_MASK)/* find a render node fd */ Please use drmGetNodeTypeFromFd(). > --- /dev/null > +++ b/amdgpu/amdgpu_internal.h > @@ -0,0 +1,210 @@ > +#ifndef _amdgpu_internal_h_ > +#define _amdgpu_internal_h_ > + Capital letters for the header guard ? > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif > + > +#include <assert.h> > +#include <pthread.h> > +#include "xf86atomic.h" > +#include "amdgpu.h" > +#include "util_double_list.h" > + > +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) > + Drop this and use util_math.h where needed ? > +/** > + * Increment src and decrement dst as if we were updating references > + * for an assignment between 2 pointers of some objects. > + * > + * \return true if dst is 0 > + */ > +static inline bool update_references(atomic_t *dst, atomic_t *src) > +{ > + if (dst != src) { > + /* bump src first */ > + if (src) { > + assert(atomic_read(src) > 0); > + atomic_inc(src); > + } > + if (dst) { > + assert(atomic_read(dst) > 0); > + return atomic_dec_and_test(dst); Am I imagining something or does the assert conditions look a bit strange ? > diff --git a/amdgpu/util_double_list.h b/amdgpu/util_double_list.h > new file mode 100644 > index 0000000..3f48ae2 > --- /dev/null > +++ b/amdgpu/util_double_list.h There are already two identical copies of this file - let's not add a third one. freedreno/list.h tests/radeon/list.h How about we move it one level up, and update the current users (incl. Makefile.sources) > --- /dev/null > +++ b/amdgpu/util_hash.c > --- /dev/null > +++ b/amdgpu/util_hash_table.c Can one use the existing drmHash functions like omap and freedreno ? Would be nice to avoid going the mesa's route which iirc has four different implementations. > --- /dev/null > +++ b/amdgpu/util_math.h FWIW we can move this a level up, so that others can use it. Obviously there is no reason to be part of this series. > diff --git a/configure.ac b/configure.ac > index 155d577..509f2d4 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -36,6 +36,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) > > # Check for programs > AC_PROG_CC > +AC_PROG_CXX > There are no C++ sources, so you don't need a C++ compiler. > @@ -236,6 +242,9 @@ if test "x$drm_cv_atomic_primitives" = "xnone"; then > LIBDRM_ATOMICS_NOT_FOUND_MSG($RADEON, radeon, Radeon, radeon) > RADEON=no > > + LIBDRM_ATOMICS_NOT_FOUND_MSG($AMDGPU, amdgpu, AMD, amdgpu) > + AMDGPU=no > + Glad to see this, unlike the original copy/paste of an insanely long message previously :) > +if test "x$AMDGPU" = xyes; then > + AC_DEFINE(HAVE_AMDGPU, 1, [Have amdgpu support]) > +fi > + Unless you're planning to add support to libkms you can drop this. > diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h > new file mode 100644 > index 0000000..d248d77 > --- /dev/null > +++ b/include/drm/amdgpu_drm.h > +struct drm_amdgpu_cs_in { > + /** Rendering context id */ > + uint32_t 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; > +}; > + > +struct drm_amdgpu_cs_out { > + uint64_t handle; > +}; > + > +union drm_amdgpu_cs { > + struct drm_amdgpu_cs_in in; > + struct drm_amdgpu_cs_out out; > +}; > + Don't think I've seen similar contruct in any of the other drm drivers. (Genuenly curious) What benefit does it bring ? I think you want to add a trailing padding for the following structures. I'm thinking of a case where, old 64bit userspace feeds in the last u32 as rubbish, to the kernel while the latter uses an updated/expanded struct. In such case the driver will either reject the request, or worse use the rubbish data. struct drm_amdgpu_gem_metadata struct drm_amdgpu_wait_cs_in struct drm_amdgpu_info_hw_ip struct drm_amdgpu_info_device Cheers Emil P.S. Based on the coding style seems like this is the combined work of 3+ developers. Anyway glad to see that it's out :-) _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel