diff options
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/hp_sdc.c | 24 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 36 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 37 | ||||
-rw-r--r-- | drivers/input/serio/sa1111ps2.c | 2 |
4 files changed, 89 insertions, 10 deletions
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index bfe49243f38b..1c9410d1822c 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -819,6 +819,7 @@ static const struct parisc_device_id hp_sdc_tbl[] = { | |||
819 | MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); | 819 | MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); |
820 | 820 | ||
821 | static int __init hp_sdc_init_hppa(struct parisc_device *d); | 821 | static int __init hp_sdc_init_hppa(struct parisc_device *d); |
822 | static struct delayed_work moduleloader_work; | ||
822 | 823 | ||
823 | static struct parisc_driver hp_sdc_driver = { | 824 | static struct parisc_driver hp_sdc_driver = { |
824 | .name = "hp_sdc", | 825 | .name = "hp_sdc", |
@@ -930,8 +931,15 @@ static int __init hp_sdc_init(void) | |||
930 | 931 | ||
931 | #if defined(__hppa__) | 932 | #if defined(__hppa__) |
932 | 933 | ||
934 | static void request_module_delayed(struct work_struct *work) | ||
935 | { | ||
936 | request_module("hp_sdc_mlc"); | ||
937 | } | ||
938 | |||
933 | static int __init hp_sdc_init_hppa(struct parisc_device *d) | 939 | static int __init hp_sdc_init_hppa(struct parisc_device *d) |
934 | { | 940 | { |
941 | int ret; | ||
942 | |||
935 | if (!d) | 943 | if (!d) |
936 | return 1; | 944 | return 1; |
937 | if (hp_sdc.dev != NULL) | 945 | if (hp_sdc.dev != NULL) |
@@ -944,13 +952,26 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) | |||
944 | hp_sdc.data_io = d->hpa.start + 0x800; | 952 | hp_sdc.data_io = d->hpa.start + 0x800; |
945 | hp_sdc.status_io = d->hpa.start + 0x801; | 953 | hp_sdc.status_io = d->hpa.start + 0x801; |
946 | 954 | ||
947 | return hp_sdc_init(); | 955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); |
956 | |||
957 | ret = hp_sdc_init(); | ||
958 | /* after sucessfull initialization give SDC some time to settle | ||
959 | * and then load the hp_sdc_mlc upper layer driver */ | ||
960 | if (!ret) | ||
961 | schedule_delayed_work(&moduleloader_work, | ||
962 | msecs_to_jiffies(2000)); | ||
963 | |||
964 | return ret; | ||
948 | } | 965 | } |
949 | 966 | ||
950 | #endif /* __hppa__ */ | 967 | #endif /* __hppa__ */ |
951 | 968 | ||
952 | static void hp_sdc_exit(void) | 969 | static void hp_sdc_exit(void) |
953 | { | 970 | { |
971 | /* do nothing if we don't have a SDC */ | ||
972 | if (!hp_sdc.dev) | ||
973 | return; | ||
974 | |||
954 | write_lock_irq(&hp_sdc.lock); | 975 | write_lock_irq(&hp_sdc.lock); |
955 | 976 | ||
956 | /* Turn off all maskable "sub-function" irq's. */ | 977 | /* Turn off all maskable "sub-function" irq's. */ |
@@ -969,6 +990,7 @@ static void hp_sdc_exit(void) | |||
969 | tasklet_kill(&hp_sdc.task); | 990 | tasklet_kill(&hp_sdc.task); |
970 | 991 | ||
971 | #if defined(__hppa__) | 992 | #if defined(__hppa__) |
993 | cancel_delayed_work_sync(&moduleloader_work); | ||
972 | if (unregister_parisc_driver(&hp_sdc_driver)) | 994 | if (unregister_parisc_driver(&hp_sdc_driver)) |
973 | printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); | 995 | printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); |
974 | #endif | 996 | #endif |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 6fa2deff7446..fb8a3cd3ffd0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -151,6 +151,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
151 | DMI_MATCH(DMI_PRODUCT_VERSION, "01"), | 151 | DMI_MATCH(DMI_PRODUCT_VERSION, "01"), |
152 | }, | 152 | }, |
153 | }, | 153 | }, |
154 | { | ||
155 | .ident = "HP DV9700", | ||
156 | .matches = { | ||
157 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
158 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), | ||
159 | DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"), | ||
160 | }, | ||
161 | }, | ||
154 | { } | 162 | { } |
155 | }; | 163 | }; |
156 | 164 | ||
@@ -369,6 +377,24 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
369 | { } | 377 | { } |
370 | }; | 378 | }; |
371 | 379 | ||
380 | static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { | ||
381 | { | ||
382 | .ident = "MSI Wind U-100", | ||
383 | .matches = { | ||
384 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), | ||
385 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
386 | }, | ||
387 | }, | ||
388 | { | ||
389 | .ident = "LG Electronics X110", | ||
390 | .matches = { | ||
391 | DMI_MATCH(DMI_BOARD_NAME, "X110"), | ||
392 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), | ||
393 | }, | ||
394 | }, | ||
395 | { } | ||
396 | }; | ||
397 | |||
372 | #ifdef CONFIG_PNP | 398 | #ifdef CONFIG_PNP |
373 | static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | 399 | static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { |
374 | { | 400 | { |
@@ -378,6 +404,13 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | |||
378 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), | 404 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), |
379 | }, | 405 | }, |
380 | }, | 406 | }, |
407 | { | ||
408 | .ident = "MSI Wind U-100", | ||
409 | .matches = { | ||
410 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), | ||
411 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
412 | }, | ||
413 | }, | ||
381 | { } | 414 | { } |
382 | }; | 415 | }; |
383 | #endif | 416 | #endif |
@@ -690,6 +723,9 @@ static int __init i8042_platform_init(void) | |||
690 | #endif | 723 | #endif |
691 | 724 | ||
692 | #ifdef CONFIG_X86 | 725 | #ifdef CONFIG_X86 |
726 | if (dmi_check_system(i8042_dmi_reset_table)) | ||
727 | i8042_reset = 1; | ||
728 | |||
693 | if (dmi_check_system(i8042_dmi_noloop_table)) | 729 | if (dmi_check_system(i8042_dmi_noloop_table)) |
694 | i8042_noloop = 1; | 730 | i8042_noloop = 1; |
695 | 731 | ||
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 170f71ee5772..3cffb704e374 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -712,22 +712,43 @@ static int i8042_controller_check(void) | |||
712 | static int i8042_controller_selftest(void) | 712 | static int i8042_controller_selftest(void) |
713 | { | 713 | { |
714 | unsigned char param; | 714 | unsigned char param; |
715 | int i = 0; | ||
715 | 716 | ||
716 | if (!i8042_reset) | 717 | if (!i8042_reset) |
717 | return 0; | 718 | return 0; |
718 | 719 | ||
719 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | 720 | /* |
720 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | 721 | * We try this 5 times; on some really fragile systems this does not |
721 | return -ENODEV; | 722 | * take the first time... |
722 | } | 723 | */ |
724 | do { | ||
725 | |||
726 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | ||
727 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | ||
728 | return -ENODEV; | ||
729 | } | ||
730 | |||
731 | if (param == I8042_RET_CTL_TEST) | ||
732 | return 0; | ||
723 | 733 | ||
724 | if (param != I8042_RET_CTL_TEST) { | ||
725 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", | 734 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", |
726 | param, I8042_RET_CTL_TEST); | 735 | param, I8042_RET_CTL_TEST); |
727 | return -EIO; | 736 | msleep(50); |
728 | } | 737 | } while (i++ < 5); |
729 | 738 | ||
739 | #ifdef CONFIG_X86 | ||
740 | /* | ||
741 | * On x86, we don't fail entire i8042 initialization if controller | ||
742 | * reset fails in hopes that keyboard port will still be functional | ||
743 | * and user will still get a working keyboard. This is especially | ||
744 | * important on netbooks. On other arches we trust hardware more. | ||
745 | */ | ||
746 | printk(KERN_INFO | ||
747 | "i8042: giving up on controller selftest, continuing anyway...\n"); | ||
730 | return 0; | 748 | return 0; |
749 | #else | ||
750 | return -EIO; | ||
751 | #endif | ||
731 | } | 752 | } |
732 | 753 | ||
733 | /* | 754 | /* |
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 57953c0eb82f..f412c69478a8 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c | |||
@@ -77,7 +77,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) | |||
77 | spin_lock(&ps2if->lock); | 77 | spin_lock(&ps2if->lock); |
78 | status = sa1111_readl(ps2if->base + SA1111_PS2STAT); | 78 | status = sa1111_readl(ps2if->base + SA1111_PS2STAT); |
79 | if (ps2if->head == ps2if->tail) { | 79 | if (ps2if->head == ps2if->tail) { |
80 | disable_irq(irq); | 80 | disable_irq_nosync(irq); |
81 | /* done */ | 81 | /* done */ |
82 | } else if (status & PS2STAT_TXE) { | 82 | } else if (status & PS2STAT_TXE) { |
83 | sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA); | 83 | sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA); |