Message ID | 20250116-qcom-ice-fix-dev-leak-v1-1-84d937683790@linaro.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | soc: qcom: ice: fix dev reference leaked through of_qcom_ice_get | expand |
On 16/01/2025 15:49, Tudor Ambarus wrote: > + > +static void devm_of_qcom_ice_put(struct device *dev, void *res) > +{ > + qcom_ice_put(*(struct qcom_ice **)res); > +} > + > +struct qcom_ice *devm_of_qcom_ice_get(struct device *dev) That's exported function, you need kerneldoc here. > +{ > + 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) > { > struct qcom_ice *engine; > diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h > index 5870a94599a2..d5f6a228df65 100644 > --- a/include/soc/qcom/ice.h > +++ b/include/soc/qcom/ice.h > @@ -34,4 +34,6 @@ int qcom_ice_program_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 *devm_of_qcom_ice_get(struct device *dev); Put should be also added for completeness. Best regards, Krzysztof
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index 393d2d1d275f..9cdf0acba6d1 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -11,6 +11,7 @@ #include <linux/cleanup.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/device.h> #include <linux/iopoll.h> #include <linux/of.h> #include <linux/of_platform.h> @@ -324,6 +325,39 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev) } 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); +} + +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) { struct qcom_ice *engine; diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h index 5870a94599a2..d5f6a228df65 100644 --- a/include/soc/qcom/ice.h +++ b/include/soc/qcom/ice.h @@ -34,4 +34,6 @@ int qcom_ice_program_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 *devm_of_qcom_ice_get(struct device *dev); + #endif /* __QCOM_ICE_H__ */
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() to spare consumers of an extra call to put the dev reference. Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org> --- drivers/soc/qcom/ice.c | 34 ++++++++++++++++++++++++++++++++++ include/soc/qcom/ice.h | 2 ++ 2 files changed, 36 insertions(+)