aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_debugfs_crc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_debugfs_crc.c')
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index 7ca486d750e9..bbc3bc4ba844 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -46,10 +46,10 @@
* it reached a given hardware component (a CRC sampling "source").
*
* Userspace can control generation of CRCs in a given CRTC by writing to the
- * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
- * Accepted values are source names (which are driver-specific) and the "auto"
- * keyword, which will let the driver select a default source of frame CRCs
- * for this CRTC.
+ * file dri/0/crtc-N/crc/control in debugfs, with N being the :ref:`index of
+ * the CRTC<crtc_index>`. Accepted values are source names (which are
+ * driver-specific) and the "auto" keyword, which will let the driver select a
+ * default source of frame CRCs for this CRTC.
*
* Once frame CRC generation is enabled, userspace can capture them by reading
* the dri/0/crtc-N/crc/data file. Each line in that file contains the frame
@@ -66,9 +66,18 @@
* the reported CRCs of frames that should have the same contents.
*
* On the driver side the implementation effort is minimal, drivers only need to
- * implement &drm_crtc_funcs.set_crc_source. The debugfs files are automatically
- * set up if that vfunc is set. CRC samples need to be captured in the driver by
- * calling drm_crtc_add_crc_entry().
+ * implement &drm_crtc_funcs.set_crc_source and &drm_crtc_funcs.verify_crc_source.
+ * The debugfs files are automatically set up if those vfuncs are set. CRC samples
+ * need to be captured in the driver by calling drm_crtc_add_crc_entry().
+ * Depending on the driver and HW requirements, &drm_crtc_funcs.set_crc_source
+ * may result in a commit (even a full modeset).
+ *
+ * CRC results must be reliable across non-full-modeset atomic commits, so if a
+ * commit via DRM_IOCTL_MODE_ATOMIC would disable or otherwise interfere with
+ * CRC generation, then the driver must mark that commit as a full modeset
+ * (drm_atomic_crtc_needs_modeset() should return true). As a result, to ensure
+ * consistent results, generic userspace must re-setup CRC generation after a
+ * legacy SETCRTC or an atomic commit with DRM_MODE_ATOMIC_ALLOW_MODESET.
*/
static int crc_control_show(struct seq_file *m, void *data)
@@ -131,12 +140,14 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
if (IS_ERR(source))
return PTR_ERR(source);
- if (source[len] == '\n')
- source[len] = '\0';
+ if (source[len - 1] == '\n')
+ source[len - 1] = '\0';
ret = crtc->funcs->verify_crc_source(crtc, source, &values_cnt);
- if (ret)
+ if (ret) {
+ kfree(source);
return ret;
+ }
spin_lock_irq(&crc->lock);
@@ -249,6 +260,11 @@ static int crtc_crc_release(struct inode *inode, struct file *filep)
struct drm_crtc *crtc = filep->f_inode->i_private;
struct drm_crtc_crc *crc = &crtc->crc;
+ /* terminate the infinite while loop if 'drm_dp_aux_crc_work' running */
+ spin_lock_irq(&crc->lock);
+ crc->opened = false;
+ spin_unlock_irq(&crc->lock);
+
crtc->funcs->set_crc_source(crtc, NULL);
spin_lock_irq(&crc->lock);
@@ -325,19 +341,17 @@ static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf,
return LINE_LEN(crc->values_cnt);
}
-static unsigned int crtc_crc_poll(struct file *file, poll_table *wait)
+static __poll_t crtc_crc_poll(struct file *file, poll_table *wait)
{
struct drm_crtc *crtc = file->f_inode->i_private;
struct drm_crtc_crc *crc = &crtc->crc;
- unsigned ret;
+ __poll_t ret = 0;
poll_wait(file, &crc->wq, wait);
spin_lock_irq(&crc->lock);
if (crc->source && crtc_crc_data_count(crc))
- ret = POLLIN | POLLRDNORM;
- else
- ret = 0;
+ ret |= EPOLLIN | EPOLLRDNORM;
spin_unlock_irq(&crc->lock);
return ret;
@@ -360,7 +374,7 @@ void drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry);
- debugfs_create_file("control", S_IRUGO, crc_ent, crtc,
+ debugfs_create_file("control", S_IRUGO | S_IWUSR, crc_ent, crtc,
&drm_crtc_crc_control_fops);
debugfs_create_file("data", S_IRUGO, crc_ent, crtc,
&drm_crtc_crc_data_fops);