diff mbox series

[v2,1/2] ACPI / utils: Introduce acpi_dev_get_first_match_dev() helper

Message ID 20190318200055.84519-1-andriy.shevchenko@linux.intel.com
State New
Headers show
Series [v2,1/2] ACPI / utils: Introduce acpi_dev_get_first_match_dev() helper | expand

Commit Message

Andy Shevchenko March 18, 2019, 8 p.m. UTC
The acpi_dev_get_first_match_name() is missing put_device() call
and thus keeping reference counting unbalanced.

In order to fix the issue introduce a new helper to convert existing users
one-by-one to a better API.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/acpi/utils.c    | 24 ++++++++++++++++++++++--
 include/acpi/acpi_bus.h |  3 +++
 include/linux/acpi.h    |  6 ++++++
 3 files changed, 31 insertions(+), 2 deletions(-)

Comments

Hans de Goede March 18, 2019, 8:51 p.m. UTC | #1
Hi,

On 18-03-19 21:00, Andy Shevchenko wrote:
> The acpi_dev_get_first_match_name() is missing put_device() call
> and thus keeping reference counting unbalanced.
> 
> In order to fix the issue introduce a new helper to convert existing users
> one-by-one to a better API.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Series looks good to me, for the series:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans


> ---
>   drivers/acpi/utils.c    | 24 ++++++++++++++++++++++--
>   include/acpi/acpi_bus.h |  3 +++
>   include/linux/acpi.h    |  6 ++++++
>   3 files changed, 31 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
> index c4b06cc075f9..5a2bae2b6c3a 100644
> --- a/drivers/acpi/utils.c
> +++ b/drivers/acpi/utils.c
> @@ -739,6 +739,7 @@ EXPORT_SYMBOL(acpi_dev_found);
>   
>   struct acpi_dev_match_info {
>   	const char *dev_name;
> +	struct acpi_device *adev;
>   	struct acpi_device_id hid[2];
>   	const char *uid;
>   	s64 hrv;
> @@ -759,6 +760,7 @@ static int acpi_dev_match_cb(struct device *dev, void *data)
>   		return 0;
>   
>   	match->dev_name = acpi_dev_name(adev);
> +	match->adev = adev;
>   
>   	if (match->hrv == -1)
>   		return 1;
> @@ -806,16 +808,34 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
>   EXPORT_SYMBOL(acpi_dev_present);
>   
>   /**
> - * acpi_dev_get_first_match_name - Return name of first match of ACPI device
> + * acpi_dev_get_first_match_dev - Return the first match of ACPI device
>    * @hid: Hardware ID of the device.
>    * @uid: Unique ID of the device, pass NULL to not check _UID
>    * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
>    *
> - * Return device name if a matching device was present
> + * Return the first match of ACPI device if a matching device was present
>    * at the moment of invocation, or NULL otherwise.
>    *
> + * The caller is responsible to call put_device() on the returned device.
> + *
>    * See additional information in acpi_dev_present() as well.
>    */
> +struct acpi_device *
> +acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> +{
> +	struct acpi_dev_match_info match = {};
> +	struct device *dev;
> +
> +	strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
> +	match.uid = uid;
> +	match.hrv = hrv;
> +
> +	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
> +	return dev ? match.adev : NULL;
> +}
> +EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
> +
> +/* DEPRECATED, use acpi_dev_get_first_match_dev() instead */
>   const char *
>   acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
>   {
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 0300374101cd..2063e9e2f384 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -91,6 +91,9 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,
>   bool acpi_dev_found(const char *hid);
>   bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);
>   
> +struct acpi_device *
> +acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);
> +
>   const char *
>   acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv);
>   
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index d5dcebd7aad3..3e1d16b00513 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -669,6 +669,12 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
>   	return false;
>   }
>   
> +static inline struct acpi_device *
> +acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> +{
> +	return NULL;
> +}
> +
>   static inline const char *
>   acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
>   {
>
Mika Westerberg March 28, 2019, 4:59 p.m. UTC | #2
On Mon, Mar 18, 2019 at 11:00:54PM +0300, Andy Shevchenko wrote:
> The acpi_dev_get_first_match_name() is missing put_device() call
> and thus keeping reference counting unbalanced.
> 
> In order to fix the issue introduce a new helper to convert existing users
> one-by-one to a better API.

I think it makes more sense to convert all the existing users to this
new API that does not leak, and remove the faulty function completely
instead of marking it deprecated.
diff mbox series

Patch

diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index c4b06cc075f9..5a2bae2b6c3a 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -739,6 +739,7 @@  EXPORT_SYMBOL(acpi_dev_found);
 
 struct acpi_dev_match_info {
 	const char *dev_name;
+	struct acpi_device *adev;
 	struct acpi_device_id hid[2];
 	const char *uid;
 	s64 hrv;
@@ -759,6 +760,7 @@  static int acpi_dev_match_cb(struct device *dev, void *data)
 		return 0;
 
 	match->dev_name = acpi_dev_name(adev);
+	match->adev = adev;
 
 	if (match->hrv == -1)
 		return 1;
@@ -806,16 +808,34 @@  bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
 EXPORT_SYMBOL(acpi_dev_present);
 
 /**
- * acpi_dev_get_first_match_name - Return name of first match of ACPI device
+ * acpi_dev_get_first_match_dev - Return the first match of ACPI device
  * @hid: Hardware ID of the device.
  * @uid: Unique ID of the device, pass NULL to not check _UID
  * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
  *
- * Return device name if a matching device was present
+ * Return the first match of ACPI device if a matching device was present
  * at the moment of invocation, or NULL otherwise.
  *
+ * The caller is responsible to call put_device() on the returned device.
+ *
  * See additional information in acpi_dev_present() as well.
  */
+struct acpi_device *
+acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
+{
+	struct acpi_dev_match_info match = {};
+	struct device *dev;
+
+	strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
+	match.uid = uid;
+	match.hrv = hrv;
+
+	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
+	return dev ? match.adev : NULL;
+}
+EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
+
+/* DEPRECATED, use acpi_dev_get_first_match_dev() instead */
 const char *
 acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
 {
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 0300374101cd..2063e9e2f384 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -91,6 +91,9 @@  acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,
 bool acpi_dev_found(const char *hid);
 bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);
 
+struct acpi_device *
+acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);
+
 const char *
 acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv);
 
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d5dcebd7aad3..3e1d16b00513 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -669,6 +669,12 @@  static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
 	return false;
 }
 
+static inline struct acpi_device *
+acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
+{
+	return NULL;
+}
+
 static inline const char *
 acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
 {