soc: qcom: ice: introduce devm_of_qcom_ice_get

[ Upstream commit 1c13d6060d612601a61423f2e8fbf9e48126acca ]

Callers of of_qcom_ice_get() leak the device reference taken by
of_find_device_by_node(). Introduce devm variant for of_qcom_ice_get().
Existing consumers need the ICE instance for the entire life of their
device, thus exporting qcom_ice_put() is not required.

Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-1-1ffa5b6884cb@linaro.org
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Stable-dep-of: cbef7442fba5 ("mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get")
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Tudor Ambarus
2025-01-17 14:18:50 +00:00
committed by Greg Kroah-Hartman
parent a505075730
commit d4f5f29c26
2 changed files with 50 additions and 0 deletions

View File

@@ -10,6 +10,7 @@
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
@@ -328,6 +329,53 @@ out:
} }
EXPORT_SYMBOL_GPL(of_qcom_ice_get); EXPORT_SYMBOL_GPL(of_qcom_ice_get);
static void qcom_ice_put(const struct qcom_ice *ice)
{
struct platform_device *pdev = to_platform_device(ice->dev);
if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"))
platform_device_put(pdev);
}
static void devm_of_qcom_ice_put(struct device *dev, void *res)
{
qcom_ice_put(*(struct qcom_ice **)res);
}
/**
* devm_of_qcom_ice_get() - Devres managed helper to get an ICE instance from
* a DT node.
* @dev: device pointer for the consumer device.
*
* This function will provide an ICE instance either by creating one for the
* consumer device if its DT node provides the 'ice' reg range and the 'ice'
* clock (for legacy DT style). On the other hand, if consumer provides a
* phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already
* be created and so this function will return that instead.
*
* Return: ICE pointer on success, NULL if there is no ICE data provided by the
* consumer or ERR_PTR() on error.
*/
struct qcom_ice *devm_of_qcom_ice_get(struct device *dev)
{
struct qcom_ice *ice, **dr;
dr = devres_alloc(devm_of_qcom_ice_put, sizeof(*dr), GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
ice = of_qcom_ice_get(dev);
if (!IS_ERR_OR_NULL(ice)) {
*dr = ice;
devres_add(dev, dr);
} else {
devres_free(dr);
}
return ice;
}
EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get);
static int qcom_ice_probe(struct platform_device *pdev) static int qcom_ice_probe(struct platform_device *pdev)
{ {
struct qcom_ice *engine; struct qcom_ice *engine;

View File

@@ -34,4 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice,
int slot); int slot);
int qcom_ice_evict_key(struct qcom_ice *ice, int slot); int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
struct qcom_ice *of_qcom_ice_get(struct device *dev); struct qcom_ice *of_qcom_ice_get(struct device *dev);
struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
#endif /* __QCOM_ICE_H__ */ #endif /* __QCOM_ICE_H__ */