aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/spu_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/cell/spu_base.c')
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c161
1 files changed, 17 insertions, 144 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index eba7a2641dce..8086eb1ed60d 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -36,6 +36,8 @@
36#include <asm/xmon.h> 36#include <asm/xmon.h>
37 37
38const struct spu_management_ops *spu_management_ops; 38const struct spu_management_ops *spu_management_ops;
39EXPORT_SYMBOL_GPL(spu_management_ops);
40
39const struct spu_priv1_ops *spu_priv1_ops; 41const struct spu_priv1_ops *spu_priv1_ops;
40 42
41static struct list_head spu_list[MAX_NUMNODES]; 43static struct list_head spu_list[MAX_NUMNODES];
@@ -290,7 +292,6 @@ spu_irq_class_1(int irq, void *data)
290 292
291 return stat ? IRQ_HANDLED : IRQ_NONE; 293 return stat ? IRQ_HANDLED : IRQ_NONE;
292} 294}
293EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom);
294 295
295static irqreturn_t 296static irqreturn_t
296spu_irq_class_2(int irq, void *data) 297spu_irq_class_2(int irq, void *data)
@@ -431,10 +432,11 @@ struct spu *spu_alloc_node(int node)
431 spu = list_entry(spu_list[node].next, struct spu, list); 432 spu = list_entry(spu_list[node].next, struct spu, list);
432 list_del_init(&spu->list); 433 list_del_init(&spu->list);
433 pr_debug("Got SPU %d %d\n", spu->number, spu->node); 434 pr_debug("Got SPU %d %d\n", spu->number, spu->node);
434 spu_init_channels(spu);
435 } 435 }
436 mutex_unlock(&spu_mutex); 436 mutex_unlock(&spu_mutex);
437 437
438 if (spu)
439 spu_init_channels(spu);
438 return spu; 440 return spu;
439} 441}
440EXPORT_SYMBOL_GPL(spu_alloc_node); 442EXPORT_SYMBOL_GPL(spu_alloc_node);
@@ -461,108 +463,6 @@ void spu_free(struct spu *spu)
461} 463}
462EXPORT_SYMBOL_GPL(spu_free); 464EXPORT_SYMBOL_GPL(spu_free);
463 465
464static int spu_handle_mm_fault(struct spu *spu)
465{
466 struct mm_struct *mm = spu->mm;
467 struct vm_area_struct *vma;
468 u64 ea, dsisr, is_write;
469 int ret;
470
471 ea = spu->dar;
472 dsisr = spu->dsisr;
473#if 0
474 if (!IS_VALID_EA(ea)) {
475 return -EFAULT;
476 }
477#endif /* XXX */
478 if (mm == NULL) {
479 return -EFAULT;
480 }
481 if (mm->pgd == NULL) {
482 return -EFAULT;
483 }
484
485 down_read(&mm->mmap_sem);
486 vma = find_vma(mm, ea);
487 if (!vma)
488 goto bad_area;
489 if (vma->vm_start <= ea)
490 goto good_area;
491 if (!(vma->vm_flags & VM_GROWSDOWN))
492 goto bad_area;
493#if 0
494 if (expand_stack(vma, ea))
495 goto bad_area;
496#endif /* XXX */
497good_area:
498 is_write = dsisr & MFC_DSISR_ACCESS_PUT;
499 if (is_write) {
500 if (!(vma->vm_flags & VM_WRITE))
501 goto bad_area;
502 } else {
503 if (dsisr & MFC_DSISR_ACCESS_DENIED)
504 goto bad_area;
505 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
506 goto bad_area;
507 }
508 ret = 0;
509 switch (handle_mm_fault(mm, vma, ea, is_write)) {
510 case VM_FAULT_MINOR:
511 current->min_flt++;
512 break;
513 case VM_FAULT_MAJOR:
514 current->maj_flt++;
515 break;
516 case VM_FAULT_SIGBUS:
517 ret = -EFAULT;
518 goto bad_area;
519 case VM_FAULT_OOM:
520 ret = -ENOMEM;
521 goto bad_area;
522 default:
523 BUG();
524 }
525 up_read(&mm->mmap_sem);
526 return ret;
527
528bad_area:
529 up_read(&mm->mmap_sem);
530 return -EFAULT;
531}
532
533int spu_irq_class_1_bottom(struct spu *spu)
534{
535 u64 ea, dsisr, access, error = 0UL;
536 int ret = 0;
537
538 ea = spu->dar;
539 dsisr = spu->dsisr;
540 if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
541 u64 flags;
542
543 access = (_PAGE_PRESENT | _PAGE_USER);
544 access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
545 local_irq_save(flags);
546 if (hash_page(ea, access, 0x300) != 0)
547 error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
548 local_irq_restore(flags);
549 }
550 if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
551 if ((ret = spu_handle_mm_fault(spu)) != 0)
552 error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
553 else
554 error &= ~CLASS1_ENABLE_STORAGE_FAULT_INTR;
555 }
556 spu->dar = 0UL;
557 spu->dsisr = 0UL;
558 if (!error) {
559 spu_restart_dma(spu);
560 } else {
561 spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE);
562 }
563 return ret;
564}
565
566struct sysdev_class spu_sysdev_class = { 466struct sysdev_class spu_sysdev_class = {
567 set_kset_name("spu") 467 set_kset_name("spu")
568}; 468};
@@ -636,12 +536,6 @@ static int spu_create_sysdev(struct spu *spu)
636 return 0; 536 return 0;
637} 537}
638 538
639static void spu_destroy_sysdev(struct spu *spu)
640{
641 sysfs_remove_device_from_node(&spu->sysdev, spu->node);
642 sysdev_unregister(&spu->sysdev);
643}
644
645static int __init create_spu(void *data) 539static int __init create_spu(void *data)
646{ 540{
647 struct spu *spu; 541 struct spu *spu;
@@ -693,58 +587,37 @@ out:
693 return ret; 587 return ret;
694} 588}
695 589
696static void destroy_spu(struct spu *spu)
697{
698 list_del_init(&spu->list);
699 list_del_init(&spu->full_list);
700
701 spu_destroy_sysdev(spu);
702 spu_free_irqs(spu);
703 spu_destroy_spu(spu);
704 kfree(spu);
705}
706
707static void cleanup_spu_base(void)
708{
709 struct spu *spu, *tmp;
710 int node;
711
712 mutex_lock(&spu_mutex);
713 for (node = 0; node < MAX_NUMNODES; node++) {
714 list_for_each_entry_safe(spu, tmp, &spu_list[node], list)
715 destroy_spu(spu);
716 }
717 mutex_unlock(&spu_mutex);
718 sysdev_class_unregister(&spu_sysdev_class);
719}
720module_exit(cleanup_spu_base);
721
722static int __init init_spu_base(void) 590static int __init init_spu_base(void)
723{ 591{
724 int i, ret; 592 int i, ret = 0;
593
594 for (i = 0; i < MAX_NUMNODES; i++)
595 INIT_LIST_HEAD(&spu_list[i]);
725 596
726 if (!spu_management_ops) 597 if (!spu_management_ops)
727 return 0; 598 goto out;
728 599
729 /* create sysdev class for spus */ 600 /* create sysdev class for spus */
730 ret = sysdev_class_register(&spu_sysdev_class); 601 ret = sysdev_class_register(&spu_sysdev_class);
731 if (ret) 602 if (ret)
732 return ret; 603 goto out;
733
734 for (i = 0; i < MAX_NUMNODES; i++)
735 INIT_LIST_HEAD(&spu_list[i]);
736 604
737 ret = spu_enumerate_spus(create_spu); 605 ret = spu_enumerate_spus(create_spu);
738 606
739 if (ret) { 607 if (ret) {
740 printk(KERN_WARNING "%s: Error initializing spus\n", 608 printk(KERN_WARNING "%s: Error initializing spus\n",
741 __FUNCTION__); 609 __FUNCTION__);
742 cleanup_spu_base(); 610 goto out_unregister_sysdev_class;
743 return ret;
744 } 611 }
745 612
746 xmon_register_spus(&spu_full_list); 613 xmon_register_spus(&spu_full_list);
747 614
615 return 0;
616
617 out_unregister_sysdev_class:
618 sysdev_class_unregister(&spu_sysdev_class);
619 out:
620
748 return ret; 621 return ret;
749} 622}
750module_init(init_spu_base); 623module_init(init_spu_base);