diff options
Diffstat (limited to 'drivers/gpu/drm/drm_debugfs_crc.c')
-rw-r--r-- | drivers/gpu/drm/drm_debugfs_crc.c | 46 |
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); |