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);
|
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 hid_dynid {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct hid_device_id id;
|
struct hid_device_id id;
|
||||||
|
@ -1063,11 +1063,9 @@ static int i2c_hid_core_suspend(struct device *dev)
|
|||||||
int ret;
|
int ret;
|
||||||
int wake_status;
|
int wake_status;
|
||||||
|
|
||||||
if (hid->driver && hid->driver->suspend) {
|
ret = hid_driver_suspend(hid, PMSG_SUSPEND);
|
||||||
ret = hid->driver->suspend(hid, PMSG_SUSPEND);
|
if (ret < 0)
|
||||||
if (ret < 0)
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save some power */
|
/* Save some power */
|
||||||
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
|
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
|
||||||
@ -1125,12 +1123,7 @@ static int i2c_hid_core_resume(struct device *dev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (hid->driver && hid->driver->reset_resume) {
|
return hid_driver_reset_resume(hid);
|
||||||
ret = hid->driver->reset_resume(hid);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -204,50 +204,35 @@ static int surface_hid_suspend(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (d->hid->driver && d->hid->driver->suspend)
|
return hid_driver_suspend(d->hid, PMSG_SUSPEND);
|
||||||
return d->hid->driver->suspend(d->hid, PMSG_SUSPEND);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int surface_hid_resume(struct device *dev)
|
static int surface_hid_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (d->hid->driver && d->hid->driver->resume)
|
return hid_driver_resume(d->hid);
|
||||||
return d->hid->driver->resume(d->hid);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int surface_hid_freeze(struct device *dev)
|
static int surface_hid_freeze(struct device *dev)
|
||||||
{
|
{
|
||||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (d->hid->driver && d->hid->driver->suspend)
|
return hid_driver_suspend(d->hid, PMSG_FREEZE);
|
||||||
return d->hid->driver->suspend(d->hid, PMSG_FREEZE);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int surface_hid_poweroff(struct device *dev)
|
static int surface_hid_poweroff(struct device *dev)
|
||||||
{
|
{
|
||||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (d->hid->driver && d->hid->driver->suspend)
|
return hid_driver_suspend(d->hid, PMSG_HIBERNATE);
|
||||||
return d->hid->driver->suspend(d->hid, PMSG_HIBERNATE);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int surface_hid_restore(struct device *dev)
|
static int surface_hid_restore(struct device *dev)
|
||||||
{
|
{
|
||||||
struct surface_hid_device *d = dev_get_drvdata(dev);
|
struct surface_hid_device *d = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (d->hid->driver && d->hid->driver->reset_resume)
|
return hid_driver_reset_resume(d->hid);
|
||||||
return d->hid->driver->reset_resume(d->hid);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct dev_pm_ops surface_hid_pm_ops = {
|
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;
|
int status = 0;
|
||||||
|
|
||||||
hid_restart_io(hid);
|
hid_restart_io(hid);
|
||||||
if (driver_suspended && hid->driver && hid->driver->resume)
|
if (driver_suspended)
|
||||||
status = hid->driver->resume(hid);
|
status = hid_driver_resume(hid);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1588,11 +1588,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
|
|||||||
{
|
{
|
||||||
set_bit(HID_SUSPENDED, &usbhid->iofl);
|
set_bit(HID_SUSPENDED, &usbhid->iofl);
|
||||||
spin_unlock_irq(&usbhid->lock);
|
spin_unlock_irq(&usbhid->lock);
|
||||||
if (hid->driver && hid->driver->suspend) {
|
status = hid_driver_suspend(hid, message);
|
||||||
status = hid->driver->suspend(hid, message);
|
if (status < 0)
|
||||||
if (status < 0)
|
goto failed;
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
driver_suspended = true;
|
driver_suspended = true;
|
||||||
} else {
|
} else {
|
||||||
usbhid_mark_busy(usbhid);
|
usbhid_mark_busy(usbhid);
|
||||||
@ -1602,8 +1600,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* TODO: resume() might need to handle suspend failure */
|
/* 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;
|
driver_suspended = true;
|
||||||
spin_lock_irq(&usbhid->lock);
|
spin_lock_irq(&usbhid->lock);
|
||||||
set_bit(HID_SUSPENDED, &usbhid->iofl);
|
set_bit(HID_SUSPENDED, &usbhid->iofl);
|
||||||
@ -1644,8 +1641,8 @@ static int hid_reset_resume(struct usb_interface *intf)
|
|||||||
int status;
|
int status;
|
||||||
|
|
||||||
status = hid_post_reset(intf);
|
status = hid_post_reset(intf);
|
||||||
if (status >= 0 && hid->driver && hid->driver->reset_resume) {
|
if (status >= 0) {
|
||||||
int ret = hid->driver->reset_resume(hid);
|
int ret = hid_driver_reset_resume(hid);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
status = ret;
|
status = ret;
|
||||||
}
|
}
|
||||||
|
@ -923,6 +923,16 @@ s32 hid_snto32(__u32 value, unsigned n);
|
|||||||
__u32 hid_field_extract(const struct hid_device *hid, __u8 *report,
|
__u32 hid_field_extract(const struct hid_device *hid, __u8 *report,
|
||||||
unsigned offset, unsigned n);
|
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
|
* hid_device_io_start - enable HID input during probe, remove
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user