Skip to contentSkip to conversation

drm/gma500: fix i2c adapter hang and leaks

PATCH In review Johan Hovold 2 participants 5 messages May 8 – May 13

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover drm/gma500: fix i2c adapter hang and leaks

I stumbled over these when looking into i2c lifetime issues.

Note that the allocated adapter (or looked up reference) appears to be leaking on successful LVDS init as well. Not sure if it matters.

Johan

Johan Hovold (3):
drm/gma500/oaktrail_hdmi: fix i2c adapter leak on setup drm/gma500/oaktrail_lvds: fix hang on init failure drm/gma500/oaktrail_lvds: fix i2c adapter leaks on init

 drivers/gpu/drm/gma500/oaktrail_hdmi.c | 1 +
 drivers/gpu/drm/gma500/oaktrail_lvds.c | 9 +++++++--
 2 files changed, 8 insertions(+), 2 deletions(-)
Signature · 1 line
2.53.0
#1 lore raw

PATCH 1/3 drm/gma500/oaktrail_hdmi: fix i2c adapter leak on setup

Make sure to drop the reference taken to the I2C adapter (and its module) when setting up HDMI to allow the adapter to be deregistered.

Fixes 1b082ccf5901 ("gma500: Add Oaktrail support")
---
 drivers/gpu/drm/gma500/oaktrail_hdmi.c | 1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/gma500/oaktrail_hdmi.c +1 -0
index 58d7e191fd56..403d21cbb3a2 100644
@@ -580,6 +580,7 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
 	} else {
 		edid = (struct edid *)raw_edid;
 		/* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
+		i2c_put_adapter(i2c_adap);
 	}
 
 	if (edid) {
Signature · 1 line
2.53.0
#2 lore raw

PATCH 2/3 drm/gma500/oaktrail_lvds: fix hang on init failure

In reply to Johan Hovold

The LVDS init code looks up an I2C adapter using i2c_get_adapter() and tries to read the EDID before falling back to allocating and registering its own adapter.

The error handling does not separate these cases so on a late init failure it will try to deregister and free also an adapter that had previously been registered. Since i2c_get_adapter() takes another reference to the adapter, deregistration hangs indefinitely while waiting for the reference to be released.

Fix this by only destroying adapters allocated during LVDS init on errors.

Fixes a57ebfc0b4da ("drm/gma500: Make oaktrail lvds use ddc adapter from drm_connector")
Cc Patrik Jakobsson <[email protected]>
---
 drivers/gpu/drm/gma500/oaktrail_lvds.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/gma500/oaktrail_lvds.c +3 -2
index 884d324f0044..983cc60a1e69 100644
@@ -293,7 +293,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
 {
 	struct gma_encoder *gma_encoder;
 	struct gma_connector *gma_connector;
-	struct gma_i2c_chan *ddc_bus;
+	struct gma_i2c_chan *ddc_bus = NULL;
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
 	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
@@ -421,7 +421,8 @@ void oaktrail_lvds_init(struct drm_device *dev,
 
 err_unlock:
 	mutex_unlock(&dev->mode_config.mutex);
-	gma_i2c_destroy(to_gma_i2c_chan(connector->ddc));
+	if (!IS_ERR_OR_NULL(ddc_bus))
+		gma_i2c_destroy(ddc_bus);
 	drm_encoder_cleanup(encoder);
 err_connector_cleanup:
 	drm_connector_cleanup(connector);
Signature · 1 line
2.53.0
#3 lore raw

PATCH 3/3 drm/gma500/oaktrail_lvds: fix i2c adapter leaks on init

In reply to Johan Hovold

The LVDS init code looks up an I2C adapter using i2c_get_adapter() and tries to read the EDID before falling back to allocating and registering its own adapter.

Make sure to drop the references taken by i2c_get_adapter() when falling back to allocating an adapter as well as on late errors to allow the looked up adapter to be deregistered.

Fixes 1b082ccf5901 ("gma500: Add Oaktrail support")
---
 drivers/gpu/drm/gma500/oaktrail_lvds.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/gpu/drm/gma500/oaktrail_lvds.c +4 -0
index 983cc60a1e69..e194d0cce067 100644
@@ -367,6 +367,8 @@ void oaktrail_lvds_init(struct drm_device *dev,
 	if (edid == NULL && dev_priv->lpc_gpio_base) {
 		ddc_bus = oaktrail_lvds_i2c_init(dev);
 		if (!IS_ERR(ddc_bus)) {
+			if (i2c_adap)
+				i2c_put_adapter(i2c_adap);
 			i2c_adap = &ddc_bus->base;
 			edid = drm_get_edid(connector, i2c_adap);
 		}
@@ -423,6 +425,8 @@ void oaktrail_lvds_init(struct drm_device *dev,
 	mutex_unlock(&dev->mode_config.mutex);
 	if (!IS_ERR_OR_NULL(ddc_bus))
 		gma_i2c_destroy(ddc_bus);
+	else if (i2c_adap)
+		i2c_put_adapter(i2c_adap);
 	drm_encoder_cleanup(encoder);
 err_connector_cleanup:
 	drm_connector_cleanup(connector);
Signature · 1 line
2.53.0
maintainer
#4 lore raw
In reply to Johan Hovold
Quoted 5 lines · Johan Hovold

I stumbled over these when looking into i2c lifetime issues.

Note that the allocated adapter (or looked up reference) appears to be leaking on successful LVDS init as well. Not sure if it matters.

Hi Johan,

Feel free to fix the leaking adapter if you have the time. Otherwise I'll put it on my todo-list.

All fixes look good to me. Applied to drm-misc-fixes.

Thanks
Patrik

Quoted 16 lines

Johan

Johan Hovold (3):
drm/gma500/oaktrail_hdmi: fix i2c adapter leak on setup drm/gma500/oaktrail_lvds: fix hang on init failure drm/gma500/oaktrail_lvds: fix i2c adapter leaks on init

 drivers/gpu/drm/gma500/oaktrail_hdmi.c | 1 +
 drivers/gpu/drm/gma500/oaktrail_lvds.c | 9 +++++++--
 2 files changed, 8 insertions(+), 2 deletions(-)

--
2.53.0