diff options
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r-- | drivers/input/serio/i8042.c | 199 |
1 files changed, 118 insertions, 81 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 708a1d3beab9..40d451ce07ff 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -27,6 +27,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
27 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); | 27 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); |
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | 29 | ||
30 | static unsigned int i8042_nokbd; | ||
31 | module_param_named(nokbd, i8042_nokbd, bool, 0); | ||
32 | MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); | ||
33 | |||
30 | static unsigned int i8042_noaux; | 34 | static unsigned int i8042_noaux; |
31 | module_param_named(noaux, i8042_noaux, bool, 0); | 35 | module_param_named(noaux, i8042_noaux, bool, 0); |
32 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); | 36 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); |
@@ -338,10 +342,10 @@ static int i8042_open(struct serio *serio) | |||
338 | 342 | ||
339 | return 0; | 343 | return 0; |
340 | 344 | ||
341 | activate_fail: | 345 | activate_fail: |
342 | free_irq(port->irq, i8042_request_irq_cookie); | 346 | free_irq(port->irq, i8042_request_irq_cookie); |
343 | 347 | ||
344 | irq_fail: | 348 | irq_fail: |
345 | serio_unregister_port_delayed(serio); | 349 | serio_unregister_port_delayed(serio); |
346 | 350 | ||
347 | return -1; | 351 | return -1; |
@@ -485,7 +489,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
485 | serio_interrupt(port->serio, data, dfl, regs); | 489 | serio_interrupt(port->serio, data, dfl, regs); |
486 | 490 | ||
487 | ret = 1; | 491 | ret = 1; |
488 | out: | 492 | out: |
489 | return IRQ_RETVAL(ret); | 493 | return IRQ_RETVAL(ret); |
490 | } | 494 | } |
491 | 495 | ||
@@ -552,7 +556,7 @@ static int i8042_enable_mux_ports(void) | |||
552 | * Enable all muxed ports. | 556 | * Enable all muxed ports. |
553 | */ | 557 | */ |
554 | 558 | ||
555 | for (i = 0; i < 4; i++) { | 559 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { |
556 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); | 560 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); |
557 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); | 561 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); |
558 | } | 562 | } |
@@ -682,7 +686,7 @@ static int __init i8042_port_register(struct i8042_port *port) | |||
682 | kfree(port->serio); | 686 | kfree(port->serio); |
683 | port->serio = NULL; | 687 | port->serio = NULL; |
684 | i8042_ctr |= port->disable; | 688 | i8042_ctr |= port->disable; |
685 | return -1; | 689 | return -EIO; |
686 | } | 690 | } |
687 | 691 | ||
688 | printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", | 692 | printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", |
@@ -977,85 +981,88 @@ static struct device_driver i8042_driver = { | |||
977 | .shutdown = i8042_shutdown, | 981 | .shutdown = i8042_shutdown, |
978 | }; | 982 | }; |
979 | 983 | ||
980 | static void __init i8042_create_kbd_port(void) | 984 | static int __init i8042_create_kbd_port(void) |
981 | { | 985 | { |
982 | struct serio *serio; | 986 | struct serio *serio; |
983 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; | 987 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; |
984 | 988 | ||
985 | serio = kmalloc(sizeof(struct serio), GFP_KERNEL); | 989 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
986 | if (serio) { | 990 | if (!serio) |
987 | memset(serio, 0, sizeof(struct serio)); | 991 | return -ENOMEM; |
988 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; | 992 | |
989 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 993 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; |
990 | serio->open = i8042_open; | 994 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
991 | serio->close = i8042_close; | 995 | serio->open = i8042_open; |
992 | serio->start = i8042_start; | 996 | serio->close = i8042_close; |
993 | serio->stop = i8042_stop; | 997 | serio->start = i8042_start; |
994 | serio->port_data = port; | 998 | serio->stop = i8042_stop; |
995 | serio->dev.parent = &i8042_platform_device->dev; | 999 | serio->port_data = port; |
996 | strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); | 1000 | serio->dev.parent = &i8042_platform_device->dev; |
997 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); | 1001 | strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); |
998 | 1002 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); | |
999 | port->serio = serio; | 1003 | |
1000 | i8042_port_register(port); | 1004 | port->serio = serio; |
1001 | } | 1005 | |
1006 | return i8042_port_register(port); | ||
1002 | } | 1007 | } |
1003 | 1008 | ||
1004 | static void __init i8042_create_aux_port(void) | 1009 | static int __init i8042_create_aux_port(void) |
1005 | { | 1010 | { |
1006 | struct serio *serio; | 1011 | struct serio *serio; |
1007 | struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; | 1012 | struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; |
1008 | 1013 | ||
1009 | serio = kmalloc(sizeof(struct serio), GFP_KERNEL); | 1014 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
1010 | if (serio) { | 1015 | if (!serio) |
1011 | memset(serio, 0, sizeof(struct serio)); | 1016 | return -ENOMEM; |
1012 | serio->id.type = SERIO_8042; | 1017 | |
1013 | serio->write = i8042_aux_write; | 1018 | serio->id.type = SERIO_8042; |
1014 | serio->open = i8042_open; | 1019 | serio->write = i8042_aux_write; |
1015 | serio->close = i8042_close; | 1020 | serio->open = i8042_open; |
1016 | serio->start = i8042_start; | 1021 | serio->close = i8042_close; |
1017 | serio->stop = i8042_stop; | 1022 | serio->start = i8042_start; |
1018 | serio->port_data = port; | 1023 | serio->stop = i8042_stop; |
1019 | serio->dev.parent = &i8042_platform_device->dev; | 1024 | serio->port_data = port; |
1020 | strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); | 1025 | serio->dev.parent = &i8042_platform_device->dev; |
1021 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 1026 | strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); |
1022 | 1027 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | |
1023 | port->serio = serio; | 1028 | |
1024 | i8042_port_register(port); | 1029 | port->serio = serio; |
1025 | } | 1030 | |
1031 | return i8042_port_register(port); | ||
1026 | } | 1032 | } |
1027 | 1033 | ||
1028 | static void __init i8042_create_mux_port(int index) | 1034 | static int __init i8042_create_mux_port(int index) |
1029 | { | 1035 | { |
1030 | struct serio *serio; | 1036 | struct serio *serio; |
1031 | struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; | 1037 | struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; |
1032 | 1038 | ||
1033 | serio = kmalloc(sizeof(struct serio), GFP_KERNEL); | 1039 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
1034 | if (serio) { | 1040 | if (!serio) |
1035 | memset(serio, 0, sizeof(struct serio)); | 1041 | return -ENOMEM; |
1036 | serio->id.type = SERIO_8042; | 1042 | |
1037 | serio->write = i8042_aux_write; | 1043 | serio->id.type = SERIO_8042; |
1038 | serio->open = i8042_open; | 1044 | serio->write = i8042_aux_write; |
1039 | serio->close = i8042_close; | 1045 | serio->open = i8042_open; |
1040 | serio->start = i8042_start; | 1046 | serio->close = i8042_close; |
1041 | serio->stop = i8042_stop; | 1047 | serio->start = i8042_start; |
1042 | serio->port_data = port; | 1048 | serio->stop = i8042_stop; |
1043 | serio->dev.parent = &i8042_platform_device->dev; | 1049 | serio->port_data = port; |
1044 | snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); | 1050 | serio->dev.parent = &i8042_platform_device->dev; |
1045 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); | 1051 | snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); |
1046 | 1052 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); | |
1047 | *port = i8042_ports[I8042_AUX_PORT_NO]; | 1053 | |
1048 | port->exists = 0; | 1054 | *port = i8042_ports[I8042_AUX_PORT_NO]; |
1049 | snprintf(port->name, sizeof(port->name), "AUX%d", index); | 1055 | port->exists = 0; |
1050 | port->mux = index; | 1056 | snprintf(port->name, sizeof(port->name), "AUX%d", index); |
1051 | port->serio = serio; | 1057 | port->mux = index; |
1052 | i8042_port_register(port); | 1058 | port->serio = serio; |
1053 | } | 1059 | |
1060 | return i8042_port_register(port); | ||
1054 | } | 1061 | } |
1055 | 1062 | ||
1056 | static int __init i8042_init(void) | 1063 | static int __init i8042_init(void) |
1057 | { | 1064 | { |
1058 | int i; | 1065 | int i, have_ports = 0; |
1059 | int err; | 1066 | int err; |
1060 | 1067 | ||
1061 | dbg_init(); | 1068 | dbg_init(); |
@@ -1063,43 +1070,73 @@ static int __init i8042_init(void) | |||
1063 | init_timer(&i8042_timer); | 1070 | init_timer(&i8042_timer); |
1064 | i8042_timer.function = i8042_timer_func; | 1071 | i8042_timer.function = i8042_timer_func; |
1065 | 1072 | ||
1066 | if (i8042_platform_init()) | 1073 | err = i8042_platform_init(); |
1067 | return -EBUSY; | 1074 | if (err) |
1075 | return err; | ||
1068 | 1076 | ||
1069 | i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; | 1077 | i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; |
1070 | i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; | 1078 | i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; |
1071 | 1079 | ||
1072 | if (i8042_controller_init()) { | 1080 | if (i8042_controller_init()) { |
1073 | i8042_platform_exit(); | 1081 | err = -ENODEV; |
1074 | return -ENODEV; | 1082 | goto err_platform_exit; |
1075 | } | 1083 | } |
1076 | 1084 | ||
1077 | err = driver_register(&i8042_driver); | 1085 | err = driver_register(&i8042_driver); |
1078 | if (err) { | 1086 | if (err) |
1079 | i8042_platform_exit(); | 1087 | goto err_controller_cleanup; |
1080 | return err; | ||
1081 | } | ||
1082 | 1088 | ||
1083 | i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); | 1089 | i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); |
1084 | if (IS_ERR(i8042_platform_device)) { | 1090 | if (IS_ERR(i8042_platform_device)) { |
1085 | driver_unregister(&i8042_driver); | 1091 | err = PTR_ERR(i8042_platform_device); |
1086 | i8042_platform_exit(); | 1092 | goto err_unregister_driver; |
1087 | return PTR_ERR(i8042_platform_device); | ||
1088 | } | 1093 | } |
1089 | 1094 | ||
1090 | if (!i8042_noaux && !i8042_check_aux()) { | 1095 | if (!i8042_noaux && !i8042_check_aux()) { |
1091 | if (!i8042_nomux && !i8042_check_mux()) | 1096 | if (!i8042_nomux && !i8042_check_mux()) { |
1092 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) | 1097 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { |
1093 | i8042_create_mux_port(i); | 1098 | err = i8042_create_mux_port(i); |
1094 | else | 1099 | if (err) |
1095 | i8042_create_aux_port(); | 1100 | goto err_unregister_ports; |
1101 | } | ||
1102 | } else { | ||
1103 | err = i8042_create_aux_port(); | ||
1104 | if (err) | ||
1105 | goto err_unregister_ports; | ||
1106 | } | ||
1107 | have_ports = 1; | ||
1096 | } | 1108 | } |
1097 | 1109 | ||
1098 | i8042_create_kbd_port(); | 1110 | if (!i8042_nokbd) { |
1111 | err = i8042_create_kbd_port(); | ||
1112 | if (err) | ||
1113 | goto err_unregister_ports; | ||
1114 | have_ports = 1; | ||
1115 | } | ||
1116 | |||
1117 | if (!have_ports) { | ||
1118 | err = -ENODEV; | ||
1119 | goto err_unregister_device; | ||
1120 | } | ||
1099 | 1121 | ||
1100 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | 1122 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); |
1101 | 1123 | ||
1102 | return 0; | 1124 | return 0; |
1125 | |||
1126 | err_unregister_ports: | ||
1127 | for (i = 0; i < I8042_NUM_PORTS; i++) | ||
1128 | if (i8042_ports[i].serio) | ||
1129 | serio_unregister_port(i8042_ports[i].serio); | ||
1130 | err_unregister_device: | ||
1131 | platform_device_unregister(i8042_platform_device); | ||
1132 | err_unregister_driver: | ||
1133 | driver_unregister(&i8042_driver); | ||
1134 | err_controller_cleanup: | ||
1135 | i8042_controller_cleanup(); | ||
1136 | err_platform_exit: | ||
1137 | i8042_platform_exit(); | ||
1138 | |||
1139 | return err; | ||
1103 | } | 1140 | } |
1104 | 1141 | ||
1105 | static void __exit i8042_exit(void) | 1142 | static void __exit i8042_exit(void) |