On Tue, Jan 15, 2013 at 12:39:35PM +0000, Chris Wilson wrote: > As a means to investigate some bad system behaviour related to the > purging of the active, inactive and unbound lists, it is useful to be > able to manually control when those lists should be cleared. > > v2: use _safe list iterators as we kick objects from the list as we > walk. > > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk> Queued for -next, thanks for the patch. -Daniel > --- > drivers/gpu/drm/i915/i915_debugfs.c | 102 +++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/i915_gem.c | 2 +- > 3 files changed, 104 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c > index 882a735..3041bab 100644 > --- a/drivers/gpu/drm/i915/i915_debugfs.c > +++ b/drivers/gpu/drm/i915/i915_debugfs.c > @@ -1776,6 +1776,100 @@ static const struct file_operations i915_ring_stop_fops = { > .llseek = default_llseek, > }; > > +#define DROP_UNBOUND 0x1 > +#define DROP_BOUND 0x2 > +#define DROP_RETIRE 0x4 > +#define DROP_ACTIVE 0x8 > +#define DROP_ALL (DROP_UNBOUND | \ > + DROP_BOUND | \ > + DROP_RETIRE | \ > + DROP_ACTIVE) > +static ssize_t > +i915_drop_caches_read(struct file *filp, > + char __user *ubuf, > + size_t max, > + loff_t *ppos) > +{ > + char buf[20]; > + int len; > + > + len = snprintf(buf, sizeof(buf), "0x%08x\n", DROP_ALL); > + if (len > sizeof(buf)) > + len = sizeof(buf); > + > + return simple_read_from_buffer(ubuf, max, ppos, buf, len); > +} > + > +static ssize_t > +i915_drop_caches_write(struct file *filp, > + const char __user *ubuf, > + size_t cnt, > + loff_t *ppos) > +{ > + struct drm_device *dev = filp->private_data; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_i915_gem_object *obj, *next; > + char buf[20]; > + int val = 0, ret; > + > + if (cnt > 0) { > + if (cnt > sizeof(buf) - 1) > + return -EINVAL; > + > + if (copy_from_user(buf, ubuf, cnt)) > + return -EFAULT; > + buf[cnt] = 0; > + > + val = simple_strtoul(buf, NULL, 0); > + } > + > + DRM_DEBUG_DRIVER("Dropping caches: 0x%08x\n", val); > + > + ret = mutex_lock_interruptible(&dev->struct_mutex); > + if (ret) > + return ret; > + > + if (val & DROP_ACTIVE) { > + ret = i915_gpu_idle(dev); > + if (ret) > + goto unlock; > + } > + > + if (val & (DROP_RETIRE | DROP_ACTIVE)) > + i915_gem_retire_requests(dev); > + > + if (val & DROP_BOUND) { > + list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list, mm_list) > + if (obj->pin_count == 0) { > + ret = i915_gem_object_unbind(obj); > + if (ret) > + goto unlock; > + } > + } > + > + if (val & DROP_UNBOUND) { > + list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list) > + if (obj->pages_pin_count == 0) { > + ret = i915_gem_object_put_pages(obj); > + if (ret) > + goto unlock; > + } > + } > + > +unlock: > + mutex_unlock(&dev->struct_mutex); > + > + return ret ?: cnt; > +} > + > +static const struct file_operations i915_drop_caches_fops = { > + .owner = THIS_MODULE, > + .open = simple_open, > + .read = i915_drop_caches_read, > + .write = i915_drop_caches_write, > + .llseek = default_llseek, > +}; > + > static ssize_t > i915_max_freq_read(struct file *filp, > char __user *ubuf, > @@ -2173,6 +2267,12 @@ int i915_debugfs_init(struct drm_minor *minor) > return ret; > > ret = i915_debugfs_create(minor->debugfs_root, minor, > + "i915_gem_drop_caches", > + &i915_drop_caches_fops); > + if (ret) > + return ret; > + > + ret = i915_debugfs_create(minor->debugfs_root, minor, > "i915_error_state", > &i915_error_state_fops); > if (ret) > @@ -2203,6 +2303,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) > 1, minor); > drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, > 1, minor); > + drm_debugfs_remove_files((struct drm_info_list *) &i915_drop_caches_fops, > + 1, minor); > drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, > 1, minor); > drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops, > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 0a42df1..233216f 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -1430,6 +1430,7 @@ int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, > bool nonblocking); > void i915_gem_object_unpin(struct drm_i915_gem_object *obj); > int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj); > +int i915_gem_object_put_pages(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); > > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index e279d91..41245e9 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -1656,7 +1656,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) > kfree(obj->pages); > } > > -static int > +int > i915_gem_object_put_pages(struct drm_i915_gem_object *obj) > { > const struct drm_i915_gem_object_ops *ops = obj->ops; > -- > 1.7.10.4 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch