diff options
author | Jack Steiner <steiner@sgi.com> | 2009-12-15 19:48:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:15 -0500 |
commit | 55484c45dbeca2eec7642932ec3f60f8a2d4bdbf (patch) | |
tree | 4927e959a656def901bb105605df4ab6977ab2d1 /drivers/misc/sgi-gru/grumain.c | |
parent | 518e5cd4aae476042bdee511e0e00c8670c0df42 (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.c | 128 |
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 | */ | ||
693 | void 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 | ||
717 | void gru_steal_context(struct gru_thread_state *gts, int blade_id) | 751 | void 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 | */ | ||
825 | static 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 | */ |
783 | struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts, | 837 | struct 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(); | ||
790 | again: | 846 | again: |
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(>s->ts_refcnt); | 873 | atomic_inc(>s->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) | |||
859 | again: | 913 | again: |
860 | mutex_lock(>s->ts_ctxlock); | 914 | mutex_lock(>s->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(>s->ts_ctxlock); | 923 | mutex_unlock(>s->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); |