Skip to content

Commit 3e173dc

Browse files
njhollinghurstpelwell
authored andcommitted
drm: rp1: VEC and DPI drivers: Fix bug #5901
Rework probe() to use devm_drm_dev_alloc(), embedding the DRM device in the DPI or VEC device as now seems to be recommended. Change order of resource allocation and driver initialization. This prevents it trying to write to an unmapped register during clean-up, which previously could crash. Signed-off-by: Nick Hollinghurst <[email protected]>
1 parent 5e78d29 commit 3e173dc

File tree

6 files changed

+75
-95
lines changed

6 files changed

+75
-95
lines changed

drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c

Lines changed: 31 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ static const u32 rp1dpi_formats[] = {
268268
static int rp1dpi_platform_probe(struct platform_device *pdev)
269269
{
270270
struct device *dev = &pdev->dev;
271-
struct drm_device *drm;
272271
struct rp1_dpi *dpi;
273272
struct drm_bridge *bridge = NULL;
274273
struct drm_panel *panel;
@@ -287,24 +286,13 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
287286
return PTR_ERR(bridge);
288287
}
289288

290-
drm = drm_dev_alloc(&rp1dpi_driver, dev);
291-
if (IS_ERR(drm)) {
292-
dev_info(dev, "%s %d", __func__, (int)__LINE__);
293-
ret = PTR_ERR(drm);
289+
dpi = devm_drm_dev_alloc(dev, &rp1dpi_driver, struct rp1_dpi, drm);
290+
if (IS_ERR(dpi)) {
291+
ret = PTR_ERR(dpi);
292+
dev_err(dev, "%s devm_drm_dev_alloc %d", __func__, ret);
294293
return ret;
295294
}
296-
dpi = drmm_kzalloc(drm, sizeof(*dpi), GFP_KERNEL);
297-
if (!dpi) {
298-
dev_info(dev, "%s %d", __func__, (int)__LINE__);
299-
drm_dev_put(drm);
300-
return -ENOMEM;
301-
}
302-
303-
init_completion(&dpi->finished);
304-
dpi->drm = drm;
305295
dpi->pdev = pdev;
306-
drm->dev_private = dpi;
307-
platform_set_drvdata(pdev, drm);
308296

309297
dpi->bus_fmt = default_bus_fmt;
310298
ret = of_property_read_u32(dev->of_node, "default_bus_fmt", &dpi->bus_fmt);
@@ -314,9 +302,8 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
314302
devm_ioremap_resource(dev,
315303
platform_get_resource(dpi->pdev, IORESOURCE_MEM, i));
316304
if (IS_ERR(dpi->hw_base[i])) {
317-
ret = PTR_ERR(dpi->hw_base[i]);
318305
dev_err(dev, "Error memory mapping regs[%d]\n", i);
319-
goto err_free_drm;
306+
return PTR_ERR(dpi->hw_base[i]);
320307
}
321308
}
322309
ret = platform_get_irq(dpi->pdev, 0);
@@ -325,35 +312,39 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
325312
IRQF_SHARED, "rp1-dpi", dpi);
326313
if (ret) {
327314
dev_err(dev, "Unable to request interrupt\n");
328-
ret = -EINVAL;
329-
goto err_free_drm;
315+
return -EINVAL;
330316
}
331-
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
332317

333318
for (i = 0; i < RP1DPI_NUM_CLOCKS; i++) {
334319
static const char * const myclocknames[RP1DPI_NUM_CLOCKS] = {
335320
"dpiclk", "plldiv", "pllcore"
336321
};
337322
dpi->clocks[i] = devm_clk_get(dev, myclocknames[i]);
338323
if (IS_ERR(dpi->clocks[i])) {
339-
ret = PTR_ERR(dpi->clocks[i]);
340-
goto err_free_drm;
324+
dev_err(dev, "Unable to request clock %s\n", myclocknames[i]);
325+
return PTR_ERR(dpi->clocks[i]);
341326
}
342327
}
343328

344-
ret = drmm_mode_config_init(drm);
329+
ret = drmm_mode_config_init(&dpi->drm);
345330
if (ret)
346-
goto err_free_drm;
347-
348-
drm->mode_config.max_width = 4096;
349-
drm->mode_config.max_height = 4096;
350-
drm->mode_config.preferred_depth = 32;
351-
drm->mode_config.prefer_shadow = 0;
352-
drm->mode_config.quirk_addfb_prefer_host_byte_order = true;
353-
drm->mode_config.funcs = &rp1dpi_mode_funcs;
354-
drm_vblank_init(drm, 1);
331+
goto done_err;
355332

356-
ret = drm_simple_display_pipe_init(drm,
333+
/* Now we have all our resources, finish driver initialization */
334+
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
335+
init_completion(&dpi->finished);
336+
dpi->drm.dev_private = dpi;
337+
platform_set_drvdata(pdev, &dpi->drm);
338+
339+
dpi->drm.mode_config.max_width = 4096;
340+
dpi->drm.mode_config.max_height = 4096;
341+
dpi->drm.mode_config.preferred_depth = 32;
342+
dpi->drm.mode_config.prefer_shadow = 0;
343+
dpi->drm.mode_config.quirk_addfb_prefer_host_byte_order = true;
344+
dpi->drm.mode_config.funcs = &rp1dpi_mode_funcs;
345+
drm_vblank_init(&dpi->drm, 1);
346+
347+
ret = drm_simple_display_pipe_init(&dpi->drm,
357348
&dpi->pipe,
358349
&rp1dpi_pipe_funcs,
359350
rp1dpi_formats,
@@ -362,22 +353,19 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
362353
if (!ret)
363354
ret = drm_simple_display_pipe_attach_bridge(&dpi->pipe, bridge);
364355
if (ret)
365-
goto err_free_drm;
356+
goto done_err;
366357

367-
drm_mode_config_reset(drm);
358+
drm_mode_config_reset(&dpi->drm);
368359

369-
ret = drm_dev_register(drm, 0);
360+
ret = drm_dev_register(&dpi->drm, 0);
370361
if (ret)
371-
goto err_free_drm;
372-
373-
drm_fbdev_generic_setup(drm, 32);
362+
return ret;
374363

375-
dev_info(dev, "%s success\n", __func__);
364+
drm_fbdev_generic_setup(&dpi->drm, 32);
376365
return ret;
377366

378-
err_free_drm:
367+
done_err:
379368
dev_err(dev, "%s fail %d\n", __func__, ret);
380-
drm_dev_put(drm);
381369
return ret;
382370
}
383371

drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
/* ---------------------------------------------------------------------- */
2929

3030
struct rp1_dpi {
31-
/* DRM and platform device pointers */
32-
struct drm_device *drm;
31+
/* DRM base and platform device pointer */
32+
struct drm_device drm;
3333
struct platform_device *pdev;
3434

3535
/* Framework and helper objects */

drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ void rp1dpi_hw_stop(struct rp1_dpi *dpi)
451451
ctrl &= ~(DPI_DMA_CONTROL_ARM_MASK | DPI_DMA_CONTROL_AUTO_REPEAT_MASK);
452452
rp1dpi_hw_write(dpi, DPI_DMA_CONTROL, ctrl);
453453
if (!wait_for_completion_timeout(&dpi->finished, HZ / 10))
454-
drm_err(dpi->drm, "%s: timed out waiting for idle\n", __func__);
454+
drm_err(&dpi->drm, "%s: timed out waiting for idle\n", __func__);
455455
rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN, 0);
456456
}
457457

@@ -473,7 +473,7 @@ irqreturn_t rp1dpi_hw_isr(int irq, void *dev)
473473
rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, u);
474474
if (dpi) {
475475
if (u & DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK)
476-
drm_err_ratelimited(dpi->drm,
476+
drm_err_ratelimited(&dpi->drm,
477477
"Underflow! (panics=0x%08x)\n",
478478
rp1dpi_hw_read(dpi, DPI_DMA_PANICS));
479479
if (u & DPI_DMA_IRQ_FLAGS_DMA_READY_MASK)

drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -361,29 +361,17 @@ static struct drm_driver rp1vec_driver = {
361361
static int rp1vec_platform_probe(struct platform_device *pdev)
362362
{
363363
struct device *dev = &pdev->dev;
364-
struct drm_device *drm;
365364
struct rp1_vec *vec;
366365
int i, ret;
367366

368367
dev_info(dev, __func__);
369-
drm = drm_dev_alloc(&rp1vec_driver, dev);
370-
if (IS_ERR(drm)) {
371-
ret = PTR_ERR(drm);
372-
dev_err(dev, "%s drm_dev_alloc %d", __func__, ret);
368+
vec = devm_drm_dev_alloc(dev, &rp1vec_driver, struct rp1_vec, drm);
369+
if (IS_ERR(vec)) {
370+
ret = PTR_ERR(vec);
371+
dev_err(dev, "%s devm_drm_dev_alloc %d", __func__, ret);
373372
return ret;
374373
}
375-
376-
vec = drmm_kzalloc(drm, sizeof(*vec), GFP_KERNEL);
377-
if (!vec) {
378-
dev_err(dev, "%s drmm_kzalloc failed", __func__);
379-
ret = -ENOMEM;
380-
goto err_free_drm;
381-
}
382-
init_completion(&vec->finished);
383-
vec->drm = drm;
384374
vec->pdev = pdev;
385-
drm->dev_private = vec;
386-
platform_set_drvdata(pdev, drm);
387375

388376
for (i = 0; i < RP1VEC_NUM_HW_BLOCKS; i++) {
389377
vec->hw_base[i] =
@@ -392,7 +380,7 @@ static int rp1vec_platform_probe(struct platform_device *pdev)
392380
if (IS_ERR(vec->hw_base[i])) {
393381
ret = PTR_ERR(vec->hw_base[i]);
394382
dev_err(dev, "Error memory mapping regs[%d]\n", i);
395-
goto err_free_drm;
383+
goto done_err;
396384
}
397385
}
398386
ret = platform_get_irq(vec->pdev, 0);
@@ -402,69 +390,73 @@ static int rp1vec_platform_probe(struct platform_device *pdev)
402390
if (ret) {
403391
dev_err(dev, "Unable to request interrupt\n");
404392
ret = -EINVAL;
405-
goto err_free_drm;
393+
goto done_err;
406394
}
407-
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
408395

409396
vec->vec_clock = devm_clk_get(dev, NULL);
410397
if (IS_ERR(vec->vec_clock)) {
411398
ret = PTR_ERR(vec->vec_clock);
412-
goto err_free_drm;
399+
goto done_err;
413400
}
414401
ret = clk_prepare_enable(vec->vec_clock);
415402

416-
ret = drmm_mode_config_init(drm);
403+
ret = drmm_mode_config_init(&vec->drm);
417404
if (ret)
418-
goto err_free_drm;
419-
drm->mode_config.max_width = 800;
420-
drm->mode_config.max_height = 576;
421-
drm->mode_config.preferred_depth = 32;
422-
drm->mode_config.prefer_shadow = 0;
423-
//drm->mode_config.fbdev_use_iomem = false;
424-
drm->mode_config.quirk_addfb_prefer_host_byte_order = true;
425-
drm->mode_config.funcs = &rp1vec_mode_funcs;
426-
drm_vblank_init(drm, 1);
427-
428-
ret = drm_mode_create_tv_properties(drm, RP1VEC_SUPPORTED_TV_MODES);
405+
goto done_err;
406+
407+
/* Now we have all our resources, finish driver initialization */
408+
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
409+
init_completion(&vec->finished);
410+
vec->drm.dev_private = vec;
411+
platform_set_drvdata(pdev, &vec->drm);
412+
413+
vec->drm.mode_config.max_width = 800;
414+
vec->drm.mode_config.max_height = 576;
415+
vec->drm.mode_config.preferred_depth = 32;
416+
vec->drm.mode_config.prefer_shadow = 0;
417+
vec->drm.mode_config.quirk_addfb_prefer_host_byte_order = true;
418+
vec->drm.mode_config.funcs = &rp1vec_mode_funcs;
419+
drm_vblank_init(&vec->drm, 1);
420+
421+
ret = drm_mode_create_tv_properties(&vec->drm, RP1VEC_SUPPORTED_TV_MODES);
429422
if (ret)
430-
goto err_free_drm;
423+
goto done_err;
431424

432-
drm_connector_init(drm, &vec->connector, &rp1vec_connector_funcs,
425+
drm_connector_init(&vec->drm, &vec->connector, &rp1vec_connector_funcs,
433426
DRM_MODE_CONNECTOR_Composite);
434427
if (ret)
435-
goto err_free_drm;
428+
goto done_err;
436429

437430
vec->connector.interlace_allowed = true;
438431
drm_connector_helper_add(&vec->connector, &rp1vec_connector_helper_funcs);
439432

440433
drm_object_attach_property(&vec->connector.base,
441-
drm->mode_config.tv_mode_property,
434+
vec->drm.mode_config.tv_mode_property,
442435
(vec->connector.cmdline_mode.tv_mode_specified) ?
443436
vec->connector.cmdline_mode.tv_mode :
444437
DRM_MODE_TV_MODE_NTSC);
445438

446-
ret = drm_simple_display_pipe_init(drm,
439+
ret = drm_simple_display_pipe_init(&vec->drm,
447440
&vec->pipe,
448441
&rp1vec_pipe_funcs,
449442
rp1vec_formats,
450443
ARRAY_SIZE(rp1vec_formats),
451444
NULL,
452445
&vec->connector);
453446
if (ret)
454-
goto err_free_drm;
447+
goto done_err;
455448

456-
drm_mode_config_reset(drm);
449+
drm_mode_config_reset(&vec->drm);
457450

458-
ret = drm_dev_register(drm, 0);
451+
ret = drm_dev_register(&vec->drm, 0);
459452
if (ret)
460-
goto err_free_drm;
453+
goto done_err;
461454

462-
drm_fbdev_generic_setup(drm, 32); /* the "32" is preferred BPP */
455+
drm_fbdev_generic_setup(&vec->drm, 32);
463456
return ret;
464457

465-
err_free_drm:
466-
dev_info(dev, "%s fail %d", __func__, ret);
467-
drm_dev_put(drm);
458+
done_err:
459+
dev_err(dev, "%s fail %d", __func__, ret);
468460
return ret;
469461
}
470462

drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
/* ---------------------------------------------------------------------- */
3232

3333
struct rp1_vec {
34-
/* DRM and platform device pointers */
35-
struct drm_device *drm;
34+
/* DRM base and platform device pointer */
35+
struct drm_device drm;
3636
struct platform_device *pdev;
3737

3838
/* Framework and helper objects */

drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ void rp1vec_hw_stop(struct rp1_vec *vec)
480480
reinit_completion(&vec->finished);
481481
VEC_WRITE(VEC_CONTROL, 0);
482482
if (!wait_for_completion_timeout(&vec->finished, HZ / 10))
483-
drm_err(vec->drm, "%s: timed out waiting for idle\n", __func__);
483+
drm_err(&vec->drm, "%s: timed out waiting for idle\n", __func__);
484484
VEC_WRITE(VEC_IRQ_ENABLES, 0);
485485
}
486486

0 commit comments

Comments
 (0)