diff options
author | Andrey Smirnov <andrew.smirnov@gmail.com> | 2018-04-10 14:32:10 -0400 |
---|---|---|
committer | Shawn Guo <shawnguo@kernel.org> | 2018-04-23 05:03:15 -0400 |
commit | f54e714cfc53b9164d1206f9ee49042195532a51 (patch) | |
tree | 7efea32f3af857ad9dde810873639a273f5324a5 | |
parent | 050f810e238f268670f14a8f8b793ba2dbf2e92f (diff) |
soc: imx: gpc: Do not pass static memory as platform data
Platform device core assumes the ownership of dev.platform_data as
well as that it is dynamically allocated and it will try to kfree it
as a part of platform_device_release(). Change the code to use
platform_device_add_data() instead of a pointer to a static memory to
avoid causing a BUG() when calling platform_device_put().
The problem can be reproduced by artificially enabling the error path
of platform_device_add() call (around line 452).
Cc: Stefan Agner <stefan@agner.ch>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
-rw-r--r-- | drivers/soc/imx/gpc.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c index c4d35f32af8d..32f0748fd067 100644 --- a/drivers/soc/imx/gpc.c +++ b/drivers/soc/imx/gpc.c | |||
@@ -443,17 +443,25 @@ static int imx_gpc_probe(struct platform_device *pdev) | |||
443 | if (domain_index >= of_id_data->num_domains) | 443 | if (domain_index >= of_id_data->num_domains) |
444 | continue; | 444 | continue; |
445 | 445 | ||
446 | domain = &imx_gpc_domains[domain_index]; | ||
447 | domain->regmap = regmap; | ||
448 | domain->ipg_rate_mhz = ipg_rate_mhz; | ||
449 | |||
450 | pd_pdev = platform_device_alloc("imx-pgc-power-domain", | 446 | pd_pdev = platform_device_alloc("imx-pgc-power-domain", |
451 | domain_index); | 447 | domain_index); |
452 | if (!pd_pdev) { | 448 | if (!pd_pdev) { |
453 | of_node_put(np); | 449 | of_node_put(np); |
454 | return -ENOMEM; | 450 | return -ENOMEM; |
455 | } | 451 | } |
456 | pd_pdev->dev.platform_data = domain; | 452 | |
453 | ret = platform_device_add_data(pd_pdev, | ||
454 | &imx_gpc_domains[domain_index], | ||
455 | sizeof(imx_gpc_domains[domain_index])); | ||
456 | if (ret) { | ||
457 | platform_device_put(pd_pdev); | ||
458 | of_node_put(np); | ||
459 | return ret; | ||
460 | } | ||
461 | domain = pd_pdev->dev.platform_data; | ||
462 | domain->regmap = regmap; | ||
463 | domain->ipg_rate_mhz = ipg_rate_mhz; | ||
464 | |||
457 | pd_pdev->dev.parent = &pdev->dev; | 465 | pd_pdev->dev.parent = &pdev->dev; |
458 | pd_pdev->dev.of_node = np; | 466 | pd_pdev->dev.of_node = np; |
459 | 467 | ||