[PATCH] drm/i915: Avoid escaping check_digital_port_conflicts() with locks held

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hitting the failure path through check_digital_port_conflicts triggers:

    ================================================
    WARNING: lock held when returning to user space!
    4.16.0-rc1-CI-kasan_1+ #1 Tainted: G        W
    ------------------------------------------------
    kms_3d/1439 is leaving the kernel with locks still held!
    1 lock held by kms_3d/1439:
    #0:  (drm_connector_list_iter){.+.+}, at: [<000000003745d183>] intel_atomic_check+0x1d9d/0x3ff0 [i915]

Rearrange the code to have a single exit path through the unlock.

Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Cc: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_display.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 95d0e7a64773..2c240adeecf6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10703,8 +10703,9 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 	struct drm_device *dev = state->dev;
 	struct drm_connector *connector;
 	struct drm_connector_list_iter conn_iter;
-	unsigned int used_ports = 0;
-	unsigned int used_mst_ports = 0;
+	unsigned long used_ports = 0;
+	unsigned long used_mst_ports = 0;
+	bool ok = false;
 
 	/*
 	 * Walk the connector list instead of the encoder
@@ -10715,6 +10716,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 	drm_for_each_connector_iter(connector, &conn_iter) {
 		struct drm_connector_state *connector_state;
 		struct intel_encoder *encoder;
+		unsigned int port_mask;
 
 		connector_state = drm_atomic_get_existing_connector_state(state, connector);
 		if (!connector_state)
@@ -10724,40 +10726,41 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 			continue;
 
 		encoder = to_intel_encoder(connector_state->best_encoder);
+		port_mask = BIT(encoder->port);
 
 		WARN_ON(!connector_state->crtc);
 
 		switch (encoder->type) {
-			unsigned int port_mask;
 		case INTEL_OUTPUT_DDI:
 			if (WARN_ON(!HAS_DDI(to_i915(dev))))
-				break;
+				goto error;
 		case INTEL_OUTPUT_DP:
 		case INTEL_OUTPUT_HDMI:
 		case INTEL_OUTPUT_EDP:
-			port_mask = 1 << encoder->port;
-
-			/* the same port mustn't appear more than once */
-			if (used_ports & port_mask)
-				return false;
+			/* the same port must not appear more than once */
+			if ((used_ports | used_mst_ports) & port_mask)
+				goto error;
 
 			used_ports |= port_mask;
 			break;
+
 		case INTEL_OUTPUT_DP_MST:
-			used_mst_ports |=
-				1 << encoder->port;
+			/* can not mix MST and SST/HDMI on the same port */
+			if (used_ports & port_mask)
+				goto error;
+
+			used_mst_ports |= port_mask;
 			break;
+
 		default:
 			break;
 		}
 	}
+	ok = true;
+error:
 	drm_connector_list_iter_end(&conn_iter);
 
-	/* can't mix MST and SST/HDMI on the same port */
-	if (used_ports & used_mst_ports)
-		return false;
-
-	return true;
+	return ok;
 }
 
 static void
-- 
2.16.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux