Skip to content

Commit 9222ba6

Browse files
tiwaidtor
authored andcommitted
Input: i8042 - add deferred probe support
We've got a bug report about the non-working keyboard on ASUS ZenBook UX425UA. It seems that the PS/2 device isn't ready immediately at boot but takes some seconds to get ready. Until now, the only workaround is to defer the probe, but it's available only when the driver is a module. However, many distros, including openSUSE as in the original report, build the PS/2 input drivers into kernel, hence it won't work easily. This patch adds the support for the deferred probe for i8042 stuff as a workaround of the problem above. When the deferred probe mode is enabled and the device couldn't be probed, it'll be repeated with the standard deferred probe mechanism. The deferred probe mode is enabled either via the new option i8042.probe_defer or via the quirk table entry. As of this patch, the quirk table contains only ASUS ZenBook UX425UA. The deferred probe part is based on Fabio's initial work. BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1190256 Signed-off-by: Takashi Iwai <[email protected]> Tested-by: Samuel Čavoj <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent efe6f16 commit 9222ba6

File tree

3 files changed

+51
-19
lines changed

3 files changed

+51
-19
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,8 @@
16271627
architectures force reset to be always executed
16281628
i8042.unlock [HW] Unlock (ignore) the keylock
16291629
i8042.kbdreset [HW] Reset device connected to KBD port
1630+
i8042.probe_defer
1631+
[HW] Allow deferred probing upon i8042 probe errors
16301632

16311633
i810= [HW,DRM]
16321634

drivers/input/serio/i8042-x86ia64io.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,17 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
995995
{ }
996996
};
997997

998+
static const struct dmi_system_id i8042_dmi_probe_defer_table[] __initconst = {
999+
{
1000+
/* ASUS ZenBook UX425UA */
1001+
.matches = {
1002+
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1003+
DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"),
1004+
},
1005+
},
1006+
{ }
1007+
};
1008+
9981009
#endif /* CONFIG_X86 */
9991010

10001011
#ifdef CONFIG_PNP
@@ -1315,6 +1326,9 @@ static int __init i8042_platform_init(void)
13151326
if (dmi_check_system(i8042_dmi_kbdreset_table))
13161327
i8042_kbdreset = true;
13171328

1329+
if (dmi_check_system(i8042_dmi_probe_defer_table))
1330+
i8042_probe_defer = true;
1331+
13181332
/*
13191333
* A20 was already enabled during early kernel init. But some buggy
13201334
* BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to

drivers/input/serio/i8042.c

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ static bool i8042_unlock;
4545
module_param_named(unlock, i8042_unlock, bool, 0);
4646
MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");
4747

48+
static bool i8042_probe_defer;
49+
module_param_named(probe_defer, i8042_probe_defer, bool, 0);
50+
MODULE_PARM_DESC(probe_defer, "Allow deferred probing.");
51+
4852
enum i8042_controller_reset_mode {
4953
I8042_RESET_NEVER,
5054
I8042_RESET_ALWAYS,
@@ -711,7 +715,7 @@ static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version)
711715
* LCS/Telegraphics.
712716
*/
713717

714-
static int __init i8042_check_mux(void)
718+
static int i8042_check_mux(void)
715719
{
716720
unsigned char mux_version;
717721

@@ -740,10 +744,10 @@ static int __init i8042_check_mux(void)
740744
/*
741745
* The following is used to test AUX IRQ delivery.
742746
*/
743-
static struct completion i8042_aux_irq_delivered __initdata;
744-
static bool i8042_irq_being_tested __initdata;
747+
static struct completion i8042_aux_irq_delivered;
748+
static bool i8042_irq_being_tested;
745749

746-
static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id)
750+
static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id)
747751
{
748752
unsigned long flags;
749753
unsigned char str, data;
@@ -770,7 +774,7 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id)
770774
* verifies success by readinng CTR. Used when testing for presence of AUX
771775
* port.
772776
*/
773-
static int __init i8042_toggle_aux(bool on)
777+
static int i8042_toggle_aux(bool on)
774778
{
775779
unsigned char param;
776780
int i;
@@ -798,7 +802,7 @@ static int __init i8042_toggle_aux(bool on)
798802
* the presence of an AUX interface.
799803
*/
800804

801-
static int __init i8042_check_aux(void)
805+
static int i8042_check_aux(void)
802806
{
803807
int retval = -1;
804808
bool irq_registered = false;
@@ -1005,7 +1009,7 @@ static int i8042_controller_init(void)
10051009

10061010
if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
10071011
pr_err("Can't read CTR while initializing i8042\n");
1008-
return -EIO;
1012+
return i8042_probe_defer ? -EPROBE_DEFER : -EIO;
10091013
}
10101014

10111015
} while (n < 2 || ctr[0] != ctr[1]);
@@ -1320,7 +1324,7 @@ static void i8042_shutdown(struct platform_device *dev)
13201324
i8042_controller_reset(false);
13211325
}
13221326

1323-
static int __init i8042_create_kbd_port(void)
1327+
static int i8042_create_kbd_port(void)
13241328
{
13251329
struct serio *serio;
13261330
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
@@ -1349,7 +1353,7 @@ static int __init i8042_create_kbd_port(void)
13491353
return 0;
13501354
}
13511355

1352-
static int __init i8042_create_aux_port(int idx)
1356+
static int i8042_create_aux_port(int idx)
13531357
{
13541358
struct serio *serio;
13551359
int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx;
@@ -1386,13 +1390,13 @@ static int __init i8042_create_aux_port(int idx)
13861390
return 0;
13871391
}
13881392

1389-
static void __init i8042_free_kbd_port(void)
1393+
static void i8042_free_kbd_port(void)
13901394
{
13911395
kfree(i8042_ports[I8042_KBD_PORT_NO].serio);
13921396
i8042_ports[I8042_KBD_PORT_NO].serio = NULL;
13931397
}
13941398

1395-
static void __init i8042_free_aux_ports(void)
1399+
static void i8042_free_aux_ports(void)
13961400
{
13971401
int i;
13981402

@@ -1402,7 +1406,7 @@ static void __init i8042_free_aux_ports(void)
14021406
}
14031407
}
14041408

1405-
static void __init i8042_register_ports(void)
1409+
static void i8042_register_ports(void)
14061410
{
14071411
int i;
14081412

@@ -1443,7 +1447,7 @@ static void i8042_free_irqs(void)
14431447
i8042_aux_irq_registered = i8042_kbd_irq_registered = false;
14441448
}
14451449

1446-
static int __init i8042_setup_aux(void)
1450+
static int i8042_setup_aux(void)
14471451
{
14481452
int (*aux_enable)(void);
14491453
int error;
@@ -1485,7 +1489,7 @@ static int __init i8042_setup_aux(void)
14851489
return error;
14861490
}
14871491

1488-
static int __init i8042_setup_kbd(void)
1492+
static int i8042_setup_kbd(void)
14891493
{
14901494
int error;
14911495

@@ -1535,7 +1539,7 @@ static int i8042_kbd_bind_notifier(struct notifier_block *nb,
15351539
return 0;
15361540
}
15371541

1538-
static int __init i8042_probe(struct platform_device *dev)
1542+
static int i8042_probe(struct platform_device *dev)
15391543
{
15401544
int error;
15411545

@@ -1600,6 +1604,7 @@ static struct platform_driver i8042_driver = {
16001604
.pm = &i8042_pm_ops,
16011605
#endif
16021606
},
1607+
.probe = i8042_probe,
16031608
.remove = i8042_remove,
16041609
.shutdown = i8042_shutdown,
16051610
};
@@ -1610,7 +1615,6 @@ static struct notifier_block i8042_kbd_bind_notifier_block = {
16101615

16111616
static int __init i8042_init(void)
16121617
{
1613-
struct platform_device *pdev;
16141618
int err;
16151619

16161620
dbg_init();
@@ -1626,17 +1630,29 @@ static int __init i8042_init(void)
16261630
/* Set this before creating the dev to allow i8042_command to work right away */
16271631
i8042_present = true;
16281632

1629-
pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0);
1630-
if (IS_ERR(pdev)) {
1631-
err = PTR_ERR(pdev);
1633+
err = platform_driver_register(&i8042_driver);
1634+
if (err)
16321635
goto err_platform_exit;
1636+
1637+
i8042_platform_device = platform_device_alloc("i8042", -1);
1638+
if (!i8042_platform_device) {
1639+
err = -ENOMEM;
1640+
goto err_unregister_driver;
16331641
}
16341642

1643+
err = platform_device_add(i8042_platform_device);
1644+
if (err)
1645+
goto err_free_device;
1646+
16351647
bus_register_notifier(&serio_bus, &i8042_kbd_bind_notifier_block);
16361648
panic_blink = i8042_panic_blink;
16371649

16381650
return 0;
16391651

1652+
err_free_device:
1653+
platform_device_put(i8042_platform_device);
1654+
err_unregister_driver:
1655+
platform_driver_unregister(&i8042_driver);
16401656
err_platform_exit:
16411657
i8042_platform_exit();
16421658
return err;

0 commit comments

Comments
 (0)