diff options
author | Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> | 2015-04-10 03:59:10 -0400 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2015-04-13 08:21:21 -0400 |
commit | 08d9bc920d465bbbbd762cac9383249c19bf69a2 (patch) | |
tree | ecd2ce9d8b5a03e9ce970fbef1a43a32bf89250e | |
parent | af8fcb9c58f1b2f02ddc04ba64710aaa52da00db (diff) |
drm/i915: Allocate connector state together with the connectors
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.
Broken by
commit 944b0c76575753da5a332aab0a1d8c6df65a076b
Author: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Date: Fri Mar 20 16:18:07 2015 +0200
drm/i915: Copy the staged connector config to the legacy atomic state
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>
Reported-and-tested-by: Nicolas Kalkhof <nkalkhof@web.de>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 62 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp_mst.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dsi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dvo.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 2 |
12 files changed, 64 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6095a998bdac..515d7123785d 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) | |||
851 | if (!crt) | 851 | if (!crt) |
852 | return; | 852 | return; |
853 | 853 | ||
854 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | 854 | intel_connector = intel_connector_alloc(); |
855 | if (!intel_connector) { | 855 | if (!intel_connector) { |
856 | kfree(crt); | 856 | kfree(crt); |
857 | return; | 857 | return; |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 47b9307da24b..3eb0efc2dd0d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -2200,7 +2200,7 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) | |||
2200 | struct intel_connector *connector; | 2200 | struct intel_connector *connector; |
2201 | enum port port = intel_dig_port->port; | 2201 | enum port port = intel_dig_port->port; |
2202 | 2202 | ||
2203 | connector = kzalloc(sizeof(*connector), GFP_KERNEL); | 2203 | connector = intel_connector_alloc(); |
2204 | if (!connector) | 2204 | if (!connector) |
2205 | return NULL; | 2205 | return NULL; |
2206 | 2206 | ||
@@ -2219,7 +2219,7 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) | |||
2219 | struct intel_connector *connector; | 2219 | struct intel_connector *connector; |
2220 | enum port port = intel_dig_port->port; | 2220 | enum port port = intel_dig_port->port; |
2221 | 2221 | ||
2222 | connector = kzalloc(sizeof(*connector), GFP_KERNEL); | 2222 | connector = intel_connector_alloc(); |
2223 | if (!connector) | 2223 | if (!connector) |
2224 | return NULL; | 2224 | return NULL; |
2225 | 2225 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 75955fee6d24..5b32b682bc3e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -5636,6 +5636,34 @@ static void intel_connector_check_state(struct intel_connector *connector) | |||
5636 | } | 5636 | } |
5637 | } | 5637 | } |
5638 | 5638 | ||
5639 | int intel_connector_init(struct intel_connector *connector) | ||
5640 | { | ||
5641 | struct drm_connector_state *connector_state; | ||
5642 | |||
5643 | connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL); | ||
5644 | if (!connector_state) | ||
5645 | return -ENOMEM; | ||
5646 | |||
5647 | connector->base.state = connector_state; | ||
5648 | return 0; | ||
5649 | } | ||
5650 | |||
5651 | struct intel_connector *intel_connector_alloc(void) | ||
5652 | { | ||
5653 | struct intel_connector *connector; | ||
5654 | |||
5655 | connector = kzalloc(sizeof *connector, GFP_KERNEL); | ||
5656 | if (!connector) | ||
5657 | return NULL; | ||
5658 | |||
5659 | if (intel_connector_init(connector) < 0) { | ||
5660 | kfree(connector); | ||
5661 | return NULL; | ||
5662 | } | ||
5663 | |||
5664 | return connector; | ||
5665 | } | ||
5666 | |||
5639 | /* Even simpler default implementation, if there's really no special case to | 5667 | /* Even simpler default implementation, if there's really no special case to |
5640 | * consider. */ | 5668 | * consider. */ |
5641 | void intel_connector_dpms(struct drm_connector *connector, int mode) | 5669 | void intel_connector_dpms(struct drm_connector *connector, int mode) |
@@ -13003,7 +13031,6 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
13003 | { | 13031 | { |
13004 | struct drm_i915_private *dev_priv = dev->dev_private; | 13032 | struct drm_i915_private *dev_priv = dev->dev_private; |
13005 | struct intel_encoder *encoder; | 13033 | struct intel_encoder *encoder; |
13006 | struct drm_connector *connector; | ||
13007 | bool dpd_is_edp = false; | 13034 | bool dpd_is_edp = false; |
13008 | 13035 | ||
13009 | intel_lvds_init(dev); | 13036 | intel_lvds_init(dev); |
@@ -13139,39 +13166,6 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
13139 | if (SUPPORTS_TV(dev)) | 13166 | if (SUPPORTS_TV(dev)) |
13140 | intel_tv_init(dev); | 13167 | intel_tv_init(dev); |
13141 | 13168 | ||
13142 | /* | ||
13143 | * FIXME: We don't have full atomic support yet, but we want to be | ||
13144 | * able to enable/test plane updates via the atomic interface in the | ||
13145 | * meantime. However as soon as we flip DRIVER_ATOMIC on, the DRM core | ||
13146 | * will take some atomic codepaths to lookup properties during | ||
13147 | * drmModeGetConnector() that unconditionally dereference | ||
13148 | * connector->state. | ||
13149 | * | ||
13150 | * We create a dummy connector state here for each connector to ensure | ||
13151 | * the DRM core doesn't try to dereference a NULL connector->state. | ||
13152 | * The actual connector properties will never be updated or contain | ||
13153 | * useful information, but since we're doing this specifically for | ||
13154 | * testing/debug of the plane operations (and only when a specific | ||
13155 | * kernel module option is given), that shouldn't really matter. | ||
13156 | * | ||
13157 | * We are also relying on these states to convert the legacy mode set | ||
13158 | * to use a drm_atomic_state struct. The states are kept consistent | ||
13159 | * with actual state, so that it is safe to rely on that instead of | ||
13160 | * the staged config. | ||
13161 | * | ||
13162 | * Once atomic support for crtc's + connectors lands, this loop should | ||
13163 | * be removed since we'll be setting up real connector state, which | ||
13164 | * will contain Intel-specific properties. | ||
13165 | */ | ||
13166 | list_for_each_entry(connector, | ||
13167 | &dev->mode_config.connector_list, | ||
13168 | head) { | ||
13169 | if (!WARN_ON(connector->state)) { | ||
13170 | connector->state = kzalloc(sizeof(*connector->state), | ||
13171 | GFP_KERNEL); | ||
13172 | } | ||
13173 | } | ||
13174 | |||
13175 | intel_psr_init(dev); | 13169 | intel_psr_init(dev); |
13176 | 13170 | ||
13177 | for_each_intel_encoder(dev, encoder) { | 13171 | 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 60e8d5d77fc5..d0237102c27e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -5590,7 +5590,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) | |||
5590 | if (!intel_dig_port) | 5590 | if (!intel_dig_port) |
5591 | return; | 5591 | return; |
5592 | 5592 | ||
5593 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | 5593 | intel_connector = intel_connector_alloc(); |
5594 | if (!intel_connector) { | 5594 | if (!intel_connector) { |
5595 | kfree(intel_dig_port); | 5595 | kfree(intel_dig_port); |
5596 | return; | 5596 | return; |
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 5329c855acce..5cb47482d29f 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 | |||
415 | struct drm_connector *connector; | 415 | struct drm_connector *connector; |
416 | int i; | 416 | int i; |
417 | 417 | ||
418 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | 418 | intel_connector = intel_connector_alloc(); |
419 | if (!intel_connector) | 419 | if (!intel_connector) |
420 | return NULL; | 420 | return NULL; |
421 | 421 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6036e3b73b7b..744db4d0c68f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -930,6 +930,8 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc); | |||
930 | void intel_crtc_control(struct drm_crtc *crtc, bool enable); | 930 | void intel_crtc_control(struct drm_crtc *crtc, bool enable); |
931 | void intel_crtc_update_dpms(struct drm_crtc *crtc); | 931 | void intel_crtc_update_dpms(struct drm_crtc *crtc); |
932 | void intel_encoder_destroy(struct drm_encoder *encoder); | 932 | void intel_encoder_destroy(struct drm_encoder *encoder); |
933 | int intel_connector_init(struct intel_connector *); | ||
934 | struct intel_connector *intel_connector_alloc(void); | ||
933 | void intel_connector_dpms(struct drm_connector *, int mode); | 935 | void intel_connector_dpms(struct drm_connector *, int mode); |
934 | bool intel_connector_get_hw_state(struct intel_connector *connector); | 936 | bool intel_connector_get_hw_state(struct intel_connector *connector); |
935 | void intel_modeset_check_state(struct drm_device *dev); | 937 | 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 572251e9810b..51966426addf 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) | |||
1007 | if (!intel_dsi) | 1007 | if (!intel_dsi) |
1008 | return; | 1008 | return; |
1009 | 1009 | ||
1010 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | 1010 | intel_connector = intel_connector_alloc(); |
1011 | if (!intel_connector) { | 1011 | if (!intel_connector) { |
1012 | kfree(intel_dsi); | 1012 | kfree(intel_dsi); |
1013 | return; | 1013 | return; |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 4ccd6c3f133d..770040ff486e 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) | |||
469 | if (!intel_dvo) | 469 | if (!intel_dvo) |
470 | return; | 470 | return; |
471 | 471 | ||
472 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | 472 | intel_connector = intel_connector_alloc(); |
473 | if (!intel_connector) { | 473 | if (!intel_connector) { |
474 | kfree(intel_dvo); | 474 | kfree(intel_dvo); |
475 | return; | 475 | return; |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index bfabd5fd9334..bfbe07b6ddce 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -1750,7 +1750,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) | |||
1750 | if (!intel_dig_port) | 1750 | if (!intel_dig_port) |
1751 | return; | 1751 | return; |
1752 | 1752 | ||
1753 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | 1753 | intel_connector = intel_connector_alloc(); |
1754 | if (!intel_connector) { | 1754 | if (!intel_connector) { |
1755 | kfree(intel_dig_port); | 1755 | kfree(intel_dig_port); |
1756 | return; | 1756 | return; |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 06d2da336f7c..5abda1d2c018 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) | |||
946 | return; | 946 | return; |
947 | } | 947 | } |
948 | 948 | ||
949 | if (intel_connector_init(&lvds_connector->base) < 0) { | ||
950 | kfree(lvds_connector); | ||
951 | kfree(lvds_encoder); | ||
952 | return; | ||
953 | } | ||
954 | |||
949 | lvds_encoder->attached_connector = lvds_connector; | 955 | lvds_encoder->attached_connector = lvds_connector; |
950 | 956 | ||
951 | intel_encoder = &lvds_encoder->base; | 957 | intel_encoder = &lvds_encoder->base; |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f5b7e1e7c5e0..e87d2f418de4 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -2426,6 +2426,22 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo, | |||
2426 | } | 2426 | } |
2427 | } | 2427 | } |
2428 | 2428 | ||
2429 | static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void) | ||
2430 | { | ||
2431 | struct intel_sdvo_connector *sdvo_connector; | ||
2432 | |||
2433 | sdvo_connector = kzalloc(sizeof(*sdvo_connector), GFP_KERNEL); | ||
2434 | if (!sdvo_connector) | ||
2435 | return NULL; | ||
2436 | |||
2437 | if (intel_connector_init(&sdvo_connector->base) < 0) { | ||
2438 | kfree(sdvo_connector); | ||
2439 | return NULL; | ||
2440 | } | ||
2441 | |||
2442 | return sdvo_connector; | ||
2443 | } | ||
2444 | |||
2429 | static bool | 2445 | static bool |
2430 | intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | 2446 | intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) |
2431 | { | 2447 | { |
@@ -2437,7 +2453,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
2437 | 2453 | ||
2438 | DRM_DEBUG_KMS("initialising DVI device %d\n", device); | 2454 | DRM_DEBUG_KMS("initialising DVI device %d\n", device); |
2439 | 2455 | ||
2440 | intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); | 2456 | intel_sdvo_connector = intel_sdvo_connector_alloc(); |
2441 | if (!intel_sdvo_connector) | 2457 | if (!intel_sdvo_connector) |
2442 | return false; | 2458 | return false; |
2443 | 2459 | ||
@@ -2491,7 +2507,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) | |||
2491 | 2507 | ||
2492 | DRM_DEBUG_KMS("initialising TV type %d\n", type); | 2508 | DRM_DEBUG_KMS("initialising TV type %d\n", type); |
2493 | 2509 | ||
2494 | intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); | 2510 | intel_sdvo_connector = intel_sdvo_connector_alloc(); |
2495 | if (!intel_sdvo_connector) | 2511 | if (!intel_sdvo_connector) |
2496 | return false; | 2512 | return false; |
2497 | 2513 | ||
@@ -2570,7 +2586,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) | |||
2570 | 2586 | ||
2571 | DRM_DEBUG_KMS("initialising LVDS device %d\n", device); | 2587 | DRM_DEBUG_KMS("initialising LVDS device %d\n", device); |
2572 | 2588 | ||
2573 | intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); | 2589 | intel_sdvo_connector = intel_sdvo_connector_alloc(); |
2574 | if (!intel_sdvo_connector) | 2590 | if (!intel_sdvo_connector) |
2575 | return false; | 2591 | return false; |
2576 | 2592 | ||
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index bc1d9d740904..8b9d325bda3c 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) | |||
1621 | return; | 1621 | return; |
1622 | } | 1622 | } |
1623 | 1623 | ||
1624 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | 1624 | intel_connector = intel_connector_alloc(); |
1625 | if (!intel_connector) { | 1625 | if (!intel_connector) { |
1626 | kfree(intel_tv); | 1626 | kfree(intel_tv); |
1627 | return; | 1627 | return; |