HID: add suspend/resume helpers
There is a lot of duplication of code in the HID low level drivers. Better have everything in one place so we can eventually extend it in a generic way. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Link: https://lore.kernel.org/r/20211202095334.14399-4-benjamin.tissoires@redhat.com
This commit is contained in:
parent
740bebf421
commit
9e35620809
|
@ -2126,6 +2126,35 @@ void hid_hw_close(struct hid_device *hdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(hid_hw_close);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int hid_driver_suspend(struct hid_device *hdev, pm_message_t state)
|
||||
{
|
||||
if (hdev->driver && hdev->driver->suspend)
|
||||
return hdev->driver->suspend(hdev, state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_driver_suspend);
|
||||
|
||||
int hid_driver_reset_resume(struct hid_device *hdev)
|
||||
{
|
||||
if (hdev->driver && hdev->driver->reset_resume)
|
||||
return hdev->driver->reset_resume(hdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_driver_reset_resume);
|
||||
|
||||
int hid_driver_resume(struct hid_device *hdev)
|
||||
{
|
||||
if (hdev->driver && hdev->driver->resume)
|
||||
return hdev->driver->resume(hdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_driver_resume);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
struct hid_dynid {
|
||||
struct list_head list;
|
||||
struct hid_device_id id;
|
||||
|
|
|
@ -1063,11 +1063,9 @@ static int i2c_hid_core_suspend(struct device *dev)
|
|||
int ret;
|
||||
int wake_status;
|
||||
|
||||
if (hid->driver && hid->driver->suspend) {
|
||||
ret = hid->driver->suspend(hid, PMSG_SUSPEND);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = hid_driver_suspend(hid, PMSG_SUSPEND);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Save some power */
|
||||
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
|
||||
|
@ -1125,12 +1123,7 @@ static int i2c_hid_core_resume(struct device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hid->driver && hid->driver->reset_resume) {
|
||||
ret = hid->driver->reset_resume(hid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return hid_driver_reset_resume(hid);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -204,50 +204,35 @@ static int surface_hid_suspend(struct device *dev)
|
|||
{
|
||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||
|
||||
if (d->hid->driver && d->hid->driver->suspend)
|
||||
return d->hid->driver->suspend(d->hid, PMSG_SUSPEND);
|
||||
|
||||
return 0;
|
||||
return hid_driver_suspend(d->hid, PMSG_SUSPEND);
|
||||
}
|
||||
|
||||
static int surface_hid_resume(struct device *dev)
|
||||
{
|
||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||
|
||||
if (d->hid->driver && d->hid->driver->resume)
|
||||
return d->hid->driver->resume(d->hid);
|
||||
|
||||
return 0;
|
||||
return hid_driver_resume(d->hid);
|
||||
}
|
||||
|
||||
static int surface_hid_freeze(struct device *dev)
|
||||
{
|
||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||
|
||||
if (d->hid->driver && d->hid->driver->suspend)
|
||||
return d->hid->driver->suspend(d->hid, PMSG_FREEZE);
|
||||
|
||||
return 0;
|
||||
return hid_driver_suspend(d->hid, PMSG_FREEZE);
|
||||
}
|
||||
|
||||
static int surface_hid_poweroff(struct device *dev)
|
||||
{
|
||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||
|
||||
if (d->hid->driver && d->hid->driver->suspend)
|
||||
return d->hid->driver->suspend(d->hid, PMSG_HIBERNATE);
|
||||
|
||||
return 0;
|
||||
return hid_driver_suspend(d->hid, PMSG_HIBERNATE);
|
||||
}
|
||||
|
||||
static int surface_hid_restore(struct device *dev)
|
||||
{
|
||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||
|
||||
if (d->hid->driver && d->hid->driver->reset_resume)
|
||||
return d->hid->driver->reset_resume(d->hid);
|
||||
|
||||
return 0;
|
||||
return hid_driver_reset_resume(d->hid);
|
||||
}
|
||||
|
||||
const struct dev_pm_ops surface_hid_pm_ops = {
|
||||
|
|
|
@ -1563,8 +1563,8 @@ static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
|
|||
int status = 0;
|
||||
|
||||
hid_restart_io(hid);
|
||||
if (driver_suspended && hid->driver && hid->driver->resume)
|
||||
status = hid->driver->resume(hid);
|
||||
if (driver_suspended)
|
||||
status = hid_driver_resume(hid);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1588,11 +1588,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
{
|
||||
set_bit(HID_SUSPENDED, &usbhid->iofl);
|
||||
spin_unlock_irq(&usbhid->lock);
|
||||
if (hid->driver && hid->driver->suspend) {
|
||||
status = hid->driver->suspend(hid, message);
|
||||
if (status < 0)
|
||||
goto failed;
|
||||
}
|
||||
status = hid_driver_suspend(hid, message);
|
||||
if (status < 0)
|
||||
goto failed;
|
||||
driver_suspended = true;
|
||||
} else {
|
||||
usbhid_mark_busy(usbhid);
|
||||
|
@ -1602,8 +1600,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
|
||||
} else {
|
||||
/* TODO: resume() might need to handle suspend failure */
|
||||
if (hid->driver && hid->driver->suspend)
|
||||
status = hid->driver->suspend(hid, message);
|
||||
status = hid_driver_suspend(hid, message);
|
||||
driver_suspended = true;
|
||||
spin_lock_irq(&usbhid->lock);
|
||||
set_bit(HID_SUSPENDED, &usbhid->iofl);
|
||||
|
@ -1644,8 +1641,8 @@ static int hid_reset_resume(struct usb_interface *intf)
|
|||
int status;
|
||||
|
||||
status = hid_post_reset(intf);
|
||||
if (status >= 0 && hid->driver && hid->driver->reset_resume) {
|
||||
int ret = hid->driver->reset_resume(hid);
|
||||
if (status >= 0) {
|
||||
int ret = hid_driver_reset_resume(hid);
|
||||
if (ret < 0)
|
||||
status = ret;
|
||||
}
|
||||
|
|
|
@ -923,6 +923,16 @@ s32 hid_snto32(__u32 value, unsigned n);
|
|||
__u32 hid_field_extract(const struct hid_device *hid, __u8 *report,
|
||||
unsigned offset, unsigned n);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int hid_driver_suspend(struct hid_device *hdev, pm_message_t state);
|
||||
int hid_driver_reset_resume(struct hid_device *hdev);
|
||||
int hid_driver_resume(struct hid_device *hdev);
|
||||
#else
|
||||
static inline int hid_driver_suspend(struct hid_device *hdev, pm_message_t state) { return 0; }
|
||||
static inline int hid_driver_reset_resume(struct hid_device *hdev) { return 0; }
|
||||
static inline int hid_driver_resume(struct hid_device *hdev) { return 0; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hid_device_io_start - enable HID input during probe, remove
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue