aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/grufault.c
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2009-04-02 19:59:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 22:05:06 -0400
commitbb04aa78ec1393295c30edad154e6f6e906955f3 (patch)
treeb1708c39b7f649f6aac36b7f04ff69083190740a /drivers/misc/sgi-gru/grufault.c
parente56484da3aa550dace96cbf1202446231471d7e1 (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/sgi-gru/grufault.c')
-rw-r--r--drivers/misc/sgi-gru/grufault.c36
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 */
579static 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(&gts->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
578int gru_user_unload_context(unsigned long arg) 611int 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;