@@ -105,6 +105,7 @@ struct i2c_hid {
105105
106106 wait_queue_head_t wait ; /* For waiting the interrupt */
107107
108+ struct mutex cmd_lock ; /* protects cmdbuf and rawbuf */
108109 struct mutex reset_lock ;
109110
110111 struct i2chid_ops * ops ;
@@ -220,6 +221,8 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
220221static int i2c_hid_read_register (struct i2c_hid * ihid , __le16 reg ,
221222 void * buf , size_t len )
222223{
224+ guard (mutex )(& ihid -> cmd_lock );
225+
223226 * (__le16 * )ihid -> cmdbuf = reg ;
224227
225228 return i2c_hid_xfer (ihid , ihid -> cmdbuf , sizeof (__le16 ), buf , len );
@@ -252,6 +255,8 @@ static int i2c_hid_get_report(struct i2c_hid *ihid,
252255
253256 i2c_hid_dbg (ihid , "%s\n" , __func__ );
254257
258+ guard (mutex )(& ihid -> cmd_lock );
259+
255260 /* Command register goes first */
256261 * (__le16 * )ihid -> cmdbuf = ihid -> hdesc .wCommandRegister ;
257262 length += sizeof (__le16 );
@@ -342,6 +347,8 @@ static int i2c_hid_set_or_send_report(struct i2c_hid *ihid,
342347 if (!do_set && le16_to_cpu (ihid -> hdesc .wMaxOutputLength ) == 0 )
343348 return - ENOSYS ;
344349
350+ guard (mutex )(& ihid -> cmd_lock );
351+
345352 if (do_set ) {
346353 /* Command register goes first */
347354 * (__le16 * )ihid -> cmdbuf = ihid -> hdesc .wCommandRegister ;
@@ -384,6 +391,8 @@ static int i2c_hid_set_power_command(struct i2c_hid *ihid, int power_state)
384391{
385392 size_t length ;
386393
394+ guard (mutex )(& ihid -> cmd_lock );
395+
387396 /* SET_POWER uses command register */
388397 * (__le16 * )ihid -> cmdbuf = ihid -> hdesc .wCommandRegister ;
389398 length = sizeof (__le16 );
@@ -440,25 +449,27 @@ static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
440449 if (ret )
441450 return ret ;
442451
443- /* Prepare reset command. Command register goes first. */
444- * (__le16 * )ihid -> cmdbuf = ihid -> hdesc .wCommandRegister ;
445- length += sizeof (__le16 );
446- /* Next is RESET command itself */
447- length += i2c_hid_encode_command (ihid -> cmdbuf + length ,
448- I2C_HID_OPCODE_RESET , 0 , 0 );
452+ scoped_guard (mutex , & ihid -> cmd_lock ) {
453+ /* Prepare reset command. Command register goes first. */
454+ * (__le16 * )ihid -> cmdbuf = ihid -> hdesc .wCommandRegister ;
455+ length += sizeof (__le16 );
456+ /* Next is RESET command itself */
457+ length += i2c_hid_encode_command (ihid -> cmdbuf + length ,
458+ I2C_HID_OPCODE_RESET , 0 , 0 );
449459
450- set_bit (I2C_HID_RESET_PENDING , & ihid -> flags );
460+ set_bit (I2C_HID_RESET_PENDING , & ihid -> flags );
451461
452- ret = i2c_hid_xfer (ihid , ihid -> cmdbuf , length , NULL , 0 );
453- if (ret ) {
454- dev_err (& ihid -> client -> dev ,
455- "failed to reset device: %d\n" , ret );
456- goto err_clear_reset ;
457- }
462+ ret = i2c_hid_xfer (ihid , ihid -> cmdbuf , length , NULL , 0 );
463+ if (ret ) {
464+ dev_err (& ihid -> client -> dev ,
465+ "failed to reset device: %d\n" , ret );
466+ break ;
467+ }
458468
459- return 0 ;
469+ return 0 ;
470+ }
460471
461- err_clear_reset :
472+ /* Clean up if sending reset command failed */
462473 clear_bit (I2C_HID_RESET_PENDING , & ihid -> flags );
463474 i2c_hid_set_power (ihid , I2C_HID_PWR_SLEEP );
464475 return ret ;
@@ -1200,6 +1211,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
12001211 ihid -> is_panel_follower = drm_is_panel_follower (& client -> dev );
12011212
12021213 init_waitqueue_head (& ihid -> wait );
1214+ mutex_init (& ihid -> cmd_lock );
12031215 mutex_init (& ihid -> reset_lock );
12041216 INIT_WORK (& ihid -> panel_follower_prepare_work , ihid_core_panel_prepare_work );
12051217
0 commit comments