2012-05-10 16:33:13 -06:00
|
|
|
/*
|
|
|
|
* Copyright 2012 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.
|
|
|
|
*
|
|
|
|
* based on nouveau_prime.c
|
|
|
|
*
|
|
|
|
* Authors: Alex Deucher
|
|
|
|
*/
|
2012-10-02 11:01:07 -06:00
|
|
|
#include <drm/drmP.h>
|
2012-05-10 16:33:13 -06:00
|
|
|
|
|
|
|
#include "radeon.h"
|
2012-10-02 11:01:07 -06:00
|
|
|
#include <drm/radeon_drm.h>
|
2014-01-09 03:03:14 -07:00
|
|
|
#include <linux/dma-buf.h>
|
2012-05-10 16:33:13 -06:00
|
|
|
|
2013-01-15 13:47:44 -07:00
|
|
|
struct sg_table *radeon_gem_prime_get_sg_table(struct drm_gem_object *obj)
|
2012-05-10 16:33:13 -06:00
|
|
|
{
|
2013-01-15 13:47:44 -07:00
|
|
|
struct radeon_bo *bo = gem_to_radeon_bo(obj);
|
2012-05-10 16:33:13 -06:00
|
|
|
int npages = bo->tbo.num_pages;
|
|
|
|
|
2013-01-15 13:47:44 -07:00
|
|
|
return drm_prime_pages_to_sg(bo->tbo.ttm->pages, npages);
|
2012-05-10 16:33:13 -06:00
|
|
|
}
|
|
|
|
|
2013-01-15 13:47:44 -07:00
|
|
|
void *radeon_gem_prime_vmap(struct drm_gem_object *obj)
|
2012-05-29 08:12:24 -06:00
|
|
|
{
|
2013-01-15 13:47:44 -07:00
|
|
|
struct radeon_bo *bo = gem_to_radeon_bo(obj);
|
2012-05-31 06:52:53 -06:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages,
|
|
|
|
&bo->dma_buf_vmap);
|
2013-01-15 13:47:44 -07:00
|
|
|
if (ret)
|
2012-05-31 06:52:53 -06:00
|
|
|
return ERR_PTR(ret);
|
2013-01-15 13:47:44 -07:00
|
|
|
|
2012-05-31 06:52:53 -06:00
|
|
|
return bo->dma_buf_vmap.virtual;
|
|
|
|
}
|
|
|
|
|
2013-01-15 13:47:44 -07:00
|
|
|
void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
|
2012-05-31 06:52:53 -06:00
|
|
|
{
|
2013-01-15 13:47:44 -07:00
|
|
|
struct radeon_bo *bo = gem_to_radeon_bo(obj);
|
2012-05-31 06:52:53 -06:00
|
|
|
|
2013-01-15 13:47:44 -07:00
|
|
|
ttm_bo_kunmap(&bo->dma_buf_vmap);
|
2012-05-31 06:52:53 -06:00
|
|
|
}
|
2013-01-15 13:47:44 -07:00
|
|
|
|
|
|
|
struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
|
2014-01-09 03:03:14 -07:00
|
|
|
struct dma_buf_attachment *attach,
|
2013-01-15 13:47:44 -07:00
|
|
|
struct sg_table *sg)
|
2012-05-10 16:33:13 -06:00
|
|
|
{
|
2014-09-18 06:11:56 -06:00
|
|
|
struct reservation_object *resv = attach->dmabuf->resv;
|
2012-05-10 16:33:13 -06:00
|
|
|
struct radeon_device *rdev = dev->dev_private;
|
|
|
|
struct radeon_bo *bo;
|
|
|
|
int ret;
|
|
|
|
|
2014-09-18 06:11:56 -06:00
|
|
|
ww_mutex_lock(&resv->lock, NULL);
|
2014-01-09 03:03:14 -07:00
|
|
|
ret = radeon_bo_create(rdev, attach->dmabuf->size, PAGE_SIZE, false,
|
2014-09-18 06:11:56 -06:00
|
|
|
RADEON_GEM_DOMAIN_GTT, 0, sg, resv, &bo);
|
|
|
|
ww_mutex_unlock(&resv->lock);
|
2012-05-10 16:33:13 -06:00
|
|
|
if (ret)
|
2013-01-15 13:47:44 -07:00
|
|
|
return ERR_PTR(ret);
|
2012-05-10 16:33:13 -06:00
|
|
|
|
|
|
|
mutex_lock(&rdev->gem.mutex);
|
|
|
|
list_add_tail(&bo->list, &rdev->gem.objects);
|
|
|
|
mutex_unlock(&rdev->gem.mutex);
|
|
|
|
|
2017-04-02 21:35:22 -06:00
|
|
|
bo->prime_shared_count = 1;
|
2013-01-15 13:47:44 -07:00
|
|
|
return &bo->gem_base;
|
2012-05-10 16:33:13 -06:00
|
|
|
}
|
|
|
|
|
2013-01-15 13:47:44 -07:00
|
|
|
int radeon_gem_prime_pin(struct drm_gem_object *obj)
|
2012-05-10 16:33:13 -06:00
|
|
|
{
|
|
|
|
struct radeon_bo *bo = gem_to_radeon_bo(obj);
|
|
|
|
int ret = 0;
|
|
|
|
|
2012-06-12 09:10:39 -06:00
|
|
|
ret = radeon_bo_reserve(bo, false);
|
|
|
|
if (unlikely(ret != 0))
|
2013-01-15 13:47:44 -07:00
|
|
|
return ret;
|
2012-06-12 09:10:39 -06:00
|
|
|
|
2012-05-10 16:33:13 -06:00
|
|
|
/* pin buffer into GTT */
|
|
|
|
ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL);
|
2017-04-02 21:35:22 -06:00
|
|
|
if (likely(ret == 0))
|
|
|
|
bo->prime_shared_count++;
|
|
|
|
|
2012-06-12 09:10:39 -06:00
|
|
|
radeon_bo_unreserve(bo);
|
2013-06-27 05:38:18 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void radeon_gem_prime_unpin(struct drm_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct radeon_bo *bo = gem_to_radeon_bo(obj);
|
|
|
|
int ret = 0;
|
2012-05-10 16:33:13 -06:00
|
|
|
|
2013-06-27 05:38:18 -06:00
|
|
|
ret = radeon_bo_reserve(bo, false);
|
|
|
|
if (unlikely(ret != 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
radeon_bo_unpin(bo);
|
2017-04-02 21:35:22 -06:00
|
|
|
if (bo->prime_shared_count)
|
|
|
|
bo->prime_shared_count--;
|
2013-06-27 05:38:18 -06:00
|
|
|
radeon_bo_unreserve(bo);
|
2012-05-10 16:33:13 -06:00
|
|
|
}
|
2014-07-01 04:57:26 -06:00
|
|
|
|
|
|
|
|
|
|
|
struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *obj)
|
|
|
|
{
|
|
|
|
struct radeon_bo *bo = gem_to_radeon_bo(obj);
|
|
|
|
|
|
|
|
return bo->tbo.resv;
|
|
|
|
}
|
2014-08-25 17:05:14 -06:00
|
|
|
|
drm/radeon: add userptr support v8
This patch adds an IOCTL for turning a pointer supplied by
userspace into a buffer object.
It imposes several restrictions upon the memory being mapped:
1. It must be page aligned (both start/end addresses, i.e ptr and size).
2. It must be normal system memory, not a pointer into another map of IO
space (e.g. it must not be a GTT mmapping of another object).
3. The BO is mapped into GTT, so the maximum amount of memory mapped at
all times is still the GTT limit.
4. The BO is only mapped readonly for now, so no write support.
5. List of backing pages is only acquired once, so they represent a
snapshot of the first use.
Exporting and sharing as well as mapping of buffer objects created by
this function is forbidden and results in an -EPERM.
v2: squash all previous changes into first public version
v3: fix tabs, map readonly, don't use MM callback any more
v4: set TTM_PAGE_FLAG_SG so that TTM never messes with the pages,
pin/unpin pages on bind/unbind instead of populate/unpopulate
v5: rebased on 3.17-wip, IOCTL renamed to userptr, reject any unknown
flags, better handle READONLY flag, improve permission check
v6: fix ptr cast warning, use set_page_dirty/mark_page_accessed on unpin
v7: add warning about it's availability in the API definition
v8: drop access_ok check, fix VM mapping bits
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v4)
Reviewed-by: Jérôme Glisse <jglisse@redhat.com> (v4)
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2014-08-07 01:36:00 -06:00
|
|
|
struct dma_buf *radeon_gem_prime_export(struct drm_device *dev,
|
|
|
|
struct drm_gem_object *gobj,
|
|
|
|
int flags)
|
|
|
|
{
|
|
|
|
struct radeon_bo *bo = gem_to_radeon_bo(gobj);
|
|
|
|
if (radeon_ttm_tt_has_userptr(bo->tbo.ttm))
|
|
|
|
return ERR_PTR(-EPERM);
|
|
|
|
return drm_gem_prime_export(dev, gobj, flags);
|
|
|
|
}
|