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; |
