Skip to content

Commit

Permalink
Merge branch 'prime-merge' of ssh://people.freedesktop.org/~airlied/l…
Browse files Browse the repository at this point in the history
…inux into drm-core-next

* 'prime-merge' of ssh://people.freedesktop.org/~airlied/linux:
  drm/radeon: add PRIME support (v2)
  i915: add dmabuf/prime buffer sharing support.
  nouveau: add PRIME support
  ttm: add prime sharing support to TTM (v2)
  udl: add prime fd->handle support.
  drm/prime: add exported buffers to current fprivs imported buffer list (v2)
  drm/prime: introduce sg->pages/addr arrays helper
  • Loading branch information
Dave Airlie committed May 23, 2012
2 parents 4d93914 + 40f5cf9 commit 5b2ba70
Show file tree
Hide file tree
Showing 50 changed files with 950 additions and 67 deletions.
21 changes: 15 additions & 6 deletions drivers/gpu/drm/drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,19 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
}
EXPORT_SYMBOL(drm_gem_object_alloc);

static void
drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
{
if (obj->import_attach) {
drm_prime_remove_imported_buf_handle(&filp->prime,
obj->import_attach->dmabuf);
}
if (obj->export_dma_buf) {
drm_prime_remove_imported_buf_handle(&filp->prime,
obj->export_dma_buf);
}
}

/**
* Removes the mapping from handle to filp for this object.
*/
Expand Down Expand Up @@ -233,9 +246,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
idr_remove(&filp->object_idr, handle);
spin_unlock(&filp->table_lock);

if (obj->import_attach)
drm_prime_remove_imported_buf_handle(&filp->prime,
obj->import_attach->dmabuf);
drm_gem_remove_prime_handles(obj, filp);

if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, filp);
Expand Down Expand Up @@ -530,9 +541,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
struct drm_gem_object *obj = ptr;
struct drm_device *dev = obj->dev;

if (obj->import_attach)
drm_prime_remove_imported_buf_handle(&file_priv->prime,
obj->import_attach->dmabuf);
drm_gem_remove_prime_handles(obj, file_priv);

if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, file_priv);
Expand Down
48 changes: 48 additions & 0 deletions drivers/gpu/drm/drm_prime.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
{
struct drm_gem_object *obj;
void *buf;
int ret;

obj = drm_gem_object_lookup(dev, file_priv, handle);
if (!obj)
Expand Down Expand Up @@ -100,6 +101,17 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
obj->export_dma_buf = buf;
*prime_fd = dma_buf_fd(buf, flags);
}
/* if we've exported this buffer the cheat and add it to the import list
* so we get the correct handle back
*/
ret = drm_prime_add_imported_buf_handle(&file_priv->prime,
obj->export_dma_buf, handle);
if (ret) {
drm_gem_object_unreference_unlocked(obj);
mutex_unlock(&file_priv->prime.lock);
return ret;
}

mutex_unlock(&file_priv->prime.lock);
return 0;
}
Expand Down Expand Up @@ -227,6 +239,42 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
}
EXPORT_SYMBOL(drm_prime_pages_to_sg);

/* export an sg table into an array of pages and addresses
this is currently required by the TTM driver in order to do correct fault
handling */
int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
dma_addr_t *addrs, int max_pages)
{
unsigned count;
struct scatterlist *sg;
struct page *page;
u32 len, offset;
int pg_index;
dma_addr_t addr;

pg_index = 0;
for_each_sg(sgt->sgl, sg, sgt->nents, count) {
len = sg->length;
offset = sg->offset;
page = sg_page(sg);
addr = sg_dma_address(sg);

while (len > 0) {
if (WARN_ON(pg_index >= max_pages))
return -1;
pages[pg_index] = page;
if (addrs)
addrs[pg_index] = addr;

page++;
addr += PAGE_SIZE;
len -= PAGE_SIZE;
pg_index++;
}
}
return 0;
}
EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
/* helper function to cleanup a GEM/prime object */
void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
{
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
dvo_ch7017.o \
dvo_ivch.o \
dvo_tfp410.o \
dvo_sil164.o
dvo_sil164.o \
i915_gem_dmabuf.o

i915-$(CONFIG_COMPAT) += i915_ioc32.o

Expand Down
8 changes: 7 additions & 1 deletion drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ static struct drm_driver driver = {
*/
.driver_features =
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME,
.load = i915_driver_load,
.unload = i915_driver_unload,
.open = i915_driver_open,
Expand All @@ -1062,6 +1062,12 @@ static struct drm_driver driver = {
.gem_init_object = i915_gem_init_object,
.gem_free_object = i915_gem_free_object,
.gem_vm_ops = &i915_gem_vm_ops,

.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = i915_gem_prime_export,
.gem_prime_import = i915_gem_prime_import,

.dumb_create = i915_gem_dumb_create,
.dumb_map_offset = i915_gem_mmap_gtt,
.dumb_destroy = i915_gem_dumb_destroy,
Expand Down
11 changes: 11 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,8 @@ struct drm_i915_gem_object {
struct scatterlist *sg_list;
int num_sg;

/* prime dma-buf support */
struct sg_table *sg_table;
/**
* Used for performing relocations during execbuffer insertion.
*/
Expand Down Expand Up @@ -1245,6 +1247,8 @@ int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj);
void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev);

int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
gfp_t gfpmask);
int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj);
int i915_gem_object_sync(struct drm_i915_gem_object *obj,
Expand Down Expand Up @@ -1342,6 +1346,13 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev,
int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level);

struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf);

struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *gem_obj, int flags);


/* i915_gem_gtt.c */
int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev);
void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev);
Expand Down
37 changes: 35 additions & 2 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/pci.h>
#include <linux/dma-buf.h>

static __must_check int i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj);
static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
Expand Down Expand Up @@ -538,6 +539,14 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
goto out;
}

/* prime objects have no backing filp to GEM pread/pwrite
* pages from.
*/
if (!obj->base.filp) {
ret = -EINVAL;
goto out;
}

trace_i915_gem_object_pread(obj, args->offset, args->size);

ret = i915_gem_shmem_pread(dev, obj, args, file);
Expand Down Expand Up @@ -880,6 +889,14 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
goto out;
}

/* prime objects have no backing filp to GEM pread/pwrite
* pages from.
*/
if (!obj->base.filp) {
ret = -EINVAL;
goto out;
}

trace_i915_gem_object_pwrite(obj, args->offset, args->size);

ret = -EFAULT;
Expand Down Expand Up @@ -1021,6 +1038,14 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
if (obj == NULL)
return -ENOENT;

/* prime objects have no backing filp to GEM mmap
* pages from.
*/
if (!obj->filp) {
drm_gem_object_unreference_unlocked(obj);
return -EINVAL;
}

addr = vm_mmap(obj->filp, 0, args->size,
PROT_READ | PROT_WRITE, MAP_SHARED,
args->offset);
Expand Down Expand Up @@ -1302,8 +1327,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
}


static int
int
i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
gfp_t gfpmask)
{
Expand All @@ -1312,6 +1336,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
struct inode *inode;
struct page *page;

if (obj->pages || obj->sg_table)
return 0;

/* Get the list of pages out of our struct file. They'll be pinned
* at this point until we release them.
*/
Expand Down Expand Up @@ -1353,6 +1380,9 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
int page_count = obj->base.size / PAGE_SIZE;
int i;

if (!obj->pages)
return;

BUG_ON(obj->madv == __I915_MADV_PURGED);

if (i915_gem_object_needs_bit17_swizzle(obj))
Expand Down Expand Up @@ -3327,6 +3357,9 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)

trace_i915_gem_object_destroy(obj);

if (gem_obj->import_attach)
drm_prime_gem_destroy(gem_obj, obj->sg_table);

if (obj->phys_obj)
i915_gem_detach_phys_object(dev, obj);

Expand Down
Loading

0 comments on commit 5b2ba70

Please sign in to comment.