Skip to content

Commit 1c13d60

Browse files
ambarusandersson
authored andcommitted
soc: qcom: ice: introduce devm_of_qcom_ice_get
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>
1 parent 707fb1f commit 1c13d60

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

drivers/soc/qcom/ice.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/cleanup.h>
1212
#include <linux/clk.h>
1313
#include <linux/delay.h>
14+
#include <linux/device.h>
1415
#include <linux/iopoll.h>
1516
#include <linux/of.h>
1617
#include <linux/of_platform.h>
@@ -324,6 +325,53 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
324325
}
325326
EXPORT_SYMBOL_GPL(of_qcom_ice_get);
326327

328+
static void qcom_ice_put(const struct qcom_ice *ice)
329+
{
330+
struct platform_device *pdev = to_platform_device(ice->dev);
331+
332+
if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"))
333+
platform_device_put(pdev);
334+
}
335+
336+
static void devm_of_qcom_ice_put(struct device *dev, void *res)
337+
{
338+
qcom_ice_put(*(struct qcom_ice **)res);
339+
}
340+
341+
/**
342+
* devm_of_qcom_ice_get() - Devres managed helper to get an ICE instance from
343+
* a DT node.
344+
* @dev: device pointer for the consumer device.
345+
*
346+
* This function will provide an ICE instance either by creating one for the
347+
* consumer device if its DT node provides the 'ice' reg range and the 'ice'
348+
* clock (for legacy DT style). On the other hand, if consumer provides a
349+
* phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already
350+
* be created and so this function will return that instead.
351+
*
352+
* Return: ICE pointer on success, NULL if there is no ICE data provided by the
353+
* consumer or ERR_PTR() on error.
354+
*/
355+
struct qcom_ice *devm_of_qcom_ice_get(struct device *dev)
356+
{
357+
struct qcom_ice *ice, **dr;
358+
359+
dr = devres_alloc(devm_of_qcom_ice_put, sizeof(*dr), GFP_KERNEL);
360+
if (!dr)
361+
return ERR_PTR(-ENOMEM);
362+
363+
ice = of_qcom_ice_get(dev);
364+
if (!IS_ERR_OR_NULL(ice)) {
365+
*dr = ice;
366+
devres_add(dev, dr);
367+
} else {
368+
devres_free(dr);
369+
}
370+
371+
return ice;
372+
}
373+
EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get);
374+
327375
static int qcom_ice_probe(struct platform_device *pdev)
328376
{
329377
struct qcom_ice *engine;

include/soc/qcom/ice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice,
3434
int slot);
3535
int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
3636
struct qcom_ice *of_qcom_ice_get(struct device *dev);
37+
struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
38+
3739
#endif /* __QCOM_ICE_H__ */

0 commit comments

Comments
 (0)