Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08d9bc92 authored by Ander Conselvan de Oliveira's avatar Ander Conselvan de Oliveira Committed by Jani Nikula
Browse files

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 944b0c76
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: default avatarAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reported-and-tested-by: default avatarNicolas Kalkhof <nkalkhof@web.de>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
parent af8fcb9c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -2200,7 +2200,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;

@@ -2219,7 +2219,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;

+28 −34
Original line number Diff line number Diff line
@@ -5636,6 +5636,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)
@@ -13003,7 +13031,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);
@@ -13139,39 +13166,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) {
+1 −1
Original line number Diff line number Diff line
@@ -5590,7 +5590,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;
+1 −1
Original line number Diff line number Diff line
@@ -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;

Loading