Skip to content

Commit bab19d1

Browse files
committed
Merge tag 'for-linus-2023101101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Benjamin Tissoires: - regression fix for i2c-hid when used on DT platforms (Johan Hovold) - kernel crash fix on removal of the Logitech USB receiver (Hans de Goede) * tag 'for-linus-2023101101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: logitech-hidpp: Fix kernel crash on receiver USB disconnect HID: i2c-hid: fix handling of unpopulated devices
2 parents 4524565 + dac5013 commit bab19d1

File tree

2 files changed

+83
-64
lines changed

2 files changed

+83
-64
lines changed

drivers/hid/hid-logitech-hidpp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4515,7 +4515,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
45154515
goto hid_hw_init_fail;
45164516
}
45174517

4518-
hidpp_connect_event(hidpp);
4518+
schedule_work(&hidpp->work);
4519+
flush_work(&hidpp->work);
45194520

45204521
if (will_restart) {
45214522
/* Reset the HID node state */

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

Lines changed: 81 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -998,45 +998,29 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
998998
return hid_driver_reset_resume(hid);
999999
}
10001000

1001-
/**
1002-
* __do_i2c_hid_core_initial_power_up() - First time power up of the i2c-hid device.
1003-
* @ihid: The ihid object created during probe.
1004-
*
1005-
* This function is called at probe time.
1006-
*
1007-
* The initial power on is where we do some basic validation that the device
1008-
* exists, where we fetch the HID descriptor, and where we create the actual
1009-
* HID devices.
1010-
*
1011-
* Return: 0 or error code.
1001+
/*
1002+
* Check that the device exists and parse the HID descriptor.
10121003
*/
1013-
static int __do_i2c_hid_core_initial_power_up(struct i2c_hid *ihid)
1004+
static int __i2c_hid_core_probe(struct i2c_hid *ihid)
10141005
{
10151006
struct i2c_client *client = ihid->client;
10161007
struct hid_device *hid = ihid->hid;
10171008
int ret;
10181009

1019-
ret = i2c_hid_core_power_up(ihid);
1020-
if (ret)
1021-
return ret;
1022-
10231010
/* Make sure there is something at this address */
10241011
ret = i2c_smbus_read_byte(client);
10251012
if (ret < 0) {
10261013
i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
1027-
ret = -ENXIO;
1028-
goto err;
1014+
return -ENXIO;
10291015
}
10301016

10311017
ret = i2c_hid_fetch_hid_descriptor(ihid);
10321018
if (ret < 0) {
10331019
dev_err(&client->dev,
10341020
"Failed to fetch the HID Descriptor\n");
1035-
goto err;
1021+
return ret;
10361022
}
10371023

1038-
enable_irq(client->irq);
1039-
10401024
hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
10411025
hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
10421026
hid->product = le16_to_cpu(ihid->hdesc.wProductID);
@@ -1050,17 +1034,49 @@ static int __do_i2c_hid_core_initial_power_up(struct i2c_hid *ihid)
10501034

10511035
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
10521036

1037+
return 0;
1038+
}
1039+
1040+
static int i2c_hid_core_register_hid(struct i2c_hid *ihid)
1041+
{
1042+
struct i2c_client *client = ihid->client;
1043+
struct hid_device *hid = ihid->hid;
1044+
int ret;
1045+
1046+
enable_irq(client->irq);
1047+
10531048
ret = hid_add_device(hid);
10541049
if (ret) {
10551050
if (ret != -ENODEV)
10561051
hid_err(client, "can't add hid device: %d\n", ret);
1057-
goto err;
1052+
disable_irq(client->irq);
1053+
return ret;
10581054
}
10591055

10601056
return 0;
1057+
}
1058+
1059+
static int i2c_hid_core_probe_panel_follower(struct i2c_hid *ihid)
1060+
{
1061+
int ret;
1062+
1063+
ret = i2c_hid_core_power_up(ihid);
1064+
if (ret)
1065+
return ret;
10611066

1062-
err:
1067+
ret = __i2c_hid_core_probe(ihid);
1068+
if (ret)
1069+
goto err_power_down;
1070+
1071+
ret = i2c_hid_core_register_hid(ihid);
1072+
if (ret)
1073+
goto err_power_down;
1074+
1075+
return 0;
1076+
1077+
err_power_down:
10631078
i2c_hid_core_power_down(ihid);
1079+
10641080
return ret;
10651081
}
10661082

@@ -1077,7 +1093,7 @@ static void ihid_core_panel_prepare_work(struct work_struct *work)
10771093
* steps.
10781094
*/
10791095
if (!hid->version)
1080-
ret = __do_i2c_hid_core_initial_power_up(ihid);
1096+
ret = i2c_hid_core_probe_panel_follower(ihid);
10811097
else
10821098
ret = i2c_hid_core_resume(ihid);
10831099

@@ -1136,7 +1152,6 @@ static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid)
11361152
struct device *dev = &ihid->client->dev;
11371153
int ret;
11381154

1139-
ihid->is_panel_follower = true;
11401155
ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_funcs;
11411156

11421157
/*
@@ -1156,30 +1171,6 @@ static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid)
11561171
return 0;
11571172
}
11581173

1159-
static int i2c_hid_core_initial_power_up(struct i2c_hid *ihid)
1160-
{
1161-
/*
1162-
* If we're a panel follower, we'll register and do our initial power
1163-
* up when the panel turns on; otherwise we do it right away.
1164-
*/
1165-
if (drm_is_panel_follower(&ihid->client->dev))
1166-
return i2c_hid_core_register_panel_follower(ihid);
1167-
else
1168-
return __do_i2c_hid_core_initial_power_up(ihid);
1169-
}
1170-
1171-
static void i2c_hid_core_final_power_down(struct i2c_hid *ihid)
1172-
{
1173-
/*
1174-
* If we're a follower, the act of unfollowing will cause us to be
1175-
* powered down. Otherwise we need to manually do it.
1176-
*/
1177-
if (ihid->is_panel_follower)
1178-
drm_panel_remove_follower(&ihid->panel_follower);
1179-
else
1180-
i2c_hid_core_suspend(ihid, true);
1181-
}
1182-
11831174
int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
11841175
u16 hid_descriptor_address, u32 quirks)
11851176
{
@@ -1211,6 +1202,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
12111202
ihid->ops = ops;
12121203
ihid->client = client;
12131204
ihid->wHIDDescRegister = cpu_to_le16(hid_descriptor_address);
1205+
ihid->is_panel_follower = drm_is_panel_follower(&client->dev);
12141206

12151207
init_waitqueue_head(&ihid->wait);
12161208
mutex_init(&ihid->reset_lock);
@@ -1224,14 +1216,10 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
12241216
return ret;
12251217
device_enable_async_suspend(&client->dev);
12261218

1227-
ret = i2c_hid_init_irq(client);
1228-
if (ret < 0)
1229-
goto err_buffers_allocated;
1230-
12311219
hid = hid_allocate_device();
12321220
if (IS_ERR(hid)) {
12331221
ret = PTR_ERR(hid);
1234-
goto err_irq;
1222+
goto err_free_buffers;
12351223
}
12361224

12371225
ihid->hid = hid;
@@ -1242,19 +1230,42 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
12421230
hid->bus = BUS_I2C;
12431231
hid->initial_quirks = quirks;
12441232

1245-
ret = i2c_hid_core_initial_power_up(ihid);
1233+
/* Power on and probe unless device is a panel follower. */
1234+
if (!ihid->is_panel_follower) {
1235+
ret = i2c_hid_core_power_up(ihid);
1236+
if (ret < 0)
1237+
goto err_destroy_device;
1238+
1239+
ret = __i2c_hid_core_probe(ihid);
1240+
if (ret < 0)
1241+
goto err_power_down;
1242+
}
1243+
1244+
ret = i2c_hid_init_irq(client);
1245+
if (ret < 0)
1246+
goto err_power_down;
1247+
1248+
/*
1249+
* If we're a panel follower, we'll register when the panel turns on;
1250+
* otherwise we do it right away.
1251+
*/
1252+
if (ihid->is_panel_follower)
1253+
ret = i2c_hid_core_register_panel_follower(ihid);
1254+
else
1255+
ret = i2c_hid_core_register_hid(ihid);
12461256
if (ret)
1247-
goto err_mem_free;
1257+
goto err_free_irq;
12481258

12491259
return 0;
12501260

1251-
err_mem_free:
1252-
hid_destroy_device(hid);
1253-
1254-
err_irq:
1261+
err_free_irq:
12551262
free_irq(client->irq, ihid);
1256-
1257-
err_buffers_allocated:
1263+
err_power_down:
1264+
if (!ihid->is_panel_follower)
1265+
i2c_hid_core_power_down(ihid);
1266+
err_destroy_device:
1267+
hid_destroy_device(hid);
1268+
err_free_buffers:
12581269
i2c_hid_free_buffers(ihid);
12591270

12601271
return ret;
@@ -1266,7 +1277,14 @@ void i2c_hid_core_remove(struct i2c_client *client)
12661277
struct i2c_hid *ihid = i2c_get_clientdata(client);
12671278
struct hid_device *hid;
12681279

1269-
i2c_hid_core_final_power_down(ihid);
1280+
/*
1281+
* If we're a follower, the act of unfollowing will cause us to be
1282+
* powered down. Otherwise we need to manually do it.
1283+
*/
1284+
if (ihid->is_panel_follower)
1285+
drm_panel_remove_follower(&ihid->panel_follower);
1286+
else
1287+
i2c_hid_core_suspend(ihid, true);
12701288

12711289
hid = ihid->hid;
12721290
hid_destroy_device(hid);

0 commit comments

Comments
 (0)