aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2009-06-17 19:28:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-18 16:03:59 -0400
commit364b76df80f62cee1b66e871df2f69db6e3d3d9e (patch)
tree7289e8489a7b4d5441a867be44ad152088517450 /drivers/misc
parent9cc9b056ea51608788609d7e26c7db55ef81bb2e (diff)
gru: dynamic allocation of kernel contexts
Change the interface to gru_alloc_gts() so that it can be used to allocate GRU contexts for kernel threads. Kernel threads do not have vdata structures for the GRU contexts. The GRU resource count are now passed explicitly instead of inside the vdata structure. Signed-off-by: Jack Steiner <steiner@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/sgi-gru/grumain.c60
-rw-r--r--drivers/misc/sgi-gru/grutables.h2
2 files changed, 33 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 */
302static struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, 302struct 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(&gts->ts_refcnt, 1); 315 atomic_set(&gts->ts_refcnt, 1);
318 mutex_init(&gts->ts_ctxlock); 316 mutex_init(&gts->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
336err: 335err:
@@ -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
648static void gru_steal_context(struct gru_thread_state *gts) 648static 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 */
716static struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts) 714static 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
723again: 721again:
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)
792again: 790again:
793 mutex_lock(&gts->ts_ctxlock); 791 mutex_lock(&gts->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(&gts->ts_ctxlock);
808 preempt_enable(); 807 preempt_enable();
808 mutex_unlock(&gts->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(&gts->ts_ctxlock);
822 preempt_enable(); 823 preempt_enable();
824 mutex_unlock(&gts->ts_ctxlock);
823 825
824 return VM_FAULT_NOPAGE; 826 return VM_FAULT_NOPAGE;
825} 827}
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index d768f54dc259..c69086c9b986 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -630,6 +630,8 @@ extern void gru_flush_all_tlb(struct gru_state *gru);
630extern int gru_proc_init(void); 630extern int gru_proc_init(void);
631extern void gru_proc_exit(void); 631extern void gru_proc_exit(void);
632 632
633extern struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
634 int cbr_au_count, int dsr_au_count, int options, int tsid);
633extern unsigned long gru_reserve_cb_resources(struct gru_state *gru, 635extern unsigned long gru_reserve_cb_resources(struct gru_state *gru,
634 int cbr_au_count, char *cbmap); 636 int cbr_au_count, char *cbmap);
635extern unsigned long gru_reserve_ds_resources(struct gru_state *gru, 637extern unsigned long gru_reserve_ds_resources(struct gru_state *gru,