diff options
author | Jack Steiner <steiner@sgi.com> | 2009-04-02 19:59:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:05:06 -0400 |
commit | bb04aa78ec1393295c30edad154e6f6e906955f3 (patch) | |
tree | b1708c39b7f649f6aac36b7f04ff69083190740a /drivers/misc | |
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>
Diffstat (limited to 'drivers/misc')
-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 61aa80a8411b..8ae426edc854 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/device.h> | 32 | #include <linux/device.h> |
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | #include <linux/security.h> | ||
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
36 | #include "gru.h" | 37 | #include "gru.h" |
37 | #include "grutables.h" | 38 | #include "grutables.h" |
@@ -575,6 +576,38 @@ int gru_get_exception_detail(unsigned long arg) | |||
575 | /* | 576 | /* |
576 | * User request to unload a context. Content is saved for possible reload. | 577 | * User request to unload a context. Content is saved for possible reload. |
577 | */ | 578 | */ |
579 | static int gru_unload_all_contexts(void) | ||
580 | { | ||
581 | struct gru_thread_state *gts; | ||
582 | struct gru_state *gru; | ||
583 | int maxgid, gid, ctxnum; | ||
584 | int nodesperblade; | ||
585 | |||
586 | if (!capable(CAP_SYS_ADMIN)) | ||
587 | return -EPERM; | ||
588 | if (num_online_nodes() > 1 && | ||
589 | (uv_node_to_blade_id(1) == uv_node_to_blade_id(0))) | ||
590 | nodesperblade = 2; | ||
591 | else | ||
592 | nodesperblade = 1; | ||
593 | maxgid = GRU_CHIPLETS_PER_BLADE * num_online_nodes() / nodesperblade; | ||
594 | for (gid = 0; gid < maxgid; gid++) { | ||
595 | gru = GID_TO_GRU(gid); | ||
596 | spin_lock(&gru->gs_lock); | ||
597 | for (ctxnum = 0; ctxnum < GRU_NUM_CCH; ctxnum++) { | ||
598 | gts = gru->gs_gts[ctxnum]; | ||
599 | if (gts && mutex_trylock(>s->ts_ctxlock)) { | ||
600 | spin_unlock(&gru->gs_lock); | ||
601 | gru_unload_context(gts, 1); | ||
602 | gru_unlock_gts(gts); | ||
603 | spin_lock(&gru->gs_lock); | ||
604 | } | ||
605 | } | ||
606 | spin_unlock(&gru->gs_lock); | ||
607 | } | ||
608 | return 0; | ||
609 | } | ||
610 | |||
578 | int gru_user_unload_context(unsigned long arg) | 611 | int gru_user_unload_context(unsigned long arg) |
579 | { | 612 | { |
580 | struct gru_thread_state *gts; | 613 | struct gru_thread_state *gts; |
@@ -586,6 +619,9 @@ int gru_user_unload_context(unsigned long arg) | |||
586 | 619 | ||
587 | gru_dbg(grudev, "gseg 0x%lx\n", req.gseg); | 620 | gru_dbg(grudev, "gseg 0x%lx\n", req.gseg); |
588 | 621 | ||
622 | if (!req.gseg) | ||
623 | return gru_unload_all_contexts(); | ||
624 | |||
589 | gts = gru_find_lock_gts(req.gseg); | 625 | gts = gru_find_lock_gts(req.gseg); |
590 | if (!gts) | 626 | if (!gts) |
591 | return -EINVAL; | 627 | return -EINVAL; |