Merge branch 'for-6.5/core' into for-linus
- more bullet-proof handling of devres-managed resources in HID core (Dmitry Torokhov) - kunit test Kconfig dependency fix (Geert Uytterhoeven)
This commit is contained in:
commit
1639f986e3
@ -1285,7 +1285,7 @@ config HID_MCP2221
|
||||
|
||||
config HID_KUNIT_TEST
|
||||
tristate "KUnit tests for HID" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT=y
|
||||
depends on KUNIT
|
||||
depends on HID_BATTERY_STRENGTH
|
||||
depends on HID_UCLOGIC
|
||||
default KUNIT_ALL_TESTS
|
||||
|
@ -2587,64 +2587,84 @@ bool hid_compare_device_paths(struct hid_device *hdev_a,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_compare_device_paths);
|
||||
|
||||
static bool hid_check_device_match(struct hid_device *hdev,
|
||||
struct hid_driver *hdrv,
|
||||
const struct hid_device_id **id)
|
||||
{
|
||||
*id = hid_match_device(hdev, hdrv);
|
||||
if (!*id)
|
||||
return false;
|
||||
|
||||
if (hdrv->match)
|
||||
return hdrv->match(hdev, hid_ignore_special_drivers);
|
||||
|
||||
/*
|
||||
* hid-generic implements .match(), so we must be dealing with a
|
||||
* different HID driver here, and can simply check if
|
||||
* hid_ignore_special_drivers is set or not.
|
||||
*/
|
||||
return !hid_ignore_special_drivers;
|
||||
}
|
||||
|
||||
static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
|
||||
{
|
||||
const struct hid_device_id *id;
|
||||
int ret;
|
||||
|
||||
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;
|
||||
|
||||
if (hdrv->probe) {
|
||||
ret = hdrv->probe(hdev, id);
|
||||
} else { /* default probe */
|
||||
ret = hid_open_report(hdev);
|
||||
if (!ret)
|
||||
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;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hid_device_probe(struct device *dev)
|
||||
{
|
||||
struct hid_driver *hdrv = to_hid_driver(dev->driver);
|
||||
struct hid_device *hdev = to_hid_device(dev);
|
||||
const struct hid_device_id *id;
|
||||
struct hid_driver *hdrv = to_hid_driver(dev->driver);
|
||||
int ret = 0;
|
||||
|
||||
if (down_interruptible(&hdev->driver_input_lock)) {
|
||||
ret = -EINTR;
|
||||
goto end;
|
||||
}
|
||||
hdev->io_started = false;
|
||||
if (down_interruptible(&hdev->driver_input_lock))
|
||||
return -EINTR;
|
||||
|
||||
hdev->io_started = false;
|
||||
clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
|
||||
|
||||
if (!hdev->driver) {
|
||||
id = hid_match_device(hdev, hdrv);
|
||||
if (id == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
if (!hdev->driver)
|
||||
ret = __hid_device_probe(hdev, hdrv);
|
||||
|
||||
if (hdrv->match) {
|
||||
if (!hdrv->match(hdev, hid_ignore_special_drivers)) {
|
||||
ret = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* hid-generic implements .match(), so if
|
||||
* hid_ignore_special_drivers is set, we can safely
|
||||
* return.
|
||||
*/
|
||||
if (hid_ignore_special_drivers) {
|
||||
ret = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the quirks that has been previously set */
|
||||
hdev->quirks = hid_lookup_quirk(hdev);
|
||||
hdev->driver = hdrv;
|
||||
if (hdrv->probe) {
|
||||
ret = hdrv->probe(hdev, id);
|
||||
} else { /* default probe */
|
||||
ret = hid_open_report(hdev);
|
||||
if (!ret)
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
}
|
||||
if (ret) {
|
||||
hid_close_report(hdev);
|
||||
hdev->driver = NULL;
|
||||
}
|
||||
}
|
||||
unlock:
|
||||
if (!hdev->io_started)
|
||||
up(&hdev->driver_input_lock);
|
||||
end:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2662,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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user