Skip to content

Commit 0fa8ee0

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
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()
2 parents 111e91a + ae3d608 commit 0fa8ee0

8 files changed

Lines changed: 55 additions & 18 deletions

File tree

drivers/input/keyboard/sunkbd.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
9999
switch (data) {
100100

101101
case SUNKBD_RET_RESET:
102-
schedule_work(&sunkbd->tq);
102+
if (sunkbd->enabled)
103+
schedule_work(&sunkbd->tq);
103104
sunkbd->reset = -1;
104105
break;
105106

@@ -200,16 +201,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
200201
}
201202

202203
/*
203-
* sunkbd_reinit() sets leds and beeps to a state the computer remembers they
204-
* were in.
204+
* sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers
205+
* they were in.
205206
*/
206207

207-
static void sunkbd_reinit(struct work_struct *work)
208+
static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
208209
{
209-
struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
210-
211-
wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
212-
213210
serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
214211
serio_write(sunkbd->serio,
215212
(!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) |
@@ -222,11 +219,39 @@ static void sunkbd_reinit(struct work_struct *work)
222219
SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
223220
}
224221

222+
223+
/*
224+
* sunkbd_reinit() wait for the keyboard reset to complete and restores state
225+
* of leds and beeps.
226+
*/
227+
228+
static void sunkbd_reinit(struct work_struct *work)
229+
{
230+
struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
231+
232+
/*
233+
* It is OK that we check sunkbd->enabled without pausing serio,
234+
* as we only want to catch true->false transition that will
235+
* happen once and we will be woken up for it.
236+
*/
237+
wait_event_interruptible_timeout(sunkbd->wait,
238+
sunkbd->reset >= 0 || !sunkbd->enabled,
239+
HZ);
240+
241+
if (sunkbd->reset >= 0 && sunkbd->enabled)
242+
sunkbd_set_leds_beeps(sunkbd);
243+
}
244+
225245
static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
226246
{
227247
serio_pause_rx(sunkbd->serio);
228248
sunkbd->enabled = enable;
229249
serio_continue_rx(sunkbd->serio);
250+
251+
if (!enable) {
252+
wake_up_interruptible(&sunkbd->wait);
253+
cancel_work_sync(&sunkbd->tq);
254+
}
230255
}
231256

232257
/*

drivers/input/misc/adxl34x.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
696696
struct input_dev *input_dev;
697697
const struct adxl34x_platform_data *pdata;
698698
int err, range, i;
699-
unsigned char revid;
699+
int revid;
700700

701701
if (!irq) {
702702
dev_err(dev, "no IRQ?\n");

drivers/input/mouse/elan_i2c.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct elan_transport_ops {
7878
int (*iap_reset)(struct i2c_client *client);
7979

8080
int (*prepare_fw_update)(struct i2c_client *client, u16 ic_type,
81-
u8 iap_version);
81+
u8 iap_version, u16 fw_page_size);
8282
int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size,
8383
const u8 *page, u16 checksum, int idx);
8484
int (*finish_fw_update)(struct i2c_client *client,

drivers/input/mouse/elan_i2c_core.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ static int __elan_update_firmware(struct elan_tp_data *data,
497497
u16 sw_checksum = 0, fw_checksum = 0;
498498

499499
error = data->ops->prepare_fw_update(client, data->ic_type,
500-
data->iap_version);
500+
data->iap_version,
501+
data->fw_page_size);
501502
if (error)
502503
return error;
503504

drivers/input/mouse/elan_i2c_i2c.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ static int elan_i2c_set_flash_key(struct i2c_client *client)
517517
return 0;
518518
}
519519

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

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

546-
if (constant == ETP_I2C_IAP_TYPE_REG)
546+
if (constant == fw_page_size / 2)
547547
return 0;
548548

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

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

596596
if (ic_type >= 0x0D && iap_version >= 1) {
597-
error = elan_read_write_iap_type(client);
597+
error = elan_read_write_iap_type(client, fw_page_size);
598598
if (error)
599599
return error;
600600
}

drivers/input/mouse/elan_i2c_smbus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ static int elan_smbus_set_flash_key(struct i2c_client *client)
340340
}
341341

342342
static int elan_smbus_prepare_fw_update(struct i2c_client *client, u16 ic_type,
343-
u8 iap_version)
343+
u8 iap_version, u16 fw_page_size)
344344
{
345345
struct device *dev = &client->dev;
346346
int len;

drivers/input/serio/i8042.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ module_param_named(unmask_kbd_data, i8042_unmask_kbd_data, bool, 0600);
122122
MODULE_PARM_DESC(unmask_kbd_data, "Unconditional enable (may reveal sensitive data) of normally sanitize-filtered kbd data traffic debug log [pre-condition: i8042.debug=1 enabled]");
123123
#endif
124124

125+
static bool i8042_present;
125126
static bool i8042_bypass_aux_irq_test;
126127
static char i8042_kbd_firmware_id[128];
127128
static char i8042_aux_firmware_id[128];
@@ -343,6 +344,9 @@ int i8042_command(unsigned char *param, int command)
343344
unsigned long flags;
344345
int retval;
345346

347+
if (!i8042_present)
348+
return -1;
349+
346350
spin_lock_irqsave(&i8042_lock, flags);
347351
retval = __i8042_command(param, command);
348352
spin_unlock_irqrestore(&i8042_lock, flags);
@@ -1612,12 +1616,15 @@ static int __init i8042_init(void)
16121616

16131617
err = i8042_platform_init();
16141618
if (err)
1615-
return err;
1619+
return (err == -ENODEV) ? 0 : err;
16161620

16171621
err = i8042_controller_check();
16181622
if (err)
16191623
goto err_platform_exit;
16201624

1625+
/* Set this before creating the dev to allow i8042_command to work right away */
1626+
i8042_present = true;
1627+
16211628
pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0);
16221629
if (IS_ERR(pdev)) {
16231630
err = PTR_ERR(pdev);
@@ -1636,6 +1643,9 @@ static int __init i8042_init(void)
16361643

16371644
static void __exit i8042_exit(void)
16381645
{
1646+
if (!i8042_present)
1647+
return;
1648+
16391649
platform_device_unregister(i8042_platform_device);
16401650
platform_driver_unregister(&i8042_driver);
16411651
i8042_platform_exit();

drivers/input/touchscreen/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ config TOUCHSCREEN_AD7879_SPI
9696
config TOUCHSCREEN_ADC
9797
tristate "Generic ADC based resistive touchscreen"
9898
depends on IIO
99+
select IIO_BUFFER
99100
select IIO_BUFFER_CB
100101
help
101102
Say Y here if you want to use the generic ADC

0 commit comments

Comments
 (0)