Re: [PATCH 09/10] drm/i915: Add debugfs test control files for Displayport compliance testing

Paulo Zanoni
2015-04-16T21:25:19Z

2015-04-15 12:38 GMT-03:00 Todd Previte <tprevite@gmail.com>:
> This patch adds 3 debugfs files for handling Displayport compliance testing
> and supercedes the previous patches that implemented debugfs support for
> compliance testing. Those patches were:
>
> - [PATCH 04/17] drm/i915: Add debugfs functions for Displayport
> compliance testing
> - [PATCH 08/17] drm/i915: Add new debugfs file for Displayport
> compliance test control
> - [PATCH 09/17] drm/i915: Add debugfs write and test param parsing
> functions for DP test control
>
> This new patch simplifies the debugfs implementation by places a single
> test control value into an individual file. Each file is readable by
> the usersapce application and the test_active file is writable to
> indicate to the kernel when userspace has completed its portion of the
> test sequence.
>
> Replacing the previous files simplifies operation and speeds response
> time for the user app, as it is required to poll on the test_active file
> in order to determine when it needs to begin its operations.
>
> V2:
> - Updated the test active variable name to match the change in
> the initial patch of the series
> V3:
> - Added a fix in the test_active_write function to prevent a NULL pointer
> dereference if the encoder on the connector is invalid
>
> Signed-off-by: Todd Previte <tprevite@gmail.com>
> ---
> drivers/gpu/drm/i915/i915_debugfs.c | 209 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 209 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 2394924..c33d390 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -3937,6 +3937,212 @@ static const struct file_operations i915_display_crc_ctl_fops = {
> .write = display_crc_ctl_write
> };
>
> +static ssize_t i915_displayport_test_active_write(struct file *file,
> + const char __user *ubuf,
> + size_t len, loff_t *offp)
> +{
> + char *input_buffer;
> + int status = 0;
> + struct seq_file *m;
> + struct drm_device *dev;
> + struct drm_connector *connector;
> + struct list_head *connector_list;
> + struct intel_dp *intel_dp;
> + int val = 0;
> +
> + m = file->private_data;
> + if (!m) {
> + status = -ENODEV;
> + return status;
> + }
> + dev = m->private;
> +
> + if (!dev) {
> + status = -ENODEV;
> + return status;
> + }
> + connector_list = &dev->mode_config.connector_list;
> +
> + if (len == 0)
> + return 0;
> +
> + input_buffer = kmalloc(len + 1, GFP_KERNEL);
> + if (!input_buffer)
> + return -ENOMEM;

In 2 spots above you use "status = -ENODEV; return status;", but here
you just "return -ENOMEM". I'd be consistent, possibly using the
shorter form in the 3 cases.

> +
> + if (copy_from_user(input_buffer, ubuf, len)) {
> + status = -EFAULT;
> + goto out;
> + }
> +
> + input_buffer[len] = '\0';
> + DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len);
> +
> + list_for_each_entry(connector, connector_list, head) {
> +
> + if (connector->connector_type !=
> + DRM_MODE_CONNECTOR_DisplayPort)
> + continue;
> +
> + if (connector->connector_type ==
> + DRM_MODE_CONNECTOR_DisplayPort &&
> + connector->status == connector_status_connected &&
> + connector->encoder != NULL) {
> + intel_dp = enc_to_intel_dp(connector->encoder);
> + status = kstrtoint(input_buffer, 10, &val);
> + if (status < 0)
> + goto out;
> + DRM_DEBUG_DRIVER("Got %d for test active\n", val);
> + /* To prevent erroneous activation of the compliance
> + * testing code, only accept an actual value of 1 here
> + */
> + if (val == 1)
> + intel_dp->compliance_test_active = 1;
> + else
> + intel_dp->compliance_test_active = 0;
> + }
> + }
> +out:
> + kfree(input_buffer);
> + if (status < 0)
> + return status;
> +
> + *offp += len;
> + return len;
> +}
> +
> +static int i915_displayport_test_active_show(struct seq_file *m, void *data)
> +{
> + struct drm_device *dev = m->private;
> + struct drm_connector *connector;
> + struct list_head *connector_list = &dev->mode_config.connector_list;
> + struct intel_dp *intel_dp;
> +
> + if (!dev)
> + return -ENODEV;
> +
> + list_for_each_entry(connector, connector_list, head) {
> +
> + if (connector->connector_type !=
> + DRM_MODE_CONNECTOR_DisplayPort)
> + continue;
> +
> + if (connector->status == connector_status_connected &&
> + connector->encoder != NULL) {
> + intel_dp = enc_to_intel_dp(connector->encoder);
> + if (intel_dp->compliance_test_active)
> + seq_puts(m, "1");
> + else
> + seq_puts(m, "0");
> + } else
> + seq_puts(m, "0");
> + }
> +
> + return 0;
> +}
> +
> +static int i915_displayport_test_active_open(struct inode *inode,
> + struct file *file)
> +{
> + struct drm_device *dev = inode->i_private;
> +
> + return single_open(file, i915_displayport_test_active_show, dev);
> +}
> +
> +static const struct file_operations i915_displayport_test_active_fops = {
> + .owner = THIS_MODULE,
> + .open = i915_displayport_test_active_open,
> + .read = seq_read,
> + .llseek = seq_lseek,
> + .release = single_release,
> + .write = i915_displayport_test_active_write
> +};
> +
> +static int i915_displayport_test_data_show(struct seq_file *m, void *data)
> +{
> + struct drm_device *dev = m->private;
> + struct drm_connector *connector;
> + struct list_head *connector_list = &dev->mode_config.connector_list;
> + struct intel_dp *intel_dp;
> +
> + if (!dev)
> + return -ENODEV;
> +
> + list_for_each_entry(connector, connector_list, head) {
> +
> + if (connector->connector_type !=
> + DRM_MODE_CONNECTOR_DisplayPort)
> + continue;
> +
> + if (connector->status == connector_status_connected &&
> + connector->encoder != NULL) {
> + intel_dp = enc_to_intel_dp(connector->encoder);
> + seq_printf(m, "%lx", intel_dp->compliance_test_data);
> + } else
> + seq_puts(m, "0");
> + }
> +
> + return 0;
> +}
> +static int i915_displayport_test_data_open(struct inode *inode,
> + struct file *file)
> +{
> + struct drm_device *dev = inode->i_private;
> +
> + return single_open(file, i915_displayport_test_data_show, dev);
> +}
> +
> +static const struct file_operations i915_displayport_test_data_fops = {
> + .owner = THIS_MODULE,
> + .open = i915_displayport_test_data_open,
> + .read = seq_read,
> + .llseek = seq_lseek,
> + .release = single_release
> +};
> +
> +static int i915_displayport_test_type_show(struct seq_file *m, void *data)
> +{
> + struct drm_device *dev = m->private;
> + struct drm_connector *connector;
> + struct list_head *connector_list = &dev->mode_config.connector_list;
> + struct intel_dp *intel_dp;
> +
> + if (!dev)
> + return -ENODEV;
> +
> + list_for_each_entry(connector, connector_list, head) {
> +
> + if (connector->connector_type !=
> + DRM_MODE_CONNECTOR_DisplayPort)
> + continue;
> +
> + if (connector->status == connector_status_connected &&
> + connector->encoder != NULL) {
> + intel_dp = enc_to_intel_dp(connector->encoder);
> + seq_printf(m, "%02lx", intel_dp->compliance_test_type);
> + } else
> + seq_puts(m, "0");
> + }
> +
> + return 0;
> +}
> +
> +static int i915_displayport_test_type_open(struct inode *inode,
> + struct file *file)
> +{
> + struct drm_device *dev = inode->i_private;
> +
> + return single_open(file, i915_displayport_test_type_show, dev);
> +}
> +
> +static const struct file_operations i915_displayport_test_type_fops = {
> + .owner = THIS_MODULE,
> + .open = i915_displayport_test_type_open,
> + .read = seq_read,
> + .llseek = seq_lseek,
> + .release = single_release
> +};
> +
> static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
> {
> struct drm_device *dev = m->private;
> @@ -4832,6 +5038,9 @@ static const struct i915_debugfs_files {
> {"i915_spr_wm_latency", &i915_spr_wm_latency_fops},
> {"i915_cur_wm_latency", &i915_cur_wm_latency_fops},
> {"i915_fbc_false_color", &i915_fbc_fc_fops},
> + {"i915_dp_test_data", &i915_displayport_test_data_fops},
> + {"i915_dp_test_type", &i915_displayport_test_type_fops},

Since both test_data and test_type are simpler, you can put them on
i915_debugfs_list instead of i915_debugfs_files. This will allow the
removal of the 2 _open functions and the 2 _fops structs, making your
patch ~30 lines smaller.

Since the stuff above is not required for the files to work:
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> + {"i915_dp_test_active", &i915_displayport_test_active_fops}
> };
>
> void intel_display_crc_init(struct drm_device *dev)
> --
> 1.9.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

--
Paulo Zanoni