aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-10-21 08:00:09 -0400
committerThierry Reding <treding@nvidia.com>2014-11-13 10:18:31 -0500
commit8fc8f7da9719c2d28fb32cdd74af9b6cd9bac20a (patch)
treef1d74b944c4205cd3941e4507d4aeb484f186718 /drivers/gpu/drm/tegra
parentc7679306a923c2feb383f709446c1110db1c56e4 (diff)
drm/tegra: Enable the hotplug interrupt only when necessary
The hotplug handling needs access to the DRM device, which only appears at ->init() time. Disable interrupts up until that time. Similarly, when an output is removed, disable the hotplug interrupt again because the DRM device (and with it the hotplug infrastructure) is going away. Also make sure to only access the DRM device if it's available. Given the above change for the hotplug interrupt this should really never happen, but the extra check doesn't hurt either. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r--drivers/gpu/drm/tegra/output.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index e6cfbde36f97..022462d3a413 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -183,7 +183,8 @@ static irqreturn_t hpd_irq(int irq, void *data)
183{ 183{
184 struct tegra_output *output = data; 184 struct tegra_output *output = data;
185 185
186 drm_helper_hpd_irq_event(output->connector.dev); 186 if (output->connector.dev)
187 drm_helper_hpd_irq_event(output->connector.dev);
187 188
188 return IRQ_HANDLED; 189 return IRQ_HANDLED;
189} 190}
@@ -255,6 +256,13 @@ int tegra_output_probe(struct tegra_output *output)
255 } 256 }
256 257
257 output->connector.polled = DRM_CONNECTOR_POLL_HPD; 258 output->connector.polled = DRM_CONNECTOR_POLL_HPD;
259
260 /*
261 * Disable the interrupt until the connector has been
262 * initialized to avoid a race in the hotplug interrupt
263 * handler.
264 */
265 disable_irq(output->hpd_irq);
258 } 266 }
259 267
260 return 0; 268 return 0;
@@ -320,10 +328,24 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
320 328
321 output->encoder.possible_crtcs = 0x3; 329 output->encoder.possible_crtcs = 0x3;
322 330
331 /*
332 * The connector is now registered and ready to receive hotplug events
333 * so the hotplug interrupt can be enabled.
334 */
335 if (gpio_is_valid(output->hpd_gpio))
336 enable_irq(output->hpd_irq);
337
323 return 0; 338 return 0;
324} 339}
325 340
326int tegra_output_exit(struct tegra_output *output) 341int tegra_output_exit(struct tegra_output *output)
327{ 342{
343 /*
344 * The connector is going away, so the interrupt must be disabled to
345 * prevent the hotplug interrupt handler from potentially crashing.
346 */
347 if (gpio_is_valid(output->hpd_gpio))
348 disable_irq(output->hpd_irq);
349
328 return 0; 350 return 0;
329} 351}