aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/grumain.c
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2009-12-15 19:48:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 10:20:15 -0500
commit55484c45dbeca2eec7642932ec3f60f8a2d4bdbf (patch)
tree4927e959a656def901bb105605df4ab6977ab2d1 /drivers/misc/sgi-gru/grumain.c
parent518e5cd4aae476042bdee511e0e00c8670c0df42 (diff)
gru: allow users to specify gru chiplet 2
Add support to the GRU driver to allow users to specify the blade & chiplet for allocation of GRU contexts. Add new statistics for context loading/unloading/retargeting. Also deleted a few GRU stats that were no longer being unused. 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/sgi-gru/grumain.c')
-rw-r--r--drivers/misc/sgi-gru/grumain.c128
1 files changed, 86 insertions, 42 deletions
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index f449c2dbc1e3..54ad7544a9a0 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -684,6 +684,40 @@ static int gru_retarget_intr(struct gru_thread_state *gts)
684 return gru_update_cch(gts, 0); 684 return gru_update_cch(gts, 0);
685} 685}
686 686
687/*
688 * Unload the gru context if it is not assigned to the correct blade or
689 * chiplet. Misassignment can occur if the process migrates to a different
690 * blade or if the user changes the selected blade/chiplet.
691 * Return 0 if context correct placed, otherwise 1
692 */
693void gru_check_context_placement(struct gru_thread_state *gts)
694{
695 struct gru_state *gru;
696 int blade_id, chiplet_id;
697
698 /*
699 * If the current task is the context owner, verify that the
700 * context is correctly placed. This test is skipped for non-owner
701 * references. Pthread apps use non-owner references to the CBRs.
702 */
703 gru = gts->ts_gru;
704 if (!gru || gts->ts_tgid_owner != current->tgid)
705 return;
706
707 blade_id = gts->ts_user_blade_id;
708 if (blade_id < 0)
709 blade_id = uv_numa_blade_id();
710
711 chiplet_id = gts->ts_user_chiplet_id;
712 if (gru->gs_blade_id != blade_id ||
713 (chiplet_id >= 0 && chiplet_id != gru->gs_chiplet_id)) {
714 STAT(check_context_unload);
715 gru_unload_context(gts, 1);
716 } else if (gru_retarget_intr(gts)) {
717 STAT(check_context_retarget_intr);
718 }
719}
720
687 721
688/* 722/*
689 * Insufficient GRU resources available on the local blade. Steal a context from 723 * Insufficient GRU resources available on the local blade. Steal a context from
@@ -714,13 +748,17 @@ static void gts_stolen(struct gru_thread_state *gts,
714 } 748 }
715} 749}
716 750
717void gru_steal_context(struct gru_thread_state *gts, int blade_id) 751void gru_steal_context(struct gru_thread_state *gts)
718{ 752{
719 struct gru_blade_state *blade; 753 struct gru_blade_state *blade;
720 struct gru_state *gru, *gru0; 754 struct gru_state *gru, *gru0;
721 struct gru_thread_state *ngts = NULL; 755 struct gru_thread_state *ngts = NULL;
722 int ctxnum, ctxnum0, flag = 0, cbr, dsr; 756 int ctxnum, ctxnum0, flag = 0, cbr, dsr;
757 int blade_id = gts->ts_user_blade_id;
758 int chiplet_id = gts->ts_user_chiplet_id;
723 759
760 if (blade_id < 0)
761 blade_id = uv_numa_blade_id();
724 cbr = gts->ts_cbr_au_count; 762 cbr = gts->ts_cbr_au_count;
725 dsr = gts->ts_dsr_au_count; 763 dsr = gts->ts_dsr_au_count;
726 764
@@ -731,35 +769,39 @@ void gru_steal_context(struct gru_thread_state *gts, int blade_id)
731 gru = blade->bs_lru_gru; 769 gru = blade->bs_lru_gru;
732 if (ctxnum == 0) 770 if (ctxnum == 0)
733 gru = next_gru(blade, gru); 771 gru = next_gru(blade, gru);
772 blade->bs_lru_gru = gru;
773 blade->bs_lru_ctxnum = ctxnum;
734 ctxnum0 = ctxnum; 774 ctxnum0 = ctxnum;
735 gru0 = gru; 775 gru0 = gru;
736 while (1) { 776 while (1) {
737 if (check_gru_resources(gru, cbr, dsr, GRU_NUM_CCH)) 777 if (chiplet_id < 0 || chiplet_id == gru->gs_chiplet_id) {
738 break; 778 if (check_gru_resources(gru, cbr, dsr, GRU_NUM_CCH))
739 spin_lock(&gru->gs_lock);
740 for (; ctxnum < GRU_NUM_CCH; ctxnum++) {
741 if (flag && gru == gru0 && ctxnum == ctxnum0)
742 break; 779 break;
743 ngts = gru->gs_gts[ctxnum]; 780 spin_lock(&gru->gs_lock);
744 /* 781 for (; ctxnum < GRU_NUM_CCH; ctxnum++) {
745 * We are grabbing locks out of order, so trylock is 782 if (flag && gru == gru0 && ctxnum == ctxnum0)
746 * needed. GTSs are usually not locked, so the odds of 783 break;
747 * success are high. If trylock fails, try to steal a 784 ngts = gru->gs_gts[ctxnum];
748 * different GSEG. 785 /*
749 */ 786 * We are grabbing locks out of order, so trylock is
750 if (ngts && is_gts_stealable(ngts, blade)) 787 * needed. GTSs are usually not locked, so the odds of
788 * success are high. If trylock fails, try to steal a
789 * different GSEG.
790 */
791 if (ngts && is_gts_stealable(ngts, blade))
792 break;
793 ngts = NULL;
794 }
795 spin_unlock(&gru->gs_lock);
796 if (ngts || (flag && gru == gru0 && ctxnum == ctxnum0))
751 break; 797 break;
752 ngts = NULL;
753 flag = 1;
754 } 798 }
755 spin_unlock(&gru->gs_lock); 799 if (flag && gru == gru0)
756 if (ngts || (flag && gru == gru0 && ctxnum == ctxnum0))
757 break; 800 break;
801 flag = 1;
758 ctxnum = 0; 802 ctxnum = 0;
759 gru = next_gru(blade, gru); 803 gru = next_gru(blade, gru);
760 } 804 }
761 blade->bs_lru_gru = gru;
762 blade->bs_lru_ctxnum = ctxnum;
763 spin_unlock(&blade->bs_lock); 805 spin_unlock(&blade->bs_lock);
764 806
765 if (ngts) { 807 if (ngts) {
@@ -778,19 +820,35 @@ void gru_steal_context(struct gru_thread_state *gts, int blade_id)
778} 820}
779 821
780/* 822/*
823 * Assign a gru context.
824 */
825static int gru_assign_context_number(struct gru_state *gru)
826{
827 int ctxnum;
828
829 ctxnum = find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH);
830 __set_bit(ctxnum, &gru->gs_context_map);
831 return ctxnum;
832}
833
834/*
781 * Scan the GRUs on the local blade & assign a GRU context. 835 * Scan the GRUs on the local blade & assign a GRU context.
782 */ 836 */
783struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts, 837struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts)
784 int blade)
785{ 838{
786 struct gru_state *gru, *grux; 839 struct gru_state *gru, *grux;
787 int i, max_active_contexts; 840 int i, max_active_contexts;
841 int blade_id = gts->ts_user_blade_id;
842 int chiplet_id = gts->ts_user_chiplet_id;
788 843
789 844 if (blade_id < 0)
845 blade_id = uv_numa_blade_id();
790again: 846again:
791 gru = NULL; 847 gru = NULL;
792 max_active_contexts = GRU_NUM_CCH; 848 max_active_contexts = GRU_NUM_CCH;
793 for_each_gru_on_blade(grux, blade, i) { 849 for_each_gru_on_blade(grux, blade_id, i) {
850 if (chiplet_id >= 0 && chiplet_id != grux->gs_chiplet_id)
851 continue;
794 if (check_gru_resources(grux, gts->ts_cbr_au_count, 852 if (check_gru_resources(grux, gts->ts_cbr_au_count,
795 gts->ts_dsr_au_count, 853 gts->ts_dsr_au_count,
796 max_active_contexts)) { 854 max_active_contexts)) {
@@ -811,12 +869,9 @@ again:
811 reserve_gru_resources(gru, gts); 869 reserve_gru_resources(gru, gts);
812 gts->ts_gru = gru; 870 gts->ts_gru = gru;
813 gts->ts_blade = gru->gs_blade_id; 871 gts->ts_blade = gru->gs_blade_id;
814 gts->ts_ctxnum = 872 gts->ts_ctxnum = gru_assign_context_number(gru);
815 find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH);
816 BUG_ON(gts->ts_ctxnum == GRU_NUM_CCH);
817 atomic_inc(&gts->ts_refcnt); 873 atomic_inc(&gts->ts_refcnt);
818 gru->gs_gts[gts->ts_ctxnum] = gts; 874 gru->gs_gts[gts->ts_ctxnum] = gts;
819 __set_bit(gts->ts_ctxnum, &gru->gs_context_map);
820 spin_unlock(&gru->gs_lock); 875 spin_unlock(&gru->gs_lock);
821 876
822 STAT(assign_context); 877 STAT(assign_context);
@@ -844,7 +899,6 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
844{ 899{
845 struct gru_thread_state *gts; 900 struct gru_thread_state *gts;
846 unsigned long paddr, vaddr; 901 unsigned long paddr, vaddr;
847 int blade_id;
848 902
849 vaddr = (unsigned long)vmf->virtual_address; 903 vaddr = (unsigned long)vmf->virtual_address;
850 gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n", 904 gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n",
@@ -859,28 +913,18 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
859again: 913again:
860 mutex_lock(&gts->ts_ctxlock); 914 mutex_lock(&gts->ts_ctxlock);
861 preempt_disable(); 915 preempt_disable();
862 blade_id = uv_numa_blade_id();
863 916
864 if (gts->ts_gru) { 917 gru_check_context_placement(gts);
865 if (gts->ts_gru->gs_blade_id != blade_id) {
866 STAT(migrated_nopfn_unload);
867 gru_unload_context(gts, 1);
868 } else {
869 if (gru_retarget_intr(gts))
870 STAT(migrated_nopfn_retarget);
871 }
872 }
873 918
874 if (!gts->ts_gru) { 919 if (!gts->ts_gru) {
875 STAT(load_user_context); 920 STAT(load_user_context);
876 if (!gru_assign_gru_context(gts, blade_id)) { 921 if (!gru_assign_gru_context(gts)) {
877 preempt_enable(); 922 preempt_enable();
878 mutex_unlock(&gts->ts_ctxlock); 923 mutex_unlock(&gts->ts_ctxlock);
879 set_current_state(TASK_INTERRUPTIBLE); 924 set_current_state(TASK_INTERRUPTIBLE);
880 schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */ 925 schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */
881 blade_id = uv_numa_blade_id();
882 if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies) 926 if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies)
883 gru_steal_context(gts, blade_id); 927 gru_steal_context(gts);
884 goto again; 928 goto again;
885 } 929 }
886 gru_load_context(gts); 930 gru_load_context(gts);