diff options
author | Jack Steiner <steiner@sgi.com> | 2009-06-18 01:28:28 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-18 22:04:03 +0200 |
commit | d5826dd6002f23940458860701ce22fba9df2614 (patch) | |
tree | b0220c628cc2606b77fd39c38144c83396b83ca9 /drivers/misc/sgi-gru/grukservices.c | |
parent | gru: fix cache coherency issues with instruction retry (diff) | |
download | linux-d5826dd6002f23940458860701ce22fba9df2614.tar.xz linux-d5826dd6002f23940458860701ce22fba9df2614.zip |
gru: add user request to explicitly unload a gru context
Add user function to explicitly unload GRU kernel contexts from the GRU.
Only contexts that are not in-use will be unloaded.
This function is primarily for testing. It is not expected that this will
be used in normal production systems.
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/grukservices.c')
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index 7586b89fd0d3..5078f57da882 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c @@ -188,6 +188,34 @@ static void gru_load_kernel_context(struct gru_blade_state *bs, int blade_id) } /* + * Free all kernel contexts that are not currently in use. + * Returns 0 if all freed, else number of inuse context. + */ +static int gru_free_kernel_contexts(void) +{ + struct gru_blade_state *bs; + struct gru_thread_state *kgts; + int bid, ret = 0; + + for (bid = 0; bid < GRU_MAX_BLADES; bid++) { + bs = gru_base[bid]; + if (!bs) + continue; + if (down_write_trylock(&bs->bs_kgts_sema)) { + kgts = bs->bs_kgts; + if (kgts && kgts->ts_gru) + gru_unload_context(kgts, 0); + kfree(kgts); + bs->bs_kgts = NULL; + up_write(&bs->bs_kgts_sema); + } else { + ret++; + } + } + return ret; +} + +/* * Lock & load the kernel context for the specified blade. */ static struct gru_blade_state *gru_lock_kernel_context(int blade_id) @@ -1009,35 +1037,22 @@ int gru_ktest(unsigned long arg) case 2: ret = quicktest2(arg); break; + case 99: + ret = gru_free_kernel_contexts(); + break; } return ret; } -int gru_kservices_init(struct gru_state *gru) +int gru_kservices_init(void) { - struct gru_blade_state *bs; - - bs = gru->gs_blade; - if (gru != &bs->bs_grus[0]) - return 0; - - init_rwsem(&bs->bs_kgts_sema); return 0; } -void gru_kservices_exit(struct gru_state *gru) +void gru_kservices_exit(void) { - struct gru_blade_state *bs; - struct gru_thread_state *kgts; - - bs = gru->gs_blade; - if (gru != &bs->bs_grus[0]) - return; - - kgts = bs->bs_kgts; - if (kgts && kgts->ts_gru) - gru_unload_context(kgts, 0); - kfree(kgts); + if (gru_free_kernel_contexts()) + BUG(); } |