@@ -93,6 +93,7 @@ struct simplefb_par {
9393
9494static void simplefb_clocks_destroy (struct simplefb_par * par );
9595static void simplefb_regulators_destroy (struct simplefb_par * par );
96+ static void simplefb_detach_genpds (void * res );
9697
9798/*
9899 * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
@@ -105,6 +106,7 @@ static void simplefb_destroy(struct fb_info *info)
105106
106107 simplefb_regulators_destroy (info -> par );
107108 simplefb_clocks_destroy (info -> par );
109+ simplefb_detach_genpds (info -> par );
108110 if (info -> screen_base )
109111 iounmap (info -> screen_base );
110112
@@ -445,13 +447,14 @@ static void simplefb_detach_genpds(void *res)
445447 if (!IS_ERR_OR_NULL (par -> genpds [i ]))
446448 dev_pm_domain_detach (par -> genpds [i ], true);
447449 }
450+ par -> num_genpds = 0 ;
448451}
449452
450453static int simplefb_attach_genpds (struct simplefb_par * par ,
451454 struct platform_device * pdev )
452455{
453456 struct device * dev = & pdev -> dev ;
454- unsigned int i ;
457+ unsigned int i , num_genpds ;
455458 int err ;
456459
457460 err = of_count_phandle_with_args (dev -> of_node , "power-domains" ,
@@ -465,26 +468,35 @@ static int simplefb_attach_genpds(struct simplefb_par *par,
465468 return err ;
466469 }
467470
468- par -> num_genpds = err ;
471+ num_genpds = err ;
469472
470473 /*
471474 * Single power-domain devices are handled by the driver core, so
472475 * nothing to do here.
473476 */
474- if (par -> num_genpds <= 1 )
477+ if (num_genpds <= 1 ) {
478+ par -> num_genpds = num_genpds ;
475479 return 0 ;
480+ }
476481
477- par -> genpds = devm_kcalloc (dev , par -> num_genpds , sizeof (* par -> genpds ),
482+ par -> genpds = devm_kcalloc (dev , num_genpds , sizeof (* par -> genpds ),
478483 GFP_KERNEL );
479484 if (!par -> genpds )
480485 return - ENOMEM ;
481486
482- par -> genpd_links = devm_kcalloc (dev , par -> num_genpds ,
487+ par -> genpd_links = devm_kcalloc (dev , num_genpds ,
483488 sizeof (* par -> genpd_links ),
484489 GFP_KERNEL );
485490 if (!par -> genpd_links )
486491 return - ENOMEM ;
487492
493+ /*
494+ * Set par->num_genpds only after genpds and genpd_links are allocated
495+ * to exit early from simplefb_detach_genpds() without full
496+ * initialisation.
497+ */
498+ par -> num_genpds = num_genpds ;
499+
488500 for (i = 0 ; i < par -> num_genpds ; i ++ ) {
489501 par -> genpds [i ] = dev_pm_domain_attach_by_id (dev , i );
490502 if (IS_ERR (par -> genpds [i ])) {
@@ -506,9 +518,10 @@ static int simplefb_attach_genpds(struct simplefb_par *par,
506518 dev_warn (dev , "failed to link power-domain %u\n" , i );
507519 }
508520
509- return devm_add_action_or_reset ( dev , simplefb_detach_genpds , par ) ;
521+ return 0 ;
510522}
511523#else
524+ static void simplefb_detach_genpds (void * res ) { }
512525static int simplefb_attach_genpds (struct simplefb_par * par ,
513526 struct platform_device * pdev )
514527{
@@ -622,18 +635,20 @@ static int simplefb_probe(struct platform_device *pdev)
622635 ret = devm_aperture_acquire_for_platform_device (pdev , par -> base , par -> size );
623636 if (ret ) {
624637 dev_err (& pdev -> dev , "Unable to acquire aperture: %d\n" , ret );
625- goto error_regulators ;
638+ goto error_genpds ;
626639 }
627640 ret = register_framebuffer (info );
628641 if (ret < 0 ) {
629642 dev_err (& pdev -> dev , "Unable to register simplefb: %d\n" , ret );
630- goto error_regulators ;
643+ goto error_genpds ;
631644 }
632645
633646 dev_info (& pdev -> dev , "fb%d: simplefb registered!\n" , info -> node );
634647
635648 return 0 ;
636649
650+ error_genpds :
651+ simplefb_detach_genpds (par );
637652error_regulators :
638653 simplefb_regulators_destroy (par );
639654error_clocks :
0 commit comments