Using the i915 client list we can easily read and set the various parameters. Signed-off-by: Ben Widawsky <ben at bwidawsk.net> --- drivers/gpu/drm/i915/i915_debugfs.c | 138 +++++++++++++++++++++++++++++++++++ 1 files changed, 138 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 59b9f22..790875d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1543,6 +1543,136 @@ static const struct file_operations i915_cache_sharing_fops = { .llseek = default_llseek, }; +static ssize_t +i915_sched_read(struct file *filp, + char __user *ubuf, + size_t max, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_file_private *temp; + unsigned high, low; + size_t len = 0; + char *buf, *buf2; + struct { + pid_t pid; + int outstanding; + int forced; + int high; + int low; + } requests[20]; + int entries, entry_size, i = 0, ret = 0; + + if (!i915_scheduler) + return 0; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + high = dev_priv->scheduler.high_watermark; + low = dev_priv->scheduler.low_watermark; + list_for_each_entry(temp, &dev_priv->i915_client_list, client_link) { + struct drm_file *file = temp->drm_file; + requests[i].pid = file->pid; + spin_lock(&temp->lock); + requests[i].outstanding = temp->outstanding_requests; + requests[i].forced = temp->forced_throttles; + spin_unlock(&temp->lock); + i++; + } + mutex_unlock(&dev->struct_mutex); + + entries = i; + + entry_size = strlen("pid 123456 = XXXX outstanding (XXXXXX forced)\n") + 1; + buf2 = drm_malloc_ab(entries, entry_size); + memset(buf2, 0, entries * entry_size); + for(i = 0; i < entries; i++) { + len += sprintf(buf2 + len, + "pid %06d = %06d outstanding (%06d forced)\n", + requests[i].pid, requests[i].outstanding, + requests[i].forced); + } + + buf = kasprintf(GFP_KERNEL, "%s\n" + "Scheduler = %s\n" + "High watermark = %d buffers\n" + "Low watermark = %d buffers\n", + buf2, "fair", high, low); + + len = strlen(buf); + + ret = simple_read_from_buffer(ubuf, max, ppos, buf, len); + + drm_free_large(buf2); + kfree(buf); + return ret; +} + +static ssize_t +i915_sched_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; + char *buf, *ptr; + uint32_t high, low; + int ret; + + buf = drm_malloc_ab(cnt + 1, 1); + if (!buf) + return -E2BIG; + + ret = copy_from_user(buf, ubuf, cnt); + if (ret) + goto out; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + low = dev_priv->scheduler.low_watermark; + high = dev_priv->scheduler.high_watermark; + + buf[cnt] = 0; + ptr = buf; + + while ((ptr != NULL) && *ptr != 0) { + if (!strncmp(ptr, "high=", 5)) + high = simple_strtoul(ptr + 5, NULL, 0); + if (!strncmp(ptr, "low=", 4)) + low = simple_strtoul(ptr + 4, NULL, 0); + ptr = strchr(ptr, ','); + if (ptr != NULL) + ptr += strspn(ptr, ", \t\n"); + } + + if (high != dev_priv->scheduler.high_watermark || + low != dev_priv->scheduler.low_watermark) { + DRM_INFO("new high = %d\n", high); + DRM_INFO("new low = %d\n", low); + dev_priv->scheduler.high_watermark = high; + dev_priv->scheduler.low_watermark = low; + } + + mutex_unlock(&dev->struct_mutex); +out: + drm_free_large(buf); + return cnt; +} + +static const struct file_operations i915_scheduler_fops = { + .owner = THIS_MODULE, + .open = i915_debugfs_common_open, + .read = i915_sched_read, + .write = i915_sched_write, +}; + + /* As the drm_debugfs_init() routines are called before dev->dev_private is * allocated we need to hook into the minor for release. */ static int @@ -1712,6 +1842,12 @@ int i915_debugfs_init(struct drm_minor *minor) if (ret) return ret; + ret = i915_debugfs_create(minor->debugfs_root, minor, + "i915_scheduler", + &i915_scheduler_fops); + if (ret) + return ret; + return drm_debugfs_create_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor->debugfs_root, minor); @@ -1729,6 +1865,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_scheduler_fops, + 1, minor); } #endif /* CONFIG_DEBUG_FS */ -- 1.7.7.3