Commit 87419412 authored by Jack Steiner's avatar Jack Steiner Committed by Linus Torvalds

sgi-gru: aSID (context management) bug fixes

This patch fixes bugs related to ASID (context id) management in the GRU
driver.  These changes are all internal to the SGI GRU driver and have no
effect on the base kernel.
Signed-off-by: default avatarJack Steiner <steiner@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent bb04aa78
...@@ -274,6 +274,7 @@ static void gru_init_chiplet(struct gru_state *gru, unsigned long paddr, ...@@ -274,6 +274,7 @@ static void gru_init_chiplet(struct gru_state *gru, unsigned long paddr,
gru->gs_blade_id = bid; gru->gs_blade_id = bid;
gru->gs_cbr_map = (GRU_CBR_AU == 64) ? ~0 : (1UL << GRU_CBR_AU) - 1; gru->gs_cbr_map = (GRU_CBR_AU == 64) ? ~0 : (1UL << GRU_CBR_AU) - 1;
gru->gs_dsr_map = (1UL << GRU_DSR_AU) - 1; gru->gs_dsr_map = (1UL << GRU_DSR_AU) - 1;
gru->gs_asid_limit = MAX_ASID;
gru_tgh_flush_init(gru); gru_tgh_flush_init(gru);
gru_dbg(grudev, "bid %d, nid %d, gid %d, vaddr %p (0x%lx)\n", gru_dbg(grudev, "bid %d, nid %d, gid %d, vaddr %p (0x%lx)\n",
bid, nid, gru->gs_gid, gru->gs_gru_base_vaddr, bid, nid, gru->gs_gid, gru->gs_gru_base_vaddr,
......
...@@ -79,7 +79,6 @@ static int gru_wrap_asid(struct gru_state *gru) ...@@ -79,7 +79,6 @@ static int gru_wrap_asid(struct gru_state *gru)
gru_dbg(grudev, "gid %d\n", gru->gs_gid); gru_dbg(grudev, "gid %d\n", gru->gs_gid);
STAT(asid_wrap); STAT(asid_wrap);
gru->gs_asid_gen++; gru->gs_asid_gen++;
gru_flush_all_tlb(gru);
return MIN_ASID; return MIN_ASID;
} }
...@@ -93,6 +92,7 @@ static int gru_reset_asid_limit(struct gru_state *gru, int asid) ...@@ -93,6 +92,7 @@ static int gru_reset_asid_limit(struct gru_state *gru, int asid)
limit = MAX_ASID; limit = MAX_ASID;
if (asid >= limit) if (asid >= limit)
asid = gru_wrap_asid(gru); asid = gru_wrap_asid(gru);
gru_flush_all_tlb(gru);
gid = gru->gs_gid; gid = gru->gs_gid;
again: again:
for (i = 0; i < GRU_NUM_CCH; i++) { for (i = 0; i < GRU_NUM_CCH; i++) {
...@@ -131,12 +131,10 @@ static int gru_assign_asid(struct gru_state *gru) ...@@ -131,12 +131,10 @@ static int gru_assign_asid(struct gru_state *gru)
{ {
int asid; int asid;
spin_lock(&gru->gs_asid_lock);
gru->gs_asid += ASID_INC; gru->gs_asid += ASID_INC;
asid = gru->gs_asid; asid = gru->gs_asid;
if (asid >= gru->gs_asid_limit) if (asid >= gru->gs_asid_limit)
asid = gru_reset_asid_limit(gru, asid); asid = gru_reset_asid_limit(gru, asid);
spin_unlock(&gru->gs_asid_lock);
gru_dbg(grudev, "gid %d, asid 0x%x\n", gru->gs_gid, asid); gru_dbg(grudev, "gid %d, asid 0x%x\n", gru->gs_gid, asid);
return asid; return asid;
...@@ -227,7 +225,9 @@ static int gru_load_mm_tracker(struct gru_state *gru, ...@@ -227,7 +225,9 @@ static int gru_load_mm_tracker(struct gru_state *gru,
spin_lock(&gms->ms_asid_lock); spin_lock(&gms->ms_asid_lock);
asid = asids->mt_asid; asid = asids->mt_asid;
if (asid == 0 || asids->mt_asid_gen != gru->gs_asid_gen) { spin_lock(&gru->gs_asid_lock);
if (asid == 0 || (asids->mt_ctxbitmap == 0 && asids->mt_asid_gen !=
gru->gs_asid_gen)) {
asid = gru_assign_asid(gru); asid = gru_assign_asid(gru);
asids->mt_asid = asid; asids->mt_asid = asid;
asids->mt_asid_gen = gru->gs_asid_gen; asids->mt_asid_gen = gru->gs_asid_gen;
...@@ -235,6 +235,7 @@ static int gru_load_mm_tracker(struct gru_state *gru, ...@@ -235,6 +235,7 @@ static int gru_load_mm_tracker(struct gru_state *gru,
} else { } else {
STAT(asid_reuse); STAT(asid_reuse);
} }
spin_unlock(&gru->gs_asid_lock);
BUG_ON(asids->mt_ctxbitmap & ctxbitmap); BUG_ON(asids->mt_ctxbitmap & ctxbitmap);
asids->mt_ctxbitmap |= ctxbitmap; asids->mt_ctxbitmap |= ctxbitmap;
...@@ -259,10 +260,12 @@ static void gru_unload_mm_tracker(struct gru_state *gru, ...@@ -259,10 +260,12 @@ static void gru_unload_mm_tracker(struct gru_state *gru,
asids = &gms->ms_asids[gru->gs_gid]; asids = &gms->ms_asids[gru->gs_gid];
ctxbitmap = (1 << gts->ts_ctxnum); ctxbitmap = (1 << gts->ts_ctxnum);
spin_lock(&gms->ms_asid_lock); spin_lock(&gms->ms_asid_lock);
spin_lock(&gru->gs_asid_lock);
BUG_ON((asids->mt_ctxbitmap & ctxbitmap) != ctxbitmap); BUG_ON((asids->mt_ctxbitmap & ctxbitmap) != ctxbitmap);
asids->mt_ctxbitmap ^= ctxbitmap; asids->mt_ctxbitmap ^= ctxbitmap;
gru_dbg(grudev, "gid %d, gts %p, gms %p, ctxnum 0x%d, asidmap 0x%lx\n", gru_dbg(grudev, "gid %d, gts %p, gms %p, ctxnum 0x%d, asidmap 0x%lx\n",
gru->gs_gid, gts, gms, gts->ts_ctxnum, gms->ms_asidmap[0]); gru->gs_gid, gts, gms, gts->ts_ctxnum, gms->ms_asidmap[0]);
spin_unlock(&gru->gs_asid_lock);
spin_unlock(&gms->ms_asid_lock); spin_unlock(&gms->ms_asid_lock);
} }
...@@ -412,6 +415,7 @@ static void gru_free_gru_context(struct gru_thread_state *gts) ...@@ -412,6 +415,7 @@ static void gru_free_gru_context(struct gru_thread_state *gts)
__clear_bit(gts->ts_ctxnum, &gru->gs_context_map); __clear_bit(gts->ts_ctxnum, &gru->gs_context_map);
gts->ts_ctxnum = NULLCTX; gts->ts_ctxnum = NULLCTX;
gts->ts_gru = NULL; gts->ts_gru = NULL;
gts->ts_blade = -1;
spin_unlock(&gru->gs_lock); spin_unlock(&gru->gs_lock);
gts_drop(gts); gts_drop(gts);
...@@ -731,6 +735,7 @@ again: ...@@ -731,6 +735,7 @@ again:
} }
reserve_gru_resources(gru, gts); reserve_gru_resources(gru, gts);
gts->ts_gru = gru; gts->ts_gru = gru;
gts->ts_blade = gru->gs_blade_id;
gts->ts_ctxnum = gts->ts_ctxnum =
find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH); find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH);
BUG_ON(gts->ts_ctxnum == GRU_NUM_CCH); BUG_ON(gts->ts_ctxnum == GRU_NUM_CCH);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment