drm/i915: use simple attribute in debugfs routines

This replaces the manual read/write routines in debugfs with the common
simple attribute helpers. Doing this gets rid of repeated copy/pasting
of copy_from_user and value formatting code.

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
[danvet: Squash in follow-up fix from Kees Cook to fix u64 divides on
32bit platforms.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Kees Cook 2013-03-10 14:10:06 -07:00 committed by Daniel Vetter
parent 5c67eeb6bf
commit 647416f9ee
1 changed files with 103 additions and 301 deletions

View File

@ -866,76 +866,42 @@ static const struct file_operations i915_error_state_fops = {
.release = i915_error_state_release, .release = i915_error_state_release,
}; };
static ssize_t static int
i915_next_seqno_read(struct file *filp, i915_next_seqno_get(void *data, u64 *val)
char __user *ubuf,
size_t max,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
char buf[80];
int len;
int ret; int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex); ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret) if (ret)
return ret; return ret;
len = snprintf(buf, sizeof(buf), *val = dev_priv->next_seqno;
"next_seqno : 0x%x\n",
dev_priv->next_seqno);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
if (len > sizeof(buf)) return 0;
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
} }
static ssize_t static int
i915_next_seqno_write(struct file *filp, i915_next_seqno_set(void *data, u64 val)
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
char buf[20];
u32 val = 1;
int ret; int ret;
if (cnt > 0) {
if (cnt > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, cnt))
return -EFAULT;
buf[cnt] = 0;
ret = kstrtouint(buf, 0, &val);
if (ret < 0)
return ret;
}
ret = mutex_lock_interruptible(&dev->struct_mutex); ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret) if (ret)
return ret; return ret;
ret = i915_gem_set_seqno(dev, val); ret = i915_gem_set_seqno(dev, val);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret ?: cnt; return ret;
} }
static const struct file_operations i915_next_seqno_fops = { DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops,
.owner = THIS_MODULE, i915_next_seqno_get, i915_next_seqno_set,
.open = simple_open, "next_seqno : 0x%llx\n");
.read = i915_next_seqno_read,
.write = i915_next_seqno_write,
.llseek = default_llseek,
};
static int i915_rstdby_delays(struct seq_file *m, void *unused) static int i915_rstdby_delays(struct seq_file *m, void *unused)
{ {
@ -1697,105 +1663,51 @@ static int i915_dpio_info(struct seq_file *m, void *data)
return 0; return 0;
} }
static ssize_t static int
i915_wedged_read(struct file *filp, i915_wedged_get(void *data, u64 *val)
char __user *ubuf,
size_t max,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
char buf[80];
int len;
len = snprintf(buf, sizeof(buf), *val = atomic_read(&dev_priv->gpu_error.reset_counter);
"wedged : %d\n",
atomic_read(&dev_priv->gpu_error.reset_counter));
if (len > sizeof(buf)) return 0;
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
} }
static ssize_t static int
i915_wedged_write(struct file *filp, i915_wedged_set(void *data, u64 val)
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
char buf[20];
int val = 1;
if (cnt > 0) { DRM_INFO("Manually setting wedged to %llu\n", val);
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_INFO("Manually setting wedged to %d\n", val);
i915_handle_error(dev, val); i915_handle_error(dev, val);
return cnt; return 0;
} }
static const struct file_operations i915_wedged_fops = { DEFINE_SIMPLE_ATTRIBUTE(i915_wedged_fops,
.owner = THIS_MODULE, i915_wedged_get, i915_wedged_set,
.open = simple_open, "wedged : %llu\n");
.read = i915_wedged_read,
.write = i915_wedged_write,
.llseek = default_llseek,
};
static ssize_t static int
i915_ring_stop_read(struct file *filp, i915_ring_stop_get(void *data, u64 *val)
char __user *ubuf,
size_t max,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
char buf[20];
int len;
len = snprintf(buf, sizeof(buf), *val = dev_priv->gpu_error.stop_rings;
"0x%08x\n", dev_priv->gpu_error.stop_rings);
if (len > sizeof(buf)) return 0;
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
} }
static ssize_t static int
i915_ring_stop_write(struct file *filp, i915_ring_stop_set(void *data, u64 val)
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
char buf[20]; int ret;
int val = 0, ret;
if (cnt > 0) { DRM_DEBUG_DRIVER("Stopping rings 0x%08llx\n", val);
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("Stopping rings 0x%08x\n", val);
ret = mutex_lock_interruptible(&dev->struct_mutex); ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret) if (ret)
@ -1804,16 +1716,12 @@ i915_ring_stop_write(struct file *filp,
dev_priv->gpu_error.stop_rings = val; dev_priv->gpu_error.stop_rings = val;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return cnt; return 0;
} }
static const struct file_operations i915_ring_stop_fops = { DEFINE_SIMPLE_ATTRIBUTE(i915_ring_stop_fops,
.owner = THIS_MODULE, i915_ring_stop_get, i915_ring_stop_set,
.open = simple_open, "0x%08llx\n");
.read = i915_ring_stop_read,
.write = i915_ring_stop_write,
.llseek = default_llseek,
};
#define DROP_UNBOUND 0x1 #define DROP_UNBOUND 0x1
#define DROP_BOUND 0x2 #define DROP_BOUND 0x2
@ -1823,46 +1731,23 @@ static const struct file_operations i915_ring_stop_fops = {
DROP_BOUND | \ DROP_BOUND | \
DROP_RETIRE | \ DROP_RETIRE | \
DROP_ACTIVE) DROP_ACTIVE)
static ssize_t static int
i915_drop_caches_read(struct file *filp, i915_drop_caches_get(void *data, u64 *val)
char __user *ubuf,
size_t max,
loff_t *ppos)
{ {
char buf[20]; *val = DROP_ALL;
int len;
len = snprintf(buf, sizeof(buf), "0x%08x\n", DROP_ALL); return 0;
if (len > sizeof(buf))
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
} }
static ssize_t static int
i915_drop_caches_write(struct file *filp, i915_drop_caches_set(void *data, u64 val)
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj, *next; struct drm_i915_gem_object *obj, *next;
char buf[20]; int ret;
int val = 0, ret;
if (cnt > 0) { DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val);
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);
/* No need to check and wait for gpu resets, only libdrm auto-restarts /* No need to check and wait for gpu resets, only libdrm auto-restarts
* on ioctls on -EAGAIN. */ * on ioctls on -EAGAIN. */
@ -1900,27 +1785,19 @@ i915_drop_caches_write(struct file *filp,
unlock: unlock:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret ?: cnt; return ret;
} }
static const struct file_operations i915_drop_caches_fops = { DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops,
.owner = THIS_MODULE, i915_drop_caches_get, i915_drop_caches_set,
.open = simple_open, "0x%08llx\n");
.read = i915_drop_caches_read,
.write = i915_drop_caches_write,
.llseek = default_llseek,
};
static ssize_t static int
i915_max_freq_read(struct file *filp, i915_max_freq_get(void *data, u64 *val)
char __user *ubuf,
size_t max,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
char buf[80]; int ret;
int len, ret;
if (!(IS_GEN6(dev) || IS_GEN7(dev))) if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV; return -ENODEV;
@ -1929,42 +1806,23 @@ i915_max_freq_read(struct file *filp,
if (ret) if (ret)
return ret; return ret;
len = snprintf(buf, sizeof(buf), *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
"max freq: %d\n", dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER);
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
if (len > sizeof(buf)) return 0;
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
} }
static ssize_t static int
i915_max_freq_write(struct file *filp, i915_max_freq_set(void *data, u64 val)
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
char buf[20]; int ret;
int val = 1, ret;
if (!(IS_GEN6(dev) || IS_GEN7(dev))) if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV; return -ENODEV;
if (cnt > 0) { DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val);
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("Manually setting max freq to %d\n", val);
ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
if (ret) if (ret)
@ -1973,30 +1831,24 @@ i915_max_freq_write(struct file *filp,
/* /*
* Turbo will still be enabled, but won't go above the set value. * Turbo will still be enabled, but won't go above the set value.
*/ */
dev_priv->rps.max_delay = val / GT_FREQUENCY_MULTIPLIER; do_div(val, GT_FREQUENCY_MULTIPLIER);
dev_priv->rps.max_delay = val;
gen6_set_rps(dev, val / GT_FREQUENCY_MULTIPLIER); gen6_set_rps(dev, val);
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return cnt; return 0;
} }
static const struct file_operations i915_max_freq_fops = { DEFINE_SIMPLE_ATTRIBUTE(i915_max_freq_fops,
.owner = THIS_MODULE, i915_max_freq_get, i915_max_freq_set,
.open = simple_open, "max freq: %llu\n");
.read = i915_max_freq_read,
.write = i915_max_freq_write,
.llseek = default_llseek,
};
static ssize_t static int
i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max, i915_min_freq_get(void *data, u64 *val)
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
char buf[80]; int ret;
int len, ret;
if (!(IS_GEN6(dev) || IS_GEN7(dev))) if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV; return -ENODEV;
@ -2005,40 +1857,23 @@ i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max,
if (ret) if (ret)
return ret; return ret;
len = snprintf(buf, sizeof(buf), *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
"min freq: %d\n", dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER);
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
if (len > sizeof(buf)) return 0;
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
} }
static ssize_t static int
i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt, i915_min_freq_set(void *data, u64 val)
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
char buf[20]; int ret;
int val = 1, ret;
if (!(IS_GEN6(dev) || IS_GEN7(dev))) if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV; return -ENODEV;
if (cnt > 0) { DRM_DEBUG_DRIVER("Manually setting min freq to %llu\n", val);
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("Manually setting min freq to %d\n", val);
ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
if (ret) if (ret)
@ -2047,33 +1882,25 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
/* /*
* Turbo will still be enabled, but won't go below the set value. * Turbo will still be enabled, but won't go below the set value.
*/ */
dev_priv->rps.min_delay = val / GT_FREQUENCY_MULTIPLIER; do_div(val, GT_FREQUENCY_MULTIPLIER);
dev_priv->rps.min_delay = val;
gen6_set_rps(dev, val / GT_FREQUENCY_MULTIPLIER); gen6_set_rps(dev, val);
mutex_unlock(&dev_priv->rps.hw_lock); mutex_unlock(&dev_priv->rps.hw_lock);
return cnt; return 0;
} }
static const struct file_operations i915_min_freq_fops = { DEFINE_SIMPLE_ATTRIBUTE(i915_min_freq_fops,
.owner = THIS_MODULE, i915_min_freq_get, i915_min_freq_set,
.open = simple_open, "min freq: %llu\n");
.read = i915_min_freq_read,
.write = i915_min_freq_write,
.llseek = default_llseek,
};
static ssize_t static int
i915_cache_sharing_read(struct file *filp, i915_cache_sharing_get(void *data, u64 *val)
char __user *ubuf,
size_t max,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
char buf[80];
u32 snpcr; u32 snpcr;
int len, ret; int ret;
if (!(IS_GEN6(dev) || IS_GEN7(dev))) if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV; return -ENODEV;
@ -2085,46 +1912,25 @@ i915_cache_sharing_read(struct file *filp,
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
mutex_unlock(&dev_priv->dev->struct_mutex); mutex_unlock(&dev_priv->dev->struct_mutex);
len = snprintf(buf, sizeof(buf), *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
"%d\n", (snpcr & GEN6_MBC_SNPCR_MASK) >>
GEN6_MBC_SNPCR_SHIFT);
if (len > sizeof(buf)) return 0;
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
} }
static ssize_t static int
i915_cache_sharing_write(struct file *filp, i915_cache_sharing_set(void *data, u64 val)
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{ {
struct drm_device *dev = filp->private_data; struct drm_device *dev = data;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
char buf[20];
u32 snpcr; u32 snpcr;
int val = 1;
if (!(IS_GEN6(dev) || IS_GEN7(dev))) if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV; return -ENODEV;
if (cnt > 0) { if (val > 3)
if (cnt > sizeof(buf) - 1)
return -EINVAL; return -EINVAL;
if (copy_from_user(buf, ubuf, cnt)) DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
return -EFAULT;
buf[cnt] = 0;
val = simple_strtoul(buf, NULL, 0);
}
if (val < 0 || val > 3)
return -EINVAL;
DRM_DEBUG_DRIVER("Manually setting uncore sharing to %d\n", val);
/* Update the cache sharing policy here as well */ /* Update the cache sharing policy here as well */
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
@ -2132,16 +1938,12 @@ i915_cache_sharing_write(struct file *filp,
snpcr |= (val << GEN6_MBC_SNPCR_SHIFT); snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
return cnt; return 0;
} }
static const struct file_operations i915_cache_sharing_fops = { DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops,
.owner = THIS_MODULE, i915_cache_sharing_get, i915_cache_sharing_set,
.open = simple_open, "%llu\n");
.read = i915_cache_sharing_read,
.write = i915_cache_sharing_write,
.llseek = default_llseek,
};
/* As the drm_debugfs_init() routines are called before dev->dev_private is /* As the drm_debugfs_init() routines are called before dev->dev_private is
* allocated we need to hook into the minor for release. */ * allocated we need to hook into the minor for release. */