Skip to content

Commit

Permalink
drm/i915: Add i915_gem_object_vmap to map GEM object to virtual space
Browse files Browse the repository at this point in the history
There are several places inside driver where a GEM object is mapped to
kernel virtual space. The mapping is either done for the whole object
or certain page range of it.

This patch introduces a function i915_gem_object_vmap to do such job.

v2: Use obj->pages->nents for iteration within i915_gem_object_vmap;
    break when it finishes all desired pages. The caller need to pass
    in actual page number. (Tvrtko Ursulin)

Signed-off-by: Alex Dai <yu.dai@intel.com>
Cc: Dave Gordon <david.s.gordon@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Alex Dai <yu.dai@intel.com>
  • Loading branch information
Alex Dai authored and 0day robot committed Feb 18, 2016
1 parent d6e3af5 commit 2700fc4
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 62 deletions.
28 changes: 1 addition & 27 deletions drivers/gpu/drm/i915/i915_cmd_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -863,37 +863,11 @@ find_reg(const struct drm_i915_reg_descriptor *table,
static u32 *vmap_batch(struct drm_i915_gem_object *obj,
unsigned start, unsigned len)
{
int i;
void *addr = NULL;
struct sg_page_iter sg_iter;
int first_page = start >> PAGE_SHIFT;
int last_page = (len + start + 4095) >> PAGE_SHIFT;
int npages = last_page - first_page;
struct page **pages;

pages = drm_malloc_ab(npages, sizeof(*pages));
if (pages == NULL) {
DRM_DEBUG_DRIVER("Failed to get space for pages\n");
goto finish;
}

i = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, first_page) {
pages[i++] = sg_page_iter_page(&sg_iter);
if (i == npages)
break;
}

addr = vmap(pages, i, 0, PAGE_KERNEL);
if (addr == NULL) {
DRM_DEBUG_DRIVER("Failed to vmap pages\n");
goto finish;
}

finish:
if (pages)
drm_free_large(pages);
return (u32*)addr;
return (u32*)i915_gem_object_vmap(obj, first_page, npages);
}

/* Returns a vmap'd pointer to dest_obj, which the caller must unmap */
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -2899,6 +2899,9 @@ struct drm_i915_gem_object *i915_gem_object_create_from_data(
struct drm_device *dev, const void *data, size_t size);
void i915_gem_free_object(struct drm_gem_object *obj);
void i915_gem_vma_destroy(struct i915_vma *vma);
void *i915_gem_object_vmap(struct drm_i915_gem_object *obj,
unsigned int first,
unsigned int npages);

/* Flags used by pin/bind&friends. */
#define PIN_MAPPABLE (1<<0)
Expand Down
47 changes: 47 additions & 0 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -5356,3 +5356,50 @@ i915_gem_object_create_from_data(struct drm_device *dev,
drm_gem_object_unreference(&obj->base);
return ERR_PTR(ret);
}

/**
* i915_gem_object_vmap - map a GEM obj into kernel virtual space
* @obj: the GEM obj to be mapped
* @first: index of the first page where mapping starts
* @npages: how many pages to be mapped, starting from first page
*
* Map a given page range of GEM obj into kernel virtual space. The caller must
* make sure the associated pages are gathered and pinned before calling this
* function. vunmap should be called after use.
*
* NULL will be returned if fails.
*/
void *i915_gem_object_vmap(struct drm_i915_gem_object *obj,
unsigned int first,
unsigned int npages)
{
struct sg_page_iter sg_iter;
struct page **pages;
void *addr;
int i;

if (first + npages > obj->pages->nents) {
DRM_DEBUG_DRIVER("Invalid page count\n");
return NULL;
}

pages = drm_malloc_ab(npages, sizeof(*pages));
if (pages == NULL) {
DRM_DEBUG_DRIVER("Failed to get space for pages\n");
return NULL;
}

i = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, first) {
pages[i++] = sg_page_iter_page(&sg_iter);
if (i == npages)
break;
}

addr = vmap(pages, npages, 0, PAGE_KERNEL);
if (addr == NULL)
DRM_DEBUG_DRIVER("Failed to vmap pages\n");
drm_free_large(pages);

return addr;
}
16 changes: 3 additions & 13 deletions drivers/gpu/drm/i915/i915_gem_dmabuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,7 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
{
struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
struct drm_device *dev = obj->base.dev;
struct sg_page_iter sg_iter;
struct page **pages;
int ret, i;
int ret;

ret = i915_mutex_lock_interruptible(dev);
if (ret)
Expand All @@ -131,16 +129,8 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)

ret = -ENOMEM;

pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
if (pages == NULL)
goto err_unpin;

i = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
pages[i++] = sg_page_iter_page(&sg_iter);

obj->dma_buf_vmapping = vmap(pages, i, 0, PAGE_KERNEL);
drm_free_large(pages);
obj->dma_buf_vmapping = i915_gem_object_vmap(obj, 0,
dma_buf->size >> PAGE_SHIFT);

if (!obj->dma_buf_vmapping)
goto err_unpin;
Expand Down
24 changes: 2 additions & 22 deletions drivers/gpu/drm/i915/intel_ringbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2064,27 +2064,6 @@ void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
i915_gem_object_ggtt_unpin(ringbuf->obj);
}

static u32 *vmap_obj(struct drm_i915_gem_object *obj)
{
struct sg_page_iter sg_iter;
struct page **pages;
void *addr;
int i;

pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
if (pages == NULL)
return NULL;

i = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
pages[i++] = sg_page_iter_page(&sg_iter);

addr = vmap(pages, i, 0, PAGE_KERNEL);
drm_free_large(pages);

return addr;
}

int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
struct intel_ringbuffer *ringbuf)
{
Expand All @@ -2103,7 +2082,8 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
return ret;
}

ringbuf->virtual_start = vmap_obj(obj);
ringbuf->virtual_start = i915_gem_object_vmap(obj, 0,
ringbuf->size >> PAGE_SHIFT);
if (ringbuf->virtual_start == NULL) {
i915_gem_object_ggtt_unpin(obj);
return -ENOMEM;
Expand Down

0 comments on commit 2700fc4

Please sign in to comment.