diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-09-04 02:41:27 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-09-04 02:41:27 -0400 |
commit | 0854e52d86080c1043bc8988daef2ebda4775f64 (patch) | |
tree | c75b3d7f50f04c0c8e4dfd5ec6230e8d6164b672 /drivers/input/serio | |
parent | 4cee99564db7f65a6f88e4b752da52768cde3802 (diff) |
Input: i8042 - clean up initialization code; abort if we
can't create all ports.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/i8042.c | 178 |
1 files changed, 100 insertions, 78 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 708a1d3beab9..f0d9c5f9cc36 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -338,10 +338,10 @@ static int i8042_open(struct serio *serio) | |||
338 | 338 | ||
339 | return 0; | 339 | return 0; |
340 | 340 | ||
341 | activate_fail: | 341 | activate_fail: |
342 | free_irq(port->irq, i8042_request_irq_cookie); | 342 | free_irq(port->irq, i8042_request_irq_cookie); |
343 | 343 | ||
344 | irq_fail: | 344 | irq_fail: |
345 | serio_unregister_port_delayed(serio); | 345 | serio_unregister_port_delayed(serio); |
346 | 346 | ||
347 | return -1; | 347 | return -1; |
@@ -485,7 +485,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
485 | serio_interrupt(port->serio, data, dfl, regs); | 485 | serio_interrupt(port->serio, data, dfl, regs); |
486 | 486 | ||
487 | ret = 1; | 487 | ret = 1; |
488 | out: | 488 | out: |
489 | return IRQ_RETVAL(ret); | 489 | return IRQ_RETVAL(ret); |
490 | } | 490 | } |
491 | 491 | ||
@@ -552,7 +552,7 @@ static int i8042_enable_mux_ports(void) | |||
552 | * Enable all muxed ports. | 552 | * Enable all muxed ports. |
553 | */ | 553 | */ |
554 | 554 | ||
555 | for (i = 0; i < 4; i++) { | 555 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { |
556 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); | 556 | i8042_command(¶m, I8042_CMD_MUX_PFX + i); |
557 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); | 557 | i8042_command(¶m, I8042_CMD_AUX_ENABLE); |
558 | } | 558 | } |
@@ -682,7 +682,7 @@ static int __init i8042_port_register(struct i8042_port *port) | |||
682 | kfree(port->serio); | 682 | kfree(port->serio); |
683 | port->serio = NULL; | 683 | port->serio = NULL; |
684 | i8042_ctr |= port->disable; | 684 | i8042_ctr |= port->disable; |
685 | return -1; | 685 | return -EIO; |
686 | } | 686 | } |
687 | 687 | ||
688 | printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", | 688 | printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", |
@@ -977,80 +977,83 @@ static struct device_driver i8042_driver = { | |||
977 | .shutdown = i8042_shutdown, | 977 | .shutdown = i8042_shutdown, |
978 | }; | 978 | }; |
979 | 979 | ||
980 | static void __init i8042_create_kbd_port(void) | 980 | static int __init i8042_create_kbd_port(void) |
981 | { | 981 | { |
982 | struct serio *serio; | 982 | struct serio *serio; |
983 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; | 983 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; |
984 | 984 | ||
985 | serio = kmalloc(sizeof(struct serio), GFP_KERNEL); | 985 | serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); |
986 | if (serio) { | 986 | if (!serio) |
987 | memset(serio, 0, sizeof(struct serio)); | 987 | return -ENOMEM; |
988 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; | 988 | |
989 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 989 | serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; |
990 | serio->open = i8042_open; | 990 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
991 | serio->close = i8042_close; | 991 | serio->open = i8042_open; |
992 | serio->start = i8042_start; | 992 | serio->close = i8042_close; |
993 | serio->stop = i8042_stop; | 993 | serio->start = i8042_start; |
994 | serio->port_data = port; | 994 | serio->stop = i8042_stop; |
995 | serio->dev.parent = &i8042_platform_device->dev; | 995 | serio->port_data = port; |
996 | strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); | 996 | serio->dev.parent = &i8042_platform_device->dev; |
997 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); | 997 | strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); |
998 | 998 | strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); | |
999 | port->serio = serio; | 999 | |
1000 | i8042_port_register(port); | 1000 | port->serio = serio; |
1001 | } | 1001 | |
1002 | return i8042_port_register(port); | ||
1002 | } | 1003 | } |
1003 | 1004 | ||
1004 | static void __init i8042_create_aux_port(void) | 1005 | static int __init i8042_create_aux_port(void) |
1005 | { | 1006 | { |
1006 | struct serio *serio; | 1007 | struct serio *serio; |
1007 | struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; | 1008 | struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; |
1008 | 1009 | ||
1009 | serio = kmalloc(sizeof(struct serio), GFP_KERNEL); | 1010 | serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); |
1010 | if (serio) { | 1011 | if (!serio) |
1011 | memset(serio, 0, sizeof(struct serio)); | 1012 | return -ENOMEM; |
1012 | serio->id.type = SERIO_8042; | 1013 | |
1013 | serio->write = i8042_aux_write; | 1014 | serio->id.type = SERIO_8042; |
1014 | serio->open = i8042_open; | 1015 | serio->write = i8042_aux_write; |
1015 | serio->close = i8042_close; | 1016 | serio->open = i8042_open; |
1016 | serio->start = i8042_start; | 1017 | serio->close = i8042_close; |
1017 | serio->stop = i8042_stop; | 1018 | serio->start = i8042_start; |
1018 | serio->port_data = port; | 1019 | serio->stop = i8042_stop; |
1019 | serio->dev.parent = &i8042_platform_device->dev; | 1020 | serio->port_data = port; |
1020 | strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); | 1021 | serio->dev.parent = &i8042_platform_device->dev; |
1021 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 1022 | strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); |
1022 | 1023 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | |
1023 | port->serio = serio; | 1024 | |
1024 | i8042_port_register(port); | 1025 | port->serio = serio; |
1025 | } | 1026 | |
1027 | return i8042_port_register(port); | ||
1026 | } | 1028 | } |
1027 | 1029 | ||
1028 | static void __init i8042_create_mux_port(int index) | 1030 | static int __init i8042_create_mux_port(int index) |
1029 | { | 1031 | { |
1030 | struct serio *serio; | 1032 | struct serio *serio; |
1031 | struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; | 1033 | struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; |
1032 | 1034 | ||
1033 | serio = kmalloc(sizeof(struct serio), GFP_KERNEL); | 1035 | serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); |
1034 | if (serio) { | 1036 | if (!serio) |
1035 | memset(serio, 0, sizeof(struct serio)); | 1037 | return -ENOMEM; |
1036 | serio->id.type = SERIO_8042; | 1038 | |
1037 | serio->write = i8042_aux_write; | 1039 | serio->id.type = SERIO_8042; |
1038 | serio->open = i8042_open; | 1040 | serio->write = i8042_aux_write; |
1039 | serio->close = i8042_close; | 1041 | serio->open = i8042_open; |
1040 | serio->start = i8042_start; | 1042 | serio->close = i8042_close; |
1041 | serio->stop = i8042_stop; | 1043 | serio->start = i8042_start; |
1042 | serio->port_data = port; | 1044 | serio->stop = i8042_stop; |
1043 | serio->dev.parent = &i8042_platform_device->dev; | 1045 | serio->port_data = port; |
1044 | snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); | 1046 | serio->dev.parent = &i8042_platform_device->dev; |
1045 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); | 1047 | snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); |
1046 | 1048 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); | |
1047 | *port = i8042_ports[I8042_AUX_PORT_NO]; | 1049 | |
1048 | port->exists = 0; | 1050 | *port = i8042_ports[I8042_AUX_PORT_NO]; |
1049 | snprintf(port->name, sizeof(port->name), "AUX%d", index); | 1051 | port->exists = 0; |
1050 | port->mux = index; | 1052 | snprintf(port->name, sizeof(port->name), "AUX%d", index); |
1051 | port->serio = serio; | 1053 | port->mux = index; |
1052 | i8042_port_register(port); | 1054 | port->serio = serio; |
1053 | } | 1055 | |
1056 | return i8042_port_register(port); | ||
1054 | } | 1057 | } |
1055 | 1058 | ||
1056 | static int __init i8042_init(void) | 1059 | static int __init i8042_init(void) |
@@ -1070,36 +1073,55 @@ static int __init i8042_init(void) | |||
1070 | i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; | 1073 | i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; |
1071 | 1074 | ||
1072 | if (i8042_controller_init()) { | 1075 | if (i8042_controller_init()) { |
1073 | i8042_platform_exit(); | 1076 | err = -ENODEV; |
1074 | return -ENODEV; | 1077 | goto err_platform_exit; |
1075 | } | 1078 | } |
1076 | 1079 | ||
1077 | err = driver_register(&i8042_driver); | 1080 | err = driver_register(&i8042_driver); |
1078 | if (err) { | 1081 | if (err) |
1079 | i8042_platform_exit(); | 1082 | goto err_controller_cleanup; |
1080 | return err; | ||
1081 | } | ||
1082 | 1083 | ||
1083 | i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); | 1084 | i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); |
1084 | if (IS_ERR(i8042_platform_device)) { | 1085 | if (IS_ERR(i8042_platform_device)) { |
1085 | driver_unregister(&i8042_driver); | 1086 | err = PTR_ERR(i8042_platform_device); |
1086 | i8042_platform_exit(); | 1087 | goto err_unregister_driver; |
1087 | return PTR_ERR(i8042_platform_device); | ||
1088 | } | 1088 | } |
1089 | 1089 | ||
1090 | if (!i8042_noaux && !i8042_check_aux()) { | 1090 | if (!i8042_noaux && !i8042_check_aux()) { |
1091 | if (!i8042_nomux && !i8042_check_mux()) | 1091 | if (!i8042_nomux && !i8042_check_mux()) { |
1092 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) | 1092 | for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { |
1093 | i8042_create_mux_port(i); | 1093 | err = i8042_create_mux_port(i); |
1094 | else | 1094 | if (err) |
1095 | i8042_create_aux_port(); | 1095 | goto err_unregister_ports; |
1096 | } | ||
1097 | } else { | ||
1098 | err = i8042_create_aux_port(); | ||
1099 | if (err) | ||
1100 | goto err_unregister_ports; | ||
1101 | } | ||
1096 | } | 1102 | } |
1097 | 1103 | ||
1098 | i8042_create_kbd_port(); | 1104 | err = i8042_create_kbd_port(); |
1105 | if (err) | ||
1106 | goto err_unregister_ports; | ||
1099 | 1107 | ||
1100 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); | 1108 | mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); |
1101 | 1109 | ||
1102 | return 0; | 1110 | return 0; |
1111 | |||
1112 | err_unregister_ports: | ||
1113 | for (i = 0; i < I8042_NUM_PORTS; i++) | ||
1114 | if (i8042_ports[i].serio) | ||
1115 | serio_unregister_port(i8042_ports[i].serio); | ||
1116 | platform_device_unregister(i8042_platform_device); | ||
1117 | err_unregister_driver: | ||
1118 | driver_unregister(&i8042_driver); | ||
1119 | err_controller_cleanup: | ||
1120 | i8042_controller_cleanup(); | ||
1121 | err_platform_exit: | ||
1122 | i8042_platform_exit(); | ||
1123 | |||
1124 | return err; | ||
1103 | } | 1125 | } |
1104 | 1126 | ||
1105 | static void __exit i8042_exit(void) | 1127 | static void __exit i8042_exit(void) |