drm/i915: Prevent kernel panic when reading/writing compliance debugfs files, v2.
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Mon, 26 Jun 2017 08:18:35 +0000 (10:18 +0200)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Mon, 3 Jul 2017 12:07:04 +0000 (14:07 +0200)
When reading all debugfs files on a system with DP-MST the kernel panics
on a null pointer dereference because intel_dp is null for a DP-MST
connector. Detect this case and skip those connectors.

Also fix the write for the DP compliance file in the same way.

Changes since v1:
- Fix i915_displayport_test_active_write too. (DK)

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Cc: Manasi Navare <manasi.d.navare@intel.com>
Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170626081835.24251-1-maarten.lankhorst@linux.intel.com
drivers/gpu/drm/i915/i915_debugfs.c

index 580bd4f4a49e6a513897b76135651c46cd17c9f3..643f56b8b87ca1edf740b469c005bdc411011c5b 100644 (file)
@@ -3778,13 +3778,18 @@ static ssize_t i915_displayport_test_active_write(struct file *file,
 
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               struct intel_encoder *encoder;
+
                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);
+               encoder = to_intel_encoder(connector->encoder);
+               if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
+                       continue;
+
+               if (encoder && connector->status == connector_status_connected) {
+                       intel_dp = enc_to_intel_dp(&encoder->base);
                        status = kstrtoint(input_buffer, 10, &val);
                        if (status < 0)
                                break;
@@ -3816,13 +3821,18 @@ static int i915_displayport_test_active_show(struct seq_file *m, void *data)
 
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               struct intel_encoder *encoder;
+
                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);
+               encoder = to_intel_encoder(connector->encoder);
+               if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
+                       continue;
+
+               if (encoder && connector->status == connector_status_connected) {
+                       intel_dp = enc_to_intel_dp(&encoder->base);
                        if (intel_dp->compliance.test_active)
                                seq_puts(m, "1");
                        else
@@ -3862,13 +3872,18 @@ static int i915_displayport_test_data_show(struct seq_file *m, void *data)
 
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               struct intel_encoder *encoder;
+
                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);
+               encoder = to_intel_encoder(connector->encoder);
+               if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
+                       continue;
+
+               if (encoder && connector->status == connector_status_connected) {
+                       intel_dp = enc_to_intel_dp(&encoder->base);
                        if (intel_dp->compliance.test_type ==
                            DP_TEST_LINK_EDID_READ)
                                seq_printf(m, "%lx",
@@ -3915,13 +3930,18 @@ static int i915_displayport_test_type_show(struct seq_file *m, void *data)
 
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               struct intel_encoder *encoder;
+
                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);
+               encoder = to_intel_encoder(connector->encoder);
+               if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
+                       continue;
+
+               if (encoder && connector->status == connector_status_connected) {
+                       intel_dp = enc_to_intel_dp(&encoder->base);
                        seq_printf(m, "%02lx", intel_dp->compliance.test_type);
                } else
                        seq_puts(m, "0");