[lkml]   [2018]   [Jul]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
Subject[RFC] soc: imx: gpc: Unregister pgc children on remove
If the gpc device is removed the platform_devices for its
imx-pgc-power-domains are still registered and trying to probe gpc again
results in an error.

Fix this by iterating children inside imx_gpc_remove and calling

Signed-off-by: Leonard Crestez <>
drivers/soc/imx/gpc.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

This was prompted by the rejection of the following series:

Tested glxgears after rebinding gpc and etnaviv by echo to

When doing probe again it triggers a warning inside


This seems to be because devicelink code does not expect consumers to
bind before suppliers but GPC code adds PGC children during its
probe function and they register a device-link to their still-probing

The warning doesn't trigger on normal boot because the pgc driver is
registered after gpc and probing is not nested. The warning can be made
to reproduce in a normal boot by making imx_gpc_probe return
-EPROBE_DEFER once (no other changes required).

This does not seem to be a valid scenario for device links so fix this
by adding a check in imx_pgc_power_domain_probe to defer if parent is not

This check is not very nice, device_is_bound seems like something that
should be internal to the driver core.

diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index 32f0748fd067..b4acdfd3cffd 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -182,10 +182,13 @@ static int imx_pgc_power_domain_probe(struct platform_device *pdev)
struct imx_pm_domain *domain = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
int ret;

+ if (!device_is_bound(dev->parent))
+ return -EPROBE_DEFER;
/* if this PD is associated with a DT node try to parse it */
if (dev->of_node) {
ret = imx_pgc_parse_dt(dev, domain);
if (ret)
return ret;
@@ -475,10 +478,19 @@ static int imx_gpc_probe(struct platform_device *pdev)

return 0;

+static int __imx_gpc_unregister_child(struct device *dev, void *data)
+ struct platform_device *pdev = to_platform_device(dev);
+ platform_device_unregister(pdev);
+ return 0;
static int imx_gpc_remove(struct platform_device *pdev)
struct device_node *pgc_node;
int ret;

@@ -502,10 +514,13 @@ static int imx_gpc_remove(struct platform_device *pdev)

ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
if (ret)
return ret;
+ } else {
+ device_for_each_child(&pdev->dev, NULL,
+ __imx_gpc_unregister_child);

return 0;

 \ /
  Last update: 2018-07-03 21:40    [W:0.042 / U:1.224 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site