diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/input/serio | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/input/serio')
-rw-r--r-- | drivers/input/serio/Kconfig | 16 | ||||
-rw-r--r-- | drivers/input/serio/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/serio/altera_ps2.c | 15 | ||||
-rw-r--r-- | drivers/input/serio/ambakmi.c | 3 | ||||
-rw-r--r-- | drivers/input/serio/ams_delta_serio.c | 3 | ||||
-rw-r--r-- | drivers/input/serio/ct82c710.c | 16 | ||||
-rw-r--r-- | drivers/input/serio/gscps2.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/hil_mlc.c | 11 | ||||
-rw-r--r-- | drivers/input/serio/hp_sdc.c | 6 | ||||
-rw-r--r-- | drivers/input/serio/hp_sdc_mlc.c | 18 | ||||
-rw-r--r-- | drivers/input/serio/i8042-sparcio.h | 8 | ||||
-rw-r--r-- | drivers/input/serio/i8042-unicore32io.h | 73 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 69 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 101 | ||||
-rw-r--r-- | drivers/input/serio/i8042.h | 16 | ||||
-rw-r--r-- | drivers/input/serio/ps2mult.c | 318 | ||||
-rw-r--r-- | drivers/input/serio/rpckbd.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/serio.c | 291 | ||||
-rw-r--r-- | drivers/input/serio/serio_raw.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/serport.c | 25 | ||||
-rw-r--r-- | drivers/input/serio/xilinx_ps2.c | 11 |
21 files changed, 749 insertions, 258 deletions
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 3bfe8fafc6ad..55f2c2293ec6 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # Input core configuration | 2 | # Input core configuration |
3 | # | 3 | # |
4 | config SERIO | 4 | config SERIO |
5 | tristate "Serial I/O support" if EMBEDDED || !X86 | 5 | tristate "Serial I/O support" if EXPERT || !X86 |
6 | default y | 6 | default y |
7 | help | 7 | help |
8 | Say Yes here if you have any input device that uses serial I/O to | 8 | Say Yes here if you have any input device that uses serial I/O to |
@@ -19,7 +19,7 @@ config SERIO | |||
19 | if SERIO | 19 | if SERIO |
20 | 20 | ||
21 | config SERIO_I8042 | 21 | config SERIO_I8042 |
22 | tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 | 22 | tristate "i8042 PC Keyboard controller" if EXPERT || !X86 |
23 | default y | 23 | default y |
24 | depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ | 24 | depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ |
25 | (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN | 25 | (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN |
@@ -168,7 +168,7 @@ config SERIO_MACEPS2 | |||
168 | module will be called maceps2. | 168 | module will be called maceps2. |
169 | 169 | ||
170 | config SERIO_LIBPS2 | 170 | config SERIO_LIBPS2 |
171 | tristate "PS/2 driver library" if EMBEDDED | 171 | tristate "PS/2 driver library" if EXPERT |
172 | depends on SERIO_I8042 || SERIO_I8042=n | 172 | depends on SERIO_I8042 || SERIO_I8042=n |
173 | help | 173 | help |
174 | Say Y here if you are using a driver for device connected | 174 | Say Y here if you are using a driver for device connected |
@@ -214,7 +214,6 @@ config SERIO_AMS_DELTA | |||
214 | tristate "Amstrad Delta (E3) mailboard support" | 214 | tristate "Amstrad Delta (E3) mailboard support" |
215 | depends on MACH_AMS_DELTA | 215 | depends on MACH_AMS_DELTA |
216 | default y | 216 | default y |
217 | select AMS_DELTA_FIQ | ||
218 | ---help--- | 217 | ---help--- |
219 | Say Y here if you have an E3 and want to use its mailboard, | 218 | Say Y here if you have an E3 and want to use its mailboard, |
220 | or any standard AT keyboard connected to the mailboard port. | 219 | or any standard AT keyboard connected to the mailboard port. |
@@ -226,4 +225,13 @@ config SERIO_AMS_DELTA | |||
226 | To compile this driver as a module, choose M here; | 225 | To compile this driver as a module, choose M here; |
227 | the module will be called ams_delta_serio. | 226 | the module will be called ams_delta_serio. |
228 | 227 | ||
228 | config SERIO_PS2MULT | ||
229 | tristate "TQC PS/2 multiplexer" | ||
230 | help | ||
231 | Say Y here if you have the PS/2 line multiplexer like the one | ||
232 | present on TQC boards. | ||
233 | |||
234 | To compile this driver as a module, choose M here: the | ||
235 | module will be called ps2mult. | ||
236 | |||
229 | endif | 237 | endif |
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 84c80bf7185e..dbbe37616c92 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o | |||
18 | obj-$(CONFIG_HP_SDC) += hp_sdc.o | 18 | obj-$(CONFIG_HP_SDC) += hp_sdc.o |
19 | obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o | 19 | obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o |
20 | obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o | 20 | obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o |
21 | obj-$(CONFIG_SERIO_PS2MULT) += ps2mult.o | ||
21 | obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o | 22 | obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o |
22 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o | 23 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o |
23 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o | 24 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o |
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index 7998560a1904..d363dc4571a3 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/of.h> | ||
22 | 23 | ||
23 | #define DRV_NAME "altera_ps2" | 24 | #define DRV_NAME "altera_ps2" |
24 | 25 | ||
@@ -173,6 +174,16 @@ static int __devexit altera_ps2_remove(struct platform_device *pdev) | |||
173 | return 0; | 174 | return 0; |
174 | } | 175 | } |
175 | 176 | ||
177 | #ifdef CONFIG_OF | ||
178 | static const struct of_device_id altera_ps2_match[] = { | ||
179 | { .compatible = "ALTR,ps2-1.0", }, | ||
180 | {}, | ||
181 | }; | ||
182 | MODULE_DEVICE_TABLE(of, altera_ps2_match); | ||
183 | #else /* CONFIG_OF */ | ||
184 | #define altera_ps2_match NULL | ||
185 | #endif /* CONFIG_OF */ | ||
186 | |||
176 | /* | 187 | /* |
177 | * Our device driver structure | 188 | * Our device driver structure |
178 | */ | 189 | */ |
@@ -182,6 +193,7 @@ static struct platform_driver altera_ps2_driver = { | |||
182 | .driver = { | 193 | .driver = { |
183 | .name = DRV_NAME, | 194 | .name = DRV_NAME, |
184 | .owner = THIS_MODULE, | 195 | .owner = THIS_MODULE, |
196 | .of_match_table = altera_ps2_match, | ||
185 | }, | 197 | }, |
186 | }; | 198 | }; |
187 | 199 | ||
@@ -189,13 +201,12 @@ static int __init altera_ps2_init(void) | |||
189 | { | 201 | { |
190 | return platform_driver_register(&altera_ps2_driver); | 202 | return platform_driver_register(&altera_ps2_driver); |
191 | } | 203 | } |
204 | module_init(altera_ps2_init); | ||
192 | 205 | ||
193 | static void __exit altera_ps2_exit(void) | 206 | static void __exit altera_ps2_exit(void) |
194 | { | 207 | { |
195 | platform_driver_unregister(&altera_ps2_driver); | 208 | platform_driver_unregister(&altera_ps2_driver); |
196 | } | 209 | } |
197 | |||
198 | module_init(altera_ps2_init); | ||
199 | module_exit(altera_ps2_exit); | 210 | module_exit(altera_ps2_exit); |
200 | 211 | ||
201 | MODULE_DESCRIPTION("Altera University Program PS2 controller driver"); | 212 | MODULE_DESCRIPTION("Altera University Program PS2 controller driver"); |
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 92563a681d65..12abc50508e5 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
@@ -107,7 +107,8 @@ static void amba_kmi_close(struct serio *io) | |||
107 | clk_disable(kmi->clk); | 107 | clk_disable(kmi->clk); |
108 | } | 108 | } |
109 | 109 | ||
110 | static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | 110 | static int __devinit amba_kmi_probe(struct amba_device *dev, |
111 | const struct amba_id *id) | ||
111 | { | 112 | { |
112 | struct amba_kmi_port *kmi; | 113 | struct amba_kmi_port *kmi; |
113 | struct serio *io; | 114 | struct serio *io; |
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c index 8f1770e1e08b..4b2a42f9f0bb 100644 --- a/drivers/input/serio/ams_delta_serio.c +++ b/drivers/input/serio/ams_delta_serio.c | |||
@@ -149,7 +149,7 @@ static int __init ams_delta_serio_init(void) | |||
149 | * at FIQ level, switch back from edge to simple interrupt handler | 149 | * at FIQ level, switch back from edge to simple interrupt handler |
150 | * to avoid bad interaction. | 150 | * to avoid bad interaction. |
151 | */ | 151 | */ |
152 | set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), | 152 | irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), |
153 | handle_simple_irq); | 153 | handle_simple_irq); |
154 | 154 | ||
155 | serio_register_port(ams_delta_serio); | 155 | serio_register_port(ams_delta_serio); |
@@ -172,6 +172,5 @@ static void __exit ams_delta_serio_exit(void) | |||
172 | free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); | 172 | free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); |
173 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); | 173 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); |
174 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); | 174 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); |
175 | kfree(ams_delta_serio); | ||
176 | } | 175 | } |
177 | module_exit(ams_delta_serio_exit); | 176 | module_exit(ams_delta_serio_exit); |
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index 4a3084695c00..852816567241 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c | |||
@@ -111,9 +111,11 @@ static void ct82c710_close(struct serio *serio) | |||
111 | static int ct82c710_open(struct serio *serio) | 111 | static int ct82c710_open(struct serio *serio) |
112 | { | 112 | { |
113 | unsigned char status; | 113 | unsigned char status; |
114 | int err; | ||
114 | 115 | ||
115 | if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL)) | 116 | err = request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL); |
116 | return -1; | 117 | if (err) |
118 | return err; | ||
117 | 119 | ||
118 | status = inb_p(CT82C710_STATUS); | 120 | status = inb_p(CT82C710_STATUS); |
119 | 121 | ||
@@ -131,7 +133,7 @@ static int ct82c710_open(struct serio *serio) | |||
131 | status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON); | 133 | status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON); |
132 | outb_p(status, CT82C710_STATUS); | 134 | outb_p(status, CT82C710_STATUS); |
133 | free_irq(CT82C710_IRQ, NULL); | 135 | free_irq(CT82C710_IRQ, NULL); |
134 | return -1; | 136 | return -EBUSY; |
135 | } | 137 | } |
136 | 138 | ||
137 | return 0; | 139 | return 0; |
@@ -191,6 +193,9 @@ static int __devinit ct82c710_probe(struct platform_device *dev) | |||
191 | 193 | ||
192 | serio_register_port(ct82c710_port); | 194 | serio_register_port(ct82c710_port); |
193 | 195 | ||
196 | printk(KERN_INFO "serio: C&T 82c710 mouse port at %#llx irq %d\n", | ||
197 | (unsigned long long)CT82C710_DATA, CT82C710_IRQ); | ||
198 | |||
194 | return 0; | 199 | return 0; |
195 | } | 200 | } |
196 | 201 | ||
@@ -237,11 +242,6 @@ static int __init ct82c710_init(void) | |||
237 | if (error) | 242 | if (error) |
238 | goto err_free_device; | 243 | goto err_free_device; |
239 | 244 | ||
240 | serio_register_port(ct82c710_port); | ||
241 | |||
242 | printk(KERN_INFO "serio: C&T 82c710 mouse port at %#llx irq %d\n", | ||
243 | (unsigned long long)CT82C710_DATA, CT82C710_IRQ); | ||
244 | |||
245 | return 0; | 245 | return 0; |
246 | 246 | ||
247 | err_free_device: | 247 | err_free_device: |
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 3c287dd879d3..4225f5d6b15f 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c | |||
@@ -358,7 +358,7 @@ static int __devinit gscps2_probe(struct parisc_device *dev) | |||
358 | gscps2_reset(ps2port); | 358 | gscps2_reset(ps2port); |
359 | ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f; | 359 | ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f; |
360 | 360 | ||
361 | snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", | 361 | snprintf(serio->name, sizeof(serio->name), "gsc-ps2-%s", |
362 | (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); | 362 | (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); |
363 | strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); | 363 | strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); |
364 | serio->id.type = SERIO_8042; | 364 | serio->id.type = SERIO_8042; |
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index c92f4edfee7b..bfd3865d886b 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c | |||
@@ -915,15 +915,15 @@ int hil_mlc_register(hil_mlc *mlc) | |||
915 | mlc->ostarted = 0; | 915 | mlc->ostarted = 0; |
916 | 916 | ||
917 | rwlock_init(&mlc->lock); | 917 | rwlock_init(&mlc->lock); |
918 | init_MUTEX(&mlc->osem); | 918 | sema_init(&mlc->osem, 1); |
919 | 919 | ||
920 | init_MUTEX(&mlc->isem); | 920 | sema_init(&mlc->isem, 1); |
921 | mlc->icount = -1; | 921 | mlc->icount = -1; |
922 | mlc->imatch = 0; | 922 | mlc->imatch = 0; |
923 | 923 | ||
924 | mlc->opercnt = 0; | 924 | mlc->opercnt = 0; |
925 | 925 | ||
926 | init_MUTEX_LOCKED(&(mlc->csem)); | 926 | sema_init(&(mlc->csem), 0); |
927 | 927 | ||
928 | hil_mlc_clear_di_scratch(mlc); | 928 | hil_mlc_clear_di_scratch(mlc); |
929 | hil_mlc_clear_di_map(mlc, 0); | 929 | hil_mlc_clear_di_map(mlc, 0); |
@@ -932,6 +932,11 @@ int hil_mlc_register(hil_mlc *mlc) | |||
932 | hil_mlc_copy_di_scratch(mlc, i); | 932 | hil_mlc_copy_di_scratch(mlc, i); |
933 | mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); | 933 | mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); |
934 | mlc->serio[i] = mlc_serio; | 934 | mlc->serio[i] = mlc_serio; |
935 | if (!mlc->serio[i]) { | ||
936 | for (; i >= 0; i--) | ||
937 | kfree(mlc->serio[i]); | ||
938 | return -ENOMEM; | ||
939 | } | ||
935 | snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); | 940 | snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); |
936 | snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); | 941 | snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); |
937 | mlc_serio->id = hil_mlc_serio_id; | 942 | mlc_serio->id = hil_mlc_serio_id; |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index bcc2d30ec245..42206205e4f5 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -905,7 +905,7 @@ static int __init hp_sdc_init(void) | |||
905 | ts_sync[1] = 0x0f; | 905 | ts_sync[1] = 0x0f; |
906 | ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; | 906 | ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; |
907 | t_sync.act.semaphore = &s_sync; | 907 | t_sync.act.semaphore = &s_sync; |
908 | init_MUTEX_LOCKED(&s_sync); | 908 | sema_init(&s_sync, 0); |
909 | hp_sdc_enqueue_transaction(&t_sync); | 909 | hp_sdc_enqueue_transaction(&t_sync); |
910 | down(&s_sync); /* Wait for t_sync to complete */ | 910 | down(&s_sync); /* Wait for t_sync to complete */ |
911 | 911 | ||
@@ -955,7 +955,7 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) | |||
955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); | 955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); |
956 | 956 | ||
957 | ret = hp_sdc_init(); | 957 | ret = hp_sdc_init(); |
958 | /* after successfull initialization give SDC some time to settle | 958 | /* after successful initialization give SDC some time to settle |
959 | * and then load the hp_sdc_mlc upper layer driver */ | 959 | * and then load the hp_sdc_mlc upper layer driver */ |
960 | if (!ret) | 960 | if (!ret) |
961 | schedule_delayed_work(&moduleloader_work, | 961 | schedule_delayed_work(&moduleloader_work, |
@@ -1039,7 +1039,7 @@ static int __init hp_sdc_register(void) | |||
1039 | return hp_sdc.dev_err; | 1039 | return hp_sdc.dev_err; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | init_MUTEX_LOCKED(&tq_init_sem); | 1042 | sema_init(&tq_init_sem, 0); |
1043 | 1043 | ||
1044 | tq_init.actidx = 0; | 1044 | tq_init.actidx = 0; |
1045 | tq_init.idx = 1; | 1045 | tq_init.idx = 1; |
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index 7d2b820ef58d..d50f0678bf47 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c | |||
@@ -305,6 +305,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc) | |||
305 | static int __init hp_sdc_mlc_init(void) | 305 | static int __init hp_sdc_mlc_init(void) |
306 | { | 306 | { |
307 | hil_mlc *mlc = &hp_sdc_mlc; | 307 | hil_mlc *mlc = &hp_sdc_mlc; |
308 | int err; | ||
308 | 309 | ||
309 | #ifdef __mc68000__ | 310 | #ifdef __mc68000__ |
310 | if (!MACH_IS_HP300) | 311 | if (!MACH_IS_HP300) |
@@ -323,22 +324,21 @@ static int __init hp_sdc_mlc_init(void) | |||
323 | mlc->out = &hp_sdc_mlc_out; | 324 | mlc->out = &hp_sdc_mlc_out; |
324 | mlc->priv = &hp_sdc_mlc_priv; | 325 | mlc->priv = &hp_sdc_mlc_priv; |
325 | 326 | ||
326 | if (hil_mlc_register(mlc)) { | 327 | err = hil_mlc_register(mlc); |
328 | if (err) { | ||
327 | printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); | 329 | printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); |
328 | goto err0; | 330 | return err; |
329 | } | 331 | } |
330 | 332 | ||
331 | if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { | 333 | if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { |
332 | printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); | 334 | printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); |
333 | goto err1; | 335 | if (hil_mlc_unregister(mlc)) |
336 | printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" | ||
337 | "This is bad. Could cause an oops.\n"); | ||
338 | return -EBUSY; | ||
334 | } | 339 | } |
340 | |||
335 | return 0; | 341 | return 0; |
336 | err1: | ||
337 | if (hil_mlc_unregister(mlc)) | ||
338 | printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" | ||
339 | "This is bad. Could cause an oops.\n"); | ||
340 | err0: | ||
341 | return -EBUSY; | ||
342 | } | 342 | } |
343 | 343 | ||
344 | static void __exit hp_sdc_mlc_exit(void) | 344 | static void __exit hp_sdc_mlc_exit(void) |
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index c5cc4508d6df..395a9af3adcd 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
@@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) | |||
49 | #define OBP_PS2MS_NAME1 "kdmouse" | 49 | #define OBP_PS2MS_NAME1 "kdmouse" |
50 | #define OBP_PS2MS_NAME2 "mouse" | 50 | #define OBP_PS2MS_NAME2 "mouse" |
51 | 51 | ||
52 | static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match) | 52 | static int __devinit sparc_i8042_probe(struct platform_device *op) |
53 | { | 53 | { |
54 | struct device_node *dp = op->dev.of_node; | 54 | struct device_node *dp = op->dev.of_node; |
55 | 55 | ||
@@ -95,7 +95,7 @@ static const struct of_device_id sparc_i8042_match[] = { | |||
95 | }; | 95 | }; |
96 | MODULE_DEVICE_TABLE(of, sparc_i8042_match); | 96 | MODULE_DEVICE_TABLE(of, sparc_i8042_match); |
97 | 97 | ||
98 | static struct of_platform_driver sparc_i8042_driver = { | 98 | static struct platform_driver sparc_i8042_driver = { |
99 | .driver = { | 99 | .driver = { |
100 | .name = "i8042", | 100 | .name = "i8042", |
101 | .owner = THIS_MODULE, | 101 | .owner = THIS_MODULE, |
@@ -116,7 +116,7 @@ static int __init i8042_platform_init(void) | |||
116 | if (!kbd_iobase) | 116 | if (!kbd_iobase) |
117 | return -ENODEV; | 117 | return -ENODEV; |
118 | } else { | 118 | } else { |
119 | int err = of_register_platform_driver(&sparc_i8042_driver); | 119 | int err = platform_driver_register(&sparc_i8042_driver); |
120 | if (err) | 120 | if (err) |
121 | return err; | 121 | return err; |
122 | 122 | ||
@@ -140,7 +140,7 @@ static inline void i8042_platform_exit(void) | |||
140 | struct device_node *root = of_find_node_by_path("/"); | 140 | struct device_node *root = of_find_node_by_path("/"); |
141 | 141 | ||
142 | if (strcmp(root->name, "SUNW,JavaStation-1")) | 142 | if (strcmp(root->name, "SUNW,JavaStation-1")) |
143 | of_unregister_platform_driver(&sparc_i8042_driver); | 143 | platform_driver_unregister(&sparc_i8042_driver); |
144 | } | 144 | } |
145 | 145 | ||
146 | #else /* !CONFIG_PCI */ | 146 | #else /* !CONFIG_PCI */ |
diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h new file mode 100644 index 000000000000..73f5cc124a36 --- /dev/null +++ b/drivers/input/serio/i8042-unicore32io.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * Code specific to PKUnity SoC and UniCore ISA | ||
3 | * | ||
4 | * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> | ||
5 | * Copyright (C) 2001-2011 Guan Xuetao | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #ifndef _I8042_UNICORE32_H | ||
12 | #define _I8042_UNICORE32_H | ||
13 | |||
14 | #include <mach/hardware.h> | ||
15 | |||
16 | /* | ||
17 | * Names. | ||
18 | */ | ||
19 | #define I8042_KBD_PHYS_DESC "isa0060/serio0" | ||
20 | #define I8042_AUX_PHYS_DESC "isa0060/serio1" | ||
21 | #define I8042_MUX_PHYS_DESC "isa0060/serio%d" | ||
22 | |||
23 | /* | ||
24 | * IRQs. | ||
25 | */ | ||
26 | #define I8042_KBD_IRQ IRQ_PS2_KBD | ||
27 | #define I8042_AUX_IRQ IRQ_PS2_AUX | ||
28 | |||
29 | /* | ||
30 | * Register numbers. | ||
31 | */ | ||
32 | #define I8042_COMMAND_REG PS2_COMMAND | ||
33 | #define I8042_STATUS_REG PS2_STATUS | ||
34 | #define I8042_DATA_REG PS2_DATA | ||
35 | |||
36 | #define I8042_REGION_START (resource_size_t)(PS2_DATA) | ||
37 | #define I8042_REGION_SIZE (resource_size_t)(16) | ||
38 | |||
39 | static inline int i8042_read_data(void) | ||
40 | { | ||
41 | return readb(I8042_DATA_REG); | ||
42 | } | ||
43 | |||
44 | static inline int i8042_read_status(void) | ||
45 | { | ||
46 | return readb(I8042_STATUS_REG); | ||
47 | } | ||
48 | |||
49 | static inline void i8042_write_data(int val) | ||
50 | { | ||
51 | writeb(val, I8042_DATA_REG); | ||
52 | } | ||
53 | |||
54 | static inline void i8042_write_command(int val) | ||
55 | { | ||
56 | writeb(val, I8042_COMMAND_REG); | ||
57 | } | ||
58 | |||
59 | static inline int i8042_platform_init(void) | ||
60 | { | ||
61 | if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) | ||
62 | return -EBUSY; | ||
63 | |||
64 | i8042_reset = 1; | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static inline void i8042_platform_exit(void) | ||
69 | { | ||
70 | release_mem_region(I8042_REGION_START, I8042_REGION_SIZE); | ||
71 | } | ||
72 | |||
73 | #endif /* _I8042_UNICORE32_H */ | ||
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index ed7ad7416b24..bb9f5d31f0d0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -351,6 +351,17 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { | |||
351 | }, | 351 | }, |
352 | }, | 352 | }, |
353 | { | 353 | { |
354 | /* | ||
355 | * Most (all?) VAIOs do not have external PS/2 ports nor | ||
356 | * they implement active multiplexing properly, and | ||
357 | * MUX discovery usually messes up keyboard/touchpad. | ||
358 | */ | ||
359 | .matches = { | ||
360 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
361 | DMI_MATCH(DMI_BOARD_NAME, "VAIO"), | ||
362 | }, | ||
363 | }, | ||
364 | { | ||
354 | /* Amoi M636/A737 */ | 365 | /* Amoi M636/A737 */ |
355 | .matches = { | 366 | .matches = { |
356 | DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), | 367 | DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), |
@@ -413,6 +424,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { | |||
413 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), | 424 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), |
414 | }, | 425 | }, |
415 | }, | 426 | }, |
427 | { | ||
428 | /* Dell Vostro V13 */ | ||
429 | .matches = { | ||
430 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
431 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), | ||
432 | }, | ||
433 | }, | ||
416 | { } | 434 | { } |
417 | }; | 435 | }; |
418 | 436 | ||
@@ -534,6 +552,17 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { | |||
534 | }; | 552 | }; |
535 | #endif | 553 | #endif |
536 | 554 | ||
555 | static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { | ||
556 | { | ||
557 | /* Dell Vostro V13 */ | ||
558 | .matches = { | ||
559 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
560 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), | ||
561 | }, | ||
562 | }, | ||
563 | { } | ||
564 | }; | ||
565 | |||
537 | /* | 566 | /* |
538 | * Some Wistron based laptops need us to explicitly enable the 'Dritek | 567 | * Some Wistron based laptops need us to explicitly enable the 'Dritek |
539 | * keyboard extension' to make their extra keys start generating scancodes. | 568 | * keyboard extension' to make their extra keys start generating scancodes. |
@@ -542,6 +571,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { | |||
542 | */ | 571 | */ |
543 | static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { | 572 | static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { |
544 | { | 573 | { |
574 | /* Acer Aspire 5100 */ | ||
575 | .matches = { | ||
576 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
577 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), | ||
578 | }, | ||
579 | }, | ||
580 | { | ||
545 | /* Acer Aspire 5610 */ | 581 | /* Acer Aspire 5610 */ |
546 | .matches = { | 582 | .matches = { |
547 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 583 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
@@ -741,7 +777,7 @@ static int __init i8042_pnp_init(void) | |||
741 | #endif | 777 | #endif |
742 | 778 | ||
743 | if (i8042_nopnp) { | 779 | if (i8042_nopnp) { |
744 | printk(KERN_INFO "i8042: PNP detection disabled\n"); | 780 | pr_info("PNP detection disabled\n"); |
745 | return 0; | 781 | return 0; |
746 | } | 782 | } |
747 | 783 | ||
@@ -758,7 +794,7 @@ static int __init i8042_pnp_init(void) | |||
758 | #if defined(__ia64__) | 794 | #if defined(__ia64__) |
759 | return -ENODEV; | 795 | return -ENODEV; |
760 | #else | 796 | #else |
761 | printk(KERN_INFO "PNP: No PS/2 controller found. Probing ports directly.\n"); | 797 | pr_info("PNP: No PS/2 controller found. Probing ports directly.\n"); |
762 | return 0; | 798 | return 0; |
763 | #endif | 799 | #endif |
764 | } | 800 | } |
@@ -770,7 +806,7 @@ static int __init i8042_pnp_init(void) | |||
770 | snprintf(aux_irq_str, sizeof(aux_irq_str), | 806 | snprintf(aux_irq_str, sizeof(aux_irq_str), |
771 | "%d", i8042_pnp_aux_irq); | 807 | "%d", i8042_pnp_aux_irq); |
772 | 808 | ||
773 | printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", | 809 | pr_info("PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", |
774 | i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", | 810 | i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", |
775 | i8042_pnp_aux_name, | 811 | i8042_pnp_aux_name, |
776 | i8042_pnp_data_reg, i8042_pnp_command_reg, | 812 | i8042_pnp_data_reg, i8042_pnp_command_reg, |
@@ -787,9 +823,7 @@ static int __init i8042_pnp_init(void) | |||
787 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && | 823 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && |
788 | i8042_pnp_data_reg != i8042_data_reg) || | 824 | i8042_pnp_data_reg != i8042_data_reg) || |
789 | !i8042_pnp_data_reg) { | 825 | !i8042_pnp_data_reg) { |
790 | printk(KERN_WARNING | 826 | pr_warn("PNP: PS/2 controller has invalid data port %#x; using default %#x\n", |
791 | "PNP: PS/2 controller has invalid data port %#x; " | ||
792 | "using default %#x\n", | ||
793 | i8042_pnp_data_reg, i8042_data_reg); | 827 | i8042_pnp_data_reg, i8042_data_reg); |
794 | i8042_pnp_data_reg = i8042_data_reg; | 828 | i8042_pnp_data_reg = i8042_data_reg; |
795 | pnp_data_busted = true; | 829 | pnp_data_busted = true; |
@@ -798,33 +832,27 @@ static int __init i8042_pnp_init(void) | |||
798 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && | 832 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && |
799 | i8042_pnp_command_reg != i8042_command_reg) || | 833 | i8042_pnp_command_reg != i8042_command_reg) || |
800 | !i8042_pnp_command_reg) { | 834 | !i8042_pnp_command_reg) { |
801 | printk(KERN_WARNING | 835 | pr_warn("PNP: PS/2 controller has invalid command port %#x; using default %#x\n", |
802 | "PNP: PS/2 controller has invalid command port %#x; " | ||
803 | "using default %#x\n", | ||
804 | i8042_pnp_command_reg, i8042_command_reg); | 836 | i8042_pnp_command_reg, i8042_command_reg); |
805 | i8042_pnp_command_reg = i8042_command_reg; | 837 | i8042_pnp_command_reg = i8042_command_reg; |
806 | pnp_data_busted = true; | 838 | pnp_data_busted = true; |
807 | } | 839 | } |
808 | 840 | ||
809 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { | 841 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { |
810 | printk(KERN_WARNING | 842 | pr_warn("PNP: PS/2 controller doesn't have KBD irq; using default %d\n", |
811 | "PNP: PS/2 controller doesn't have KBD irq; " | 843 | i8042_kbd_irq); |
812 | "using default %d\n", i8042_kbd_irq); | ||
813 | i8042_pnp_kbd_irq = i8042_kbd_irq; | 844 | i8042_pnp_kbd_irq = i8042_kbd_irq; |
814 | pnp_data_busted = true; | 845 | pnp_data_busted = true; |
815 | } | 846 | } |
816 | 847 | ||
817 | if (!i8042_noaux && !i8042_pnp_aux_irq) { | 848 | if (!i8042_noaux && !i8042_pnp_aux_irq) { |
818 | if (!pnp_data_busted && i8042_pnp_kbd_irq) { | 849 | if (!pnp_data_busted && i8042_pnp_kbd_irq) { |
819 | printk(KERN_WARNING | 850 | pr_warn("PNP: PS/2 appears to have AUX port disabled, " |
820 | "PNP: PS/2 appears to have AUX port disabled, " | 851 | "if this is incorrect please boot with i8042.nopnp\n"); |
821 | "if this is incorrect please boot with " | ||
822 | "i8042.nopnp\n"); | ||
823 | i8042_noaux = true; | 852 | i8042_noaux = true; |
824 | } else { | 853 | } else { |
825 | printk(KERN_WARNING | 854 | pr_warn("PNP: PS/2 controller doesn't have AUX irq; using default %d\n", |
826 | "PNP: PS/2 controller doesn't have AUX irq; " | 855 | i8042_aux_irq); |
827 | "using default %d\n", i8042_aux_irq); | ||
828 | i8042_pnp_aux_irq = i8042_aux_irq; | 856 | i8042_pnp_aux_irq = i8042_aux_irq; |
829 | } | 857 | } |
830 | } | 858 | } |
@@ -886,6 +914,9 @@ static int __init i8042_platform_init(void) | |||
886 | if (dmi_check_system(i8042_dmi_nomux_table)) | 914 | if (dmi_check_system(i8042_dmi_nomux_table)) |
887 | i8042_nomux = true; | 915 | i8042_nomux = true; |
888 | 916 | ||
917 | if (dmi_check_system(i8042_dmi_notimeout_table)) | ||
918 | i8042_notimeout = true; | ||
919 | |||
889 | if (dmi_check_system(i8042_dmi_dritek_table)) | 920 | if (dmi_check_system(i8042_dmi_dritek_table)) |
890 | i8042_dritek = true; | 921 | i8042_dritek = true; |
891 | #endif /* CONFIG_X86 */ | 922 | #endif /* CONFIG_X86 */ |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index f58513160480..d37a48e099d0 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * the Free Software Foundation. | 10 | * the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | |||
13 | #include <linux/types.h> | 15 | #include <linux/types.h> |
14 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
@@ -61,6 +63,10 @@ static bool i8042_noloop; | |||
61 | module_param_named(noloop, i8042_noloop, bool, 0); | 63 | module_param_named(noloop, i8042_noloop, bool, 0); |
62 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); | 64 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); |
63 | 65 | ||
66 | static bool i8042_notimeout; | ||
67 | module_param_named(notimeout, i8042_notimeout, bool, 0); | ||
68 | MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); | ||
69 | |||
64 | #ifdef CONFIG_X86 | 70 | #ifdef CONFIG_X86 |
65 | static bool i8042_dritek; | 71 | static bool i8042_dritek; |
66 | module_param_named(dritek, i8042_dritek, bool, 0); | 72 | module_param_named(dritek, i8042_dritek, bool, 0); |
@@ -225,8 +231,8 @@ static int i8042_flush(void) | |||
225 | udelay(50); | 231 | udelay(50); |
226 | data = i8042_read_data(); | 232 | data = i8042_read_data(); |
227 | i++; | 233 | i++; |
228 | dbg("%02x <- i8042 (flush, %s)", data, | 234 | dbg("%02x <- i8042 (flush, %s)\n", |
229 | str & I8042_STR_AUXDATA ? "aux" : "kbd"); | 235 | data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); |
230 | } | 236 | } |
231 | 237 | ||
232 | spin_unlock_irqrestore(&i8042_lock, flags); | 238 | spin_unlock_irqrestore(&i8042_lock, flags); |
@@ -253,32 +259,32 @@ static int __i8042_command(unsigned char *param, int command) | |||
253 | if (error) | 259 | if (error) |
254 | return error; | 260 | return error; |
255 | 261 | ||
256 | dbg("%02x -> i8042 (command)", command & 0xff); | 262 | dbg("%02x -> i8042 (command)\n", command & 0xff); |
257 | i8042_write_command(command & 0xff); | 263 | i8042_write_command(command & 0xff); |
258 | 264 | ||
259 | for (i = 0; i < ((command >> 12) & 0xf); i++) { | 265 | for (i = 0; i < ((command >> 12) & 0xf); i++) { |
260 | error = i8042_wait_write(); | 266 | error = i8042_wait_write(); |
261 | if (error) | 267 | if (error) |
262 | return error; | 268 | return error; |
263 | dbg("%02x -> i8042 (parameter)", param[i]); | 269 | dbg("%02x -> i8042 (parameter)\n", param[i]); |
264 | i8042_write_data(param[i]); | 270 | i8042_write_data(param[i]); |
265 | } | 271 | } |
266 | 272 | ||
267 | for (i = 0; i < ((command >> 8) & 0xf); i++) { | 273 | for (i = 0; i < ((command >> 8) & 0xf); i++) { |
268 | error = i8042_wait_read(); | 274 | error = i8042_wait_read(); |
269 | if (error) { | 275 | if (error) { |
270 | dbg(" -- i8042 (timeout)"); | 276 | dbg(" -- i8042 (timeout)\n"); |
271 | return error; | 277 | return error; |
272 | } | 278 | } |
273 | 279 | ||
274 | if (command == I8042_CMD_AUX_LOOP && | 280 | if (command == I8042_CMD_AUX_LOOP && |
275 | !(i8042_read_status() & I8042_STR_AUXDATA)) { | 281 | !(i8042_read_status() & I8042_STR_AUXDATA)) { |
276 | dbg(" -- i8042 (auxerr)"); | 282 | dbg(" -- i8042 (auxerr)\n"); |
277 | return -1; | 283 | return -1; |
278 | } | 284 | } |
279 | 285 | ||
280 | param[i] = i8042_read_data(); | 286 | param[i] = i8042_read_data(); |
281 | dbg("%02x <- i8042 (return)", param[i]); | 287 | dbg("%02x <- i8042 (return)\n", param[i]); |
282 | } | 288 | } |
283 | 289 | ||
284 | return 0; | 290 | return 0; |
@@ -309,7 +315,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c) | |||
309 | spin_lock_irqsave(&i8042_lock, flags); | 315 | spin_lock_irqsave(&i8042_lock, flags); |
310 | 316 | ||
311 | if (!(retval = i8042_wait_write())) { | 317 | if (!(retval = i8042_wait_write())) { |
312 | dbg("%02x -> i8042 (kbd-data)", c); | 318 | dbg("%02x -> i8042 (kbd-data)\n", c); |
313 | i8042_write_data(c); | 319 | i8042_write_data(c); |
314 | } | 320 | } |
315 | 321 | ||
@@ -355,17 +361,14 @@ static void i8042_port_close(struct serio *serio) | |||
355 | 361 | ||
356 | i8042_ctr &= ~irq_bit; | 362 | i8042_ctr &= ~irq_bit; |
357 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 363 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
358 | printk(KERN_WARNING | 364 | pr_warn("Can't write CTR while closing %s port\n", port_name); |
359 | "i8042.c: Can't write CTR while closing %s port.\n", | ||
360 | port_name); | ||
361 | 365 | ||
362 | udelay(50); | 366 | udelay(50); |
363 | 367 | ||
364 | i8042_ctr &= ~disable_bit; | 368 | i8042_ctr &= ~disable_bit; |
365 | i8042_ctr |= irq_bit; | 369 | i8042_ctr |= irq_bit; |
366 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 370 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
367 | printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n", | 371 | pr_err("Can't reactivate %s port\n", port_name); |
368 | port_name); | ||
369 | 372 | ||
370 | /* | 373 | /* |
371 | * See if there is any data appeared while we were messing with | 374 | * See if there is any data appeared while we were messing with |
@@ -456,7 +459,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
456 | str = i8042_read_status(); | 459 | str = i8042_read_status(); |
457 | if (unlikely(~str & I8042_STR_OBF)) { | 460 | if (unlikely(~str & I8042_STR_OBF)) { |
458 | spin_unlock_irqrestore(&i8042_lock, flags); | 461 | spin_unlock_irqrestore(&i8042_lock, flags); |
459 | if (irq) dbg("Interrupt %d, without any data", irq); | 462 | if (irq) |
463 | dbg("Interrupt %d, without any data\n", irq); | ||
460 | ret = 0; | 464 | ret = 0; |
461 | goto out; | 465 | goto out; |
462 | } | 466 | } |
@@ -469,7 +473,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
469 | 473 | ||
470 | dfl = 0; | 474 | dfl = 0; |
471 | if (str & I8042_STR_MUXERR) { | 475 | if (str & I8042_STR_MUXERR) { |
472 | dbg("MUX error, status is %02x, data is %02x", str, data); | 476 | dbg("MUX error, status is %02x, data is %02x\n", |
477 | str, data); | ||
473 | /* | 478 | /* |
474 | * When MUXERR condition is signalled the data register can only contain | 479 | * When MUXERR condition is signalled the data register can only contain |
475 | * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately | 480 | * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately |
@@ -503,7 +508,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
503 | } else { | 508 | } else { |
504 | 509 | ||
505 | dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | | 510 | dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | |
506 | ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); | 511 | ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); |
507 | 512 | ||
508 | port_no = (str & I8042_STR_AUXDATA) ? | 513 | port_no = (str & I8042_STR_AUXDATA) ? |
509 | I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; | 514 | I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; |
@@ -512,7 +517,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
512 | port = &i8042_ports[port_no]; | 517 | port = &i8042_ports[port_no]; |
513 | serio = port->exists ? port->serio : NULL; | 518 | serio = port->exists ? port->serio : NULL; |
514 | 519 | ||
515 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", | 520 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)\n", |
516 | data, port_no, irq, | 521 | data, port_no, irq, |
517 | dfl & SERIO_PARITY ? ", bad parity" : "", | 522 | dfl & SERIO_PARITY ? ", bad parity" : "", |
518 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); | 523 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); |
@@ -540,7 +545,7 @@ static int i8042_enable_kbd_port(void) | |||
540 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 545 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
541 | i8042_ctr &= ~I8042_CTR_KBDINT; | 546 | i8042_ctr &= ~I8042_CTR_KBDINT; |
542 | i8042_ctr |= I8042_CTR_KBDDIS; | 547 | i8042_ctr |= I8042_CTR_KBDDIS; |
543 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); | 548 | pr_err("Failed to enable KBD port\n"); |
544 | return -EIO; | 549 | return -EIO; |
545 | } | 550 | } |
546 | 551 | ||
@@ -559,7 +564,7 @@ static int i8042_enable_aux_port(void) | |||
559 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 564 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
560 | i8042_ctr &= ~I8042_CTR_AUXINT; | 565 | i8042_ctr &= ~I8042_CTR_AUXINT; |
561 | i8042_ctr |= I8042_CTR_AUXDIS; | 566 | i8042_ctr |= I8042_CTR_AUXDIS; |
562 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); | 567 | pr_err("Failed to enable AUX port\n"); |
563 | return -EIO; | 568 | return -EIO; |
564 | } | 569 | } |
565 | 570 | ||
@@ -641,7 +646,7 @@ static int __init i8042_check_mux(void) | |||
641 | if (i8042_set_mux_mode(true, &mux_version)) | 646 | if (i8042_set_mux_mode(true, &mux_version)) |
642 | return -1; | 647 | return -1; |
643 | 648 | ||
644 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | 649 | pr_info("Detected active multiplexing controller, rev %d.%d\n", |
645 | (mux_version >> 4) & 0xf, mux_version & 0xf); | 650 | (mux_version >> 4) & 0xf, mux_version & 0xf); |
646 | 651 | ||
647 | /* | 652 | /* |
@@ -651,7 +656,7 @@ static int __init i8042_check_mux(void) | |||
651 | i8042_ctr &= ~I8042_CTR_AUXINT; | 656 | i8042_ctr &= ~I8042_CTR_AUXINT; |
652 | 657 | ||
653 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 658 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
654 | printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); | 659 | pr_err("Failed to disable AUX port, can't use MUX\n"); |
655 | return -EIO; | 660 | return -EIO; |
656 | } | 661 | } |
657 | 662 | ||
@@ -676,8 +681,8 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) | |||
676 | str = i8042_read_status(); | 681 | str = i8042_read_status(); |
677 | if (str & I8042_STR_OBF) { | 682 | if (str & I8042_STR_OBF) { |
678 | data = i8042_read_data(); | 683 | data = i8042_read_data(); |
679 | dbg("%02x <- i8042 (aux_test_irq, %s)", | 684 | dbg("%02x <- i8042 (aux_test_irq, %s)\n", |
680 | data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); | 685 | data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); |
681 | if (i8042_irq_being_tested && | 686 | if (i8042_irq_being_tested && |
682 | data == 0xa5 && (str & I8042_STR_AUXDATA)) | 687 | data == 0xa5 && (str & I8042_STR_AUXDATA)) |
683 | complete(&i8042_aux_irq_delivered); | 688 | complete(&i8042_aux_irq_delivered); |
@@ -770,8 +775,8 @@ static int __init i8042_check_aux(void) | |||
770 | */ | 775 | */ |
771 | 776 | ||
772 | if (i8042_toggle_aux(false)) { | 777 | if (i8042_toggle_aux(false)) { |
773 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); | 778 | pr_warn("Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); |
774 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); | 779 | pr_warn("If AUX port is really absent please use the 'i8042.noaux' option\n"); |
775 | } | 780 | } |
776 | 781 | ||
777 | if (i8042_toggle_aux(true)) | 782 | if (i8042_toggle_aux(true)) |
@@ -819,7 +824,7 @@ static int __init i8042_check_aux(void) | |||
819 | * AUX IRQ was never delivered so we need to flush the controller to | 824 | * AUX IRQ was never delivered so we need to flush the controller to |
820 | * get rid of the byte we put there; otherwise keyboard may not work. | 825 | * get rid of the byte we put there; otherwise keyboard may not work. |
821 | */ | 826 | */ |
822 | dbg(" -- i8042 (aux irq test timeout)"); | 827 | dbg(" -- i8042 (aux irq test timeout)\n"); |
823 | i8042_flush(); | 828 | i8042_flush(); |
824 | retval = -1; | 829 | retval = -1; |
825 | } | 830 | } |
@@ -845,7 +850,7 @@ static int __init i8042_check_aux(void) | |||
845 | static int i8042_controller_check(void) | 850 | static int i8042_controller_check(void) |
846 | { | 851 | { |
847 | if (i8042_flush() == I8042_BUFFER_SIZE) { | 852 | if (i8042_flush() == I8042_BUFFER_SIZE) { |
848 | printk(KERN_ERR "i8042.c: No controller found.\n"); | 853 | pr_err("No controller found\n"); |
849 | return -ENODEV; | 854 | return -ENODEV; |
850 | } | 855 | } |
851 | 856 | ||
@@ -864,15 +869,15 @@ static int i8042_controller_selftest(void) | |||
864 | do { | 869 | do { |
865 | 870 | ||
866 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | 871 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { |
867 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | 872 | pr_err("i8042 controller selftest timeout\n"); |
868 | return -ENODEV; | 873 | return -ENODEV; |
869 | } | 874 | } |
870 | 875 | ||
871 | if (param == I8042_RET_CTL_TEST) | 876 | if (param == I8042_RET_CTL_TEST) |
872 | return 0; | 877 | return 0; |
873 | 878 | ||
874 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", | 879 | dbg("i8042 controller selftest: %#x != %#x\n", |
875 | param, I8042_RET_CTL_TEST); | 880 | param, I8042_RET_CTL_TEST); |
876 | msleep(50); | 881 | msleep(50); |
877 | } while (i++ < 5); | 882 | } while (i++ < 5); |
878 | 883 | ||
@@ -883,10 +888,10 @@ static int i8042_controller_selftest(void) | |||
883 | * and user will still get a working keyboard. This is especially | 888 | * and user will still get a working keyboard. This is especially |
884 | * important on netbooks. On other arches we trust hardware more. | 889 | * important on netbooks. On other arches we trust hardware more. |
885 | */ | 890 | */ |
886 | printk(KERN_INFO | 891 | pr_info("giving up on controller selftest, continuing anyway...\n"); |
887 | "i8042: giving up on controller selftest, continuing anyway...\n"); | ||
888 | return 0; | 892 | return 0; |
889 | #else | 893 | #else |
894 | pr_err("i8042 controller selftest failed\n"); | ||
890 | return -EIO; | 895 | return -EIO; |
891 | #endif | 896 | #endif |
892 | } | 897 | } |
@@ -909,8 +914,7 @@ static int i8042_controller_init(void) | |||
909 | 914 | ||
910 | do { | 915 | do { |
911 | if (n >= 10) { | 916 | if (n >= 10) { |
912 | printk(KERN_ERR | 917 | pr_err("Unable to get stable CTR read\n"); |
913 | "i8042.c: Unable to get stable CTR read.\n"); | ||
914 | return -EIO; | 918 | return -EIO; |
915 | } | 919 | } |
916 | 920 | ||
@@ -918,8 +922,7 @@ static int i8042_controller_init(void) | |||
918 | udelay(50); | 922 | udelay(50); |
919 | 923 | ||
920 | if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { | 924 | if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { |
921 | printk(KERN_ERR | 925 | pr_err("Can't read CTR while initializing i8042\n"); |
922 | "i8042.c: Can't read CTR while initializing i8042.\n"); | ||
923 | return -EIO; | 926 | return -EIO; |
924 | } | 927 | } |
925 | 928 | ||
@@ -943,7 +946,7 @@ static int i8042_controller_init(void) | |||
943 | if (i8042_unlock) | 946 | if (i8042_unlock) |
944 | i8042_ctr |= I8042_CTR_IGNKEYLOCK; | 947 | i8042_ctr |= I8042_CTR_IGNKEYLOCK; |
945 | else | 948 | else |
946 | printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n"); | 949 | pr_warn("Warning: Keylock active\n"); |
947 | } | 950 | } |
948 | spin_unlock_irqrestore(&i8042_lock, flags); | 951 | spin_unlock_irqrestore(&i8042_lock, flags); |
949 | 952 | ||
@@ -970,7 +973,7 @@ static int i8042_controller_init(void) | |||
970 | */ | 973 | */ |
971 | 974 | ||
972 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 975 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
973 | printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); | 976 | pr_err("Can't write CTR while initializing i8042\n"); |
974 | return -EIO; | 977 | return -EIO; |
975 | } | 978 | } |
976 | 979 | ||
@@ -1000,7 +1003,7 @@ static void i8042_controller_reset(void) | |||
1000 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); | 1003 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); |
1001 | 1004 | ||
1002 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | 1005 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) |
1003 | printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); | 1006 | pr_warn("Can't write CTR while resetting\n"); |
1004 | 1007 | ||
1005 | /* | 1008 | /* |
1006 | * Disable MUX mode if present. | 1009 | * Disable MUX mode if present. |
@@ -1021,7 +1024,7 @@ static void i8042_controller_reset(void) | |||
1021 | */ | 1024 | */ |
1022 | 1025 | ||
1023 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | 1026 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) |
1024 | printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); | 1027 | pr_warn("Can't restore CTR\n"); |
1025 | } | 1028 | } |
1026 | 1029 | ||
1027 | 1030 | ||
@@ -1045,14 +1048,14 @@ static long i8042_panic_blink(int state) | |||
1045 | led = (state) ? 0x01 | 0x04 : 0; | 1048 | led = (state) ? 0x01 | 0x04 : 0; |
1046 | while (i8042_read_status() & I8042_STR_IBF) | 1049 | while (i8042_read_status() & I8042_STR_IBF) |
1047 | DELAY; | 1050 | DELAY; |
1048 | dbg("%02x -> i8042 (panic blink)", 0xed); | 1051 | dbg("%02x -> i8042 (panic blink)\n", 0xed); |
1049 | i8042_suppress_kbd_ack = 2; | 1052 | i8042_suppress_kbd_ack = 2; |
1050 | i8042_write_data(0xed); /* set leds */ | 1053 | i8042_write_data(0xed); /* set leds */ |
1051 | DELAY; | 1054 | DELAY; |
1052 | while (i8042_read_status() & I8042_STR_IBF) | 1055 | while (i8042_read_status() & I8042_STR_IBF) |
1053 | DELAY; | 1056 | DELAY; |
1054 | DELAY; | 1057 | DELAY; |
1055 | dbg("%02x -> i8042 (panic blink)", led); | 1058 | dbg("%02x -> i8042 (panic blink)\n", led); |
1056 | i8042_write_data(led); | 1059 | i8042_write_data(led); |
1057 | DELAY; | 1060 | DELAY; |
1058 | return delay; | 1061 | return delay; |
@@ -1063,14 +1066,12 @@ static long i8042_panic_blink(int state) | |||
1063 | #ifdef CONFIG_X86 | 1066 | #ifdef CONFIG_X86 |
1064 | static void i8042_dritek_enable(void) | 1067 | static void i8042_dritek_enable(void) |
1065 | { | 1068 | { |
1066 | char param = 0x90; | 1069 | unsigned char param = 0x90; |
1067 | int error; | 1070 | int error; |
1068 | 1071 | ||
1069 | error = i8042_command(¶m, 0x1059); | 1072 | error = i8042_command(¶m, 0x1059); |
1070 | if (error) | 1073 | if (error) |
1071 | printk(KERN_WARNING | 1074 | pr_warn("Failed to enable DRITEK extension: %d\n", error); |
1072 | "Failed to enable DRITEK extension: %d\n", | ||
1073 | error); | ||
1074 | } | 1075 | } |
1075 | #endif | 1076 | #endif |
1076 | 1077 | ||
@@ -1105,10 +1106,10 @@ static int i8042_controller_resume(bool force_reset) | |||
1105 | i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; | 1106 | i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; |
1106 | i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); | 1107 | i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); |
1107 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 1108 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
1108 | printk(KERN_WARNING "i8042: Can't write CTR to resume, retrying...\n"); | 1109 | pr_warn("Can't write CTR to resume, retrying...\n"); |
1109 | msleep(50); | 1110 | msleep(50); |
1110 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 1111 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
1111 | printk(KERN_ERR "i8042: CTR write retry failed\n"); | 1112 | pr_err("CTR write retry failed\n"); |
1112 | return -EIO; | 1113 | return -EIO; |
1113 | } | 1114 | } |
1114 | } | 1115 | } |
@@ -1121,9 +1122,7 @@ static int i8042_controller_resume(bool force_reset) | |||
1121 | 1122 | ||
1122 | if (i8042_mux_present) { | 1123 | if (i8042_mux_present) { |
1123 | if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) | 1124 | if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) |
1124 | printk(KERN_WARNING | 1125 | pr_warn("failed to resume active multiplexor, mouse won't work\n"); |
1125 | "i8042: failed to resume active multiplexor, " | ||
1126 | "mouse won't work.\n"); | ||
1127 | } else if (i8042_ports[I8042_AUX_PORT_NO].serio) | 1126 | } else if (i8042_ports[I8042_AUX_PORT_NO].serio) |
1128 | i8042_enable_aux_port(); | 1127 | i8042_enable_aux_port(); |
1129 | 1128 | ||
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index cbc1beb66574..3452708fbe3b 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "i8042-sparcio.h" | 26 | #include "i8042-sparcio.h" |
27 | #elif defined(CONFIG_X86) || defined(CONFIG_IA64) | 27 | #elif defined(CONFIG_X86) || defined(CONFIG_IA64) |
28 | #include "i8042-x86ia64io.h" | 28 | #include "i8042-x86ia64io.h" |
29 | #elif defined(CONFIG_UNICORE32) | ||
30 | #include "i8042-unicore32io.h" | ||
29 | #else | 31 | #else |
30 | #include "i8042-io.h" | 32 | #include "i8042-io.h" |
31 | #endif | 33 | #endif |
@@ -89,15 +91,19 @@ | |||
89 | #ifdef DEBUG | 91 | #ifdef DEBUG |
90 | static unsigned long i8042_start_time; | 92 | static unsigned long i8042_start_time; |
91 | #define dbg_init() do { i8042_start_time = jiffies; } while (0) | 93 | #define dbg_init() do { i8042_start_time = jiffies; } while (0) |
92 | #define dbg(format, arg...) \ | 94 | #define dbg(format, arg...) \ |
93 | do { \ | 95 | do { \ |
94 | if (i8042_debug) \ | 96 | if (i8042_debug) \ |
95 | printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" , \ | 97 | printk(KERN_DEBUG KBUILD_MODNAME ": [%d] " format, \ |
96 | ## arg, (int) (jiffies - i8042_start_time)); \ | 98 | (int) (jiffies - i8042_start_time), ##arg); \ |
97 | } while (0) | 99 | } while (0) |
98 | #else | 100 | #else |
99 | #define dbg_init() do { } while (0) | 101 | #define dbg_init() do { } while (0) |
100 | #define dbg(format, arg...) do {} while (0) | 102 | #define dbg(format, arg...) \ |
103 | do { \ | ||
104 | if (0) \ | ||
105 | printk(KERN_DEBUG pr_fmt(format), ##arg); \ | ||
106 | } while (0) | ||
101 | #endif | 107 | #endif |
102 | 108 | ||
103 | #endif /* _I8042_H */ | 109 | #endif /* _I8042_H */ |
diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c new file mode 100644 index 000000000000..15aa81c9f1fb --- /dev/null +++ b/drivers/input/serio/ps2mult.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * TQC PS/2 Multiplexer driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Dmitry Eremin-Solenikov | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/serio.h> | ||
16 | |||
17 | MODULE_AUTHOR("Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>"); | ||
18 | MODULE_DESCRIPTION("TQC PS/2 Multiplexer driver"); | ||
19 | MODULE_LICENSE("GPL"); | ||
20 | |||
21 | #define PS2MULT_KB_SELECTOR 0xA0 | ||
22 | #define PS2MULT_MS_SELECTOR 0xA1 | ||
23 | #define PS2MULT_ESCAPE 0x7D | ||
24 | #define PS2MULT_BSYNC 0x7E | ||
25 | #define PS2MULT_SESSION_START 0x55 | ||
26 | #define PS2MULT_SESSION_END 0x56 | ||
27 | |||
28 | struct ps2mult_port { | ||
29 | struct serio *serio; | ||
30 | unsigned char sel; | ||
31 | bool registered; | ||
32 | }; | ||
33 | |||
34 | #define PS2MULT_NUM_PORTS 2 | ||
35 | #define PS2MULT_KBD_PORT 0 | ||
36 | #define PS2MULT_MOUSE_PORT 1 | ||
37 | |||
38 | struct ps2mult { | ||
39 | struct serio *mx_serio; | ||
40 | struct ps2mult_port ports[PS2MULT_NUM_PORTS]; | ||
41 | |||
42 | spinlock_t lock; | ||
43 | struct ps2mult_port *in_port; | ||
44 | struct ps2mult_port *out_port; | ||
45 | bool escape; | ||
46 | }; | ||
47 | |||
48 | /* First MUST come PS2MULT_NUM_PORTS selectors */ | ||
49 | static const unsigned char ps2mult_controls[] = { | ||
50 | PS2MULT_KB_SELECTOR, PS2MULT_MS_SELECTOR, | ||
51 | PS2MULT_ESCAPE, PS2MULT_BSYNC, | ||
52 | PS2MULT_SESSION_START, PS2MULT_SESSION_END, | ||
53 | }; | ||
54 | |||
55 | static const struct serio_device_id ps2mult_serio_ids[] = { | ||
56 | { | ||
57 | .type = SERIO_RS232, | ||
58 | .proto = SERIO_PS2MULT, | ||
59 | .id = SERIO_ANY, | ||
60 | .extra = SERIO_ANY, | ||
61 | }, | ||
62 | { 0 } | ||
63 | }; | ||
64 | |||
65 | MODULE_DEVICE_TABLE(serio, ps2mult_serio_ids); | ||
66 | |||
67 | static void ps2mult_select_port(struct ps2mult *psm, struct ps2mult_port *port) | ||
68 | { | ||
69 | struct serio *mx_serio = psm->mx_serio; | ||
70 | |||
71 | serio_write(mx_serio, port->sel); | ||
72 | psm->out_port = port; | ||
73 | dev_dbg(&mx_serio->dev, "switched to sel %02x\n", port->sel); | ||
74 | } | ||
75 | |||
76 | static int ps2mult_serio_write(struct serio *serio, unsigned char data) | ||
77 | { | ||
78 | struct serio *mx_port = serio->parent; | ||
79 | struct ps2mult *psm = serio_get_drvdata(mx_port); | ||
80 | struct ps2mult_port *port = serio->port_data; | ||
81 | bool need_escape; | ||
82 | unsigned long flags; | ||
83 | |||
84 | spin_lock_irqsave(&psm->lock, flags); | ||
85 | |||
86 | if (psm->out_port != port) | ||
87 | ps2mult_select_port(psm, port); | ||
88 | |||
89 | need_escape = memchr(ps2mult_controls, data, sizeof(ps2mult_controls)); | ||
90 | |||
91 | dev_dbg(&serio->dev, | ||
92 | "write: %s%02x\n", need_escape ? "ESC " : "", data); | ||
93 | |||
94 | if (need_escape) | ||
95 | serio_write(mx_port, PS2MULT_ESCAPE); | ||
96 | |||
97 | serio_write(mx_port, data); | ||
98 | |||
99 | spin_unlock_irqrestore(&psm->lock, flags); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int ps2mult_serio_start(struct serio *serio) | ||
105 | { | ||
106 | struct ps2mult *psm = serio_get_drvdata(serio->parent); | ||
107 | struct ps2mult_port *port = serio->port_data; | ||
108 | unsigned long flags; | ||
109 | |||
110 | spin_lock_irqsave(&psm->lock, flags); | ||
111 | port->registered = true; | ||
112 | spin_unlock_irqrestore(&psm->lock, flags); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static void ps2mult_serio_stop(struct serio *serio) | ||
118 | { | ||
119 | struct ps2mult *psm = serio_get_drvdata(serio->parent); | ||
120 | struct ps2mult_port *port = serio->port_data; | ||
121 | unsigned long flags; | ||
122 | |||
123 | spin_lock_irqsave(&psm->lock, flags); | ||
124 | port->registered = false; | ||
125 | spin_unlock_irqrestore(&psm->lock, flags); | ||
126 | } | ||
127 | |||
128 | static int ps2mult_create_port(struct ps2mult *psm, int i) | ||
129 | { | ||
130 | struct serio *mx_serio = psm->mx_serio; | ||
131 | struct serio *serio; | ||
132 | |||
133 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | ||
134 | if (!serio) | ||
135 | return -ENOMEM; | ||
136 | |||
137 | strlcpy(serio->name, "TQC PS/2 Multiplexer", sizeof(serio->name)); | ||
138 | snprintf(serio->phys, sizeof(serio->phys), | ||
139 | "%s/port%d", mx_serio->phys, i); | ||
140 | serio->id.type = SERIO_8042; | ||
141 | serio->write = ps2mult_serio_write; | ||
142 | serio->start = ps2mult_serio_start; | ||
143 | serio->stop = ps2mult_serio_stop; | ||
144 | serio->parent = psm->mx_serio; | ||
145 | serio->port_data = &psm->ports[i]; | ||
146 | |||
147 | psm->ports[i].serio = serio; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static void ps2mult_reset(struct ps2mult *psm) | ||
153 | { | ||
154 | unsigned long flags; | ||
155 | |||
156 | spin_lock_irqsave(&psm->lock, flags); | ||
157 | |||
158 | serio_write(psm->mx_serio, PS2MULT_SESSION_END); | ||
159 | serio_write(psm->mx_serio, PS2MULT_SESSION_START); | ||
160 | |||
161 | ps2mult_select_port(psm, &psm->ports[PS2MULT_KBD_PORT]); | ||
162 | |||
163 | spin_unlock_irqrestore(&psm->lock, flags); | ||
164 | } | ||
165 | |||
166 | static int ps2mult_connect(struct serio *serio, struct serio_driver *drv) | ||
167 | { | ||
168 | struct ps2mult *psm; | ||
169 | int i; | ||
170 | int error; | ||
171 | |||
172 | if (!serio->write) | ||
173 | return -EINVAL; | ||
174 | |||
175 | psm = kzalloc(sizeof(*psm), GFP_KERNEL); | ||
176 | if (!psm) | ||
177 | return -ENOMEM; | ||
178 | |||
179 | spin_lock_init(&psm->lock); | ||
180 | psm->mx_serio = serio; | ||
181 | |||
182 | for (i = 0; i < PS2MULT_NUM_PORTS; i++) { | ||
183 | psm->ports[i].sel = ps2mult_controls[i]; | ||
184 | error = ps2mult_create_port(psm, i); | ||
185 | if (error) | ||
186 | goto err_out; | ||
187 | } | ||
188 | |||
189 | psm->in_port = psm->out_port = &psm->ports[PS2MULT_KBD_PORT]; | ||
190 | |||
191 | serio_set_drvdata(serio, psm); | ||
192 | error = serio_open(serio, drv); | ||
193 | if (error) | ||
194 | goto err_out; | ||
195 | |||
196 | ps2mult_reset(psm); | ||
197 | |||
198 | for (i = 0; i < PS2MULT_NUM_PORTS; i++) { | ||
199 | struct serio *s = psm->ports[i].serio; | ||
200 | |||
201 | dev_info(&serio->dev, "%s port at %s\n", s->name, serio->phys); | ||
202 | serio_register_port(s); | ||
203 | } | ||
204 | |||
205 | return 0; | ||
206 | |||
207 | err_out: | ||
208 | while (--i >= 0) | ||
209 | kfree(psm->ports[i].serio); | ||
210 | kfree(psm); | ||
211 | return error; | ||
212 | } | ||
213 | |||
214 | static void ps2mult_disconnect(struct serio *serio) | ||
215 | { | ||
216 | struct ps2mult *psm = serio_get_drvdata(serio); | ||
217 | |||
218 | /* Note that serio core already take care of children ports */ | ||
219 | serio_write(serio, PS2MULT_SESSION_END); | ||
220 | serio_close(serio); | ||
221 | kfree(psm); | ||
222 | |||
223 | serio_set_drvdata(serio, NULL); | ||
224 | } | ||
225 | |||
226 | static int ps2mult_reconnect(struct serio *serio) | ||
227 | { | ||
228 | struct ps2mult *psm = serio_get_drvdata(serio); | ||
229 | |||
230 | ps2mult_reset(psm); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static irqreturn_t ps2mult_interrupt(struct serio *serio, | ||
236 | unsigned char data, unsigned int dfl) | ||
237 | { | ||
238 | struct ps2mult *psm = serio_get_drvdata(serio); | ||
239 | struct ps2mult_port *in_port; | ||
240 | unsigned long flags; | ||
241 | |||
242 | dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, dfl); | ||
243 | |||
244 | spin_lock_irqsave(&psm->lock, flags); | ||
245 | |||
246 | if (psm->escape) { | ||
247 | psm->escape = false; | ||
248 | in_port = psm->in_port; | ||
249 | if (in_port->registered) | ||
250 | serio_interrupt(in_port->serio, data, dfl); | ||
251 | goto out; | ||
252 | } | ||
253 | |||
254 | switch (data) { | ||
255 | case PS2MULT_ESCAPE: | ||
256 | dev_dbg(&serio->dev, "ESCAPE\n"); | ||
257 | psm->escape = true; | ||
258 | break; | ||
259 | |||
260 | case PS2MULT_BSYNC: | ||
261 | dev_dbg(&serio->dev, "BSYNC\n"); | ||
262 | psm->in_port = psm->out_port; | ||
263 | break; | ||
264 | |||
265 | case PS2MULT_SESSION_START: | ||
266 | dev_dbg(&serio->dev, "SS\n"); | ||
267 | break; | ||
268 | |||
269 | case PS2MULT_SESSION_END: | ||
270 | dev_dbg(&serio->dev, "SE\n"); | ||
271 | break; | ||
272 | |||
273 | case PS2MULT_KB_SELECTOR: | ||
274 | dev_dbg(&serio->dev, "KB\n"); | ||
275 | psm->in_port = &psm->ports[PS2MULT_KBD_PORT]; | ||
276 | break; | ||
277 | |||
278 | case PS2MULT_MS_SELECTOR: | ||
279 | dev_dbg(&serio->dev, "MS\n"); | ||
280 | psm->in_port = &psm->ports[PS2MULT_MOUSE_PORT]; | ||
281 | break; | ||
282 | |||
283 | default: | ||
284 | in_port = psm->in_port; | ||
285 | if (in_port->registered) | ||
286 | serio_interrupt(in_port->serio, data, dfl); | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | out: | ||
291 | spin_unlock_irqrestore(&psm->lock, flags); | ||
292 | return IRQ_HANDLED; | ||
293 | } | ||
294 | |||
295 | static struct serio_driver ps2mult_drv = { | ||
296 | .driver = { | ||
297 | .name = "ps2mult", | ||
298 | }, | ||
299 | .description = "TQC PS/2 Multiplexer driver", | ||
300 | .id_table = ps2mult_serio_ids, | ||
301 | .interrupt = ps2mult_interrupt, | ||
302 | .connect = ps2mult_connect, | ||
303 | .disconnect = ps2mult_disconnect, | ||
304 | .reconnect = ps2mult_reconnect, | ||
305 | }; | ||
306 | |||
307 | static int __init ps2mult_init(void) | ||
308 | { | ||
309 | return serio_register_driver(&ps2mult_drv); | ||
310 | } | ||
311 | |||
312 | static void __exit ps2mult_exit(void) | ||
313 | { | ||
314 | serio_unregister_driver(&ps2mult_drv); | ||
315 | } | ||
316 | |||
317 | module_init(ps2mult_init); | ||
318 | module_exit(ps2mult_exit); | ||
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 9da6fbcaaa7e..7ec3c97dc1b9 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c | |||
@@ -90,7 +90,7 @@ static int rpckbd_open(struct serio *port) | |||
90 | 90 | ||
91 | if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) { | 91 | if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) { |
92 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n"); | 92 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n"); |
93 | free_irq(IRQ_KEYBOARDRX, NULL); | 93 | free_irq(IRQ_KEYBOARDRX, port); |
94 | return -EBUSY; | 94 | return -EBUSY; |
95 | } | 95 | } |
96 | 96 | ||
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index c3b626e9eae7..ba70058e2be3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -32,12 +32,10 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/serio.h> | 33 | #include <linux/serio.h> |
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/wait.h> | ||
36 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
38 | #include <linux/kthread.h> | 37 | #include <linux/workqueue.h> |
39 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
40 | #include <linux/freezer.h> | ||
41 | 39 | ||
42 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 40 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
43 | MODULE_DESCRIPTION("Serio abstraction core"); | 41 | MODULE_DESCRIPTION("Serio abstraction core"); |
@@ -45,7 +43,7 @@ MODULE_LICENSE("GPL"); | |||
45 | 43 | ||
46 | /* | 44 | /* |
47 | * serio_mutex protects entire serio subsystem and is taken every time | 45 | * serio_mutex protects entire serio subsystem and is taken every time |
48 | * serio port or driver registrered or unregistered. | 46 | * serio port or driver registered or unregistered. |
49 | */ | 47 | */ |
50 | static DEFINE_MUTEX(serio_mutex); | 48 | static DEFINE_MUTEX(serio_mutex); |
51 | 49 | ||
@@ -56,7 +54,7 @@ static struct bus_type serio_bus; | |||
56 | static void serio_add_port(struct serio *serio); | 54 | static void serio_add_port(struct serio *serio); |
57 | static int serio_reconnect_port(struct serio *serio); | 55 | static int serio_reconnect_port(struct serio *serio); |
58 | static void serio_disconnect_port(struct serio *serio); | 56 | static void serio_disconnect_port(struct serio *serio); |
59 | static void serio_reconnect_chain(struct serio *serio); | 57 | static void serio_reconnect_subtree(struct serio *serio); |
60 | static void serio_attach_driver(struct serio_driver *drv); | 58 | static void serio_attach_driver(struct serio_driver *drv); |
61 | 59 | ||
62 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) | 60 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) |
@@ -152,7 +150,7 @@ static void serio_find_driver(struct serio *serio) | |||
152 | enum serio_event_type { | 150 | enum serio_event_type { |
153 | SERIO_RESCAN_PORT, | 151 | SERIO_RESCAN_PORT, |
154 | SERIO_RECONNECT_PORT, | 152 | SERIO_RECONNECT_PORT, |
155 | SERIO_RECONNECT_CHAIN, | 153 | SERIO_RECONNECT_SUBTREE, |
156 | SERIO_REGISTER_PORT, | 154 | SERIO_REGISTER_PORT, |
157 | SERIO_ATTACH_DRIVER, | 155 | SERIO_ATTACH_DRIVER, |
158 | }; | 156 | }; |
@@ -166,58 +164,22 @@ struct serio_event { | |||
166 | 164 | ||
167 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ | 165 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ |
168 | static LIST_HEAD(serio_event_list); | 166 | static LIST_HEAD(serio_event_list); |
169 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); | ||
170 | static struct task_struct *serio_task; | ||
171 | 167 | ||
172 | static int serio_queue_event(void *object, struct module *owner, | 168 | static struct serio_event *serio_get_event(void) |
173 | enum serio_event_type event_type) | ||
174 | { | 169 | { |
170 | struct serio_event *event = NULL; | ||
175 | unsigned long flags; | 171 | unsigned long flags; |
176 | struct serio_event *event; | ||
177 | int retval = 0; | ||
178 | 172 | ||
179 | spin_lock_irqsave(&serio_event_lock, flags); | 173 | spin_lock_irqsave(&serio_event_lock, flags); |
180 | 174 | ||
181 | /* | 175 | if (!list_empty(&serio_event_list)) { |
182 | * Scan event list for the other events for the same serio port, | 176 | event = list_first_entry(&serio_event_list, |
183 | * starting with the most recent one. If event is the same we | 177 | struct serio_event, node); |
184 | * do not need add new one. If event is of different type we | 178 | list_del_init(&event->node); |
185 | * need to add this event and should not look further because | ||
186 | * we need to preseve sequence of distinct events. | ||
187 | */ | ||
188 | list_for_each_entry_reverse(event, &serio_event_list, node) { | ||
189 | if (event->object == object) { | ||
190 | if (event->type == event_type) | ||
191 | goto out; | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); | ||
197 | if (!event) { | ||
198 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
199 | retval = -ENOMEM; | ||
200 | goto out; | ||
201 | } | ||
202 | |||
203 | if (!try_module_get(owner)) { | ||
204 | pr_warning("Can't get module reference, dropping event %d\n", | ||
205 | event_type); | ||
206 | kfree(event); | ||
207 | retval = -EINVAL; | ||
208 | goto out; | ||
209 | } | 179 | } |
210 | 180 | ||
211 | event->type = event_type; | ||
212 | event->object = object; | ||
213 | event->owner = owner; | ||
214 | |||
215 | list_add_tail(&event->node, &serio_event_list); | ||
216 | wake_up(&serio_wait); | ||
217 | |||
218 | out: | ||
219 | spin_unlock_irqrestore(&serio_event_lock, flags); | 181 | spin_unlock_irqrestore(&serio_event_lock, flags); |
220 | return retval; | 182 | return event; |
221 | } | 183 | } |
222 | 184 | ||
223 | static void serio_free_event(struct serio_event *event) | 185 | static void serio_free_event(struct serio_event *event) |
@@ -226,7 +188,8 @@ static void serio_free_event(struct serio_event *event) | |||
226 | kfree(event); | 188 | kfree(event); |
227 | } | 189 | } |
228 | 190 | ||
229 | static void serio_remove_duplicate_events(struct serio_event *event) | 191 | static void serio_remove_duplicate_events(void *object, |
192 | enum serio_event_type type) | ||
230 | { | 193 | { |
231 | struct serio_event *e, *next; | 194 | struct serio_event *e, *next; |
232 | unsigned long flags; | 195 | unsigned long flags; |
@@ -234,13 +197,13 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
234 | spin_lock_irqsave(&serio_event_lock, flags); | 197 | spin_lock_irqsave(&serio_event_lock, flags); |
235 | 198 | ||
236 | list_for_each_entry_safe(e, next, &serio_event_list, node) { | 199 | list_for_each_entry_safe(e, next, &serio_event_list, node) { |
237 | if (event->object == e->object) { | 200 | if (object == e->object) { |
238 | /* | 201 | /* |
239 | * If this event is of different type we should not | 202 | * If this event is of different type we should not |
240 | * look further - we only suppress duplicate events | 203 | * look further - we only suppress duplicate events |
241 | * that were sent back-to-back. | 204 | * that were sent back-to-back. |
242 | */ | 205 | */ |
243 | if (event->type != e->type) | 206 | if (type != e->type) |
244 | break; | 207 | break; |
245 | 208 | ||
246 | list_del_init(&e->node); | 209 | list_del_init(&e->node); |
@@ -251,25 +214,7 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
251 | spin_unlock_irqrestore(&serio_event_lock, flags); | 214 | spin_unlock_irqrestore(&serio_event_lock, flags); |
252 | } | 215 | } |
253 | 216 | ||
254 | 217 | static void serio_handle_event(struct work_struct *work) | |
255 | static struct serio_event *serio_get_event(void) | ||
256 | { | ||
257 | struct serio_event *event = NULL; | ||
258 | unsigned long flags; | ||
259 | |||
260 | spin_lock_irqsave(&serio_event_lock, flags); | ||
261 | |||
262 | if (!list_empty(&serio_event_list)) { | ||
263 | event = list_first_entry(&serio_event_list, | ||
264 | struct serio_event, node); | ||
265 | list_del_init(&event->node); | ||
266 | } | ||
267 | |||
268 | spin_unlock_irqrestore(&serio_event_lock, flags); | ||
269 | return event; | ||
270 | } | ||
271 | |||
272 | static void serio_handle_event(void) | ||
273 | { | 218 | { |
274 | struct serio_event *event; | 219 | struct serio_event *event; |
275 | 220 | ||
@@ -292,8 +237,8 @@ static void serio_handle_event(void) | |||
292 | serio_find_driver(event->object); | 237 | serio_find_driver(event->object); |
293 | break; | 238 | break; |
294 | 239 | ||
295 | case SERIO_RECONNECT_CHAIN: | 240 | case SERIO_RECONNECT_SUBTREE: |
296 | serio_reconnect_chain(event->object); | 241 | serio_reconnect_subtree(event->object); |
297 | break; | 242 | break; |
298 | 243 | ||
299 | case SERIO_ATTACH_DRIVER: | 244 | case SERIO_ATTACH_DRIVER: |
@@ -301,13 +246,66 @@ static void serio_handle_event(void) | |||
301 | break; | 246 | break; |
302 | } | 247 | } |
303 | 248 | ||
304 | serio_remove_duplicate_events(event); | 249 | serio_remove_duplicate_events(event->object, event->type); |
305 | serio_free_event(event); | 250 | serio_free_event(event); |
306 | } | 251 | } |
307 | 252 | ||
308 | mutex_unlock(&serio_mutex); | 253 | mutex_unlock(&serio_mutex); |
309 | } | 254 | } |
310 | 255 | ||
256 | static DECLARE_WORK(serio_event_work, serio_handle_event); | ||
257 | |||
258 | static int serio_queue_event(void *object, struct module *owner, | ||
259 | enum serio_event_type event_type) | ||
260 | { | ||
261 | unsigned long flags; | ||
262 | struct serio_event *event; | ||
263 | int retval = 0; | ||
264 | |||
265 | spin_lock_irqsave(&serio_event_lock, flags); | ||
266 | |||
267 | /* | ||
268 | * Scan event list for the other events for the same serio port, | ||
269 | * starting with the most recent one. If event is the same we | ||
270 | * do not need add new one. If event is of different type we | ||
271 | * need to add this event and should not look further because | ||
272 | * we need to preseve sequence of distinct events. | ||
273 | */ | ||
274 | list_for_each_entry_reverse(event, &serio_event_list, node) { | ||
275 | if (event->object == object) { | ||
276 | if (event->type == event_type) | ||
277 | goto out; | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); | ||
283 | if (!event) { | ||
284 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
285 | retval = -ENOMEM; | ||
286 | goto out; | ||
287 | } | ||
288 | |||
289 | if (!try_module_get(owner)) { | ||
290 | pr_warning("Can't get module reference, dropping event %d\n", | ||
291 | event_type); | ||
292 | kfree(event); | ||
293 | retval = -EINVAL; | ||
294 | goto out; | ||
295 | } | ||
296 | |||
297 | event->type = event_type; | ||
298 | event->object = object; | ||
299 | event->owner = owner; | ||
300 | |||
301 | list_add_tail(&event->node, &serio_event_list); | ||
302 | queue_work(system_long_wq, &serio_event_work); | ||
303 | |||
304 | out: | ||
305 | spin_unlock_irqrestore(&serio_event_lock, flags); | ||
306 | return retval; | ||
307 | } | ||
308 | |||
311 | /* | 309 | /* |
312 | * Remove all events that have been submitted for a given | 310 | * Remove all events that have been submitted for a given |
313 | * object, be it serio port or driver. | 311 | * object, be it serio port or driver. |
@@ -330,12 +328,10 @@ static void serio_remove_pending_events(void *object) | |||
330 | } | 328 | } |
331 | 329 | ||
332 | /* | 330 | /* |
333 | * Destroy child serio port (if any) that has not been fully registered yet. | 331 | * Locate child serio port (if any) that has not been fully registered yet. |
334 | * | 332 | * |
335 | * Note that we rely on the fact that port can have only one child and therefore | 333 | * Children are registered by driver's connect() handler so there can't be a |
336 | * only one child registration request can be pending. Additionally, children | 334 | * grandchild pending registration together with a child. |
337 | * are registered by driver's connect() handler so there can't be a grandchild | ||
338 | * pending registration together with a child. | ||
339 | */ | 335 | */ |
340 | static struct serio *serio_get_pending_child(struct serio *parent) | 336 | static struct serio *serio_get_pending_child(struct serio *parent) |
341 | { | 337 | { |
@@ -359,18 +355,6 @@ static struct serio *serio_get_pending_child(struct serio *parent) | |||
359 | return child; | 355 | return child; |
360 | } | 356 | } |
361 | 357 | ||
362 | static int serio_thread(void *nothing) | ||
363 | { | ||
364 | do { | ||
365 | serio_handle_event(); | ||
366 | wait_event_interruptible(serio_wait, | ||
367 | kthread_should_stop() || !list_empty(&serio_event_list)); | ||
368 | } while (!kthread_should_stop()); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | |||
374 | /* | 358 | /* |
375 | * Serio port operations | 359 | * Serio port operations |
376 | */ | 360 | */ |
@@ -449,14 +433,16 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
449 | if (!strncmp(buf, "none", count)) { | 433 | if (!strncmp(buf, "none", count)) { |
450 | serio_disconnect_port(serio); | 434 | serio_disconnect_port(serio); |
451 | } else if (!strncmp(buf, "reconnect", count)) { | 435 | } else if (!strncmp(buf, "reconnect", count)) { |
452 | serio_reconnect_chain(serio); | 436 | serio_reconnect_subtree(serio); |
453 | } else if (!strncmp(buf, "rescan", count)) { | 437 | } else if (!strncmp(buf, "rescan", count)) { |
454 | serio_disconnect_port(serio); | 438 | serio_disconnect_port(serio); |
455 | serio_find_driver(serio); | 439 | serio_find_driver(serio); |
440 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | ||
456 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { | 441 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { |
457 | serio_disconnect_port(serio); | 442 | serio_disconnect_port(serio); |
458 | error = serio_bind_driver(serio, to_serio_driver(drv)); | 443 | error = serio_bind_driver(serio, to_serio_driver(drv)); |
459 | put_driver(drv); | 444 | put_driver(drv); |
445 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | ||
460 | } else { | 446 | } else { |
461 | error = -EINVAL; | 447 | error = -EINVAL; |
462 | } | 448 | } |
@@ -516,6 +502,8 @@ static void serio_init_port(struct serio *serio) | |||
516 | __module_get(THIS_MODULE); | 502 | __module_get(THIS_MODULE); |
517 | 503 | ||
518 | INIT_LIST_HEAD(&serio->node); | 504 | INIT_LIST_HEAD(&serio->node); |
505 | INIT_LIST_HEAD(&serio->child_node); | ||
506 | INIT_LIST_HEAD(&serio->children); | ||
519 | spin_lock_init(&serio->lock); | 507 | spin_lock_init(&serio->lock); |
520 | mutex_init(&serio->drv_mutex); | 508 | mutex_init(&serio->drv_mutex); |
521 | device_initialize(&serio->dev); | 509 | device_initialize(&serio->dev); |
@@ -538,12 +526,13 @@ static void serio_init_port(struct serio *serio) | |||
538 | */ | 526 | */ |
539 | static void serio_add_port(struct serio *serio) | 527 | static void serio_add_port(struct serio *serio) |
540 | { | 528 | { |
529 | struct serio *parent = serio->parent; | ||
541 | int error; | 530 | int error; |
542 | 531 | ||
543 | if (serio->parent) { | 532 | if (parent) { |
544 | serio_pause_rx(serio->parent); | 533 | serio_pause_rx(parent); |
545 | serio->parent->child = serio; | 534 | list_add_tail(&serio->child_node, &parent->children); |
546 | serio_continue_rx(serio->parent); | 535 | serio_continue_rx(parent); |
547 | } | 536 | } |
548 | 537 | ||
549 | list_add_tail(&serio->node, &serio_list); | 538 | list_add_tail(&serio->node, &serio_list); |
@@ -559,15 +548,14 @@ static void serio_add_port(struct serio *serio) | |||
559 | } | 548 | } |
560 | 549 | ||
561 | /* | 550 | /* |
562 | * serio_destroy_port() completes deregistration process and removes | 551 | * serio_destroy_port() completes unregistration process and removes |
563 | * port from the system | 552 | * port from the system |
564 | */ | 553 | */ |
565 | static void serio_destroy_port(struct serio *serio) | 554 | static void serio_destroy_port(struct serio *serio) |
566 | { | 555 | { |
567 | struct serio *child; | 556 | struct serio *child; |
568 | 557 | ||
569 | child = serio_get_pending_child(serio); | 558 | while ((child = serio_get_pending_child(serio)) != NULL) { |
570 | if (child) { | ||
571 | serio_remove_pending_events(child); | 559 | serio_remove_pending_events(child); |
572 | put_device(&child->dev); | 560 | put_device(&child->dev); |
573 | } | 561 | } |
@@ -577,7 +565,7 @@ static void serio_destroy_port(struct serio *serio) | |||
577 | 565 | ||
578 | if (serio->parent) { | 566 | if (serio->parent) { |
579 | serio_pause_rx(serio->parent); | 567 | serio_pause_rx(serio->parent); |
580 | serio->parent->child = NULL; | 568 | list_del_init(&serio->child_node); |
581 | serio_continue_rx(serio->parent); | 569 | serio_continue_rx(serio->parent); |
582 | serio->parent = NULL; | 570 | serio->parent = NULL; |
583 | } | 571 | } |
@@ -609,46 +597,82 @@ static int serio_reconnect_port(struct serio *serio) | |||
609 | } | 597 | } |
610 | 598 | ||
611 | /* | 599 | /* |
612 | * Reconnect serio port and all its children (re-initialize attached devices) | 600 | * Reconnect serio port and all its children (re-initialize attached |
601 | * devices). | ||
613 | */ | 602 | */ |
614 | static void serio_reconnect_chain(struct serio *serio) | 603 | static void serio_reconnect_subtree(struct serio *root) |
615 | { | 604 | { |
605 | struct serio *s = root; | ||
606 | int error; | ||
607 | |||
616 | do { | 608 | do { |
617 | if (serio_reconnect_port(serio)) { | 609 | error = serio_reconnect_port(s); |
618 | /* Ok, old children are now gone, we are done */ | 610 | if (!error) { |
619 | break; | 611 | /* |
612 | * Reconnect was successful, move on to do the | ||
613 | * first child. | ||
614 | */ | ||
615 | if (!list_empty(&s->children)) { | ||
616 | s = list_first_entry(&s->children, | ||
617 | struct serio, child_node); | ||
618 | continue; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * Either it was a leaf node or reconnect failed and it | ||
624 | * became a leaf node. Continue reconnecting starting with | ||
625 | * the next sibling of the parent node. | ||
626 | */ | ||
627 | while (s != root) { | ||
628 | struct serio *parent = s->parent; | ||
629 | |||
630 | if (!list_is_last(&s->child_node, &parent->children)) { | ||
631 | s = list_entry(s->child_node.next, | ||
632 | struct serio, child_node); | ||
633 | break; | ||
634 | } | ||
635 | |||
636 | s = parent; | ||
620 | } | 637 | } |
621 | serio = serio->child; | 638 | } while (s != root); |
622 | } while (serio); | ||
623 | } | 639 | } |
624 | 640 | ||
625 | /* | 641 | /* |
626 | * serio_disconnect_port() unbinds a port from its driver. As a side effect | 642 | * serio_disconnect_port() unbinds a port from its driver. As a side effect |
627 | * all child ports are unbound and destroyed. | 643 | * all children ports are unbound and destroyed. |
628 | */ | 644 | */ |
629 | static void serio_disconnect_port(struct serio *serio) | 645 | static void serio_disconnect_port(struct serio *serio) |
630 | { | 646 | { |
631 | struct serio *s, *parent; | 647 | struct serio *s = serio; |
648 | |||
649 | /* | ||
650 | * Children ports should be disconnected and destroyed | ||
651 | * first; we travel the tree in depth-first order. | ||
652 | */ | ||
653 | while (!list_empty(&serio->children)) { | ||
654 | |||
655 | /* Locate a leaf */ | ||
656 | while (!list_empty(&s->children)) | ||
657 | s = list_first_entry(&s->children, | ||
658 | struct serio, child_node); | ||
632 | 659 | ||
633 | if (serio->child) { | ||
634 | /* | 660 | /* |
635 | * Children ports should be disconnected and destroyed | 661 | * Prune this leaf node unless it is the one we |
636 | * first, staring with the leaf one, since we don't want | 662 | * started with. |
637 | * to do recursion | ||
638 | */ | 663 | */ |
639 | for (s = serio; s->child; s = s->child) | 664 | if (s != serio) { |
640 | /* empty */; | 665 | struct serio *parent = s->parent; |
641 | |||
642 | do { | ||
643 | parent = s->parent; | ||
644 | 666 | ||
645 | device_release_driver(&s->dev); | 667 | device_release_driver(&s->dev); |
646 | serio_destroy_port(s); | 668 | serio_destroy_port(s); |
647 | } while ((s = parent) != serio); | 669 | |
670 | s = parent; | ||
671 | } | ||
648 | } | 672 | } |
649 | 673 | ||
650 | /* | 674 | /* |
651 | * Ok, no children left, now disconnect this port | 675 | * OK, no children left, now disconnect this port. |
652 | */ | 676 | */ |
653 | device_release_driver(&serio->dev); | 677 | device_release_driver(&serio->dev); |
654 | } | 678 | } |
@@ -661,7 +685,7 @@ EXPORT_SYMBOL(serio_rescan); | |||
661 | 685 | ||
662 | void serio_reconnect(struct serio *serio) | 686 | void serio_reconnect(struct serio *serio) |
663 | { | 687 | { |
664 | serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN); | 688 | serio_queue_event(serio, NULL, SERIO_RECONNECT_SUBTREE); |
665 | } | 689 | } |
666 | EXPORT_SYMBOL(serio_reconnect); | 690 | EXPORT_SYMBOL(serio_reconnect); |
667 | 691 | ||
@@ -689,14 +713,16 @@ void serio_unregister_port(struct serio *serio) | |||
689 | EXPORT_SYMBOL(serio_unregister_port); | 713 | EXPORT_SYMBOL(serio_unregister_port); |
690 | 714 | ||
691 | /* | 715 | /* |
692 | * Safely unregisters child port if one is present. | 716 | * Safely unregisters children ports if they are present. |
693 | */ | 717 | */ |
694 | void serio_unregister_child_port(struct serio *serio) | 718 | void serio_unregister_child_port(struct serio *serio) |
695 | { | 719 | { |
720 | struct serio *s, *next; | ||
721 | |||
696 | mutex_lock(&serio_mutex); | 722 | mutex_lock(&serio_mutex); |
697 | if (serio->child) { | 723 | list_for_each_entry_safe(s, next, &serio->children, child_node) { |
698 | serio_disconnect_port(serio->child); | 724 | serio_disconnect_port(s); |
699 | serio_destroy_port(serio->child); | 725 | serio_destroy_port(s); |
700 | } | 726 | } |
701 | mutex_unlock(&serio_mutex); | 727 | mutex_unlock(&serio_mutex); |
702 | } | 728 | } |
@@ -1003,21 +1029,18 @@ static int __init serio_init(void) | |||
1003 | return error; | 1029 | return error; |
1004 | } | 1030 | } |
1005 | 1031 | ||
1006 | serio_task = kthread_run(serio_thread, NULL, "kseriod"); | ||
1007 | if (IS_ERR(serio_task)) { | ||
1008 | bus_unregister(&serio_bus); | ||
1009 | error = PTR_ERR(serio_task); | ||
1010 | pr_err("Failed to start kseriod, error: %d\n", error); | ||
1011 | return error; | ||
1012 | } | ||
1013 | |||
1014 | return 0; | 1032 | return 0; |
1015 | } | 1033 | } |
1016 | 1034 | ||
1017 | static void __exit serio_exit(void) | 1035 | static void __exit serio_exit(void) |
1018 | { | 1036 | { |
1019 | bus_unregister(&serio_bus); | 1037 | bus_unregister(&serio_bus); |
1020 | kthread_stop(serio_task); | 1038 | |
1039 | /* | ||
1040 | * There should not be any outstanding events but work may | ||
1041 | * still be scheduled so simply cancel it. | ||
1042 | */ | ||
1043 | cancel_work_sync(&serio_event_work); | ||
1021 | } | 1044 | } |
1022 | 1045 | ||
1023 | subsys_initcall(serio_init); | 1046 | subsys_initcall(serio_init); |
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 998664854440..b7ba4597f7f0 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/smp_lock.h> | ||
15 | #include <linux/poll.h> | 14 | #include <linux/poll.h> |
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/serio.h> | 16 | #include <linux/serio.h> |
@@ -243,6 +242,7 @@ static const struct file_operations serio_raw_fops = { | |||
243 | .write = serio_raw_write, | 242 | .write = serio_raw_write, |
244 | .poll = serio_raw_poll, | 243 | .poll = serio_raw_poll, |
245 | .fasync = serio_raw_fasync, | 244 | .fasync = serio_raw_fasync, |
245 | .llseek = noop_llseek, | ||
246 | }; | 246 | }; |
247 | 247 | ||
248 | 248 | ||
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 6d345112bcb7..8755f5f3ad37 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -116,14 +116,15 @@ static void serport_ldisc_close(struct tty_struct *tty) | |||
116 | 116 | ||
117 | /* | 117 | /* |
118 | * serport_ldisc_receive() is called by the low level tty driver when characters | 118 | * serport_ldisc_receive() is called by the low level tty driver when characters |
119 | * are ready for us. We forward the characters, one by one to the 'interrupt' | 119 | * are ready for us. We forward the characters and flags, one by one to the |
120 | * routine. | 120 | * 'interrupt' routine. |
121 | */ | 121 | */ |
122 | 122 | ||
123 | static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) | 123 | static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) |
124 | { | 124 | { |
125 | struct serport *serport = (struct serport*) tty->disc_data; | 125 | struct serport *serport = (struct serport*) tty->disc_data; |
126 | unsigned long flags; | 126 | unsigned long flags; |
127 | unsigned int ch_flags; | ||
127 | int i; | 128 | int i; |
128 | 129 | ||
129 | spin_lock_irqsave(&serport->lock, flags); | 130 | spin_lock_irqsave(&serport->lock, flags); |
@@ -131,8 +132,23 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c | |||
131 | if (!test_bit(SERPORT_ACTIVE, &serport->flags)) | 132 | if (!test_bit(SERPORT_ACTIVE, &serport->flags)) |
132 | goto out; | 133 | goto out; |
133 | 134 | ||
134 | for (i = 0; i < count; i++) | 135 | for (i = 0; i < count; i++) { |
135 | serio_interrupt(serport->serio, cp[i], 0); | 136 | switch (fp[i]) { |
137 | case TTY_FRAME: | ||
138 | ch_flags = SERIO_FRAME; | ||
139 | break; | ||
140 | |||
141 | case TTY_PARITY: | ||
142 | ch_flags = SERIO_PARITY; | ||
143 | break; | ||
144 | |||
145 | default: | ||
146 | ch_flags = 0; | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | serio_interrupt(serport->serio, cp[i], ch_flags); | ||
151 | } | ||
136 | 152 | ||
137 | out: | 153 | out: |
138 | spin_unlock_irqrestore(&serport->lock, flags); | 154 | spin_unlock_irqrestore(&serport->lock, flags); |
@@ -165,6 +181,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u | |||
165 | serio->open = serport_serio_open; | 181 | serio->open = serport_serio_open; |
166 | serio->close = serport_serio_close; | 182 | serio->close = serport_serio_close; |
167 | serio->port_data = serport; | 183 | serio->port_data = serport; |
184 | serio->dev.parent = tty->dev; | ||
168 | 185 | ||
169 | serio_register_port(serport->serio); | 186 | serio_register_port(serport->serio); |
170 | printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name)); | 187 | printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name)); |
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index bb14449fb022..80baa53da5b1 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -225,15 +225,14 @@ static void sxps2_close(struct serio *pserio) | |||
225 | /** | 225 | /** |
226 | * xps2_of_probe - probe method for the PS/2 device. | 226 | * xps2_of_probe - probe method for the PS/2 device. |
227 | * @of_dev: pointer to OF device structure | 227 | * @of_dev: pointer to OF device structure |
228 | * @match: pointer to the stucture used for matching a device | 228 | * @match: pointer to the structure used for matching a device |
229 | * | 229 | * |
230 | * This function probes the PS/2 device in the device tree. | 230 | * This function probes the PS/2 device in the device tree. |
231 | * It initializes the driver data structure and the hardware. | 231 | * It initializes the driver data structure and the hardware. |
232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative | 232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative |
233 | * value if there is an error. | 233 | * value if there is an error. |
234 | */ | 234 | */ |
235 | static int __devinit xps2_of_probe(struct platform_device *ofdev, | 235 | static int __devinit xps2_of_probe(struct platform_device *ofdev) |
236 | const struct of_device_id *match) | ||
237 | { | 236 | { |
238 | struct resource r_irq; /* Interrupt resources */ | 237 | struct resource r_irq; /* Interrupt resources */ |
239 | struct resource r_mem; /* IO mem resources */ | 238 | struct resource r_mem; /* IO mem resources */ |
@@ -361,7 +360,7 @@ static const struct of_device_id xps2_of_match[] __devinitconst = { | |||
361 | }; | 360 | }; |
362 | MODULE_DEVICE_TABLE(of, xps2_of_match); | 361 | MODULE_DEVICE_TABLE(of, xps2_of_match); |
363 | 362 | ||
364 | static struct of_platform_driver xps2_of_driver = { | 363 | static struct platform_driver xps2_of_driver = { |
365 | .driver = { | 364 | .driver = { |
366 | .name = DRIVER_NAME, | 365 | .name = DRIVER_NAME, |
367 | .owner = THIS_MODULE, | 366 | .owner = THIS_MODULE, |
@@ -373,12 +372,12 @@ static struct of_platform_driver xps2_of_driver = { | |||
373 | 372 | ||
374 | static int __init xps2_init(void) | 373 | static int __init xps2_init(void) |
375 | { | 374 | { |
376 | return of_register_platform_driver(&xps2_of_driver); | 375 | return platform_driver_register(&xps2_of_driver); |
377 | } | 376 | } |
378 | 377 | ||
379 | static void __exit xps2_cleanup(void) | 378 | static void __exit xps2_cleanup(void) |
380 | { | 379 | { |
381 | of_unregister_platform_driver(&xps2_of_driver); | 380 | platform_driver_unregister(&xps2_of_driver); |
382 | } | 381 | } |
383 | 382 | ||
384 | module_init(xps2_init); | 383 | module_init(xps2_init); |