aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard/hilkbd.c
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2009-03-05 02:27:15 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-03-08 19:35:45 -0400
commitb0ecc7309443dbcf1a0ce2d93f39f5d92c124d42 (patch)
treede6767f1d01117e29d1c3783f3269afb8c30fa46 /drivers/input/keyboard/hilkbd.c
parentadcb523eb39e0dd2f712d8dbd8e18b5d36a97825 (diff)
Input: hilkbd - fix crash when removing hilkbd module
On parisc machines, which don't have HIL, removing the hilkbd module panics the kernel. Fix this by adding proper implementations for the probe and remove functions to the parisc_driver structure. A few functions were renamed to clean up the code and make it easier readable. Disable the MODULE_DEVICE_TABLE() macro on parisc since the kernel module autoloader should instead prefer the hp_sdc driver which takes care of full HIL support, including HIL mouse and HIL tablets. [dtor@mail.ru: fix some section markups] Signed-off-by: Helge Deller <deller@gmx.de> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/keyboard/hilkbd.c')
-rw-r--r--drivers/input/keyboard/hilkbd.c140
1 files changed, 80 insertions, 60 deletions
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index aacf71f3cd44..e9d639ec283d 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -198,45 +198,28 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
198} 198}
199 199
200 200
201/* initialise HIL */ 201/* initialize HIL */
202static int __init 202static int __devinit hil_keyb_init(void)
203hil_keyb_init(void)
204{ 203{
205 unsigned char c; 204 unsigned char c;
206 unsigned int i, kbid; 205 unsigned int i, kbid;
207 wait_queue_head_t hil_wait; 206 wait_queue_head_t hil_wait;
208 int err; 207 int err;
209 208
210 if (hil_dev.dev) { 209 if (hil_dev.dev)
211 return -ENODEV; /* already initialized */ 210 return -ENODEV; /* already initialized */
212 }
213 211
212 init_waitqueue_head(&hil_wait);
214 spin_lock_init(&hil_dev.lock); 213 spin_lock_init(&hil_dev.lock);
214
215 hil_dev.dev = input_allocate_device(); 215 hil_dev.dev = input_allocate_device();
216 if (!hil_dev.dev) 216 if (!hil_dev.dev)
217 return -ENOMEM; 217 return -ENOMEM;
218 218
219#if defined(CONFIG_HP300)
220 if (!MACH_IS_HP300) {
221 err = -ENODEV;
222 goto err1;
223 }
224 if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
225 printk(KERN_ERR "HIL: hardware register was not found\n");
226 err = -ENODEV;
227 goto err1;
228 }
229 if (!request_region(HILBASE + HIL_DATA, 2, "hil")) {
230 printk(KERN_ERR "HIL: IOPORT region already used\n");
231 err = -EIO;
232 goto err1;
233 }
234#endif
235
236 err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); 219 err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
237 if (err) { 220 if (err) {
238 printk(KERN_ERR "HIL: Can't get IRQ\n"); 221 printk(KERN_ERR "HIL: Can't get IRQ\n");
239 goto err2; 222 goto err1;
240 } 223 }
241 224
242 /* Turn on interrupts */ 225 /* Turn on interrupts */
@@ -246,11 +229,9 @@ hil_keyb_init(void)
246 hil_dev.valid = 0; /* clear any pending data */ 229 hil_dev.valid = 0; /* clear any pending data */
247 hil_do(HIL_READKBDSADR, NULL, 0); 230 hil_do(HIL_READKBDSADR, NULL, 0);
248 231
249 init_waitqueue_head(&hil_wait); 232 wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3 * HZ);
250 wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); 233 if (!hil_dev.valid)
251 if (!hil_dev.valid) {
252 printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); 234 printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n");
253 }
254 235
255 c = hil_dev.c; 236 c = hil_dev.c;
256 hil_dev.valid = 0; 237 hil_dev.valid = 0;
@@ -268,7 +249,7 @@ hil_keyb_init(void)
268 249
269 for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) 250 for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
270 if (hphilkeyb_keycode[i] != KEY_RESERVED) 251 if (hphilkeyb_keycode[i] != KEY_RESERVED)
271 set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); 252 __set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
272 253
273 hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); 254 hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
274 hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | 255 hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) |
@@ -287,34 +268,45 @@ hil_keyb_init(void)
287 err = input_register_device(hil_dev.dev); 268 err = input_register_device(hil_dev.dev);
288 if (err) { 269 if (err) {
289 printk(KERN_ERR "HIL: Can't register device\n"); 270 printk(KERN_ERR "HIL: Can't register device\n");
290 goto err3; 271 goto err2;
291 } 272 }
273
292 printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", 274 printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
293 hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); 275 hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
294 276
295 return 0; 277 return 0;
296 278
297err3: 279err2:
298 hil_do(HIL_INTOFF, NULL, 0); 280 hil_do(HIL_INTOFF, NULL, 0);
299 disable_irq(HIL_IRQ);
300 free_irq(HIL_IRQ, hil_dev.dev_id); 281 free_irq(HIL_IRQ, hil_dev.dev_id);
301err2:
302#if defined(CONFIG_HP300)
303 release_region(HILBASE + HIL_DATA, 2);
304err1: 282err1:
305#endif
306 input_free_device(hil_dev.dev); 283 input_free_device(hil_dev.dev);
307 hil_dev.dev = NULL; 284 hil_dev.dev = NULL;
308 return err; 285 return err;
309} 286}
310 287
288static void __devexit hil_keyb_exit(void)
289{
290 if (HIL_IRQ)
291 free_irq(HIL_IRQ, hil_dev.dev_id);
292
293 /* Turn off interrupts */
294 hil_do(HIL_INTOFF, NULL, 0);
295
296 input_unregister_device(hil_dev.dev);
297 hil_dev.dev = NULL;
298}
311 299
312#if defined(CONFIG_PARISC) 300#if defined(CONFIG_PARISC)
313static int __init 301static int __devinit hil_probe_chip(struct parisc_device *dev)
314hil_init_chip(struct parisc_device *dev)
315{ 302{
303 /* Only allow one HIL keyboard */
304 if (hil_dev.dev)
305 return -ENODEV;
306
316 if (!dev->irq) { 307 if (!dev->irq) {
317 printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start); 308 printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%p\n",
309 (void *)dev->hpa.start);
318 return -ENODEV; 310 return -ENODEV;
319 } 311 }
320 312
@@ -327,51 +319,79 @@ hil_init_chip(struct parisc_device *dev)
327 return hil_keyb_init(); 319 return hil_keyb_init();
328} 320}
329 321
322static int __devexit hil_remove_chip(struct parisc_device *dev)
323{
324 hil_keyb_exit();
325
326 return 0;
327}
328
330static struct parisc_device_id hil_tbl[] = { 329static struct parisc_device_id hil_tbl[] = {
331 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, 330 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
332 { 0, } 331 { 0, }
333}; 332};
334 333
334#if 0
335/* Disabled to avoid conflicts with the HP SDC HIL drivers */
335MODULE_DEVICE_TABLE(parisc, hil_tbl); 336MODULE_DEVICE_TABLE(parisc, hil_tbl);
337#endif
336 338
337static struct parisc_driver hil_driver = { 339static struct parisc_driver hil_driver = {
338 .name = "hil", 340 .name = "hil",
339 .id_table = hil_tbl, 341 .id_table = hil_tbl,
340 .probe = hil_init_chip, 342 .probe = hil_probe_chip,
343 .remove = __devexit_p(hil_remove_chip),
341}; 344};
342#endif /* CONFIG_PARISC */
343
344 345
345static int __init hil_init(void) 346static int __init hil_init(void)
346{ 347{
347#if defined(CONFIG_PARISC)
348 return register_parisc_driver(&hil_driver); 348 return register_parisc_driver(&hil_driver);
349#else
350 return hil_keyb_init();
351#endif
352} 349}
353 350
354
355static void __exit hil_exit(void) 351static void __exit hil_exit(void)
356{ 352{
357 if (HIL_IRQ) { 353 unregister_parisc_driver(&hil_driver);
358 disable_irq(HIL_IRQ); 354}
359 free_irq(HIL_IRQ, hil_dev.dev_id); 355
356#else /* !CONFIG_PARISC */
357
358static int __init hil_init(void)
359{
360 int error;
361
362 /* Only allow one HIL keyboard */
363 if (hil_dev.dev)
364 return -EBUSY;
365
366 if (!MACH_IS_HP300)
367 return -ENODEV;
368
369 if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
370 printk(KERN_ERR "HIL: hardware register was not found\n");
371 return -ENODEV;
360 } 372 }
361 373
362 /* Turn off interrupts */ 374 if (!request_region(HILBASE + HIL_DATA, 2, "hil")) {
363 hil_do(HIL_INTOFF, NULL, 0); 375 printk(KERN_ERR "HIL: IOPORT region already used\n");
376 return -EIO;
377 }
364 378
365 input_unregister_device(hil_dev.dev); 379 error = hil_keyb_init();
380 if (error) {
381 release_region(HILBASE + HIL_DATA, 2);
382 return error;
383 }
366 384
367 hil_dev.dev = NULL; 385 return 0;
386}
368 387
369#if defined(CONFIG_PARISC) 388static void __exit hil_exit(void)
370 unregister_parisc_driver(&hil_driver); 389{
371#else 390 hil_keyb_exit();
372 release_region(HILBASE+HIL_DATA, 2); 391 release_region(HILBASE + HIL_DATA, 2);
373#endif
374} 392}
375 393
394#endif /* CONFIG_PARISC */
395
376module_init(hil_init); 396module_init(hil_init);
377module_exit(hil_exit); 397module_exit(hil_exit);