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 | |
| 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>
| -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) |
