Commit 9e356208 authored by Benjamin Tissoires's avatar Benjamin Tissoires
Browse files

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: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20211202095334.14399-4-benjamin.tissoires@redhat.com
parent 740bebf4
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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;
+4 −11
Original line number Diff line number Diff line
@@ -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);
	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

+5 −20
Original line number Diff line number Diff line
@@ -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 = {
+8 −11
Original line number Diff line number Diff line
@@ -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);
			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;
	}
+10 −0
Original line number Diff line number Diff line
@@ -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
 *