Commit b1694109 authored by Benjamin Tissoires's avatar Benjamin Tissoires
Browse files

Merge branch 'i2c-hid' into for-linus

- ensure various commands do not interfere with each other (Dmitry
  Torokhov)
parents 6937a82d b4ed18a3
Loading
Loading
Loading
Loading
+27 −15
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ struct i2c_hid {

	wait_queue_head_t	wait;		/* For waiting the interrupt */

	struct mutex		cmd_lock;	/* protects cmdbuf and rawbuf */
	struct mutex		reset_lock;

	struct i2chid_ops	*ops;
@@ -220,6 +221,8 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
static int i2c_hid_read_register(struct i2c_hid *ihid, __le16 reg,
				 void *buf, size_t len)
{
	guard(mutex)(&ihid->cmd_lock);

	*(__le16 *)ihid->cmdbuf = reg;

	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,

	i2c_hid_dbg(ihid, "%s\n", __func__);

	guard(mutex)(&ihid->cmd_lock);

	/* Command register goes first */
	*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
	length += sizeof(__le16);
@@ -342,6 +347,8 @@ static int i2c_hid_set_or_send_report(struct i2c_hid *ihid,
	if (!do_set && le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0)
		return -ENOSYS;

	guard(mutex)(&ihid->cmd_lock);

	if (do_set) {
		/* Command register goes first */
		*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
@@ -384,6 +391,8 @@ static int i2c_hid_set_power_command(struct i2c_hid *ihid, int power_state)
{
	size_t length;

	guard(mutex)(&ihid->cmd_lock);

	/* SET_POWER uses command register */
	*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
	length = sizeof(__le16);
@@ -440,6 +449,7 @@ static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
	if (ret)
		return ret;

	scoped_guard(mutex, &ihid->cmd_lock) {
		/* Prepare reset command. Command register goes first. */
		*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
		length += sizeof(__le16);
@@ -453,12 +463,13 @@ static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
		if (ret) {
			dev_err(&ihid->client->dev,
				"failed to reset device: %d\n", ret);
		goto err_clear_reset;
			break;
		}

		return 0;
	}

err_clear_reset:
	/* Clean up if sending reset command failed */
	clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
	i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
	return ret;
@@ -1200,6 +1211,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
	ihid->is_panel_follower = drm_is_panel_follower(&client->dev);

	init_waitqueue_head(&ihid->wait);
	mutex_init(&ihid->cmd_lock);
	mutex_init(&ihid->reset_lock);
	INIT_WORK(&ihid->panel_follower_prepare_work, ihid_core_panel_prepare_work);