2023-05-23 21:20:48

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH v2 0/2] HID: ensure timely release of driver resources

These 2 patches address an issue in HID subsystem where cleanup code in
the bus code runs before releasing devres-managed resources by the
driver core.

This is a V2 of the patch, which was split in 2 parts - generic cleanup
and the actualy change addressing the issue.

Link: https://lore.kernel.org/r/[email protected]
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
---
Dmitry Torokhov (2):
HID: split apart hid_device_probe to make logic more apparent
HID: ensure timely release of driver-allocated resources

drivers/hid/hid-core.c | 118 +++++++++++++++++++++++++++++--------------------
include/linux/hid.h | 1 +
2 files changed, 72 insertions(+), 47 deletions(-)
---
base-commit: 9f925874281f7e8855855d6210d6e29d844e4307
change-id: 20230523-hid-devres-b0edd05de354

Best regards,
--
Dmitry



2023-05-23 21:25:24

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH v2 2/2] HID: ensure timely release of driver-allocated resources

More and more drivers rely on devres to manage their resources, however
if bus' probe() and release() methods are not trivial and control some
of resources as well (for example enable or disable clocks, or attach
device to a power domain), we need to make sure that driver-allocated
resources are released immediately after driver's remove() method
returns, and not postponed until driver core gets around to releasing
resources.

In case of HID we should not try to close the report and release
associated memory until after all devres callbacks are executed. To fix
that we open a new devres group before calling driver's probe() and
explicitly release it when we return from driver's remove().

This is similar to what we did for I2C bus in commit 5b5475826c52 ("i2c:
ensure timely release of driver-allocated resources"). It is tempting to
try and move this into driver core, but actually doing so is challenging,
we need to split bus' remove() method into pre- and post-remove methods,
which would make the logic even less clear.

Reported-by: Stephen Boyd <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>
---
drivers/hid/hid-core.c | 17 +++++++++++++++++
include/linux/hid.h | 1 +
2 files changed, 18 insertions(+)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 1f0bb2784bfc..4b7062dcefec 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2614,6 +2614,10 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
if (!hid_check_device_match(hdev, hdrv, &id))
return -ENODEV;

+ hdev->devres_group_id = devres_open_group(&hdev->dev, NULL, GFP_KERNEL);
+ if (!hdev->devres_group_id)
+ return -ENOMEM;
+
/* reset the quirks that has been previously set */
hdev->quirks = hid_lookup_quirk(hdev);
hdev->driver = hdrv;
@@ -2626,7 +2630,16 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}

+ /*
+ * Note that we are not closing the devres group opened above so
+ * even resources that were attached to the device after probe is
+ * run are released when hid_device_remove() is executed. This is
+ * needed as some drivers would allocate additional resources,
+ * for example when updating firmware.
+ */
+
if (ret) {
+ devres_release_group(&hdev->dev, hdev->devres_group_id);
hid_close_report(hdev);
hdev->driver = NULL;
}
@@ -2669,6 +2682,10 @@ static void hid_device_remove(struct device *dev)
hdrv->remove(hdev);
else /* default remove */
hid_hw_stop(hdev);
+
+ /* Release all devres resources allocated by the driver */
+ devres_release_group(&hdev->dev, hdev->devres_group_id);
+
hid_close_report(hdev);
hdev->driver = NULL;
}
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 4e4c4fe36911..39e21e3815ad 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -597,6 +597,7 @@ struct hid_device { /* device report descriptor */
struct semaphore driver_input_lock; /* protects the current driver */
struct device dev; /* device */
struct hid_driver *driver;
+ void *devres_group_id; /* ID of probe devres group */

const struct hid_ll_driver *ll_driver;
struct mutex ll_open_lock;

--
2.40.1.698.g37aff9b760-goog


2023-05-26 19:07:09

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH v2 0/2] HID: ensure timely release of driver resources

On Tue, 23 May 2023, Dmitry Torokhov wrote:

> These 2 patches address an issue in HID subsystem where cleanup code in
> the bus code runs before releasing devres-managed resources by the
> driver core.
>
> This is a V2 of the patch, which was split in 2 parts - generic cleanup
> and the actualy change addressing the issue.
>
> Link: https://lore.kernel.org/r/[email protected]
> Link: https://lore.kernel.org/r/[email protected]
> Signed-off-by: Dmitry Torokhov <[email protected]>
> ---
> Dmitry Torokhov (2):
> HID: split apart hid_device_probe to make logic more apparent
> HID: ensure timely release of driver-allocated resources
>
> drivers/hid/hid-core.c | 118 +++++++++++++++++++++++++++++--------------------
> include/linux/hid.h | 1 +
> 2 files changed, 72 insertions(+), 47 deletions(-)

Now queued in hid.git#for-6.5/core.

Thanks,

--
Jiri Kosina
SUSE Labs