aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/gruhandles.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-gru/gruhandles.c')
-rw-r--r--drivers/misc/sgi-gru/gruhandles.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c
new file mode 100644
index 000000000000..5b82e7def16d
--- /dev/null
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -0,0 +1,197 @@
1/*
2 * GRU KERNEL MCS INSTRUCTIONS
3 *
4 * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include "gru.h"
23#include "grulib.h"
24#include "grutables.h"
25
26/* 10 sec */
27#ifdef CONFIG_IA64
28#include <asm/processor.h>
29#define GRU_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10)
30#else
31#include <asm/tsc.h>
32#define GRU_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
33#endif
34
35/* Extract the status field from a kernel handle */
36#define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3)
37
38static void start_instruction(void *h)
39{
40 unsigned long *w0 = h;
41
42 wmb(); /* setting CMD bit must be last */
43 *w0 = *w0 | 1;
44 gru_flush_cache(h);
45}
46
47static int wait_instruction_complete(void *h, enum mcs_op opc)
48{
49 int status;
50 cycles_t start_time = get_cycles();
51
52 while (1) {
53 cpu_relax();
54 status = GET_MSEG_HANDLE_STATUS(h);
55 if (status != CCHSTATUS_ACTIVE)
56 break;
57 if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time))
58 panic("GRU %p is malfunctioning\n", h);
59 }
60 return status;
61}
62
63#if defined CONFIG_IA64
64static void cch_allocate_set_asids(
65 struct gru_context_configuration_handle *cch, int asidval)
66{
67 int i;
68
69 for (i = 0; i < 8; i++) {
70 cch->asid[i] = (asidval++);
71#if 0
72 /* ZZZ hugepages not supported yet */
73 if (i == RGN_HPAGE)
74 cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift);
75 else
76#endif
77 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT);
78 }
79}
80#elif defined CONFIG_X86_64
81static void cch_allocate_set_asids(
82 struct gru_context_configuration_handle *cch, int asidval)
83{
84 int i;
85
86 for (i = 0; i < 8; i++) {
87 cch->asid[i] = asidval++;
88 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) |
89 GRU_SIZEAVAIL(21);
90 }
91}
92#endif
93
94int cch_allocate(struct gru_context_configuration_handle *cch,
95 int asidval, unsigned long cbrmap,
96 unsigned long dsrmap)
97{
98 cch_allocate_set_asids(cch, asidval);
99 cch->dsr_allocation_map = dsrmap;
100 cch->cbr_allocation_map = cbrmap;
101 cch->opc = CCHOP_ALLOCATE;
102 start_instruction(cch);
103 return wait_instruction_complete(cch, cchop_allocate);
104}
105
106int cch_start(struct gru_context_configuration_handle *cch)
107{
108 cch->opc = CCHOP_START;
109 start_instruction(cch);
110 return wait_instruction_complete(cch, cchop_start);
111}
112
113int cch_interrupt(struct gru_context_configuration_handle *cch)
114{
115 cch->opc = CCHOP_INTERRUPT;
116 start_instruction(cch);
117 return wait_instruction_complete(cch, cchop_interrupt);
118}
119
120int cch_deallocate(struct gru_context_configuration_handle *cch)
121{
122 cch->opc = CCHOP_DEALLOCATE;
123 start_instruction(cch);
124 return wait_instruction_complete(cch, cchop_deallocate);
125}
126
127int cch_interrupt_sync(struct gru_context_configuration_handle
128 *cch)
129{
130 cch->opc = CCHOP_INTERRUPT_SYNC;
131 start_instruction(cch);
132 return wait_instruction_complete(cch, cchop_interrupt_sync);
133}
134
135int tgh_invalidate(struct gru_tlb_global_handle *tgh,
136 unsigned long vaddr, unsigned long vaddrmask,
137 int asid, int pagesize, int global, int n,
138 unsigned short ctxbitmap)
139{
140 tgh->vaddr = vaddr;
141 tgh->asid = asid;
142 tgh->pagesize = pagesize;
143 tgh->n = n;
144 tgh->global = global;
145 tgh->vaddrmask = vaddrmask;
146 tgh->ctxbitmap = ctxbitmap;
147 tgh->opc = TGHOP_TLBINV;
148 start_instruction(tgh);
149 return wait_instruction_complete(tgh, tghop_invalidate);
150}
151
152void tfh_write_only(struct gru_tlb_fault_handle *tfh,
153 unsigned long pfn, unsigned long vaddr,
154 int asid, int dirty, int pagesize)
155{
156 tfh->fillasid = asid;
157 tfh->fillvaddr = vaddr;
158 tfh->pfn = pfn;
159 tfh->dirty = dirty;
160 tfh->pagesize = pagesize;
161 tfh->opc = TFHOP_WRITE_ONLY;
162 start_instruction(tfh);
163}
164
165void tfh_write_restart(struct gru_tlb_fault_handle *tfh,
166 unsigned long paddr, int gaa,
167 unsigned long vaddr, int asid, int dirty,
168 int pagesize)
169{
170 tfh->fillasid = asid;
171 tfh->fillvaddr = vaddr;
172 tfh->pfn = paddr >> GRU_PADDR_SHIFT;
173 tfh->gaa = gaa;
174 tfh->dirty = dirty;
175 tfh->pagesize = pagesize;
176 tfh->opc = TFHOP_WRITE_RESTART;
177 start_instruction(tfh);
178}
179
180void tfh_restart(struct gru_tlb_fault_handle *tfh)
181{
182 tfh->opc = TFHOP_RESTART;
183 start_instruction(tfh);
184}
185
186void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh)
187{
188 tfh->opc = TFHOP_USER_POLLING_MODE;
189 start_instruction(tfh);
190}
191
192void tfh_exception(struct gru_tlb_fault_handle *tfh)
193{
194 tfh->opc = TFHOP_EXCEPTION;
195 start_instruction(tfh);
196}
197