diff options
Diffstat (limited to 'drivers/macintosh/adb.c')
-rw-r--r-- | drivers/macintosh/adb.c | 174 |
1 files changed, 78 insertions, 96 deletions
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index b7adde4324e4..7ce0ea64465c 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
36 | #include <linux/completion.h> | 36 | #include <linux/completion.h> |
37 | #include <linux/device.h> | 37 | #include <linux/device.h> |
38 | #include <linux/kthread.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/semaphore.h> | 41 | #include <asm/semaphore.h> |
@@ -82,21 +83,11 @@ struct adb_driver *adb_controller; | |||
82 | BLOCKING_NOTIFIER_HEAD(adb_client_list); | 83 | BLOCKING_NOTIFIER_HEAD(adb_client_list); |
83 | static int adb_got_sleep; | 84 | static int adb_got_sleep; |
84 | static int adb_inited; | 85 | static int adb_inited; |
85 | static pid_t adb_probe_task_pid; | ||
86 | static DECLARE_MUTEX(adb_probe_mutex); | 86 | static DECLARE_MUTEX(adb_probe_mutex); |
87 | static struct completion adb_probe_task_comp; | ||
88 | static int sleepy_trackpad; | 87 | static int sleepy_trackpad; |
89 | static int autopoll_devs; | 88 | static int autopoll_devs; |
90 | int __adb_probe_sync; | 89 | int __adb_probe_sync; |
91 | 90 | ||
92 | #ifdef CONFIG_PM_SLEEP | ||
93 | static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when); | ||
94 | static struct pmu_sleep_notifier adb_sleep_notifier = { | ||
95 | adb_notify_sleep, | ||
96 | SLEEP_LEVEL_ADB, | ||
97 | }; | ||
98 | #endif | ||
99 | |||
100 | static int adb_scan_bus(void); | 91 | static int adb_scan_bus(void); |
101 | static int do_adb_reset_bus(void); | 92 | static int do_adb_reset_bus(void); |
102 | static void adbdev_init(void); | 93 | static void adbdev_init(void); |
@@ -134,16 +125,6 @@ static void printADBreply(struct adb_request *req) | |||
134 | } | 125 | } |
135 | #endif | 126 | #endif |
136 | 127 | ||
137 | |||
138 | static __inline__ void adb_wait_ms(unsigned int ms) | ||
139 | { | ||
140 | if (current->pid && adb_probe_task_pid && | ||
141 | adb_probe_task_pid == current->pid) | ||
142 | msleep(ms); | ||
143 | else | ||
144 | mdelay(ms); | ||
145 | } | ||
146 | |||
147 | static int adb_scan_bus(void) | 128 | static int adb_scan_bus(void) |
148 | { | 129 | { |
149 | int i, highFree=0, noMovement; | 130 | int i, highFree=0, noMovement; |
@@ -248,13 +229,10 @@ static int adb_scan_bus(void) | |||
248 | static int | 229 | static int |
249 | adb_probe_task(void *x) | 230 | adb_probe_task(void *x) |
250 | { | 231 | { |
251 | strcpy(current->comm, "kadbprobe"); | ||
252 | |||
253 | printk(KERN_INFO "adb: starting probe task...\n"); | 232 | printk(KERN_INFO "adb: starting probe task...\n"); |
254 | do_adb_reset_bus(); | 233 | do_adb_reset_bus(); |
255 | printk(KERN_INFO "adb: finished probe task...\n"); | 234 | printk(KERN_INFO "adb: finished probe task...\n"); |
256 | 235 | ||
257 | adb_probe_task_pid = 0; | ||
258 | up(&adb_probe_mutex); | 236 | up(&adb_probe_mutex); |
259 | 237 | ||
260 | return 0; | 238 | return 0; |
@@ -263,7 +241,7 @@ adb_probe_task(void *x) | |||
263 | static void | 241 | static void |
264 | __adb_probe_task(struct work_struct *bullshit) | 242 | __adb_probe_task(struct work_struct *bullshit) |
265 | { | 243 | { |
266 | adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL); | 244 | kthread_run(adb_probe_task, NULL, "kadbprobe"); |
267 | } | 245 | } |
268 | 246 | ||
269 | static DECLARE_WORK(adb_reset_work, __adb_probe_task); | 247 | static DECLARE_WORK(adb_reset_work, __adb_probe_task); |
@@ -281,6 +259,36 @@ adb_reset_bus(void) | |||
281 | return 0; | 259 | return 0; |
282 | } | 260 | } |
283 | 261 | ||
262 | #ifdef CONFIG_PM | ||
263 | /* | ||
264 | * notify clients before sleep | ||
265 | */ | ||
266 | static int adb_suspend(struct platform_device *dev, pm_message_t state) | ||
267 | { | ||
268 | adb_got_sleep = 1; | ||
269 | /* We need to get a lock on the probe thread */ | ||
270 | down(&adb_probe_mutex); | ||
271 | /* Stop autopoll */ | ||
272 | if (adb_controller->autopoll) | ||
273 | adb_controller->autopoll(0); | ||
274 | blocking_notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * reset bus after sleep | ||
281 | */ | ||
282 | static int adb_resume(struct platform_device *dev) | ||
283 | { | ||
284 | adb_got_sleep = 0; | ||
285 | up(&adb_probe_mutex); | ||
286 | adb_reset_bus(); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | #endif /* CONFIG_PM */ | ||
291 | |||
284 | int __init adb_init(void) | 292 | int __init adb_init(void) |
285 | { | 293 | { |
286 | struct adb_driver *driver; | 294 | struct adb_driver *driver; |
@@ -313,15 +321,12 @@ int __init adb_init(void) | |||
313 | printk(KERN_WARNING "Warning: no ADB interface detected\n"); | 321 | printk(KERN_WARNING "Warning: no ADB interface detected\n"); |
314 | adb_controller = NULL; | 322 | adb_controller = NULL; |
315 | } else { | 323 | } else { |
316 | #ifdef CONFIG_PM_SLEEP | ||
317 | pmu_register_sleep_notifier(&adb_sleep_notifier); | ||
318 | #endif /* CONFIG_PM */ | ||
319 | #ifdef CONFIG_PPC | 324 | #ifdef CONFIG_PPC |
320 | if (machine_is_compatible("AAPL,PowerBook1998") || | 325 | if (machine_is_compatible("AAPL,PowerBook1998") || |
321 | machine_is_compatible("PowerBook1,1")) | 326 | machine_is_compatible("PowerBook1,1")) |
322 | sleepy_trackpad = 1; | 327 | sleepy_trackpad = 1; |
323 | #endif /* CONFIG_PPC */ | 328 | #endif /* CONFIG_PPC */ |
324 | init_completion(&adb_probe_task_comp); | 329 | |
325 | adbdev_init(); | 330 | adbdev_init(); |
326 | adb_reset_bus(); | 331 | adb_reset_bus(); |
327 | } | 332 | } |
@@ -330,33 +335,6 @@ int __init adb_init(void) | |||
330 | 335 | ||
331 | __initcall(adb_init); | 336 | __initcall(adb_init); |
332 | 337 | ||
333 | #ifdef CONFIG_PM | ||
334 | /* | ||
335 | * notify clients before sleep and reset bus afterwards | ||
336 | */ | ||
337 | void | ||
338 | adb_notify_sleep(struct pmu_sleep_notifier *self, int when) | ||
339 | { | ||
340 | switch (when) { | ||
341 | case PBOOK_SLEEP_REQUEST: | ||
342 | adb_got_sleep = 1; | ||
343 | /* We need to get a lock on the probe thread */ | ||
344 | down(&adb_probe_mutex); | ||
345 | /* Stop autopoll */ | ||
346 | if (adb_controller->autopoll) | ||
347 | adb_controller->autopoll(0); | ||
348 | blocking_notifier_call_chain(&adb_client_list, | ||
349 | ADB_MSG_POWERDOWN, NULL); | ||
350 | break; | ||
351 | case PBOOK_WAKE: | ||
352 | adb_got_sleep = 0; | ||
353 | up(&adb_probe_mutex); | ||
354 | adb_reset_bus(); | ||
355 | break; | ||
356 | } | ||
357 | } | ||
358 | #endif /* CONFIG_PM */ | ||
359 | |||
360 | static int | 338 | static int |
361 | do_adb_reset_bus(void) | 339 | do_adb_reset_bus(void) |
362 | { | 340 | { |
@@ -373,7 +351,7 @@ do_adb_reset_bus(void) | |||
373 | 351 | ||
374 | if (sleepy_trackpad) { | 352 | if (sleepy_trackpad) { |
375 | /* Let the trackpad settle down */ | 353 | /* Let the trackpad settle down */ |
376 | adb_wait_ms(500); | 354 | msleep(500); |
377 | } | 355 | } |
378 | 356 | ||
379 | down(&adb_handler_sem); | 357 | down(&adb_handler_sem); |
@@ -389,7 +367,7 @@ do_adb_reset_bus(void) | |||
389 | 367 | ||
390 | if (sleepy_trackpad) { | 368 | if (sleepy_trackpad) { |
391 | /* Let the trackpad settle down */ | 369 | /* Let the trackpad settle down */ |
392 | adb_wait_ms(1500); | 370 | msleep(1500); |
393 | } | 371 | } |
394 | 372 | ||
395 | if (!ret) { | 373 | if (!ret) { |
@@ -413,41 +391,27 @@ adb_poll(void) | |||
413 | adb_controller->poll(); | 391 | adb_controller->poll(); |
414 | } | 392 | } |
415 | 393 | ||
416 | static void | 394 | static void adb_sync_req_done(struct adb_request *req) |
417 | adb_probe_wakeup(struct adb_request *req) | ||
418 | { | 395 | { |
419 | complete(&adb_probe_task_comp); | 396 | struct completion *comp = req->arg; |
420 | } | ||
421 | 397 | ||
422 | /* Static request used during probe */ | 398 | complete(comp); |
423 | static struct adb_request adb_sreq; | 399 | } |
424 | static unsigned long adb_sreq_lock; // Use semaphore ! */ | ||
425 | 400 | ||
426 | int | 401 | int |
427 | adb_request(struct adb_request *req, void (*done)(struct adb_request *), | 402 | adb_request(struct adb_request *req, void (*done)(struct adb_request *), |
428 | int flags, int nbytes, ...) | 403 | int flags, int nbytes, ...) |
429 | { | 404 | { |
430 | va_list list; | 405 | va_list list; |
431 | int i, use_sreq; | 406 | int i; |
432 | int rc; | 407 | int rc; |
408 | struct completion comp; | ||
433 | 409 | ||
434 | if ((adb_controller == NULL) || (adb_controller->send_request == NULL)) | 410 | if ((adb_controller == NULL) || (adb_controller->send_request == NULL)) |
435 | return -ENXIO; | 411 | return -ENXIO; |
436 | if (nbytes < 1) | 412 | if (nbytes < 1) |
437 | return -EINVAL; | 413 | return -EINVAL; |
438 | if (req == NULL && (flags & ADBREQ_NOSEND)) | 414 | |
439 | return -EINVAL; | ||
440 | |||
441 | if (req == NULL) { | ||
442 | if (test_and_set_bit(0,&adb_sreq_lock)) { | ||
443 | printk("adb.c: Warning: contention on static request !\n"); | ||
444 | return -EPERM; | ||
445 | } | ||
446 | req = &adb_sreq; | ||
447 | flags |= ADBREQ_SYNC; | ||
448 | use_sreq = 1; | ||
449 | } else | ||
450 | use_sreq = 0; | ||
451 | req->nbytes = nbytes+1; | 415 | req->nbytes = nbytes+1; |
452 | req->done = done; | 416 | req->done = done; |
453 | req->reply_expected = flags & ADBREQ_REPLY; | 417 | req->reply_expected = flags & ADBREQ_REPLY; |
@@ -460,25 +424,18 @@ adb_request(struct adb_request *req, void (*done)(struct adb_request *), | |||
460 | if (flags & ADBREQ_NOSEND) | 424 | if (flags & ADBREQ_NOSEND) |
461 | return 0; | 425 | return 0; |
462 | 426 | ||
463 | /* Synchronous requests send from the probe thread cause it to | 427 | /* Synchronous requests block using an on-stack completion */ |
464 | * block. Beware that the "done" callback will be overriden ! | 428 | if (flags & ADBREQ_SYNC) { |
465 | */ | 429 | WARN_ON(done); |
466 | if ((flags & ADBREQ_SYNC) && | 430 | req->done = adb_sync_req_done; |
467 | (current->pid && adb_probe_task_pid && | 431 | req->arg = ∁ |
468 | adb_probe_task_pid == current->pid)) { | 432 | init_completion(&comp); |
469 | req->done = adb_probe_wakeup; | ||
470 | rc = adb_controller->send_request(req, 0); | ||
471 | if (rc || req->complete) | ||
472 | goto bail; | ||
473 | wait_for_completion(&adb_probe_task_comp); | ||
474 | rc = 0; | ||
475 | goto bail; | ||
476 | } | 433 | } |
477 | 434 | ||
478 | rc = adb_controller->send_request(req, flags & ADBREQ_SYNC); | 435 | rc = adb_controller->send_request(req, 0); |
479 | bail: | 436 | |
480 | if (use_sreq) | 437 | if ((flags & ADBREQ_SYNC) && !rc && !req->complete) |
481 | clear_bit(0, &adb_sreq_lock); | 438 | wait_for_completion(&comp); |
482 | 439 | ||
483 | return rc; | 440 | return rc; |
484 | } | 441 | } |
@@ -864,7 +821,29 @@ static const struct file_operations adb_fops = { | |||
864 | .release = adb_release, | 821 | .release = adb_release, |
865 | }; | 822 | }; |
866 | 823 | ||
867 | static void | 824 | static struct platform_driver adb_pfdrv = { |
825 | .driver = { | ||
826 | .name = "adb", | ||
827 | }, | ||
828 | #ifdef CONFIG_PM | ||
829 | .suspend = adb_suspend, | ||
830 | .resume = adb_resume, | ||
831 | #endif | ||
832 | }; | ||
833 | |||
834 | static struct platform_device adb_pfdev = { | ||
835 | .name = "adb", | ||
836 | }; | ||
837 | |||
838 | static int __init | ||
839 | adb_dummy_probe(struct platform_device *dev) | ||
840 | { | ||
841 | if (dev == &adb_pfdev) | ||
842 | return 0; | ||
843 | return -ENODEV; | ||
844 | } | ||
845 | |||
846 | static void __init | ||
868 | adbdev_init(void) | 847 | adbdev_init(void) |
869 | { | 848 | { |
870 | if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) { | 849 | if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) { |
@@ -876,4 +855,7 @@ adbdev_init(void) | |||
876 | if (IS_ERR(adb_dev_class)) | 855 | if (IS_ERR(adb_dev_class)) |
877 | return; | 856 | return; |
878 | device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), "adb"); | 857 | device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), "adb"); |
858 | |||
859 | platform_device_register(&adb_pfdev); | ||
860 | platform_driver_probe(&adb_pfdrv, adb_dummy_probe); | ||
879 | } | 861 | } |