Skip to content

Commit 675cd87

Browse files
committed
HID: i2c-hid: Rearrange probe() to power things up later
In a future patch, we want to change i2c-hid not to necessarily power up the touchscreen during probe. In preparation for that, rearrange the probe function so that we put as much stuff _before_ powering up the device as possible. This change is expected to have no functional effect. Reviewed-by: Maxime Ripard <[email protected]> Reviewed-by: Benjamin Tissoires <[email protected]> Acked-by: Benjamin Tissoires <[email protected]> Signed-off-by: Douglas Anderson <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/20230727101636.v4.6.Ifcc9b0a44895d164788966f9b9511fe094ca8cf9@changeid
1 parent a889ee1 commit 675cd87

File tree

1 file changed

+77
-47
lines changed

1 file changed

+77
-47
lines changed

drivers/hid/i2c-hid/i2c-hid-core.c

Lines changed: 77 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,8 @@ static int i2c_hid_init_irq(struct i2c_client *client)
855855
irqflags = IRQF_TRIGGER_LOW;
856856

857857
ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq,
858-
irqflags | IRQF_ONESHOT, client->name, ihid);
858+
irqflags | IRQF_ONESHOT | IRQF_NO_AUTOEN,
859+
client->name, ihid);
859860
if (ret < 0) {
860861
dev_warn(&client->dev,
861862
"Could not register for %s interrupt, irq = %d,"
@@ -940,6 +941,72 @@ static void i2c_hid_core_shutdown_tail(struct i2c_hid *ihid)
940941
ihid->ops->shutdown_tail(ihid->ops);
941942
}
942943

944+
/**
945+
* i2c_hid_core_initial_power_up() - First time power up of the i2c-hid device.
946+
* @ihid: The ihid object created during probe.
947+
*
948+
* This function is called at probe time.
949+
*
950+
* The initial power on is where we do some basic validation that the device
951+
* exists, where we fetch the HID descriptor, and where we create the actual
952+
* HID devices.
953+
*
954+
* Return: 0 or error code.
955+
*/
956+
static int i2c_hid_core_initial_power_up(struct i2c_hid *ihid)
957+
{
958+
struct i2c_client *client = ihid->client;
959+
struct hid_device *hid = ihid->hid;
960+
int ret;
961+
962+
ret = i2c_hid_core_power_up(ihid);
963+
if (ret)
964+
return ret;
965+
966+
/* Make sure there is something at this address */
967+
ret = i2c_smbus_read_byte(client);
968+
if (ret < 0) {
969+
i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
970+
ret = -ENXIO;
971+
goto err;
972+
}
973+
974+
ret = i2c_hid_fetch_hid_descriptor(ihid);
975+
if (ret < 0) {
976+
dev_err(&client->dev,
977+
"Failed to fetch the HID Descriptor\n");
978+
goto err;
979+
}
980+
981+
enable_irq(client->irq);
982+
983+
hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
984+
hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
985+
hid->product = le16_to_cpu(ihid->hdesc.wProductID);
986+
987+
hid->initial_quirks |= i2c_hid_get_dmi_quirks(hid->vendor,
988+
hid->product);
989+
990+
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
991+
client->name, (u16)hid->vendor, (u16)hid->product);
992+
strscpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
993+
994+
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
995+
996+
ret = hid_add_device(hid);
997+
if (ret) {
998+
if (ret != -ENODEV)
999+
hid_err(client, "can't add hid device: %d\n", ret);
1000+
goto err;
1001+
}
1002+
1003+
return 0;
1004+
1005+
err:
1006+
i2c_hid_core_power_down(ihid);
1007+
return ret;
1008+
}
1009+
9431010
int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
9441011
u16 hid_descriptor_address, u32 quirks)
9451012
{
@@ -966,16 +1033,10 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
9661033
if (!ihid)
9671034
return -ENOMEM;
9681035

969-
ihid->ops = ops;
970-
971-
ret = i2c_hid_core_power_up(ihid);
972-
if (ret)
973-
return ret;
974-
9751036
i2c_set_clientdata(client, ihid);
9761037

1038+
ihid->ops = ops;
9771039
ihid->client = client;
978-
9791040
ihid->wHIDDescRegister = cpu_to_le16(hid_descriptor_address);
9801041

9811042
init_waitqueue_head(&ihid->wait);
@@ -986,28 +1047,12 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
9861047
* real computation later. */
9871048
ret = i2c_hid_alloc_buffers(ihid, HID_MIN_BUFFER_SIZE);
9881049
if (ret < 0)
989-
goto err_powered;
990-
1050+
return ret;
9911051
device_enable_async_suspend(&client->dev);
9921052

993-
/* Make sure there is something at this address */
994-
ret = i2c_smbus_read_byte(client);
995-
if (ret < 0) {
996-
i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
997-
ret = -ENXIO;
998-
goto err_powered;
999-
}
1000-
1001-
ret = i2c_hid_fetch_hid_descriptor(ihid);
1002-
if (ret < 0) {
1003-
dev_err(&client->dev,
1004-
"Failed to fetch the HID Descriptor\n");
1005-
goto err_powered;
1006-
}
1007-
10081053
ret = i2c_hid_init_irq(client);
10091054
if (ret < 0)
1010-
goto err_powered;
1055+
goto err_buffers_allocated;
10111056

10121057
hid = hid_allocate_device();
10131058
if (IS_ERR(hid)) {
@@ -1021,26 +1066,11 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
10211066
hid->ll_driver = &i2c_hid_ll_driver;
10221067
hid->dev.parent = &client->dev;
10231068
hid->bus = BUS_I2C;
1024-
hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
1025-
hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
1026-
hid->product = le16_to_cpu(ihid->hdesc.wProductID);
1027-
10281069
hid->initial_quirks = quirks;
1029-
hid->initial_quirks |= i2c_hid_get_dmi_quirks(hid->vendor,
1030-
hid->product);
1031-
1032-
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
1033-
client->name, (u16)hid->vendor, (u16)hid->product);
1034-
strscpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
1035-
1036-
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
10371070

1038-
ret = hid_add_device(hid);
1039-
if (ret) {
1040-
if (ret != -ENODEV)
1041-
hid_err(client, "can't add hid device: %d\n", ret);
1071+
ret = i2c_hid_core_initial_power_up(ihid);
1072+
if (ret)
10421073
goto err_mem_free;
1043-
}
10441074

10451075
return 0;
10461076

@@ -1050,9 +1080,9 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
10501080
err_irq:
10511081
free_irq(client->irq, ihid);
10521082

1053-
err_powered:
1054-
i2c_hid_core_power_down(ihid);
1083+
err_buffers_allocated:
10551084
i2c_hid_free_buffers(ihid);
1085+
10561086
return ret;
10571087
}
10581088
EXPORT_SYMBOL_GPL(i2c_hid_core_probe);
@@ -1062,15 +1092,15 @@ void i2c_hid_core_remove(struct i2c_client *client)
10621092
struct i2c_hid *ihid = i2c_get_clientdata(client);
10631093
struct hid_device *hid;
10641094

1095+
i2c_hid_core_power_down(ihid);
1096+
10651097
hid = ihid->hid;
10661098
hid_destroy_device(hid);
10671099

10681100
free_irq(client->irq, ihid);
10691101

10701102
if (ihid->bufsize)
10711103
i2c_hid_free_buffers(ihid);
1072-
1073-
i2c_hid_core_power_down(ihid);
10741104
}
10751105
EXPORT_SYMBOL_GPL(i2c_hid_core_remove);
10761106

0 commit comments

Comments
 (0)