Input: i8042 - try to get stable CTR value when initializing

If user presses keys while i8042 is being initialized there is a chance
that keyboard data will be mistaken for results of Read Control Register
command causing futher troubles. Work around this issue by reading CTR
several times and stop when we get matching results.

Reported-and-tested-by: Dave Young <hidave.darkstar@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

+28 -7
+28 -7
drivers/input/serio/i8042.c
··· 836 static int i8042_controller_init(void) 837 { 838 unsigned long flags; 839 840 /* 841 - * Save the CTR for restoral on unload / reboot. 842 */ 843 844 - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { 845 - printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); 846 - return -EIO; 847 - } 848 849 - i8042_initial_ctr = i8042_ctr; 850 851 /* 852 * Disable the keyboard interface and interrupt. ··· 910 return -EIO; 911 } 912 913 return 0; 914 } 915 ··· 935 i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; 936 i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); 937 938 - if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) 939 printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); 940 941 /*
··· 836 static int i8042_controller_init(void) 837 { 838 unsigned long flags; 839 + int n = 0; 840 + unsigned char ctr[2]; 841 842 /* 843 + * Save the CTR for restore on unload / reboot. 844 */ 845 846 + do { 847 + if (n >= 10) { 848 + printk(KERN_ERR 849 + "i8042.c: Unable to get stable CTR read.\n"); 850 + return -EIO; 851 + } 852 853 + if (n != 0) 854 + udelay(50); 855 + 856 + if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { 857 + printk(KERN_ERR 858 + "i8042.c: Can't read CTR while initializing i8042.\n"); 859 + return -EIO; 860 + } 861 + 862 + } while (n < 2 || ctr[0] != ctr[1]); 863 + 864 + i8042_initial_ctr = i8042_ctr = ctr[0]; 865 866 /* 867 * Disable the keyboard interface and interrupt. ··· 895 return -EIO; 896 } 897 898 + /* 899 + * Flush whatever accumulated while we were disabling keyboard port. 900 + */ 901 + 902 + i8042_flush(); 903 + 904 return 0; 905 } 906 ··· 914 i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; 915 i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); 916 917 + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) 918 printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); 919 920 /*