diff options
author | Jack Steiner <steiner@sgi.com> | 2009-04-02 16:59:07 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 19:05:06 -0700 |
commit | bb04aa78ec1393295c30edad154e6f6e906955f3 (patch) | |
tree | b1708c39b7f649f6aac36b7f04ff69083190740a | |
parent | e56484da3aa550dace96cbf1202446231471d7e1 (diff) |
sgi-gru: add support for a user to explicitly unload a GRU context
Add support for a user to explicitly unload a GRU context.
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>
-rw-r--r-- | drivers/misc/sgi-gru/grufault.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c index 61aa80a8411..8ae426edc85 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c @@ -32,6 +32,7 @@ #include <linux/device.h> #include <linux/io.h> #include <linux/uaccess.h> +#include <linux/security.h> #include <asm/pgtable.h> #include "gru.h" #include "grutables.h" @@ -575,6 +576,38 @@ int gru_get_exception_detail(unsigned long arg) /* * User request to unload a context. Content is saved for possible reload. */ +static int gru_unload_all_contexts(void) +{ + struct gru_thread_state *gts; + struct gru_state *gru; + int maxgid, gid, ctxnum; + int nodesperblade; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (num_online_nodes() > 1 && + (uv_node_to_blade_id(1) == uv_node_to_blade_id(0))) + nodesperblade = 2; + else + nodesperblade = 1; + maxgid = GRU_CHIPLETS_PER_BLADE * num_online_nodes() / nodesperblade; + for (gid = 0; gid < maxgid; gid++) { + gru = GID_TO_GRU(gid); + spin_lock(&gru->gs_lock); + for (ctxnum = 0; ctxnum < GRU_NUM_CCH; ctxnum++) { + gts = gru->gs_gts[ctxnum]; + if (gts && mutex_trylock(>s->ts_ctxlock)) { + spin_unlock(&gru->gs_lock); + gru_unload_context(gts, 1); + gru_unlock_gts(gts); + spin_lock(&gru->gs_lock); + } + } + spin_unlock(&gru->gs_lock); + } + return 0; +} + int gru_user_unload_context(unsigned long arg) { struct gru_thread_state *gts; @@ -586,6 +619,9 @@ int gru_user_unload_context(unsigned long arg) gru_dbg(grudev, "gseg 0x%lx\n", req.gseg); + if (!req.gseg) + return gru_unload_all_contexts(); + gts = gru_find_lock_gts(req.gseg); if (!gts) return -EINVAL; |