aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2016-12-12 04:28:47 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2017-02-17 08:25:59 -0500
commit896bbc3ef1b065688163ce6c09c31e55fb4cd9f5 (patch)
tree3304d2c6587ae3d5451f25191ddf7daba3d4f546
parent8f1597c8f1a58830b67a033309e4b141ee99e379 (diff)
drm: exynos: Perform initialization/cleanup at probe/remove time
The drm driver .load() operation is prone to race conditions as it initializes the driver after registering the device nodes. Its usage is deprecated, inline it in the probe function and call drm_dev_alloc() and drm_dev_register() explicitly. For consistency inline the .unload() handler in the remove function as well. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Sean Paul <seanpaul@chromium.org> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Daniel Stone <daniels@collabora.com> Acked-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dpi.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c241
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c1
7 files changed, 126 insertions, 123 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 1ef0be338b85..b445b50a5dc4 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -101,7 +101,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
101 struct exynos_dp_device *dp = to_dp(plat_data); 101 struct exynos_dp_device *dp = to_dp(plat_data);
102 int ret; 102 int ret;
103 103
104 drm_connector_register(connector);
105 dp->connector = connector; 104 dp->connector = connector;
106 105
107 /* Pre-empt DP connector creation if there's a bridge */ 106 /* Pre-empt DP connector creation if there's a bridge */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index ad6b73c7fc59..3aab71a485ba 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -114,7 +114,6 @@ static int exynos_dpi_create_connector(struct drm_encoder *encoder)
114 } 114 }
115 115
116 drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs); 116 drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
117 drm_connector_register(connector);
118 drm_mode_connector_attach_encoder(connector, encoder); 117 drm_mode_connector_attach_encoder(connector, encoder);
119 118
120 return 0; 119 return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 035d02ecffcd..497714c8e970 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -40,118 +40,6 @@
40 40
41static struct device *exynos_drm_get_dma_device(void); 41static struct device *exynos_drm_get_dma_device(void);
42 42
43static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
44{
45 struct exynos_drm_private *private;
46 struct drm_encoder *encoder;
47 unsigned int clone_mask;
48 int cnt, ret;
49
50 private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
51 if (!private)
52 return -ENOMEM;
53
54 init_waitqueue_head(&private->wait);
55 spin_lock_init(&private->lock);
56
57 dev_set_drvdata(dev->dev, dev);
58 dev->dev_private = (void *)private;
59
60 /* the first real CRTC device is used for all dma mapping operations */
61 private->dma_dev = exynos_drm_get_dma_device();
62 if (!private->dma_dev) {
63 DRM_ERROR("no device found for DMA mapping operations.\n");
64 ret = -ENODEV;
65 goto err_free_private;
66 }
67 DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
68 dev_name(private->dma_dev));
69
70 /* create common IOMMU mapping for all devices attached to Exynos DRM */
71 ret = drm_create_iommu_mapping(dev);
72 if (ret < 0) {
73 DRM_ERROR("failed to create iommu mapping.\n");
74 goto err_free_private;
75 }
76
77 drm_mode_config_init(dev);
78
79 exynos_drm_mode_config_init(dev);
80
81 /* setup possible_clones. */
82 cnt = 0;
83 clone_mask = 0;
84 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
85 clone_mask |= (1 << (cnt++));
86
87 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
88 encoder->possible_clones = clone_mask;
89
90 platform_set_drvdata(dev->platformdev, dev);
91
92 /* Try to bind all sub drivers. */
93 ret = component_bind_all(dev->dev, dev);
94 if (ret)
95 goto err_mode_config_cleanup;
96
97 ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
98 if (ret)
99 goto err_unbind_all;
100
101 /* Probe non kms sub drivers and virtual display driver. */
102 ret = exynos_drm_device_subdrv_probe(dev);
103 if (ret)
104 goto err_cleanup_vblank;
105
106 drm_mode_config_reset(dev);
107
108 /*
109 * enable drm irq mode.
110 * - with irq_enabled = true, we can use the vblank feature.
111 *
112 * P.S. note that we wouldn't use drm irq handler but
113 * just specific driver own one instead because
114 * drm framework supports only one irq handler.
115 */
116 dev->irq_enabled = true;
117
118 /* init kms poll for handling hpd */
119 drm_kms_helper_poll_init(dev);
120
121 /* force connectors detection */
122 drm_helper_hpd_irq_event(dev);
123
124 return 0;
125
126err_cleanup_vblank:
127 drm_vblank_cleanup(dev);
128err_unbind_all:
129 component_unbind_all(dev->dev, dev);
130err_mode_config_cleanup:
131 drm_mode_config_cleanup(dev);
132 drm_release_iommu_mapping(dev);
133err_free_private:
134 kfree(private);
135
136 return ret;
137}
138
139static void exynos_drm_unload(struct drm_device *dev)
140{
141 exynos_drm_device_subdrv_remove(dev);
142
143 exynos_drm_fbdev_fini(dev);
144 drm_kms_helper_poll_fini(dev);
145
146 drm_vblank_cleanup(dev);
147 component_unbind_all(dev->dev, dev);
148 drm_mode_config_cleanup(dev);
149 drm_release_iommu_mapping(dev);
150
151 kfree(dev->dev_private);
152 dev->dev_private = NULL;
153}
154
155int exynos_atomic_check(struct drm_device *dev, 43int exynos_atomic_check(struct drm_device *dev,
156 struct drm_atomic_state *state) 44 struct drm_atomic_state *state)
157{ 45{
@@ -257,8 +145,6 @@ static const struct file_operations exynos_drm_driver_fops = {
257static struct drm_driver exynos_drm_driver = { 145static struct drm_driver exynos_drm_driver = {
258 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME 146 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
259 | DRIVER_ATOMIC | DRIVER_RENDER, 147 | DRIVER_ATOMIC | DRIVER_RENDER,
260 .load = exynos_drm_load,
261 .unload = exynos_drm_unload,
262 .open = exynos_drm_open, 148 .open = exynos_drm_open,
263 .preclose = exynos_drm_preclose, 149 .preclose = exynos_drm_preclose,
264 .lastclose = exynos_drm_lastclose, 150 .lastclose = exynos_drm_lastclose,
@@ -436,12 +322,135 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
436 322
437static int exynos_drm_bind(struct device *dev) 323static int exynos_drm_bind(struct device *dev)
438{ 324{
439 return drm_platform_init(&exynos_drm_driver, to_platform_device(dev)); 325 struct exynos_drm_private *private;
326 struct drm_encoder *encoder;
327 struct drm_device *drm;
328 unsigned int clone_mask;
329 int cnt, ret;
330
331 drm = drm_dev_alloc(&exynos_drm_driver, dev);
332 if (IS_ERR(drm))
333 return PTR_ERR(drm);
334
335 private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
336 if (!private) {
337 ret = -ENOMEM;
338 goto err_free_drm;
339 }
340
341 init_waitqueue_head(&private->wait);
342 spin_lock_init(&private->lock);
343
344 dev_set_drvdata(dev, drm);
345 drm->dev_private = (void *)private;
346
347 /* the first real CRTC device is used for all dma mapping operations */
348 private->dma_dev = exynos_drm_get_dma_device();
349 if (!private->dma_dev) {
350 DRM_ERROR("no device found for DMA mapping operations.\n");
351 ret = -ENODEV;
352 goto err_free_private;
353 }
354 DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
355 dev_name(private->dma_dev));
356
357 /* create common IOMMU mapping for all devices attached to Exynos DRM */
358 ret = drm_create_iommu_mapping(drm);
359 if (ret < 0) {
360 DRM_ERROR("failed to create iommu mapping.\n");
361 goto err_free_private;
362 }
363
364 drm_mode_config_init(drm);
365
366 exynos_drm_mode_config_init(drm);
367
368 /* setup possible_clones. */
369 cnt = 0;
370 clone_mask = 0;
371 list_for_each_entry(encoder, &drm->mode_config.encoder_list, head)
372 clone_mask |= (1 << (cnt++));
373
374 list_for_each_entry(encoder, &drm->mode_config.encoder_list, head)
375 encoder->possible_clones = clone_mask;
376
377 /* Try to bind all sub drivers. */
378 ret = component_bind_all(drm->dev, drm);
379 if (ret)
380 goto err_mode_config_cleanup;
381
382 ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
383 if (ret)
384 goto err_unbind_all;
385
386 /* Probe non kms sub drivers and virtual display driver. */
387 ret = exynos_drm_device_subdrv_probe(drm);
388 if (ret)
389 goto err_cleanup_vblank;
390
391 drm_mode_config_reset(drm);
392
393 /*
394 * enable drm irq mode.
395 * - with irq_enabled = true, we can use the vblank feature.
396 *
397 * P.S. note that we wouldn't use drm irq handler but
398 * just specific driver own one instead because
399 * drm framework supports only one irq handler.
400 */
401 drm->irq_enabled = true;
402
403 /* init kms poll for handling hpd */
404 drm_kms_helper_poll_init(drm);
405
406 /* force connectors detection */
407 drm_helper_hpd_irq_event(drm);
408
409 /* register the DRM device */
410 ret = drm_dev_register(drm, 0);
411 if (ret < 0)
412 goto err_cleanup_fbdev;
413
414 return 0;
415
416err_cleanup_fbdev:
417 exynos_drm_fbdev_fini(drm);
418 drm_kms_helper_poll_fini(drm);
419 exynos_drm_device_subdrv_remove(drm);
420err_cleanup_vblank:
421 drm_vblank_cleanup(drm);
422err_unbind_all:
423 component_unbind_all(drm->dev, drm);
424err_mode_config_cleanup:
425 drm_mode_config_cleanup(drm);
426 drm_release_iommu_mapping(drm);
427err_free_private:
428 kfree(private);
429err_free_drm:
430 drm_dev_unref(drm);
431
432 return ret;
440} 433}
441 434
442static void exynos_drm_unbind(struct device *dev) 435static void exynos_drm_unbind(struct device *dev)
443{ 436{
444 drm_put_dev(dev_get_drvdata(dev)); 437 struct drm_device *drm = dev_get_drvdata(dev);
438
439 drm_dev_unregister(drm);
440
441 exynos_drm_device_subdrv_remove(drm);
442
443 exynos_drm_fbdev_fini(drm);
444 drm_kms_helper_poll_fini(drm);
445
446 component_unbind_all(drm->dev, drm);
447 drm_mode_config_cleanup(drm);
448 drm_release_iommu_mapping(drm);
449
450 kfree(drm->dev_private);
451 drm->dev_private = NULL;
452
453 drm_dev_unref(drm);
445} 454}
446 455
447static const struct component_master_ops exynos_drm_ops = { 456static const struct component_master_ops exynos_drm_ops = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 812e2ec0761d..43a45abc524f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1587,7 +1587,6 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
1587 } 1587 }
1588 1588
1589 drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs); 1589 drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
1590 drm_connector_register(connector);
1591 drm_mode_connector_attach_encoder(connector, encoder); 1590 drm_mode_connector_attach_encoder(connector, encoder);
1592 1591
1593 return 0; 1592 return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index bcdb2720b68e..114ba4073524 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -120,7 +120,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
120 struct exynos_drm_gem *exynos_gem; 120 struct exynos_drm_gem *exynos_gem;
121 struct drm_device *dev = helper->dev; 121 struct drm_device *dev = helper->dev;
122 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 122 struct drm_mode_fb_cmd2 mode_cmd = { 0 };
123 struct platform_device *pdev = dev->platformdev;
124 unsigned long size; 123 unsigned long size;
125 int ret; 124 int ret;
126 125
@@ -143,7 +142,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
143 * memory area. 142 * memory area.
144 */ 143 */
145 if (IS_ERR(exynos_gem) && is_drm_iommu_supported(dev)) { 144 if (IS_ERR(exynos_gem) && is_drm_iommu_supported(dev)) {
146 dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n"); 145 dev_warn(dev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
147 exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, 146 exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG,
148 size); 147 size);
149 } 148 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 57fe514d5c5b..6bbb0ea8a6af 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -359,7 +359,6 @@ static int vidi_create_connector(struct drm_encoder *encoder)
359 } 359 }
360 360
361 drm_connector_helper_add(connector, &vidi_connector_helper_funcs); 361 drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
362 drm_connector_register(connector);
363 drm_mode_connector_attach_encoder(connector, encoder); 362 drm_mode_connector_attach_encoder(connector, encoder);
364 363
365 return 0; 364 return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 88ccc0469316..74f725067140 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -921,7 +921,6 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
921 } 921 }
922 922
923 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs); 923 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
924 drm_connector_register(connector);
925 drm_mode_connector_attach_encoder(connector, encoder); 924 drm_mode_connector_attach_encoder(connector, encoder);
926 925
927 if (hdata->bridge) { 926 if (hdata->bridge) {