diff options
author | Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> | 2008-01-18 15:30:40 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-01-25 06:52:51 -0500 |
commit | b4cb2941f855993410ca456ef998888434e86098 (patch) | |
tree | 297e8856810ad6d647d15d3e0c6a81285d0e95d7 /arch | |
parent | e06bcf3cc3a6c45a16e9ffeb0401380aebfdea02 (diff) |
[POWERPC] PS3: Use the HVs storage device notification mechanism properly
The PS3 hypervisor has a storage device notification mechanism to wait
until a storage device is ready. Unfortunately the storage device
probing code used this mechanism in an incorrect way, needing a
polling loop and handling of devices that are not yet ready.
This change corrects this by:
- First waiting for the reception of an asynchronous notification
that a new storage device became ready,
- Then looking up the storage device in the device repository.
On shutdown, the storage probe thread is stopped and the storage
notification device is closed using a reboot notifier.
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/ps3/device-init.c | 426 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/platform.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/repository.c | 29 |
3 files changed, 223 insertions, 234 deletions
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c index 5642dc0d050e..5695e00219e4 100644 --- a/arch/powerpc/platforms/ps3/device-init.c +++ b/arch/powerpc/platforms/ps3/device-init.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/reboot.h> | ||
26 | 27 | ||
27 | #include <asm/firmware.h> | 28 | #include <asm/firmware.h> |
28 | #include <asm/lv1call.h> | 29 | #include <asm/lv1call.h> |
@@ -238,166 +239,6 @@ static int __init ps3_setup_vuart_device(enum ps3_match_id match_id, | |||
238 | return result; | 239 | return result; |
239 | } | 240 | } |
240 | 241 | ||
241 | static int ps3stor_wait_for_completion(u64 dev_id, u64 tag, | ||
242 | unsigned int timeout) | ||
243 | { | ||
244 | int result = -1; | ||
245 | unsigned int retries = 0; | ||
246 | u64 status; | ||
247 | |||
248 | for (retries = 0; retries < timeout; retries++) { | ||
249 | result = lv1_storage_check_async_status(dev_id, tag, &status); | ||
250 | if (!result) | ||
251 | break; | ||
252 | |||
253 | msleep(1); | ||
254 | } | ||
255 | |||
256 | if (result) | ||
257 | pr_debug("%s:%u: check_async_status: %s, status %lx\n", | ||
258 | __func__, __LINE__, ps3_result(result), status); | ||
259 | |||
260 | return result; | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * ps3_storage_wait_for_device - Wait for a storage device to become ready. | ||
265 | * @repo: The repository device to wait for. | ||
266 | * | ||
267 | * Uses the hypervisor's storage device notification mechanism to wait until | ||
268 | * a storage device is ready. The device notification mechanism uses a | ||
269 | * psuedo device (id = -1) to asynchronously notify the guest when storage | ||
270 | * devices become ready. The notification device has a block size of 512 | ||
271 | * bytes. | ||
272 | */ | ||
273 | |||
274 | static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) | ||
275 | { | ||
276 | int error = -ENODEV; | ||
277 | int result; | ||
278 | const u64 notification_dev_id = (u64)-1LL; | ||
279 | const unsigned int timeout = HZ; | ||
280 | u64 lpar; | ||
281 | u64 tag; | ||
282 | void *buf; | ||
283 | enum ps3_notify_type { | ||
284 | notify_device_ready = 0, | ||
285 | notify_region_probe = 1, | ||
286 | notify_region_update = 2, | ||
287 | }; | ||
288 | struct { | ||
289 | u64 operation_code; /* must be zero */ | ||
290 | u64 event_mask; /* OR of 1UL << enum ps3_notify_type */ | ||
291 | } *notify_cmd; | ||
292 | struct { | ||
293 | u64 event_type; /* enum ps3_notify_type */ | ||
294 | u64 bus_id; | ||
295 | u64 dev_id; | ||
296 | u64 dev_type; | ||
297 | u64 dev_port; | ||
298 | } *notify_event; | ||
299 | |||
300 | pr_debug(" -> %s:%u: (%lu:%lu:%u)\n", __func__, __LINE__, repo->bus_id, | ||
301 | repo->dev_id, repo->dev_type); | ||
302 | |||
303 | buf = kzalloc(512, GFP_KERNEL); | ||
304 | if (!buf) | ||
305 | return -ENOMEM; | ||
306 | |||
307 | lpar = ps3_mm_phys_to_lpar(__pa(buf)); | ||
308 | notify_cmd = buf; | ||
309 | notify_event = buf; | ||
310 | |||
311 | result = lv1_open_device(repo->bus_id, notification_dev_id, 0); | ||
312 | if (result) { | ||
313 | printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__, | ||
314 | __LINE__, ps3_result(result)); | ||
315 | goto fail_free; | ||
316 | } | ||
317 | |||
318 | /* Setup and write the request for device notification. */ | ||
319 | |||
320 | notify_cmd->operation_code = 0; /* must be zero */ | ||
321 | notify_cmd->event_mask = 1UL << notify_region_probe; | ||
322 | |||
323 | result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar, | ||
324 | &tag); | ||
325 | if (result) { | ||
326 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, | ||
327 | ps3_result(result)); | ||
328 | goto fail_close; | ||
329 | } | ||
330 | |||
331 | /* Wait for the write completion */ | ||
332 | |||
333 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
334 | timeout); | ||
335 | if (result) { | ||
336 | printk(KERN_ERR "%s:%u: write not completed %s\n", __func__, | ||
337 | __LINE__, ps3_result(result)); | ||
338 | goto fail_close; | ||
339 | } | ||
340 | |||
341 | /* Loop here processing the requested notification events. */ | ||
342 | |||
343 | while (1) { | ||
344 | memset(notify_event, 0, sizeof(*notify_event)); | ||
345 | |||
346 | result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0, | ||
347 | lpar, &tag); | ||
348 | if (result) { | ||
349 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, | ||
350 | __LINE__, ps3_result(result)); | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
355 | timeout); | ||
356 | if (result) { | ||
357 | printk(KERN_ERR "%s:%u: read not completed %s\n", | ||
358 | __func__, __LINE__, ps3_result(result)); | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | pr_debug("%s:%d: notify event (%u:%u:%u): event_type 0x%lx, " | ||
363 | "port %lu\n", __func__, __LINE__, repo->bus_index, | ||
364 | repo->dev_index, repo->dev_type, | ||
365 | notify_event->event_type, notify_event->dev_port); | ||
366 | |||
367 | if (notify_event->event_type != notify_region_probe || | ||
368 | notify_event->bus_id != repo->bus_id) { | ||
369 | pr_debug("%s:%u: bad notify_event: event %lu, " | ||
370 | "dev_id %lu, dev_type %lu\n", | ||
371 | __func__, __LINE__, notify_event->event_type, | ||
372 | notify_event->dev_id, notify_event->dev_type); | ||
373 | break; | ||
374 | } | ||
375 | |||
376 | if (notify_event->dev_id == repo->dev_id && | ||
377 | notify_event->dev_type == repo->dev_type) { | ||
378 | pr_debug("%s:%u: device ready (%u:%u:%u)\n", __func__, | ||
379 | __LINE__, repo->bus_index, repo->dev_index, | ||
380 | repo->dev_type); | ||
381 | error = 0; | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | if (notify_event->dev_id == repo->dev_id && | ||
386 | notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) { | ||
387 | pr_debug("%s:%u: no access: dev_id %lu\n", __func__, | ||
388 | __LINE__, repo->dev_id); | ||
389 | break; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | fail_close: | ||
394 | lv1_close_device(repo->bus_id, notification_dev_id); | ||
395 | fail_free: | ||
396 | kfree(buf); | ||
397 | pr_debug(" <- %s:%u\n", __func__, __LINE__); | ||
398 | return error; | ||
399 | } | ||
400 | |||
401 | static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | 242 | static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, |
402 | enum ps3_match_id match_id) | 243 | enum ps3_match_id match_id) |
403 | { | 244 | { |
@@ -449,16 +290,6 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | |||
449 | goto fail_find_interrupt; | 290 | goto fail_find_interrupt; |
450 | } | 291 | } |
451 | 292 | ||
452 | /* FIXME: Arrange to only do this on a 'cold' boot */ | ||
453 | |||
454 | result = ps3_storage_wait_for_device(repo); | ||
455 | if (result) { | ||
456 | printk(KERN_ERR "%s:%u: storage_notification failed %d\n", | ||
457 | __func__, __LINE__, result); | ||
458 | result = -ENODEV; | ||
459 | goto fail_probe_notification; | ||
460 | } | ||
461 | |||
462 | for (i = 0; i < num_regions; i++) { | 293 | for (i = 0; i < num_regions; i++) { |
463 | unsigned int id; | 294 | unsigned int id; |
464 | u64 start, size; | 295 | u64 start, size; |
@@ -494,7 +325,6 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | |||
494 | 325 | ||
495 | fail_device_register: | 326 | fail_device_register: |
496 | fail_read_region: | 327 | fail_read_region: |
497 | fail_probe_notification: | ||
498 | fail_find_interrupt: | 328 | fail_find_interrupt: |
499 | kfree(p); | 329 | kfree(p); |
500 | fail_malloc: | 330 | fail_malloc: |
@@ -659,62 +489,248 @@ static int ps3_register_repository_device( | |||
659 | return result; | 489 | return result; |
660 | } | 490 | } |
661 | 491 | ||
492 | |||
493 | #define PS3_NOTIFICATION_DEV_ID ULONG_MAX | ||
494 | #define PS3_NOTIFICATION_INTERRUPT_ID 0 | ||
495 | |||
496 | struct ps3_notification_device { | ||
497 | struct ps3_system_bus_device sbd; | ||
498 | spinlock_t lock; | ||
499 | u64 tag; | ||
500 | u64 lv1_status; | ||
501 | struct completion done; | ||
502 | }; | ||
503 | |||
504 | enum ps3_notify_type { | ||
505 | notify_device_ready = 0, | ||
506 | notify_region_probe = 1, | ||
507 | notify_region_update = 2, | ||
508 | }; | ||
509 | |||
510 | struct ps3_notify_cmd { | ||
511 | u64 operation_code; /* must be zero */ | ||
512 | u64 event_mask; /* OR of 1UL << enum ps3_notify_type */ | ||
513 | }; | ||
514 | |||
515 | struct ps3_notify_event { | ||
516 | u64 event_type; /* enum ps3_notify_type */ | ||
517 | u64 bus_id; | ||
518 | u64 dev_id; | ||
519 | u64 dev_type; | ||
520 | u64 dev_port; | ||
521 | }; | ||
522 | |||
523 | static irqreturn_t ps3_notification_interrupt(int irq, void *data) | ||
524 | { | ||
525 | struct ps3_notification_device *dev = data; | ||
526 | int res; | ||
527 | u64 tag, status; | ||
528 | |||
529 | spin_lock(&dev->lock); | ||
530 | res = lv1_storage_get_async_status(PS3_NOTIFICATION_DEV_ID, &tag, | ||
531 | &status); | ||
532 | if (tag != dev->tag) | ||
533 | pr_err("%s:%u: tag mismatch, got %lx, expected %lx\n", | ||
534 | __func__, __LINE__, tag, dev->tag); | ||
535 | |||
536 | if (res) { | ||
537 | pr_err("%s:%u: res %d status 0x%lx\n", __func__, __LINE__, res, | ||
538 | status); | ||
539 | } else { | ||
540 | pr_debug("%s:%u: completed, status 0x%lx\n", __func__, | ||
541 | __LINE__, status); | ||
542 | dev->lv1_status = status; | ||
543 | complete(&dev->done); | ||
544 | } | ||
545 | spin_unlock(&dev->lock); | ||
546 | return IRQ_HANDLED; | ||
547 | } | ||
548 | |||
549 | static int ps3_notification_read_write(struct ps3_notification_device *dev, | ||
550 | u64 lpar, int write) | ||
551 | { | ||
552 | const char *op = write ? "write" : "read"; | ||
553 | unsigned long flags; | ||
554 | int res; | ||
555 | |||
556 | init_completion(&dev->done); | ||
557 | spin_lock_irqsave(&dev->lock, flags); | ||
558 | res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar, | ||
559 | &dev->tag) | ||
560 | : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar, | ||
561 | &dev->tag); | ||
562 | spin_unlock_irqrestore(&dev->lock, flags); | ||
563 | if (res) { | ||
564 | pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res); | ||
565 | return -EPERM; | ||
566 | } | ||
567 | pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op); | ||
568 | |||
569 | res = wait_event_interruptible(dev->done.wait, | ||
570 | dev->done.done || kthread_should_stop()); | ||
571 | if (kthread_should_stop()) | ||
572 | res = -EINTR; | ||
573 | if (res) { | ||
574 | pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op); | ||
575 | return res; | ||
576 | } | ||
577 | |||
578 | if (dev->lv1_status) { | ||
579 | pr_err("%s:%u: %s not completed, status 0x%lx\n", __func__, | ||
580 | __LINE__, op, dev->lv1_status); | ||
581 | return -EIO; | ||
582 | } | ||
583 | pr_debug("%s:%u: notification %s completed\n", __func__, __LINE__, op); | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static struct task_struct *probe_task; | ||
589 | |||
662 | /** | 590 | /** |
663 | * ps3_probe_thread - Background repository probing at system startup. | 591 | * ps3_probe_thread - Background repository probing at system startup. |
664 | * | 592 | * |
665 | * This implementation only supports background probing on a single bus. | 593 | * This implementation only supports background probing on a single bus. |
594 | * It uses the hypervisor's storage device notification mechanism to wait until | ||
595 | * a storage device is ready. The device notification mechanism uses a | ||
596 | * pseudo device to asynchronously notify the guest when storage devices become | ||
597 | * ready. The notification device has a block size of 512 bytes. | ||
666 | */ | 598 | */ |
667 | 599 | ||
668 | static int ps3_probe_thread(void *data) | 600 | static int ps3_probe_thread(void *data) |
669 | { | 601 | { |
670 | struct ps3_repository_device *repo = data; | 602 | struct ps3_notification_device dev; |
671 | int result; | 603 | struct ps3_repository_device repo; |
672 | unsigned int ms = 250; | 604 | int res; |
605 | unsigned int irq; | ||
606 | u64 lpar; | ||
607 | void *buf; | ||
608 | struct ps3_notify_cmd *notify_cmd; | ||
609 | struct ps3_notify_event *notify_event; | ||
673 | 610 | ||
674 | pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); | 611 | pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); |
675 | 612 | ||
613 | buf = kzalloc(512, GFP_KERNEL); | ||
614 | if (!buf) | ||
615 | return -ENOMEM; | ||
616 | |||
617 | lpar = ps3_mm_phys_to_lpar(__pa(buf)); | ||
618 | notify_cmd = buf; | ||
619 | notify_event = buf; | ||
620 | |||
621 | /* dummy system bus device */ | ||
622 | dev.sbd.bus_id = (u64)data; | ||
623 | dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID; | ||
624 | dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID; | ||
625 | |||
626 | res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0); | ||
627 | if (res) { | ||
628 | pr_err("%s:%u: lv1_open_device failed %s\n", __func__, | ||
629 | __LINE__, ps3_result(res)); | ||
630 | goto fail_free; | ||
631 | } | ||
632 | |||
633 | res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY, | ||
634 | &irq); | ||
635 | if (res) { | ||
636 | pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n", | ||
637 | __func__, __LINE__, res); | ||
638 | goto fail_close_device; | ||
639 | } | ||
640 | |||
641 | spin_lock_init(&dev.lock); | ||
642 | |||
643 | res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED, | ||
644 | "ps3_notification", &dev); | ||
645 | if (res) { | ||
646 | pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__, | ||
647 | res); | ||
648 | goto fail_sb_event_receive_port_destroy; | ||
649 | } | ||
650 | |||
651 | /* Setup and write the request for device notification. */ | ||
652 | notify_cmd->operation_code = 0; /* must be zero */ | ||
653 | notify_cmd->event_mask = 1UL << notify_region_probe; | ||
654 | |||
655 | res = ps3_notification_read_write(&dev, lpar, 1); | ||
656 | if (res) | ||
657 | goto fail_free_irq; | ||
658 | |||
659 | /* Loop here processing the requested notification events. */ | ||
676 | do { | 660 | do { |
677 | try_to_freeze(); | 661 | try_to_freeze(); |
678 | 662 | ||
679 | pr_debug("%s:%u: probing...\n", __func__, __LINE__); | 663 | memset(notify_event, 0, sizeof(*notify_event)); |
680 | 664 | ||
681 | do { | 665 | res = ps3_notification_read_write(&dev, lpar, 0); |
682 | result = ps3_repository_find_device(repo); | 666 | if (res) |
683 | |||
684 | if (result == -ENODEV) | ||
685 | pr_debug("%s:%u: nothing new\n", __func__, | ||
686 | __LINE__); | ||
687 | else if (result) | ||
688 | pr_debug("%s:%u: find device error.\n", | ||
689 | __func__, __LINE__); | ||
690 | else { | ||
691 | pr_debug("%s:%u: found device (%u:%u:%u)\n", | ||
692 | __func__, __LINE__, repo->bus_index, | ||
693 | repo->dev_index, repo->dev_type); | ||
694 | ps3_register_repository_device(repo); | ||
695 | ps3_repository_bump_device(repo); | ||
696 | ms = 250; | ||
697 | } | ||
698 | } while (!result); | ||
699 | |||
700 | pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms); | ||
701 | |||
702 | if ( ms > 60000) | ||
703 | break; | 667 | break; |
704 | 668 | ||
705 | msleep_interruptible(ms); | 669 | pr_debug("%s:%u: notify event type 0x%lx bus id %lu dev id %lu" |
670 | " type %lu port %lu\n", __func__, __LINE__, | ||
671 | notify_event->event_type, notify_event->bus_id, | ||
672 | notify_event->dev_id, notify_event->dev_type, | ||
673 | notify_event->dev_port); | ||
674 | |||
675 | if (notify_event->event_type != notify_region_probe || | ||
676 | notify_event->bus_id != dev.sbd.bus_id) { | ||
677 | pr_warning("%s:%u: bad notify_event: event %lu, " | ||
678 | "dev_id %lu, dev_type %lu\n", | ||
679 | __func__, __LINE__, notify_event->event_type, | ||
680 | notify_event->dev_id, | ||
681 | notify_event->dev_type); | ||
682 | continue; | ||
683 | } | ||
706 | 684 | ||
707 | /* An exponential backoff. */ | 685 | res = ps3_repository_find_device_by_id(&repo, dev.sbd.bus_id, |
708 | ms <<= 1; | 686 | notify_event->dev_id); |
687 | if (res) { | ||
688 | pr_warning("%s:%u: device %lu:%lu not found\n", | ||
689 | __func__, __LINE__, dev.sbd.bus_id, | ||
690 | notify_event->dev_id); | ||
691 | continue; | ||
692 | } | ||
693 | |||
694 | pr_debug("%s:%u: device %lu:%lu found\n", __func__, __LINE__, | ||
695 | dev.sbd.bus_id, notify_event->dev_id); | ||
696 | ps3_register_repository_device(&repo); | ||
709 | 697 | ||
710 | } while (!kthread_should_stop()); | 698 | } while (!kthread_should_stop()); |
711 | 699 | ||
700 | fail_free_irq: | ||
701 | free_irq(irq, &dev); | ||
702 | fail_sb_event_receive_port_destroy: | ||
703 | ps3_sb_event_receive_port_destroy(&dev.sbd, irq); | ||
704 | fail_close_device: | ||
705 | lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id); | ||
706 | fail_free: | ||
707 | kfree(buf); | ||
708 | |||
709 | probe_task = NULL; | ||
710 | |||
712 | pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); | 711 | pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); |
713 | 712 | ||
714 | return 0; | 713 | return 0; |
715 | } | 714 | } |
716 | 715 | ||
717 | /** | 716 | /** |
717 | * ps3_stop_probe_thread - Stops the background probe thread. | ||
718 | * | ||
719 | */ | ||
720 | |||
721 | static int ps3_stop_probe_thread(struct notifier_block *nb, unsigned long code, | ||
722 | void *data) | ||
723 | { | ||
724 | if (probe_task) | ||
725 | kthread_stop(probe_task); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | static struct notifier_block nb = { | ||
730 | .notifier_call = ps3_stop_probe_thread | ||
731 | }; | ||
732 | |||
733 | /** | ||
718 | * ps3_start_probe_thread - Starts the background probe thread. | 734 | * ps3_start_probe_thread - Starts the background probe thread. |
719 | * | 735 | * |
720 | */ | 736 | */ |
@@ -723,7 +739,7 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | |||
723 | { | 739 | { |
724 | int result; | 740 | int result; |
725 | struct task_struct *task; | 741 | struct task_struct *task; |
726 | static struct ps3_repository_device repo; /* must be static */ | 742 | struct ps3_repository_device repo; |
727 | 743 | ||
728 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | 744 | pr_debug(" -> %s:%d\n", __func__, __LINE__); |
729 | 745 | ||
@@ -746,7 +762,8 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | |||
746 | return -ENODEV; | 762 | return -ENODEV; |
747 | } | 763 | } |
748 | 764 | ||
749 | task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type); | 765 | task = kthread_run(ps3_probe_thread, (void *)repo.bus_id, |
766 | "ps3-probe-%u", bus_type); | ||
750 | 767 | ||
751 | if (IS_ERR(task)) { | 768 | if (IS_ERR(task)) { |
752 | result = PTR_ERR(task); | 769 | result = PTR_ERR(task); |
@@ -755,6 +772,9 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | |||
755 | return result; | 772 | return result; |
756 | } | 773 | } |
757 | 774 | ||
775 | probe_task = task; | ||
776 | register_reboot_notifier(&nb); | ||
777 | |||
758 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 778 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
759 | return 0; | 779 | return 0; |
760 | } | 780 | } |
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index 5c6d1b1db3df..0fdb3221d2f0 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h | |||
@@ -89,8 +89,6 @@ enum ps3_dev_type { | |||
89 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ | 89 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ |
90 | PS3_DEV_TYPE_SB_GPIO = 6, | 90 | PS3_DEV_TYPE_SB_GPIO = 6, |
91 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ | 91 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ |
92 | PS3_DEV_TYPE_STOR_DUMMY = 32, | ||
93 | PS3_DEV_TYPE_NOACCESS = 255, | ||
94 | }; | 92 | }; |
95 | 93 | ||
96 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | 94 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, |
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index 79dfa19613dc..782dc895231f 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c | |||
@@ -344,35 +344,6 @@ int ps3_repository_find_device(struct ps3_repository_device *repo) | |||
344 | return result; | 344 | return result; |
345 | } | 345 | } |
346 | 346 | ||
347 | if (tmp.bus_type == PS3_BUS_TYPE_STORAGE) { | ||
348 | /* | ||
349 | * A storage device may show up in the repository before the | ||
350 | * hypervisor has finished probing its type and regions | ||
351 | */ | ||
352 | unsigned int num_regions; | ||
353 | |||
354 | if (tmp.dev_type == PS3_DEV_TYPE_STOR_DUMMY) { | ||
355 | pr_debug("%s:%u storage device not ready\n", __func__, | ||
356 | __LINE__); | ||
357 | return -ENODEV; | ||
358 | } | ||
359 | |||
360 | result = ps3_repository_read_stor_dev_num_regions(tmp.bus_index, | ||
361 | tmp.dev_index, | ||
362 | &num_regions); | ||
363 | if (result) { | ||
364 | pr_debug("%s:%d read_stor_dev_num_regions failed\n", | ||
365 | __func__, __LINE__); | ||
366 | return result; | ||
367 | } | ||
368 | |||
369 | if (!num_regions) { | ||
370 | pr_debug("%s:%u storage device has no regions yet\n", | ||
371 | __func__, __LINE__); | ||
372 | return -ENODEV; | ||
373 | } | ||
374 | } | ||
375 | |||
376 | result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, | 347 | result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, |
377 | &tmp.dev_id); | 348 | &tmp.dev_id); |
378 | 349 | ||