aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-01-15 07:39:35 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-17 16:07:57 -0500
commitdd624afd533bdc87b8c10835515a0c8b2b9868b1 (patch)
treee60ac4ebeeab688a32b28cfc3d4143768a58f6fc
parent0fa877965194fa79fe87944844185d90cfc35352 (diff)
drm/i915: Add a debug interface to forcibly evict and shrink our object caches
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@chris-wilson.co.uk> [danvet: Add a small comment explaining why we don't need to check and wait for gpu resets, acked by Chris on irc.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c104
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c2
3 files changed, 106 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index f7d88e99ebf0..f94418bd1ed2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1776,6 +1776,102 @@ static const struct file_operations i915_ring_stop_fops = {
1776 .llseek = default_llseek, 1776 .llseek = default_llseek,
1777}; 1777};
1778 1778
1779#define DROP_UNBOUND 0x1
1780#define DROP_BOUND 0x2
1781#define DROP_RETIRE 0x4
1782#define DROP_ACTIVE 0x8
1783#define DROP_ALL (DROP_UNBOUND | \
1784 DROP_BOUND | \
1785 DROP_RETIRE | \
1786 DROP_ACTIVE)
1787static ssize_t
1788i915_drop_caches_read(struct file *filp,
1789 char __user *ubuf,
1790 size_t max,
1791 loff_t *ppos)
1792{
1793 char buf[20];
1794 int len;
1795
1796 len = snprintf(buf, sizeof(buf), "0x%08x\n", DROP_ALL);
1797 if (len > sizeof(buf))
1798 len = sizeof(buf);
1799
1800 return simple_read_from_buffer(ubuf, max, ppos, buf, len);
1801}
1802
1803static ssize_t
1804i915_drop_caches_write(struct file *filp,
1805 const char __user *ubuf,
1806 size_t cnt,
1807 loff_t *ppos)
1808{
1809 struct drm_device *dev = filp->private_data;
1810 struct drm_i915_private *dev_priv = dev->dev_private;
1811 struct drm_i915_gem_object *obj, *next;
1812 char buf[20];
1813 int val = 0, ret;
1814
1815 if (cnt > 0) {
1816 if (cnt > sizeof(buf) - 1)
1817 return -EINVAL;
1818
1819 if (copy_from_user(buf, ubuf, cnt))
1820 return -EFAULT;
1821 buf[cnt] = 0;
1822
1823 val = simple_strtoul(buf, NULL, 0);
1824 }
1825
1826 DRM_DEBUG_DRIVER("Dropping caches: 0x%08x\n", val);
1827
1828 /* No need to check and wait for gpu resets, only libdrm auto-restarts
1829 * on ioctls on -EAGAIN. */
1830 ret = mutex_lock_interruptible(&dev->struct_mutex);
1831 if (ret)
1832 return ret;
1833
1834 if (val & DROP_ACTIVE) {
1835 ret = i915_gpu_idle(dev);
1836 if (ret)
1837 goto unlock;
1838 }
1839
1840 if (val & (DROP_RETIRE | DROP_ACTIVE))
1841 i915_gem_retire_requests(dev);
1842
1843 if (val & DROP_BOUND) {
1844 list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list, mm_list)
1845 if (obj->pin_count == 0) {
1846 ret = i915_gem_object_unbind(obj);
1847 if (ret)
1848 goto unlock;
1849 }
1850 }
1851
1852 if (val & DROP_UNBOUND) {
1853 list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
1854 if (obj->pages_pin_count == 0) {
1855 ret = i915_gem_object_put_pages(obj);
1856 if (ret)
1857 goto unlock;
1858 }
1859 }
1860
1861unlock:
1862 mutex_unlock(&dev->struct_mutex);
1863
1864 return ret ?: cnt;
1865}
1866
1867static const struct file_operations i915_drop_caches_fops = {
1868 .owner = THIS_MODULE,
1869 .open = simple_open,
1870 .read = i915_drop_caches_read,
1871 .write = i915_drop_caches_write,
1872 .llseek = default_llseek,
1873};
1874
1779static ssize_t 1875static ssize_t
1780i915_max_freq_read(struct file *filp, 1876i915_max_freq_read(struct file *filp,
1781 char __user *ubuf, 1877 char __user *ubuf,
@@ -2173,6 +2269,12 @@ int i915_debugfs_init(struct drm_minor *minor)
2173 return ret; 2269 return ret;
2174 2270
2175 ret = i915_debugfs_create(minor->debugfs_root, minor, 2271 ret = i915_debugfs_create(minor->debugfs_root, minor,
2272 "i915_gem_drop_caches",
2273 &i915_drop_caches_fops);
2274 if (ret)
2275 return ret;
2276
2277 ret = i915_debugfs_create(minor->debugfs_root, minor,
2176 "i915_error_state", 2278 "i915_error_state",
2177 &i915_error_state_fops); 2279 &i915_error_state_fops);
2178 if (ret) 2280 if (ret)
@@ -2203,6 +2305,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
2203 1, minor); 2305 1, minor);
2204 drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, 2306 drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
2205 1, minor); 2307 1, minor);
2308 drm_debugfs_remove_files((struct drm_info_list *) &i915_drop_caches_fops,
2309 1, minor);
2206 drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, 2310 drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops,
2207 1, minor); 2311 1, minor);
2208 drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops, 2312 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 35ecabc711ed..8f5b2816fc03 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1445,6 +1445,7 @@ int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
1445 bool nonblocking); 1445 bool nonblocking);
1446void i915_gem_object_unpin(struct drm_i915_gem_object *obj); 1446void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
1447int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj); 1447int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj);
1448int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
1448void i915_gem_release_mmap(struct drm_i915_gem_object *obj); 1449void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
1449void i915_gem_lastclose(struct drm_device *dev); 1450void i915_gem_lastclose(struct drm_device *dev);
1450 1451
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 313bdbaba3cd..9d33fb3f8d42 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1662,7 +1662,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
1662 kfree(obj->pages); 1662 kfree(obj->pages);
1663} 1663}
1664 1664
1665static int 1665int
1666i915_gem_object_put_pages(struct drm_i915_gem_object *obj) 1666i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
1667{ 1667{
1668 const struct drm_i915_gem_object_ops *ops = obj->ops; 1668 const struct drm_i915_gem_object_ops *ops = obj->ops;