Commit 0fa8ee0d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull input fixes from Dmitry Torokhov:
 "A fix for use-after-free in the Sun keyboard driver, a fix to firmware
  updates on newer ICs in the Elan touchpad diver, and a couple misc
  driver fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: elan_i2c - fix firmware update on newer ICs
  Input: resistive-adc-touch - fix kconfig dependency on IIO_BUFFER
  Input: sunkbd - avoid use-after-free in teardown paths
  Input: i8042 - allow insmod to succeed on devices without an i8042 controller
  Input: adxl34x - clean up a data type in adxl34x_probe()
parents 111e91a6 ae3d6083
Loading
Loading
Loading
Loading
+33 −8
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
	switch (data) {

	case SUNKBD_RET_RESET:
		if (sunkbd->enabled)
			schedule_work(&sunkbd->tq);
		sunkbd->reset = -1;
		break;
@@ -200,16 +201,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
}

/*
 * sunkbd_reinit() sets leds and beeps to a state the computer remembers they
 * were in.
 * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers
 * they were in.
 */

static void sunkbd_reinit(struct work_struct *work)
static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
{
	struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);

	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);

	serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
	serio_write(sunkbd->serio,
		(!!test_bit(LED_CAPSL,   sunkbd->dev->led) << 3) |
@@ -222,11 +219,39 @@ static void sunkbd_reinit(struct work_struct *work)
		SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
}


/*
 * sunkbd_reinit() wait for the keyboard reset to complete and restores state
 * of leds and beeps.
 */

static void sunkbd_reinit(struct work_struct *work)
{
	struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);

	/*
	 * It is OK that we check sunkbd->enabled without pausing serio,
	 * as we only want to catch true->false transition that will
	 * happen once and we will be woken up for it.
	 */
	wait_event_interruptible_timeout(sunkbd->wait,
					 sunkbd->reset >= 0 || !sunkbd->enabled,
					 HZ);

	if (sunkbd->reset >= 0 && sunkbd->enabled)
		sunkbd_set_leds_beeps(sunkbd);
}

static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
{
	serio_pause_rx(sunkbd->serio);
	sunkbd->enabled = enable;
	serio_continue_rx(sunkbd->serio);

	if (!enable) {
		wake_up_interruptible(&sunkbd->wait);
		cancel_work_sync(&sunkbd->tq);
	}
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -696,7 +696,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
	struct input_dev *input_dev;
	const struct adxl34x_platform_data *pdata;
	int err, range, i;
	unsigned char revid;
	int revid;

	if (!irq) {
		dev_err(dev, "no IRQ?\n");
+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ struct elan_transport_ops {
	int (*iap_reset)(struct i2c_client *client);

	int (*prepare_fw_update)(struct i2c_client *client, u16 ic_type,
				 u8 iap_version);
				 u8 iap_version, u16 fw_page_size);
	int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size,
			      const u8 *page, u16 checksum, int idx);
	int (*finish_fw_update)(struct i2c_client *client,
+2 −1
Original line number Diff line number Diff line
@@ -497,7 +497,8 @@ static int __elan_update_firmware(struct elan_tp_data *data,
	u16 sw_checksum = 0, fw_checksum = 0;

	error = data->ops->prepare_fw_update(client, data->ic_type,
					     data->iap_version);
					     data->iap_version,
					     data->fw_page_size);
	if (error)
		return error;

+5 −5
Original line number Diff line number Diff line
@@ -517,7 +517,7 @@ static int elan_i2c_set_flash_key(struct i2c_client *client)
	return 0;
}

static int elan_read_write_iap_type(struct i2c_client *client)
static int elan_read_write_iap_type(struct i2c_client *client, u16 fw_page_size)
{
	int error;
	u16 constant;
@@ -526,7 +526,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)

	do {
		error = elan_i2c_write_cmd(client, ETP_I2C_IAP_TYPE_CMD,
					   ETP_I2C_IAP_TYPE_REG);
					   fw_page_size / 2);
		if (error) {
			dev_err(&client->dev,
				"cannot write iap type: %d\n", error);
@@ -543,7 +543,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
		constant = le16_to_cpup((__le16 *)val);
		dev_dbg(&client->dev, "iap type reg: 0x%04x\n", constant);

		if (constant == ETP_I2C_IAP_TYPE_REG)
		if (constant == fw_page_size / 2)
			return 0;

	} while (--retry > 0);
@@ -553,7 +553,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
}

static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
				      u8 iap_version)
				      u8 iap_version, u16 fw_page_size)
{
	struct device *dev = &client->dev;
	int error;
@@ -594,7 +594,7 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
	}

	if (ic_type >= 0x0D && iap_version >= 1) {
		error = elan_read_write_iap_type(client);
		error = elan_read_write_iap_type(client, fw_page_size);
		if (error)
			return error;
	}
Loading