diff mbox

drm/i915: Allocate connector state together with the connectors

Message ID 1428652750-7978-1-git-send-email-ander.conselvan.de.oliveira@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ander Conselvan de Oliveira April 10, 2015, 7:59 a.m. UTC
Connector states were being allocated in intel_setup_outputs() in loop
over all connectors. That meant hot-added connectors would have a NULL
state. Since the change to use a struct drm_atomic_state for the legacy
modeset, connector states are necessary for the i915 driver to function
properly, so that would lead to oopses.

v2: Fix test for intel_connector_init() success in lvds and sdvo (PRTS)

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
---

Hi Nicolas,

(Seems like I dropped you from Cc when sending v1, sorry about that)

Could you please test if this patch solves the issue?

Thanks,
Ander


 drivers/gpu/drm/i915/intel_crt.c     |  2 +-
 drivers/gpu/drm/i915/intel_ddi.c     |  4 +--
 drivers/gpu/drm/i915/intel_display.c | 62 ++++++++++++++++--------------------
 drivers/gpu/drm/i915/intel_dp.c      |  2 +-
 drivers/gpu/drm/i915/intel_dp_mst.c  |  2 +-
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 drivers/gpu/drm/i915/intel_dsi.c     |  2 +-
 drivers/gpu/drm/i915/intel_dvo.c     |  2 +-
 drivers/gpu/drm/i915/intel_hdmi.c    |  2 +-
 drivers/gpu/drm/i915/intel_lvds.c    |  6 ++++
 drivers/gpu/drm/i915/intel_sdvo.c    | 22 +++++++++++--
 drivers/gpu/drm/i915/intel_tv.c      |  2 +-
 12 files changed, 64 insertions(+), 46 deletions(-)

Comments

Shuang He April 10, 2015, 11:10 a.m. UTC | #1
Tested-By: Intel Graphics QA PRTS (Patch Regression Test System Contact: shuang.he@intel.com)
Task id: 6168
-------------------------------------Summary-------------------------------------
Platform          Delta          drm-intel-nightly          Series Applied
PNV                 -7              276/276              269/276
ILK                                  301/301              301/301
SNB                                  316/316              316/316
IVB                                  328/328              328/328
BYT                                  285/285              285/285
HSW                                  394/394              394/394
BDW                                  321/321              321/321
-------------------------------------Detailed-------------------------------------
Platform  Test                                drm-intel-nightly          Series Applied
*PNV  igt@gem_tiled_pread_pwrite      PASS(2)      FAIL(1)PASS(1)
 PNV  igt@gem_userptr_blits@coherency-sync      CRASH(1)PASS(1)      CRASH(2)
 PNV  igt@gem_userptr_blits@coherency-unsync      CRASH(1)PASS(1)      CRASH(2)
 PNV  igt@gen3_render_linear_blits      FAIL(1)PASS(1)      FAIL(2)
 PNV  igt@gen3_render_mixed_blits      FAIL(1)PASS(1)      FAIL(2)
 PNV  igt@gen3_render_tiledx_blits      FAIL(1)PASS(1)      FAIL(2)
 PNV  igt@gen3_render_tiledy_blits      FAIL(1)PASS(1)      FAIL(2)
Note: You need to pay more attention to line start with '*'
Nicolas Kalkhof April 11, 2015, 6:23 a.m. UTC | #2
Hello,

it seems I got kicked off Cc. Anyway I can confirm that the supplied patch works an I can hotplug to my docking station and switch between DP/eDP without Oops. :)

Thanks for the swift help!

Kind Regards
Daniel Vetter April 13, 2015, 9:24 a.m. UTC | #3
On Sat, Apr 11, 2015 at 08:23:06AM +0200, Nicolas Kalkhof wrote:
> Hello,
> 
> it seems I got kicked off Cc. Anyway I can confirm that the supplied
> patch works an I can hotplug to my docking station and switch between
> DP/eDP without Oops. :)

Thanks for the test feedback, patch applied.
-Daniel
Nicolas Kalkhof May 8, 2015, 10:44 a.m. UTC | #4
Hello,
 
the kernel oops reported back in April (http://lists.freedesktop.org/archives/intel-gfx/2015-April/064066.html) is back resulting in the same oops as soon as I connect my Laptop to its docking station or boot with docking already connected. The issue was introduced again somewhere between commit
 
79114e880c84257bfe5581a84578e84a79f35bac[http://cgit.freedesktop.org/drm-intel/commit/?id=79114e880c84257bfe5581a84578e84a79f35bac] 2015-05-07 07:33:05
 
and
 
e6d052f03c23e5d2c29d55d88666a6502fa15c90[http://cgit.freedesktop.org/drm-intel/commit/?id=e6d052f03c23e5d2c29d55d88666a6502fa15c90] 2015-05-07 16:14:32
 
In between were a lot of drm patches however I currently don't have the time to bisect the code down to the bad commit. Hops this helps to pinpoint somewhere near to the issue??!

Regards

 

Gesendet: Montag, 13. April 2015 um 11:24 Uhr
Von: "Daniel Vetter" <daniel@ffwll.ch>
An: "Nicolas Kalkhof" <nkalkhof@web.de>
Cc: ander.conselvan.de.oliveira@intel.com, intel-gfx@lists.freedesktop.org
Betreff: Re: [Intel-gfx] [PATCH] drm/i915: Allocate connector state together with the connectors
On Sat, Apr 11, 2015 at 08:23:06AM +0200, Nicolas Kalkhof wrote:
> Hello,
>
> it seems I got kicked off Cc. Anyway I can confirm that the supplied
> patch works an I can hotplug to my docking station and switch between
> DP/eDP without Oops. :)

Thanks for the test feedback, patch applied.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch[http://blog.ffwll.ch]
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index fa5699c..93bb515 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -851,7 +851,7 @@  void intel_crt_init(struct drm_device *dev)
 	if (!crt)
 		return;
 
-	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	intel_connector = intel_connector_alloc();
 	if (!intel_connector) {
 		kfree(crt);
 		return;
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 8c692d8..486f6fa 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2101,7 +2101,7 @@  intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
 	struct intel_connector *connector;
 	enum port port = intel_dig_port->port;
 
-	connector = kzalloc(sizeof(*connector), GFP_KERNEL);
+	connector = intel_connector_alloc();
 	if (!connector)
 		return NULL;
 
@@ -2120,7 +2120,7 @@  intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port)
 	struct intel_connector *connector;
 	enum port port = intel_dig_port->port;
 
-	connector = kzalloc(sizeof(*connector), GFP_KERNEL);
+	connector = intel_connector_alloc();
 	if (!connector)
 		return NULL;
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bc8e221..2263a71 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5658,6 +5658,34 @@  static void intel_connector_check_state(struct intel_connector *connector)
 	}
 }
 
+int intel_connector_init(struct intel_connector *connector)
+{
+	struct drm_connector_state *connector_state;
+
+	connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL);
+	if (!connector_state)
+		return -ENOMEM;
+
+	connector->base.state = connector_state;
+	return 0;
+}
+
+struct intel_connector *intel_connector_alloc(void)
+{
+	struct intel_connector *connector;
+
+	connector = kzalloc(sizeof *connector, GFP_KERNEL);
+	if (!connector)
+		return NULL;
+
+	if (intel_connector_init(connector) < 0) {
+		kfree(connector);
+		return NULL;
+	}
+
+	return connector;
+}
+
 /* Even simpler default implementation, if there's really no special case to
  * consider. */
 void intel_connector_dpms(struct drm_connector *connector, int mode)
@@ -13135,7 +13163,6 @@  static void intel_setup_outputs(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_encoder *encoder;
-	struct drm_connector *connector;
 	bool dpd_is_edp = false;
 
 	intel_lvds_init(dev);
@@ -13271,39 +13298,6 @@  static void intel_setup_outputs(struct drm_device *dev)
 	if (SUPPORTS_TV(dev))
 		intel_tv_init(dev);
 
-	/*
-	 * FIXME:  We don't have full atomic support yet, but we want to be
-	 * able to enable/test plane updates via the atomic interface in the
-	 * meantime.  However as soon as we flip DRIVER_ATOMIC on, the DRM core
-	 * will take some atomic codepaths to lookup properties during
-	 * drmModeGetConnector() that unconditionally dereference
-	 * connector->state.
-	 *
-	 * We create a dummy connector state here for each connector to ensure
-	 * the DRM core doesn't try to dereference a NULL connector->state.
-	 * The actual connector properties will never be updated or contain
-	 * useful information, but since we're doing this specifically for
-	 * testing/debug of the plane operations (and only when a specific
-	 * kernel module option is given), that shouldn't really matter.
-	 *
-	 * We are also relying on these states to convert the legacy mode set
-	 * to use a drm_atomic_state struct. The states are kept consistent
-	 * with actual state, so that it is safe to rely on that instead of
-	 * the staged config.
-	 *
-	 * Once atomic support for crtc's + connectors lands, this loop should
-	 * be removed since we'll be setting up real connector state, which
-	 * will contain Intel-specific properties.
-	 */
-	list_for_each_entry(connector,
-			    &dev->mode_config.connector_list,
-			    head) {
-		if (!WARN_ON(connector->state)) {
-			connector->state = kzalloc(sizeof(*connector->state),
-						   GFP_KERNEL);
-		}
-	}
-
 	intel_psr_init(dev);
 
 	for_each_intel_encoder(dev, encoder) {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1b87969..589cd92 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5602,7 +5602,7 @@  intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	if (!intel_dig_port)
 		return;
 
-	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	intel_connector = intel_connector_alloc();
 	if (!intel_connector) {
 		kfree(intel_dig_port);
 		return;
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index adcc5e6..7335089 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -415,7 +415,7 @@  static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
 	struct drm_connector *connector;
 	int i;
 
-	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	intel_connector = intel_connector_alloc();
 	if (!intel_connector)
 		return NULL;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 686014b..e07dc4a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -928,6 +928,8 @@  void intel_crtc_restore_mode(struct drm_crtc *crtc);
 void intel_crtc_control(struct drm_crtc *crtc, bool enable);
 void intel_crtc_update_dpms(struct drm_crtc *crtc);
 void intel_encoder_destroy(struct drm_encoder *encoder);
+int intel_connector_init(struct intel_connector *);
+struct intel_connector *intel_connector_alloc(void);
 void intel_connector_dpms(struct drm_connector *, int mode);
 bool intel_connector_get_hw_state(struct intel_connector *connector);
 void intel_modeset_check_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 572251e..5196642 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -1007,7 +1007,7 @@  void intel_dsi_init(struct drm_device *dev)
 	if (!intel_dsi)
 		return;
 
-	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	intel_connector = intel_connector_alloc();
 	if (!intel_connector) {
 		kfree(intel_dsi);
 		return;
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 9a27ec7..7c9f852 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -469,7 +469,7 @@  void intel_dvo_init(struct drm_device *dev)
 	if (!intel_dvo)
 		return;
 
-	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	intel_connector = intel_connector_alloc();
 	if (!intel_connector) {
 		kfree(intel_dvo);
 		return;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 26222e6..02252d9 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1755,7 +1755,7 @@  void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 	if (!intel_dig_port)
 		return;
 
-	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	intel_connector = intel_connector_alloc();
 	if (!intel_connector) {
 		kfree(intel_dig_port);
 		return;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 314a5d5..9a9df0f 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -946,6 +946,12 @@  void intel_lvds_init(struct drm_device *dev)
 		return;
 	}
 
+	if (intel_connector_init(&lvds_connector->base) < 0) {
+		kfree(lvds_connector);
+		kfree(lvds_encoder);
+		return;
+	}
+
 	lvds_encoder->attached_connector = lvds_connector;
 
 	intel_encoder = &lvds_encoder->base;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index b121796..10cd332 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2427,6 +2427,22 @@  intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
 	}
 }
 
+static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
+{
+	struct intel_sdvo_connector *sdvo_connector;
+
+	sdvo_connector = kzalloc(sizeof(*sdvo_connector), GFP_KERNEL);
+	if (!sdvo_connector)
+		return NULL;
+
+	if (intel_connector_init(&sdvo_connector->base) < 0) {
+		kfree(sdvo_connector);
+		return NULL;
+	}
+
+	return sdvo_connector;
+}
+
 static bool
 intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 {
@@ -2438,7 +2454,7 @@  intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 
 	DRM_DEBUG_KMS("initialising DVI device %d\n", device);
 
-	intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
+	intel_sdvo_connector = intel_sdvo_connector_alloc();
 	if (!intel_sdvo_connector)
 		return false;
 
@@ -2492,7 +2508,7 @@  intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
 	DRM_DEBUG_KMS("initialising TV type %d\n", type);
 
-	intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
+	intel_sdvo_connector = intel_sdvo_connector_alloc();
 	if (!intel_sdvo_connector)
 		return false;
 
@@ -2571,7 +2587,7 @@  intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 
 	DRM_DEBUG_KMS("initialising LVDS device %d\n", device);
 
-	intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
+	intel_sdvo_connector = intel_sdvo_connector_alloc();
 	if (!intel_sdvo_connector)
 		return false;
 
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index bc1d9d7..8b9d325 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1621,7 +1621,7 @@  intel_tv_init(struct drm_device *dev)
 		return;
 	}
 
-	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+	intel_connector = intel_connector_alloc();
 	if (!intel_connector) {
 		kfree(intel_tv);
 		return;