mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 18:24:14 +08:00
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. 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>
This commit is contained in:
parent
a6631bc8d6
commit
9bdbd0b911
@ -851,7 +851,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||||||
if (!crt)
|
if (!crt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
|
intel_connector = intel_connector_alloc();
|
||||||
if (!intel_connector) {
|
if (!intel_connector) {
|
||||||
kfree(crt);
|
kfree(crt);
|
||||||
return;
|
return;
|
||||||
|
@ -2101,7 +2101,7 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
|
|||||||
struct intel_connector *connector;
|
struct intel_connector *connector;
|
||||||
enum port port = intel_dig_port->port;
|
enum port port = intel_dig_port->port;
|
||||||
|
|
||||||
connector = kzalloc(sizeof(*connector), GFP_KERNEL);
|
connector = intel_connector_alloc();
|
||||||
if (!connector)
|
if (!connector)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -2120,7 +2120,7 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port)
|
|||||||
struct intel_connector *connector;
|
struct intel_connector *connector;
|
||||||
enum port port = intel_dig_port->port;
|
enum port port = intel_dig_port->port;
|
||||||
|
|
||||||
connector = kzalloc(sizeof(*connector), GFP_KERNEL);
|
connector = intel_connector_alloc();
|
||||||
if (!connector)
|
if (!connector)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -5685,6 +5685,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
|
/* Even simpler default implementation, if there's really no special case to
|
||||||
* consider. */
|
* consider. */
|
||||||
void intel_connector_dpms(struct drm_connector *connector, int mode)
|
void intel_connector_dpms(struct drm_connector *connector, int mode)
|
||||||
@ -13187,7 +13215,6 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_encoder *encoder;
|
struct intel_encoder *encoder;
|
||||||
struct drm_connector *connector;
|
|
||||||
bool dpd_is_edp = false;
|
bool dpd_is_edp = false;
|
||||||
|
|
||||||
intel_lvds_init(dev);
|
intel_lvds_init(dev);
|
||||||
@ -13323,39 +13350,6 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|||||||
if (SUPPORTS_TV(dev))
|
if (SUPPORTS_TV(dev))
|
||||||
intel_tv_init(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);
|
intel_psr_init(dev);
|
||||||
|
|
||||||
for_each_intel_encoder(dev, encoder) {
|
for_each_intel_encoder(dev, encoder) {
|
||||||
|
@ -5602,7 +5602,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
|
|||||||
if (!intel_dig_port)
|
if (!intel_dig_port)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
|
intel_connector = intel_connector_alloc();
|
||||||
if (!intel_connector) {
|
if (!intel_connector) {
|
||||||
kfree(intel_dig_port);
|
kfree(intel_dig_port);
|
||||||
return;
|
return;
|
||||||
|
@ -415,7 +415,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
|
|||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
|
intel_connector = intel_connector_alloc();
|
||||||
if (!intel_connector)
|
if (!intel_connector)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -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_control(struct drm_crtc *crtc, bool enable);
|
||||||
void intel_crtc_update_dpms(struct drm_crtc *crtc);
|
void intel_crtc_update_dpms(struct drm_crtc *crtc);
|
||||||
void intel_encoder_destroy(struct drm_encoder *encoder);
|
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);
|
void intel_connector_dpms(struct drm_connector *, int mode);
|
||||||
bool intel_connector_get_hw_state(struct intel_connector *connector);
|
bool intel_connector_get_hw_state(struct intel_connector *connector);
|
||||||
void intel_modeset_check_state(struct drm_device *dev);
|
void intel_modeset_check_state(struct drm_device *dev);
|
||||||
|
@ -1007,7 +1007,7 @@ void intel_dsi_init(struct drm_device *dev)
|
|||||||
if (!intel_dsi)
|
if (!intel_dsi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
|
intel_connector = intel_connector_alloc();
|
||||||
if (!intel_connector) {
|
if (!intel_connector) {
|
||||||
kfree(intel_dsi);
|
kfree(intel_dsi);
|
||||||
return;
|
return;
|
||||||
|
@ -469,7 +469,7 @@ void intel_dvo_init(struct drm_device *dev)
|
|||||||
if (!intel_dvo)
|
if (!intel_dvo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
|
intel_connector = intel_connector_alloc();
|
||||||
if (!intel_connector) {
|
if (!intel_connector) {
|
||||||
kfree(intel_dvo);
|
kfree(intel_dvo);
|
||||||
return;
|
return;
|
||||||
|
@ -1755,7 +1755,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
|
|||||||
if (!intel_dig_port)
|
if (!intel_dig_port)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
|
intel_connector = intel_connector_alloc();
|
||||||
if (!intel_connector) {
|
if (!intel_connector) {
|
||||||
kfree(intel_dig_port);
|
kfree(intel_dig_port);
|
||||||
return;
|
return;
|
||||||
|
@ -946,6 +946,12 @@ void intel_lvds_init(struct drm_device *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (intel_connector_init(&lvds_connector->base) < 0) {
|
||||||
|
kfree(lvds_connector);
|
||||||
|
kfree(lvds_encoder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
lvds_encoder->attached_connector = lvds_connector;
|
lvds_encoder->attached_connector = lvds_connector;
|
||||||
|
|
||||||
intel_encoder = &lvds_encoder->base;
|
intel_encoder = &lvds_encoder->base;
|
||||||
|
@ -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
|
static bool
|
||||||
intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
|
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);
|
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)
|
if (!intel_sdvo_connector)
|
||||||
return false;
|
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);
|
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)
|
if (!intel_sdvo_connector)
|
||||||
return false;
|
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);
|
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)
|
if (!intel_sdvo_connector)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1621,7 +1621,7 @@ intel_tv_init(struct drm_device *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
|
intel_connector = intel_connector_alloc();
|
||||||
if (!intel_connector) {
|
if (!intel_connector) {
|
||||||
kfree(intel_tv);
|
kfree(intel_tv);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user