[Mesa-dev] [PATCH] winsys/radeon: add user pointer support

Marek Olšák maraeo at gmail.com
Wed Feb 11 01:59:00 PST 2015


On Wed, Feb 11, 2015 at 9:48 AM, Christian König
<deathsimple at vodafone.de> wrote:
> Since you always need to have a fallback anyway in case you got memory the
> GPU can't handle (mapped file etc...) you can just call the IOCTL, check the
> return value and if it didn't worked go the fallback path.
>
> Or do you need to know if it's available or not to make the extension
> available or not? Mhm, didn't really considered that case while writing it.

Yes. As an alternative plan, I guess I can try calling the ioctl with
a NULL pointer during winsys initialization. Is there a special return
value that will tell me the ioctl doesn't exist? It's a crude way of
checking for ioctl support indeed, but it might be sufficient.

Marek

>
> Yeah, we should probably have bumped the version number,
> Christian.
>
> Am 11.02.2015 um 02:03 schrieb Marek Olšák:
>
>> One more thing. How can userspace check if this is supported by the
>> kernel driver? The DRM version should have been bumped probably.
>>
>> Marek
>>
>> On Tue, Feb 10, 2015 at 9:35 AM, Christian König
>> <deathsimple at vodafone.de> wrote:
>>>
>>> Am 10.02.2015 um 03:41 schrieb Alex Deucher:
>>>>
>>>> On Mon, Feb 9, 2015 at 7:29 PM, Marek Olšák <maraeo at gmail.com> wrote:
>>>>>
>>>>> Hi Christian,
>>>>>
>>>>> What hardware is this supported on? SI and later? Or even r600? r300?
>>>>
>>>> Theoretically r300 and newer hardware, however, the kernel currently
>>>> only allows it on r600 and newer since we never tested it on r300
>>>> class hardware.
>>>
>>>
>>> It also won't work if the AGP GART is used, but using AGP hardware with
>>> the
>>> PCIE GART should work fine.
>>>
>>> Getting it to work on R300 is just a matter of removing the single line
>>> check in the kernel and really testing it a bit.
>>>
>>> Regards,
>>> Christian.
>>>
>>>
>>>> Alex
>>>>
>>>>> Thanks,
>>>>>
>>>>> Marek
>>>>>
>>>>> On Thu, Feb 5, 2015 at 6:34 PM, Christian König
>>>>> <deathsimple at vodafone.de>
>>>>> wrote:
>>>>>>
>>>>>> From: Christian König <christian.koenig at amd.com>
>>>>>>
>>>>>> Signed-off-by: Christian König <christian.koenig at amd.com>
>>>>>> ---
>>>>>>    src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 102
>>>>>> ++++++++++++++++++++++++++
>>>>>>    src/gallium/winsys/radeon/drm/radeon_winsys.h |  11 +++
>>>>>>    2 files changed, 113 insertions(+)
>>>>>>
>>>>>> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>>>>>> b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>>>>>> index 1ebec10..2605ca6 100644
>>>>>> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>>>>>> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>>>>>> @@ -42,6 +42,24 @@
>>>>>>    #include <fcntl.h>
>>>>>>    #include <stdio.h>
>>>>>>
>>>>>> +#ifndef DRM_RADEON_GEM_USERPTR
>>>>>> +
>>>>>> +#define DRM_RADEON_GEM_USERPTR         0x2d
>>>>>> +
>>>>>> +#define RADEON_GEM_USERPTR_READONLY    (1 << 0)
>>>>>> +#define RADEON_GEM_USERPTR_ANONONLY    (1 << 1)
>>>>>> +#define RADEON_GEM_USERPTR_VALIDATE    (1 << 2)
>>>>>> +#define RADEON_GEM_USERPTR_REGISTER    (1 << 3)
>>>>>> +
>>>>>> +struct drm_radeon_gem_userptr {
>>>>>> +       uint64_t                addr;
>>>>>> +       uint64_t                size;
>>>>>> +       uint32_t                flags;
>>>>>> +       uint32_t                handle;
>>>>>> +};
>>>>>> +
>>>>>> +#endif
>>>>>> +
>>>>>>    extern const struct pb_vtbl radeon_bo_vtbl;
>>>>>>
>>>>>>    static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo)
>>>>>> @@ -846,6 +864,89 @@ radeon_winsys_bo_create(struct radeon_winsys
>>>>>> *rws,
>>>>>>        return (struct pb_buffer*)buffer;
>>>>>>    }
>>>>>>
>>>>>> +static struct pb_buffer *radeon_winsys_bo_from_ptr(struct
>>>>>> radeon_winsys
>>>>>> *rws,
>>>>>> +                                                   void *pointer,
>>>>>> unsigned size)
>>>>>> +{
>>>>>> +    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
>>>>>> +    struct radeon_bomgr *mgr = radeon_bomgr(ws->kman);
>>>>>> +    struct drm_radeon_gem_userptr args;
>>>>>> +    struct radeon_bo *bo;
>>>>>> +    int r;
>>>>>> +
>>>>>> +    bo = CALLOC_STRUCT(radeon_bo);
>>>>>> +    if (!bo)
>>>>>> +        return NULL;
>>>>>> +
>>>>>> +    memset(&args, 0, sizeof(args));
>>>>>> +    args.addr = (uintptr_t)pointer;
>>>>>> +    args.size = size;
>>>>>> +    args.flags = RADEON_GEM_USERPTR_ANONONLY |
>>>>>> +        RADEON_GEM_USERPTR_VALIDATE |
>>>>>> +        RADEON_GEM_USERPTR_REGISTER;
>>>>>> +    if (drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_USERPTR,
>>>>>> +                            &args, sizeof(args))) {
>>>>>> +        FREE(bo);
>>>>>> +        return NULL;
>>>>>> +    }
>>>>>> +
>>>>>> +    pipe_mutex_lock(mgr->bo_handles_mutex);
>>>>>> +
>>>>>> +    /* Initialize it. */
>>>>>> +    pipe_reference_init(&bo->base.reference, 1);
>>>>>> +    bo->handle = args.handle;
>>>>>> +    bo->base.alignment = 0;
>>>>>> +    bo->base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
>>>>>> +    bo->base.size = size;
>>>>>> +    bo->base.vtbl = &radeon_bo_vtbl;
>>>>>> +    bo->mgr = mgr;
>>>>>> +    bo->rws = mgr->rws;
>>>>>> +    bo->va = 0;
>>>>>> +    bo->initial_domain = RADEON_DOMAIN_GTT;
>>>>>> +    pipe_mutex_init(bo->map_mutex);
>>>>>> +
>>>>>> +    util_hash_table_set(mgr->bo_handles,
>>>>>> (void*)(uintptr_t)bo->handle,
>>>>>> bo);
>>>>>> +
>>>>>> +    pipe_mutex_unlock(mgr->bo_handles_mutex);
>>>>>> +
>>>>>> +    if (mgr->va) {
>>>>>> +        struct drm_radeon_gem_va va;
>>>>>> +
>>>>>> +        bo->va = radeon_bomgr_find_va(mgr, bo->base.size, 1 << 20);
>>>>>> +
>>>>>> +        va.handle = bo->handle;
>>>>>> +        va.operation = RADEON_VA_MAP;
>>>>>> +        va.vm_id = 0;
>>>>>> +        va.offset = bo->va;
>>>>>> +        va.flags = RADEON_VM_PAGE_READABLE |
>>>>>> +                   RADEON_VM_PAGE_WRITEABLE |
>>>>>> +                   RADEON_VM_PAGE_SNOOPED;
>>>>>> +        va.offset = bo->va;
>>>>>> +        r = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_VA, &va,
>>>>>> sizeof(va));
>>>>>> +        if (r && va.operation == RADEON_VA_RESULT_ERROR) {
>>>>>> +            fprintf(stderr, "radeon: Failed to assign virtual address
>>>>>> space\n");
>>>>>> +            radeon_bo_destroy(&bo->base);
>>>>>> +            return NULL;
>>>>>> +        }
>>>>>> +        pipe_mutex_lock(mgr->bo_handles_mutex);
>>>>>> +        if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
>>>>>> +            struct pb_buffer *b = &bo->base;
>>>>>> +            struct radeon_bo *old_bo =
>>>>>> +                util_hash_table_get(mgr->bo_vas,
>>>>>> (void*)(uintptr_t)va.offset);
>>>>>> +
>>>>>> +            pipe_mutex_unlock(mgr->bo_handles_mutex);
>>>>>> +            pb_reference(&b, &old_bo->base);
>>>>>> +            return b;
>>>>>> +        }
>>>>>> +
>>>>>> +        util_hash_table_set(mgr->bo_vas, (void*)(uintptr_t)bo->va,
>>>>>> bo);
>>>>>> +        pipe_mutex_unlock(mgr->bo_handles_mutex);
>>>>>> +    }
>>>>>> +
>>>>>> +    ws->allocated_gtt += align(bo->base.size, 4096);
>>>>>> +
>>>>>> +    return (struct pb_buffer*)bo;
>>>>>> +}
>>>>>> +
>>>>>>    static struct pb_buffer *radeon_winsys_bo_from_handle(struct
>>>>>> radeon_winsys *rws,
>>>>>>                                                          struct
>>>>>> winsys_handle *whandle,
>>>>>>                                                          unsigned
>>>>>> *stride)
>>>>>> @@ -1040,6 +1141,7 @@ void radeon_bomgr_init_functions(struct
>>>>>> radeon_drm_winsys *ws)
>>>>>>        ws->base.buffer_is_busy = radeon_bo_is_busy;
>>>>>>        ws->base.buffer_create = radeon_winsys_bo_create;
>>>>>>        ws->base.buffer_from_handle = radeon_winsys_bo_from_handle;
>>>>>> +    ws->base.buffer_from_ptr = radeon_winsys_bo_from_ptr;
>>>>>>        ws->base.buffer_get_handle = radeon_winsys_bo_get_handle;
>>>>>>        ws->base.buffer_get_virtual_address = radeon_winsys_bo_va;
>>>>>>        ws->base.buffer_get_initial_domain =
>>>>>> radeon_bo_get_initial_domain;
>>>>>> diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h
>>>>>> b/src/gallium/winsys/radeon/drm/radeon_winsys.h
>>>>>> index 5dc9313..d9fa1ab 100644
>>>>>> --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
>>>>>> +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
>>>>>> @@ -394,6 +394,17 @@ struct radeon_winsys {
>>>>>>                                                unsigned *stride);
>>>>>>
>>>>>>        /**
>>>>>> +     * Get a winsys buffer from a user pointer. The resulting buffer
>>>>>> can't be
>>>>>> +     * mapped or exported. Both pointer and size must be page
>>>>>> aligned.
>>>>>> +     *
>>>>>> +     * \param ws        The winsys this function is called from.
>>>>>> +     * \param pointer   User pointer to turn into a buffer object.
>>>>>> +     * \param Size      Size in bytes for the new buffer.
>>>>>> +     */
>>>>>> +    struct pb_buffer *(*buffer_from_ptr)(struct radeon_winsys *ws,
>>>>>> +                                         void *pointer, unsigned
>>>>>> size);
>>>>>> +
>>>>>> +    /**
>>>>>>         * Get a winsys handle from a winsys buffer. The internal
>>>>>> structure
>>>>>>         * of the handle is platform-specific and only a winsys should
>>>>>> access it.
>>>>>>         *
>>>>>> --
>>>>>> 1.9.1
>>>>>>
>>>>>> _______________________________________________
>>>>>> mesa-dev mailing list
>>>>>> mesa-dev at lists.freedesktop.org
>>>>>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>>>>>
>>>>> _______________________________________________
>>>>> mesa-dev mailing list
>>>>> mesa-dev at lists.freedesktop.org
>>>>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>>>
>>>
>


More information about the mesa-dev mailing list