diff options
Diffstat (limited to 'drivers/misc/sgi-gru/grumain.c')
-rw-r--r-- | drivers/misc/sgi-gru/grumain.c | 60 |
1 files changed, 31 insertions, 29 deletions
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c index 374af38862e6..14baabc79da4 100644 --- a/drivers/misc/sgi-gru/grumain.c +++ b/drivers/misc/sgi-gru/grumain.c | |||
@@ -299,15 +299,13 @@ static struct gru_thread_state *gru_find_current_gts_nolock(struct gru_vma_data | |||
299 | /* | 299 | /* |
300 | * Allocate a thread state structure. | 300 | * Allocate a thread state structure. |
301 | */ | 301 | */ |
302 | static struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, | 302 | struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, |
303 | struct gru_vma_data *vdata, | 303 | int cbr_au_count, int dsr_au_count, int options, int tsid) |
304 | int tsid) | ||
305 | { | 304 | { |
306 | struct gru_thread_state *gts; | 305 | struct gru_thread_state *gts; |
307 | int bytes; | 306 | int bytes; |
308 | 307 | ||
309 | bytes = DSR_BYTES(vdata->vd_dsr_au_count) + | 308 | bytes = DSR_BYTES(dsr_au_count) + CBR_BYTES(cbr_au_count); |
310 | CBR_BYTES(vdata->vd_cbr_au_count); | ||
311 | bytes += sizeof(struct gru_thread_state); | 309 | bytes += sizeof(struct gru_thread_state); |
312 | gts = kzalloc(bytes, GFP_KERNEL); | 310 | gts = kzalloc(bytes, GFP_KERNEL); |
313 | if (!gts) | 311 | if (!gts) |
@@ -316,21 +314,22 @@ static struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, | |||
316 | STAT(gts_alloc); | 314 | STAT(gts_alloc); |
317 | atomic_set(>s->ts_refcnt, 1); | 315 | atomic_set(>s->ts_refcnt, 1); |
318 | mutex_init(>s->ts_ctxlock); | 316 | mutex_init(>s->ts_ctxlock); |
319 | gts->ts_cbr_au_count = vdata->vd_cbr_au_count; | 317 | gts->ts_cbr_au_count = cbr_au_count; |
320 | gts->ts_dsr_au_count = vdata->vd_dsr_au_count; | 318 | gts->ts_dsr_au_count = dsr_au_count; |
321 | gts->ts_user_options = vdata->vd_user_options; | 319 | gts->ts_user_options = options; |
322 | gts->ts_tsid = tsid; | 320 | gts->ts_tsid = tsid; |
323 | gts->ts_user_options = vdata->vd_user_options; | ||
324 | gts->ts_ctxnum = NULLCTX; | 321 | gts->ts_ctxnum = NULLCTX; |
325 | gts->ts_mm = current->mm; | ||
326 | gts->ts_vma = vma; | ||
327 | gts->ts_tlb_int_select = -1; | 322 | gts->ts_tlb_int_select = -1; |
328 | gts->ts_gms = gru_register_mmu_notifier(); | ||
329 | gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT); | 323 | gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT); |
330 | if (!gts->ts_gms) | 324 | if (vma) { |
331 | goto err; | 325 | gts->ts_mm = current->mm; |
326 | gts->ts_vma = vma; | ||
327 | gts->ts_gms = gru_register_mmu_notifier(); | ||
328 | if (!gts->ts_gms) | ||
329 | goto err; | ||
330 | } | ||
332 | 331 | ||
333 | gru_dbg(grudev, "alloc vdata %p, new gts %p\n", vdata, gts); | 332 | gru_dbg(grudev, "alloc gts %p\n", gts); |
334 | return gts; | 333 | return gts; |
335 | 334 | ||
336 | err: | 335 | err: |
@@ -381,7 +380,8 @@ struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct *vma, | |||
381 | struct gru_vma_data *vdata = vma->vm_private_data; | 380 | struct gru_vma_data *vdata = vma->vm_private_data; |
382 | struct gru_thread_state *gts, *ngts; | 381 | struct gru_thread_state *gts, *ngts; |
383 | 382 | ||
384 | gts = gru_alloc_gts(vma, vdata, tsid); | 383 | gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count, vdata->vd_dsr_au_count, |
384 | vdata->vd_user_options, tsid); | ||
385 | if (!gts) | 385 | if (!gts) |
386 | return NULL; | 386 | return NULL; |
387 | 387 | ||
@@ -645,7 +645,7 @@ static int gru_retarget_intr(struct gru_thread_state *gts) | |||
645 | #define next_gru(b, g) (((g) < &(b)->bs_grus[GRU_CHIPLETS_PER_BLADE - 1]) ? \ | 645 | #define next_gru(b, g) (((g) < &(b)->bs_grus[GRU_CHIPLETS_PER_BLADE - 1]) ? \ |
646 | ((g)+1) : &(b)->bs_grus[0]) | 646 | ((g)+1) : &(b)->bs_grus[0]) |
647 | 647 | ||
648 | static void gru_steal_context(struct gru_thread_state *gts) | 648 | static void gru_steal_context(struct gru_thread_state *gts, int blade_id) |
649 | { | 649 | { |
650 | struct gru_blade_state *blade; | 650 | struct gru_blade_state *blade; |
651 | struct gru_state *gru, *gru0; | 651 | struct gru_state *gru, *gru0; |
@@ -655,8 +655,7 @@ static void gru_steal_context(struct gru_thread_state *gts) | |||
655 | cbr = gts->ts_cbr_au_count; | 655 | cbr = gts->ts_cbr_au_count; |
656 | dsr = gts->ts_dsr_au_count; | 656 | dsr = gts->ts_dsr_au_count; |
657 | 657 | ||
658 | preempt_disable(); | 658 | blade = gru_base[blade_id]; |
659 | blade = gru_base[uv_numa_blade_id()]; | ||
660 | spin_lock(&blade->bs_lock); | 659 | spin_lock(&blade->bs_lock); |
661 | 660 | ||
662 | ctxnum = next_ctxnum(blade->bs_lru_ctxnum); | 661 | ctxnum = next_ctxnum(blade->bs_lru_ctxnum); |
@@ -693,7 +692,6 @@ static void gru_steal_context(struct gru_thread_state *gts) | |||
693 | blade->bs_lru_gru = gru; | 692 | blade->bs_lru_gru = gru; |
694 | blade->bs_lru_ctxnum = ctxnum; | 693 | blade->bs_lru_ctxnum = ctxnum; |
695 | spin_unlock(&blade->bs_lock); | 694 | spin_unlock(&blade->bs_lock); |
696 | preempt_enable(); | ||
697 | 695 | ||
698 | if (ngts) { | 696 | if (ngts) { |
699 | STAT(steal_context); | 697 | STAT(steal_context); |
@@ -713,17 +711,17 @@ static void gru_steal_context(struct gru_thread_state *gts) | |||
713 | /* | 711 | /* |
714 | * Scan the GRUs on the local blade & assign a GRU context. | 712 | * Scan the GRUs on the local blade & assign a GRU context. |
715 | */ | 713 | */ |
716 | static struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts) | 714 | static struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts, |
715 | int blade) | ||
717 | { | 716 | { |
718 | struct gru_state *gru, *grux; | 717 | struct gru_state *gru, *grux; |
719 | int i, max_active_contexts; | 718 | int i, max_active_contexts; |
720 | 719 | ||
721 | preempt_disable(); | ||
722 | 720 | ||
723 | again: | 721 | again: |
724 | gru = NULL; | 722 | gru = NULL; |
725 | max_active_contexts = GRU_NUM_CCH; | 723 | max_active_contexts = GRU_NUM_CCH; |
726 | for_each_gru_on_blade(grux, uv_numa_blade_id(), i) { | 724 | for_each_gru_on_blade(grux, blade, i) { |
727 | if (check_gru_resources(grux, gts->ts_cbr_au_count, | 725 | if (check_gru_resources(grux, gts->ts_cbr_au_count, |
728 | gts->ts_dsr_au_count, | 726 | gts->ts_dsr_au_count, |
729 | max_active_contexts)) { | 727 | max_active_contexts)) { |
@@ -763,7 +761,6 @@ again: | |||
763 | STAT(assign_context_failed); | 761 | STAT(assign_context_failed); |
764 | } | 762 | } |
765 | 763 | ||
766 | preempt_enable(); | ||
767 | return gru; | 764 | return gru; |
768 | } | 765 | } |
769 | 766 | ||
@@ -778,6 +775,7 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
778 | { | 775 | { |
779 | struct gru_thread_state *gts; | 776 | struct gru_thread_state *gts; |
780 | unsigned long paddr, vaddr; | 777 | unsigned long paddr, vaddr; |
778 | int blade_id; | ||
781 | 779 | ||
782 | vaddr = (unsigned long)vmf->virtual_address; | 780 | vaddr = (unsigned long)vmf->virtual_address; |
783 | gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n", | 781 | gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n", |
@@ -792,8 +790,10 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
792 | again: | 790 | again: |
793 | mutex_lock(>s->ts_ctxlock); | 791 | mutex_lock(>s->ts_ctxlock); |
794 | preempt_disable(); | 792 | preempt_disable(); |
793 | blade_id = uv_numa_blade_id(); | ||
794 | |||
795 | if (gts->ts_gru) { | 795 | if (gts->ts_gru) { |
796 | if (gts->ts_gru->gs_blade_id != uv_numa_blade_id()) { | 796 | if (gts->ts_gru->gs_blade_id != blade_id) { |
797 | STAT(migrated_nopfn_unload); | 797 | STAT(migrated_nopfn_unload); |
798 | gru_unload_context(gts, 1); | 798 | gru_unload_context(gts, 1); |
799 | } else { | 799 | } else { |
@@ -803,12 +803,14 @@ again: | |||
803 | } | 803 | } |
804 | 804 | ||
805 | if (!gts->ts_gru) { | 805 | if (!gts->ts_gru) { |
806 | if (!gru_assign_gru_context(gts)) { | 806 | if (!gru_assign_gru_context(gts, blade_id)) { |
807 | mutex_unlock(>s->ts_ctxlock); | ||
808 | preempt_enable(); | 807 | preempt_enable(); |
808 | mutex_unlock(>s->ts_ctxlock); | ||
809 | set_current_state(TASK_INTERRUPTIBLE); | ||
809 | schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */ | 810 | schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */ |
811 | blade_id = uv_numa_blade_id(); | ||
810 | if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies) | 812 | if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies) |
811 | gru_steal_context(gts); | 813 | gru_steal_context(gts, blade_id); |
812 | goto again; | 814 | goto again; |
813 | } | 815 | } |
814 | gru_load_context(gts); | 816 | gru_load_context(gts); |
@@ -818,8 +820,8 @@ again: | |||
818 | vma->vm_page_prot); | 820 | vma->vm_page_prot); |
819 | } | 821 | } |
820 | 822 | ||
821 | mutex_unlock(>s->ts_ctxlock); | ||
822 | preempt_enable(); | 823 | preempt_enable(); |
824 | mutex_unlock(>s->ts_ctxlock); | ||
823 | 825 | ||
824 | return VM_FAULT_NOPAGE; | 826 | return VM_FAULT_NOPAGE; |
825 | } | 827 | } |