Skip to content

Commit 5ec9d83

Browse files
Laurent Pinchartgregkh
authored andcommitted
drm: rcar-du: Perform initialization/cleanup at probe/remove time
commit c1d4b38 upstream. 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 <[email protected]> Acked-by: Daniel Vetter <[email protected]> Signed-off-by: Thong Ho <[email protected]> Signed-off-by: Nhan Nguyen <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 0354df9 commit 5ec9d83

File tree

4 files changed

+106
-114
lines changed

4 files changed

+106
-114
lines changed

drivers/gpu/drm/rcar-du/rcar_du_drv.c

Lines changed: 103 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -144,82 +144,6 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table);
144144
* DRM operations
145145
*/
146146

147-
static int rcar_du_unload(struct drm_device *dev)
148-
{
149-
struct rcar_du_device *rcdu = dev->dev_private;
150-
151-
if (rcdu->fbdev)
152-
drm_fbdev_cma_fini(rcdu->fbdev);
153-
154-
drm_kms_helper_poll_fini(dev);
155-
drm_mode_config_cleanup(dev);
156-
drm_vblank_cleanup(dev);
157-
158-
dev->irq_enabled = 0;
159-
dev->dev_private = NULL;
160-
161-
return 0;
162-
}
163-
164-
static int rcar_du_load(struct drm_device *dev, unsigned long flags)
165-
{
166-
struct platform_device *pdev = dev->platformdev;
167-
struct device_node *np = pdev->dev.of_node;
168-
struct rcar_du_device *rcdu;
169-
struct resource *mem;
170-
int ret;
171-
172-
if (np == NULL) {
173-
dev_err(dev->dev, "no platform data\n");
174-
return -ENODEV;
175-
}
176-
177-
rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
178-
if (rcdu == NULL) {
179-
dev_err(dev->dev, "failed to allocate private data\n");
180-
return -ENOMEM;
181-
}
182-
183-
init_waitqueue_head(&rcdu->commit.wait);
184-
185-
rcdu->dev = &pdev->dev;
186-
rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
187-
rcdu->ddev = dev;
188-
dev->dev_private = rcdu;
189-
190-
/* I/O resources */
191-
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
192-
rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
193-
if (IS_ERR(rcdu->mmio))
194-
return PTR_ERR(rcdu->mmio);
195-
196-
/* Initialize vertical blanking interrupts handling. Start with vblank
197-
* disabled for all CRTCs.
198-
*/
199-
ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
200-
if (ret < 0) {
201-
dev_err(&pdev->dev, "failed to initialize vblank\n");
202-
goto done;
203-
}
204-
205-
/* DRM/KMS objects */
206-
ret = rcar_du_modeset_init(rcdu);
207-
if (ret < 0) {
208-
dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
209-
goto done;
210-
}
211-
212-
dev->irq_enabled = 1;
213-
214-
platform_set_drvdata(pdev, rcdu);
215-
216-
done:
217-
if (ret)
218-
rcar_du_unload(dev);
219-
220-
return ret;
221-
}
222-
223147
static void rcar_du_lastclose(struct drm_device *dev)
224148
{
225149
struct rcar_du_device *rcdu = dev->dev_private;
@@ -260,10 +184,7 @@ static const struct file_operations rcar_du_fops = {
260184
static struct drm_driver rcar_du_driver = {
261185
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
262186
| DRIVER_ATOMIC,
263-
.load = rcar_du_load,
264-
.unload = rcar_du_unload,
265187
.lastclose = rcar_du_lastclose,
266-
.set_busid = drm_platform_set_busid,
267188
.get_vblank_counter = drm_vblank_no_hw_counter,
268189
.enable_vblank = rcar_du_enable_vblank,
269190
.disable_vblank = rcar_du_disable_vblank,
@@ -323,18 +244,116 @@ static const struct dev_pm_ops rcar_du_pm_ops = {
323244
* Platform driver
324245
*/
325246

326-
static int rcar_du_probe(struct platform_device *pdev)
247+
static int rcar_du_remove(struct platform_device *pdev)
327248
{
328-
return drm_platform_init(&rcar_du_driver, pdev);
249+
struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
250+
struct drm_device *ddev = rcdu->ddev;
251+
252+
mutex_lock(&ddev->mode_config.mutex);
253+
drm_connector_unplug_all(ddev);
254+
mutex_unlock(&ddev->mode_config.mutex);
255+
256+
drm_dev_unregister(ddev);
257+
258+
if (rcdu->fbdev)
259+
drm_fbdev_cma_fini(rcdu->fbdev);
260+
261+
drm_kms_helper_poll_fini(ddev);
262+
drm_mode_config_cleanup(ddev);
263+
drm_vblank_cleanup(ddev);
264+
265+
drm_dev_unref(ddev);
266+
267+
return 0;
329268
}
330269

331-
static int rcar_du_remove(struct platform_device *pdev)
270+
static int rcar_du_probe(struct platform_device *pdev)
332271
{
333-
struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
272+
struct device_node *np = pdev->dev.of_node;
273+
struct rcar_du_device *rcdu;
274+
struct drm_connector *connector;
275+
struct drm_device *ddev;
276+
struct resource *mem;
277+
int ret;
278+
279+
if (np == NULL) {
280+
dev_err(&pdev->dev, "no device tree node\n");
281+
return -ENODEV;
282+
}
283+
284+
/* Allocate and initialize the DRM and R-Car device structures. */
285+
rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
286+
if (rcdu == NULL)
287+
return -ENOMEM;
288+
289+
init_waitqueue_head(&rcdu->commit.wait);
290+
291+
rcdu->dev = &pdev->dev;
292+
rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
293+
294+
ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
295+
if (!ddev)
296+
return -ENOMEM;
297+
298+
drm_dev_set_unique(ddev, dev_name(&pdev->dev));
299+
300+
rcdu->ddev = ddev;
301+
ddev->dev_private = rcdu;
334302

335-
drm_put_dev(rcdu->ddev);
303+
platform_set_drvdata(pdev, rcdu);
304+
305+
/* I/O resources */
306+
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
307+
rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
308+
if (IS_ERR(rcdu->mmio)) {
309+
ret = PTR_ERR(rcdu->mmio);
310+
goto error;
311+
}
312+
313+
/* Initialize vertical blanking interrupts handling. Start with vblank
314+
* disabled for all CRTCs.
315+
*/
316+
ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
317+
if (ret < 0) {
318+
dev_err(&pdev->dev, "failed to initialize vblank\n");
319+
goto error;
320+
}
321+
322+
/* DRM/KMS objects */
323+
ret = rcar_du_modeset_init(rcdu);
324+
if (ret < 0) {
325+
dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
326+
goto error;
327+
}
328+
329+
ddev->irq_enabled = 1;
330+
331+
/* Register the DRM device with the core and the connectors with
332+
* sysfs.
333+
*/
334+
ret = drm_dev_register(ddev, 0);
335+
if (ret)
336+
goto error;
337+
338+
mutex_lock(&ddev->mode_config.mutex);
339+
drm_for_each_connector(connector, ddev) {
340+
ret = drm_connector_register(connector);
341+
if (ret < 0)
342+
break;
343+
}
344+
mutex_unlock(&ddev->mode_config.mutex);
345+
346+
if (ret < 0)
347+
goto error;
348+
349+
DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
336350

337351
return 0;
352+
353+
error:
354+
rcar_du_remove(pdev);
355+
356+
return ret;
338357
}
339358

340359
static struct platform_driver rcar_du_platform_driver = {

drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
5555
.best_encoder = rcar_du_connector_best_encoder,
5656
};
5757

58-
static void rcar_du_hdmi_connector_destroy(struct drm_connector *connector)
59-
{
60-
drm_connector_unregister(connector);
61-
drm_connector_cleanup(connector);
62-
}
63-
6458
static enum drm_connector_status
6559
rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
6660
{
@@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = {
7973
.reset = drm_atomic_helper_connector_reset,
8074
.detect = rcar_du_hdmi_connector_detect,
8175
.fill_modes = drm_helper_probe_single_connector_modes,
82-
.destroy = rcar_du_hdmi_connector_destroy,
76+
.destroy = drm_connector_cleanup,
8377
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
8478
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
8579
};
@@ -108,9 +102,6 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
108102
return ret;
109103

110104
drm_connector_helper_add(connector, &connector_helper_funcs);
111-
ret = drm_connector_register(connector);
112-
if (ret < 0)
113-
return ret;
114105

115106
connector->dpms = DRM_MODE_DPMS_OFF;
116107
drm_object_property_set_value(&connector->base,

drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
6262
.best_encoder = rcar_du_connector_best_encoder,
6363
};
6464

65-
static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
66-
{
67-
drm_connector_unregister(connector);
68-
drm_connector_cleanup(connector);
69-
}
70-
7165
static enum drm_connector_status
7266
rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
7367
{
@@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = {
7973
.reset = drm_atomic_helper_connector_reset,
8074
.detect = rcar_du_lvds_connector_detect,
8175
.fill_modes = drm_helper_probe_single_connector_modes,
82-
.destroy = rcar_du_lvds_connector_destroy,
76+
.destroy = drm_connector_cleanup,
8377
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
8478
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
8579
};
@@ -117,9 +111,6 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
117111
return ret;
118112

119113
drm_connector_helper_add(connector, &connector_helper_funcs);
120-
ret = drm_connector_register(connector);
121-
if (ret < 0)
122-
return ret;
123114

124115
connector->dpms = DRM_MODE_DPMS_OFF;
125116
drm_object_property_set_value(&connector->base,

drivers/gpu/drm/rcar-du/rcar_du_vgacon.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
3131
.best_encoder = rcar_du_connector_best_encoder,
3232
};
3333

34-
static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
35-
{
36-
drm_connector_unregister(connector);
37-
drm_connector_cleanup(connector);
38-
}
39-
4034
static enum drm_connector_status
4135
rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
4236
{
@@ -48,7 +42,7 @@ static const struct drm_connector_funcs connector_funcs = {
4842
.reset = drm_atomic_helper_connector_reset,
4943
.detect = rcar_du_vga_connector_detect,
5044
.fill_modes = drm_helper_probe_single_connector_modes,
51-
.destroy = rcar_du_vga_connector_destroy,
45+
.destroy = drm_connector_cleanup,
5246
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
5347
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
5448
};
@@ -76,9 +70,6 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
7670
return ret;
7771

7872
drm_connector_helper_add(connector, &connector_helper_funcs);
79-
ret = drm_connector_register(connector);
80-
if (ret < 0)
81-
return ret;
8273

8374
connector->dpms = DRM_MODE_DPMS_OFF;
8475
drm_object_property_set_value(&connector->base,

0 commit comments

Comments
 (0)