> We've wanted this for a few consumers that touch the pages directly (such as > the following commit), which have been doing the refcounting outside of > get/put pages.
No idea if this is a valid point or not but whenever I see refcount that isn't a kref my internal, "should this be a kref" o-meter goes off. Dave. > --- > drivers/gpu/drm/i915/i915_drv.h | 3 +- > drivers/gpu/drm/i915/i915_gem.c | 70 > ++++++++++++++++++++------------------- > 2 files changed, 38 insertions(+), 35 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index d6cc986..75e3384 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -404,7 +404,8 @@ struct drm_i915_gem_object { > /** AGP memory structure for our GTT binding. */ > DRM_AGP_MEM *agp_mem; > > - struct page **page_list; > + struct page **pages; > + int pages_refcount; > > /** > * Current offset of the object in GTT space. > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index 35f8c7b..b998d65 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -43,8 +43,8 @@ static int i915_gem_object_set_cpu_read_domain_range(struct > drm_gem_object *obj, > uint64_t offset, > uint64_t size); > static void i915_gem_object_set_to_full_cpu_read_domain(struct > drm_gem_object *obj); > -static int i915_gem_object_get_page_list(struct drm_gem_object *obj); > -static void i915_gem_object_free_page_list(struct drm_gem_object *obj); > +static int i915_gem_object_get_pages(struct drm_gem_object *obj); > +static void i915_gem_object_put_pages(struct drm_gem_object *obj); > static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); > static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, > unsigned alignment); > @@ -928,29 +928,30 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void > *data, > } > > static void > -i915_gem_object_free_page_list(struct drm_gem_object *obj) > +i915_gem_object_put_pages(struct drm_gem_object *obj) > { > struct drm_i915_gem_object *obj_priv = obj->driver_private; > int page_count = obj->size / PAGE_SIZE; > int i; > > - if (obj_priv->page_list == NULL) > - return; > + BUG_ON(obj_priv->pages_refcount == 0); > > + if (--obj_priv->pages_refcount != 0) > + return; > > for (i = 0; i < page_count; i++) > - if (obj_priv->page_list[i] != NULL) { > + if (obj_priv->pages[i] != NULL) { > if (obj_priv->dirty) > - set_page_dirty(obj_priv->page_list[i]); > - mark_page_accessed(obj_priv->page_list[i]); > - page_cache_release(obj_priv->page_list[i]); > + set_page_dirty(obj_priv->pages[i]); > + mark_page_accessed(obj_priv->pages[i]); > + page_cache_release(obj_priv->pages[i]); > } > obj_priv->dirty = 0; > > - drm_free(obj_priv->page_list, > + drm_free(obj_priv->pages, > page_count * sizeof(struct page *), > DRM_MEM_DRIVER); > - obj_priv->page_list = NULL; > + obj_priv->pages = NULL; > } > > static void > @@ -1402,7 +1403,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) > if (obj_priv->fence_reg != I915_FENCE_REG_NONE) > i915_gem_clear_fence_reg(obj); > > - i915_gem_object_free_page_list(obj); > + i915_gem_object_put_pages(obj); > > if (obj_priv->gtt_space) { > atomic_dec(&dev->gtt_count); > @@ -1521,7 +1522,7 @@ i915_gem_evict_everything(struct drm_device *dev) > } > > static int > -i915_gem_object_get_page_list(struct drm_gem_object *obj) > +i915_gem_object_get_pages(struct drm_gem_object *obj) > { > struct drm_i915_gem_object *obj_priv = obj->driver_private; > int page_count, i; > @@ -1530,18 +1531,19 @@ i915_gem_object_get_page_list(struct drm_gem_object > *obj) > struct page *page; > int ret; > > - if (obj_priv->page_list) > + if (obj_priv->pages_refcount++ != 0) > return 0; > > /* Get the list of pages out of our struct file. They'll be pinned > * at this point until we release them. > */ > page_count = obj->size / PAGE_SIZE; > - BUG_ON(obj_priv->page_list != NULL); > - obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *), > - DRM_MEM_DRIVER); > - if (obj_priv->page_list == NULL) { > + BUG_ON(obj_priv->pages != NULL); > + obj_priv->pages = drm_calloc(page_count, sizeof(struct page *), > + DRM_MEM_DRIVER); > + if (obj_priv->pages == NULL) { > DRM_ERROR("Faled to allocate page list\n"); > + obj_priv->pages_refcount--; > return -ENOMEM; > } > > @@ -1552,10 +1554,10 @@ i915_gem_object_get_page_list(struct drm_gem_object > *obj) > if (IS_ERR(page)) { > ret = PTR_ERR(page); > DRM_ERROR("read_mapping_page failed: %d\n", ret); > - i915_gem_object_free_page_list(obj); > + i915_gem_object_put_pages(obj); > return ret; > } > - obj_priv->page_list[i] = page; > + obj_priv->pages[i] = page; > } > return 0; > } > @@ -1878,7 +1880,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, > unsigned alignment) > DRM_INFO("Binding object of size %d at 0x%08x\n", > obj->size, obj_priv->gtt_offset); > #endif > - ret = i915_gem_object_get_page_list(obj); > + ret = i915_gem_object_get_pages(obj); > if (ret) { > drm_mm_put_block(obj_priv->gtt_space); > obj_priv->gtt_space = NULL; > @@ -1890,12 +1892,12 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object > *obj, unsigned alignment) > * into the GTT. > */ > obj_priv->agp_mem = drm_agp_bind_pages(dev, > - obj_priv->page_list, > + obj_priv->pages, > page_count, > obj_priv->gtt_offset, > obj_priv->agp_type); > if (obj_priv->agp_mem == NULL) { > - i915_gem_object_free_page_list(obj); > + i915_gem_object_put_pages(obj); > drm_mm_put_block(obj_priv->gtt_space); > obj_priv->gtt_space = NULL; > return -ENOMEM; > @@ -1922,10 +1924,10 @@ i915_gem_clflush_object(struct drm_gem_object *obj) > * to GPU, and we can ignore the cache flush because it'll happen > * again at bind time. > */ > - if (obj_priv->page_list == NULL) > + if (obj_priv->pages == NULL) > return; > > - drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE); > + drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); > } > > /** Flushes any GPU write domain for the object if it's dirty. */ > @@ -2270,7 +2272,7 @@ i915_gem_object_set_to_full_cpu_read_domain(struct > drm_gem_object *obj) > for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) { > if (obj_priv->page_cpu_valid[i]) > continue; > - drm_clflush_pages(obj_priv->page_list + i, 1); > + drm_clflush_pages(obj_priv->pages + i, 1); > } > drm_agp_chipset_flush(dev); > } > @@ -2336,7 +2338,7 @@ i915_gem_object_set_cpu_read_domain_range(struct > drm_gem_object *obj, > if (obj_priv->page_cpu_valid[i]) > continue; > > - drm_clflush_pages(obj_priv->page_list + i, 1); > + drm_clflush_pages(obj_priv->pages + i, 1); > > obj_priv->page_cpu_valid[i] = 1; > } > @@ -3304,7 +3306,7 @@ i915_gem_init_hws(struct drm_device *dev) > > dev_priv->status_gfx_addr = obj_priv->gtt_offset; > > - dev_priv->hw_status_page = kmap(obj_priv->page_list[0]); > + dev_priv->hw_status_page = kmap(obj_priv->pages[0]); > if (dev_priv->hw_status_page == NULL) { > DRM_ERROR("Failed to map status page.\n"); > memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); > @@ -3334,7 +3336,7 @@ i915_gem_cleanup_hws(struct drm_device *dev) > obj = dev_priv->hws_obj; > obj_priv = obj->driver_private; > > - kunmap(obj_priv->page_list[0]); > + kunmap(obj_priv->pages[0]); > i915_gem_object_unpin(obj); > drm_gem_object_unreference(obj); > dev_priv->hws_obj = NULL; > @@ -3637,20 +3639,20 @@ void i915_gem_detach_phys_object(struct drm_device > *dev, > if (!obj_priv->phys_obj) > return; > > - ret = i915_gem_object_get_page_list(obj); > + ret = i915_gem_object_get_pages(obj); > if (ret) > goto out; > > page_count = obj->size / PAGE_SIZE; > > for (i = 0; i < page_count; i++) { > - char *dst = kmap_atomic(obj_priv->page_list[i], KM_USER0); > + char *dst = kmap_atomic(obj_priv->pages[i], KM_USER0); > char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); > > memcpy(dst, src, PAGE_SIZE); > kunmap_atomic(dst, KM_USER0); > } > - drm_clflush_pages(obj_priv->page_list, page_count); > + drm_clflush_pages(obj_priv->pages, page_count); > drm_agp_chipset_flush(dev); > out: > obj_priv->phys_obj->cur_obj = NULL; > @@ -3693,7 +3695,7 @@ i915_gem_attach_phys_object(struct drm_device *dev, > obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1]; > obj_priv->phys_obj->cur_obj = obj; > > - ret = i915_gem_object_get_page_list(obj); > + ret = i915_gem_object_get_pages(obj); > if (ret) { > DRM_ERROR("failed to get page list\n"); > goto out; > @@ -3702,7 +3704,7 @@ i915_gem_attach_phys_object(struct drm_device *dev, > page_count = obj->size / PAGE_SIZE; > > for (i = 0; i < page_count; i++) { > - char *src = kmap_atomic(obj_priv->page_list[i], KM_USER0); > + char *src = kmap_atomic(obj_priv->pages[i], KM_USER0); > char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); > > memcpy(dst, src, PAGE_SIZE); > ------------------------------------------------------------------------------ -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel