Commit 5c7e02a8 authored by Hans de Goede's avatar Hans de Goede Committed by Jiri Kosina
Browse files

HID: i2c-hid: Put ACPI enumerated devices in D3 on shutdown



The i2c-hid driver would quietly fail to probe the i2c-hid sensor-hub
with an ACPI device-id of SMO91D0 every other boot.

Specifically, the i2c_smbus_read_byte() "Make sure there is something at
this address" check would fail every other boot.

It seems that the BIOS does not properly reset/power-cycle the device
leaving it in a confused state where it refuses to respond to i2c-xfers.
On boots where probing the device failed, the driver-core puts the device
in D3 after the probe-failure, which causes the probe to succeed the next
boot.

Putting the device in D3 from the shutdown-handler fixes the sensors not
working every other boot.

This has been tested on both a Lenovo Miix 2-10 and a Dell Venue 8 Pro 5830
both of which use an i2c-hid sensor-hub with an ACPI id of SMO91D0.

Note that it is safe to call acpi_device_set_power() with a NULL pointer
as first argument, so on none ACPI enumerated devices this change is a
no-op.

Cc: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Acked-by: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 1811977c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -943,6 +943,11 @@ static void i2c_hid_acpi_enable_wakeup(struct device *dev)
	}
}

static void i2c_hid_acpi_shutdown(struct device *dev)
{
	acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D3_COLD);
}

static const struct acpi_device_id i2c_hid_acpi_match[] = {
	{"ACPI0C50", 0 },
	{"PNP0C50", 0 },
@@ -959,6 +964,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {}

static inline void i2c_hid_acpi_enable_wakeup(struct device *dev) {}

static inline void i2c_hid_acpi_shutdown(struct device *dev) {}
#endif

#ifdef CONFIG_OF
@@ -1175,6 +1182,8 @@ static void i2c_hid_shutdown(struct i2c_client *client)

	i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
	free_irq(client->irq, ihid);

	i2c_hid_acpi_shutdown(&client->dev);
}

#ifdef CONFIG_PM_SLEEP