aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-09-14 00:16:56 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-09-14 00:16:56 -0400
commitfc8e1ead9314cf0e0f1922e661428b93d3a50d88 (patch)
treef3cb97c4769b74f6627a59769f1ed5c92a13c58a /drivers/misc
parent2bcaa6a4238094c5695d5b1943078388d82d3004 (diff)
parent9de48cc300fb10f7d9faa978670becf5e352462a (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/c2port/core.c2
-rw-r--r--drivers/misc/cb710/Kconfig25
-rw-r--r--drivers/misc/cb710/Makefile8
-rw-r--r--drivers/misc/cb710/core.c357
-rw-r--r--drivers/misc/cb710/debug.c119
-rw-r--r--drivers/misc/cb710/sgbuf2.c146
-rw-r--r--drivers/misc/eeprom/Kconfig14
-rw-r--r--drivers/misc/eeprom/Makefile1
-rw-r--r--drivers/misc/eeprom/at25.c4
-rw-r--r--drivers/misc/eeprom/max6875.c246
-rw-r--r--drivers/misc/sgi-gru/Makefile2
-rw-r--r--drivers/misc/sgi-gru/gru_instructions.h68
-rw-r--r--drivers/misc/sgi-gru/grufault.c118
-rw-r--r--drivers/misc/sgi-gru/grufile.c72
-rw-r--r--drivers/misc/sgi-gru/gruhandles.c17
-rw-r--r--drivers/misc/sgi-gru/gruhandles.h30
-rw-r--r--drivers/misc/sgi-gru/grukdump.c232
-rw-r--r--drivers/misc/sgi-gru/grukservices.c563
-rw-r--r--drivers/misc/sgi-gru/grukservices.h51
-rw-r--r--drivers/misc/sgi-gru/grulib.h69
-rw-r--r--drivers/misc/sgi-gru/grumain.c187
-rw-r--r--drivers/misc/sgi-gru/gruprocfs.c17
-rw-r--r--drivers/misc/sgi-gru/grutables.h60
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c2
-rw-r--r--drivers/misc/sgi-xp/xpnet.c7
27 files changed, 2094 insertions, 325 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6d1ac180f6ee..68ab39d7cb35 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -235,5 +235,6 @@ config ISL29003
235 235
236source "drivers/misc/c2port/Kconfig" 236source "drivers/misc/c2port/Kconfig"
237source "drivers/misc/eeprom/Kconfig" 237source "drivers/misc/eeprom/Kconfig"
238source "drivers/misc/cb710/Kconfig"
238 239
239endif # MISC_DEVICES 240endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 7871f05dcb9b..36f733cd60e6 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_HP_ILO) += hpilo.o
21obj-$(CONFIG_ISL29003) += isl29003.o 21obj-$(CONFIG_ISL29003) += isl29003.o
22obj-$(CONFIG_C2PORT) += c2port/ 22obj-$(CONFIG_C2PORT) += c2port/
23obj-y += eeprom/ 23obj-y += eeprom/
24obj-y += cb710/
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
index 0207dd59090d..b5346b4db91a 100644
--- a/drivers/misc/c2port/core.c
+++ b/drivers/misc/c2port/core.c
@@ -15,6 +15,7 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/kmemcheck.h>
18#include <linux/ctype.h> 19#include <linux/ctype.h>
19#include <linux/delay.h> 20#include <linux/delay.h>
20#include <linux/idr.h> 21#include <linux/idr.h>
@@ -891,6 +892,7 @@ struct c2port_device *c2port_device_register(char *name,
891 return ERR_PTR(-EINVAL); 892 return ERR_PTR(-EINVAL);
892 893
893 c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL); 894 c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL);
895 kmemcheck_annotate_bitfield(c2dev, flags);
894 if (unlikely(!c2dev)) 896 if (unlikely(!c2dev))
895 return ERR_PTR(-ENOMEM); 897 return ERR_PTR(-ENOMEM);
896 898
diff --git a/drivers/misc/cb710/Kconfig b/drivers/misc/cb710/Kconfig
new file mode 100644
index 000000000000..22429b8b1068
--- /dev/null
+++ b/drivers/misc/cb710/Kconfig
@@ -0,0 +1,25 @@
1config CB710_CORE
2 tristate "ENE CB710/720 Flash memory card reader support"
3 depends on PCI
4 help
5 This option enables support for PCI ENE CB710/720 Flash memory card
6 reader found in some laptops (ie. some versions of HP Compaq nx9500).
7
8 You will also have to select some flash card format drivers (MMC/SD,
9 MemoryStick).
10
11 This driver can also be built as a module. If so, the module
12 will be called cb710.
13
14config CB710_DEBUG
15 bool "Enable driver debugging"
16 depends on CB710_CORE != n
17 default n
18 help
19 This is an option for use by developers; most people should
20 say N here. This adds a lot of debugging output to dmesg.
21
22config CB710_DEBUG_ASSUMPTIONS
23 bool
24 depends on CB710_CORE != n
25 default y
diff --git a/drivers/misc/cb710/Makefile b/drivers/misc/cb710/Makefile
new file mode 100644
index 000000000000..7b80cbf1a609
--- /dev/null
+++ b/drivers/misc/cb710/Makefile
@@ -0,0 +1,8 @@
1ifeq ($(CONFIG_CB710_DEBUG),y)
2 EXTRA_CFLAGS += -DDEBUG
3endif
4
5obj-$(CONFIG_CB710_CORE) += cb710.o
6
7cb710-y := core.o sgbuf2.o
8cb710-$(CONFIG_CB710_DEBUG) += debug.o
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
new file mode 100644
index 000000000000..b14eab0f2ba5
--- /dev/null
+++ b/drivers/misc/cb710/core.c
@@ -0,0 +1,357 @@
1/*
2 * cb710/core.c
3 *
4 * Copyright by Michał Mirosław, 2008-2009
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 version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/slab.h>
13#include <linux/pci.h>
14#include <linux/spinlock.h>
15#include <linux/idr.h>
16#include <linux/cb710.h>
17
18static DEFINE_IDA(cb710_ida);
19static DEFINE_SPINLOCK(cb710_ida_lock);
20
21void cb710_pci_update_config_reg(struct pci_dev *pdev,
22 int reg, uint32_t mask, uint32_t xor)
23{
24 u32 rval;
25
26 pci_read_config_dword(pdev, reg, &rval);
27 rval = (rval & mask) ^ xor;
28 pci_write_config_dword(pdev, reg, rval);
29}
30EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg);
31
32/* Some magic writes based on Windows driver init code */
33static int __devinit cb710_pci_configure(struct pci_dev *pdev)
34{
35 unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
36 struct pci_dev *pdev0 = pci_get_slot(pdev->bus, devfn);
37 u32 val;
38
39 cb710_pci_update_config_reg(pdev, 0x48,
40 ~0x000000FF, 0x0000003F);
41
42 pci_read_config_dword(pdev, 0x48, &val);
43 if (val & 0x80000000)
44 return 0;
45
46 if (!pdev0)
47 return -ENODEV;
48
49 if (pdev0->vendor == PCI_VENDOR_ID_ENE
50 && pdev0->device == PCI_DEVICE_ID_ENE_720) {
51 cb710_pci_update_config_reg(pdev0, 0x8C,
52 ~0x00F00000, 0x00100000);
53 cb710_pci_update_config_reg(pdev0, 0xB0,
54 ~0x08000000, 0x08000000);
55 }
56
57 cb710_pci_update_config_reg(pdev0, 0x8C,
58 ~0x00000F00, 0x00000200);
59 cb710_pci_update_config_reg(pdev0, 0x90,
60 ~0x00060000, 0x00040000);
61
62 pci_dev_put(pdev0);
63
64 return 0;
65}
66
67static irqreturn_t cb710_irq_handler(int irq, void *data)
68{
69 struct cb710_chip *chip = data;
70 struct cb710_slot *slot = &chip->slot[0];
71 irqreturn_t handled = IRQ_NONE;
72 unsigned nr;
73
74 spin_lock(&chip->irq_lock); /* incl. smp_rmb() */
75
76 for (nr = chip->slots; nr; ++slot, --nr) {
77 cb710_irq_handler_t handler_func = slot->irq_handler;
78 if (handler_func && handler_func(slot))
79 handled = IRQ_HANDLED;
80 }
81
82 spin_unlock(&chip->irq_lock);
83
84 return handled;
85}
86
87static void cb710_release_slot(struct device *dev)
88{
89#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
90 struct cb710_slot *slot = cb710_pdev_to_slot(to_platform_device(dev));
91 struct cb710_chip *chip = cb710_slot_to_chip(slot);
92
93 /* slot struct can be freed now */
94 atomic_dec(&chip->slot_refs_count);
95#endif
96}
97
98static int __devinit cb710_register_slot(struct cb710_chip *chip,
99 unsigned slot_mask, unsigned io_offset, const char *name)
100{
101 int nr = chip->slots;
102 struct cb710_slot *slot = &chip->slot[nr];
103 int err;
104
105 dev_dbg(cb710_chip_dev(chip),
106 "register: %s.%d; slot %d; mask %d; IO offset: 0x%02X\n",
107 name, chip->platform_id, nr, slot_mask, io_offset);
108
109 /* slot->irq_handler == NULL here; this needs to be
110 * seen before platform_device_register() */
111 ++chip->slots;
112 smp_wmb();
113
114 slot->iobase = chip->iobase + io_offset;
115 slot->pdev.name = name;
116 slot->pdev.id = chip->platform_id;
117 slot->pdev.dev.parent = &chip->pdev->dev;
118 slot->pdev.dev.release = cb710_release_slot;
119
120 err = platform_device_register(&slot->pdev);
121
122#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
123 atomic_inc(&chip->slot_refs_count);
124#endif
125
126 if (err) {
127 /* device_initialize() called from platform_device_register()
128 * wants this on error path */
129 platform_device_put(&slot->pdev);
130
131 /* slot->irq_handler == NULL here anyway, so no lock needed */
132 --chip->slots;
133 return err;
134 }
135
136 chip->slot_mask |= slot_mask;
137
138 return 0;
139}
140
141static void cb710_unregister_slot(struct cb710_chip *chip,
142 unsigned slot_mask)
143{
144 int nr = chip->slots - 1;
145
146 if (!(chip->slot_mask & slot_mask))
147 return;
148
149 platform_device_unregister(&chip->slot[nr].pdev);
150
151 /* complementary to spin_unlock() in cb710_set_irq_handler() */
152 smp_rmb();
153 BUG_ON(chip->slot[nr].irq_handler != NULL);
154
155 /* slot->irq_handler == NULL here, so no lock needed */
156 --chip->slots;
157 chip->slot_mask &= ~slot_mask;
158}
159
160void cb710_set_irq_handler(struct cb710_slot *slot,
161 cb710_irq_handler_t handler)
162{
163 struct cb710_chip *chip = cb710_slot_to_chip(slot);
164 unsigned long flags;
165
166 spin_lock_irqsave(&chip->irq_lock, flags);
167 slot->irq_handler = handler;
168 spin_unlock_irqrestore(&chip->irq_lock, flags);
169}
170EXPORT_SYMBOL_GPL(cb710_set_irq_handler);
171
172#ifdef CONFIG_PM
173
174static int cb710_suspend(struct pci_dev *pdev, pm_message_t state)
175{
176 struct cb710_chip *chip = pci_get_drvdata(pdev);
177
178 free_irq(pdev->irq, chip);
179 pci_save_state(pdev);
180 pci_disable_device(pdev);
181 if (state.event & PM_EVENT_SLEEP)
182 pci_set_power_state(pdev, PCI_D3cold);
183 return 0;
184}
185
186static int cb710_resume(struct pci_dev *pdev)
187{
188 struct cb710_chip *chip = pci_get_drvdata(pdev);
189 int err;
190
191 pci_set_power_state(pdev, PCI_D0);
192 pci_restore_state(pdev);
193 err = pcim_enable_device(pdev);
194 if (err)
195 return err;
196
197 return devm_request_irq(&pdev->dev, pdev->irq,
198 cb710_irq_handler, IRQF_SHARED, KBUILD_MODNAME, chip);
199}
200
201#endif /* CONFIG_PM */
202
203static int __devinit cb710_probe(struct pci_dev *pdev,
204 const struct pci_device_id *ent)
205{
206 struct cb710_chip *chip;
207 unsigned long flags;
208 u32 val;
209 int err;
210 int n = 0;
211
212 err = cb710_pci_configure(pdev);
213 if (err)
214 return err;
215
216 /* this is actually magic... */
217 pci_read_config_dword(pdev, 0x48, &val);
218 if (!(val & 0x80000000)) {
219 pci_write_config_dword(pdev, 0x48, val|0x71000000);
220 pci_read_config_dword(pdev, 0x48, &val);
221 }
222
223 dev_dbg(&pdev->dev, "PCI config[0x48] = 0x%08X\n", val);
224 if (!(val & 0x70000000))
225 return -ENODEV;
226 val = (val >> 28) & 7;
227 if (val & CB710_SLOT_MMC)
228 ++n;
229 if (val & CB710_SLOT_MS)
230 ++n;
231 if (val & CB710_SLOT_SM)
232 ++n;
233
234 chip = devm_kzalloc(&pdev->dev,
235 sizeof(*chip) + n * sizeof(*chip->slot), GFP_KERNEL);
236 if (!chip)
237 return -ENOMEM;
238
239 err = pcim_enable_device(pdev);
240 if (err)
241 return err;
242
243 err = pcim_iomap_regions(pdev, 0x0001, KBUILD_MODNAME);
244 if (err)
245 return err;
246
247 chip->pdev = pdev;
248 chip->iobase = pcim_iomap_table(pdev)[0];
249
250 pci_set_drvdata(pdev, chip);
251
252 err = devm_request_irq(&pdev->dev, pdev->irq,
253 cb710_irq_handler, IRQF_SHARED, KBUILD_MODNAME, chip);
254 if (err)
255 return err;
256
257 do {
258 if (!ida_pre_get(&cb710_ida, GFP_KERNEL))
259 return -ENOMEM;
260
261 spin_lock_irqsave(&cb710_ida_lock, flags);
262 err = ida_get_new(&cb710_ida, &chip->platform_id);
263 spin_unlock_irqrestore(&cb710_ida_lock, flags);
264
265 if (err && err != -EAGAIN)
266 return err;
267 } while (err);
268
269
270 dev_info(&pdev->dev, "id %d, IO 0x%p, IRQ %d\n",
271 chip->platform_id, chip->iobase, pdev->irq);
272
273 if (val & CB710_SLOT_MMC) { /* MMC/SD slot */
274 err = cb710_register_slot(chip,
275 CB710_SLOT_MMC, 0x00, "cb710-mmc");
276 if (err)
277 return err;
278 }
279
280 if (val & CB710_SLOT_MS) { /* MemoryStick slot */
281 err = cb710_register_slot(chip,
282 CB710_SLOT_MS, 0x40, "cb710-ms");
283 if (err)
284 goto unreg_mmc;
285 }
286
287 if (val & CB710_SLOT_SM) { /* SmartMedia slot */
288 err = cb710_register_slot(chip,
289 CB710_SLOT_SM, 0x60, "cb710-sm");
290 if (err)
291 goto unreg_ms;
292 }
293
294 return 0;
295unreg_ms:
296 cb710_unregister_slot(chip, CB710_SLOT_MS);
297unreg_mmc:
298 cb710_unregister_slot(chip, CB710_SLOT_MMC);
299
300#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
301 BUG_ON(atomic_read(&chip->slot_refs_count) != 0);
302#endif
303 return err;
304}
305
306static void __devexit cb710_remove_one(struct pci_dev *pdev)
307{
308 struct cb710_chip *chip = pci_get_drvdata(pdev);
309 unsigned long flags;
310
311 cb710_unregister_slot(chip, CB710_SLOT_SM);
312 cb710_unregister_slot(chip, CB710_SLOT_MS);
313 cb710_unregister_slot(chip, CB710_SLOT_MMC);
314#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
315 BUG_ON(atomic_read(&chip->slot_refs_count) != 0);
316#endif
317
318 spin_lock_irqsave(&cb710_ida_lock, flags);
319 ida_remove(&cb710_ida, chip->platform_id);
320 spin_unlock_irqrestore(&cb710_ida_lock, flags);
321}
322
323static const struct pci_device_id cb710_pci_tbl[] = {
324 { PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_CB710_FLASH,
325 PCI_ANY_ID, PCI_ANY_ID, },
326 { 0, }
327};
328
329static struct pci_driver cb710_driver = {
330 .name = KBUILD_MODNAME,
331 .id_table = cb710_pci_tbl,
332 .probe = cb710_probe,
333 .remove = __devexit_p(cb710_remove_one),
334#ifdef CONFIG_PM
335 .suspend = cb710_suspend,
336 .resume = cb710_resume,
337#endif
338};
339
340static int __init cb710_init_module(void)
341{
342 return pci_register_driver(&cb710_driver);
343}
344
345static void __exit cb710_cleanup_module(void)
346{
347 pci_unregister_driver(&cb710_driver);
348 ida_destroy(&cb710_ida);
349}
350
351module_init(cb710_init_module);
352module_exit(cb710_cleanup_module);
353
354MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>");
355MODULE_DESCRIPTION("ENE CB710 memory card reader driver");
356MODULE_LICENSE("GPL");
357MODULE_DEVICE_TABLE(pci, cb710_pci_tbl);
diff --git a/drivers/misc/cb710/debug.c b/drivers/misc/cb710/debug.c
new file mode 100644
index 000000000000..02358d086e03
--- /dev/null
+++ b/drivers/misc/cb710/debug.c
@@ -0,0 +1,119 @@
1/*
2 * cb710/debug.c
3 *
4 * Copyright by Michał Mirosław, 2008-2009
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 version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/cb710.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/slab.h>
14
15#define CB710_REG_COUNT 0x80
16
17static const u16 allow[CB710_REG_COUNT/16] = {
18 0xFFF0, 0xFFFF, 0xFFFF, 0xFFFF,
19 0xFFF0, 0xFFFF, 0xFFFF, 0xFFFF,
20};
21static const char *const prefix[ARRAY_SIZE(allow)] = {
22 "MMC", "MMC", "MMC", "MMC",
23 "MS?", "MS?", "SM?", "SM?"
24};
25
26static inline int allow_reg_read(unsigned block, unsigned offset, unsigned bits)
27{
28 unsigned mask = (1 << bits/8) - 1;
29 offset *= bits/8;
30 return ((allow[block] >> offset) & mask) == mask;
31}
32
33#define CB710_READ_REGS_TEMPLATE(t) \
34static void cb710_read_regs_##t(void __iomem *iobase, \
35 u##t *reg, unsigned select) \
36{ \
37 unsigned i, j; \
38 \
39 for (i = 0; i < ARRAY_SIZE(allow); ++i, reg += 16/(t/8)) { \
40 if (!(select & (1 << i))) \
41 continue; \
42 \
43 for (j = 0; j < 0x10/(t/8); ++j) { \
44 if (!allow_reg_read(i, j, t)) \
45 continue; \
46 reg[j] = ioread##t(iobase \
47 + (i << 4) + (j * (t/8))); \
48 } \
49 } \
50}
51
52static const char cb710_regf_8[] = "%02X";
53static const char cb710_regf_16[] = "%04X";
54static const char cb710_regf_32[] = "%08X";
55static const char cb710_xes[] = "xxxxxxxx";
56
57#define CB710_DUMP_REGS_TEMPLATE(t) \
58static void cb710_dump_regs_##t(struct device *dev, \
59 const u##t *reg, unsigned select) \
60{ \
61 const char *const xp = &cb710_xes[8 - t/4]; \
62 const char *const format = cb710_regf_##t; \
63 \
64 char msg[100], *p; \
65 unsigned i, j; \
66 \
67 for (i = 0; i < ARRAY_SIZE(allow); ++i, reg += 16/(t/8)) { \
68 if (!(select & (1 << i))) \
69 continue; \
70 p = msg; \
71 for (j = 0; j < 0x10/(t/8); ++j) { \
72 *p++ = ' '; \
73 if (j == 8/(t/8)) \
74 *p++ = ' '; \
75 if (allow_reg_read(i, j, t)) \
76 p += sprintf(p, format, reg[j]); \
77 else \
78 p += sprintf(p, "%s", xp); \
79 } \
80 dev_dbg(dev, "%s 0x%02X %s\n", prefix[i], i << 4, msg); \
81 } \
82}
83
84#define CB710_READ_AND_DUMP_REGS_TEMPLATE(t) \
85static void cb710_read_and_dump_regs_##t(struct cb710_chip *chip, \
86 unsigned select) \
87{ \
88 u##t regs[CB710_REG_COUNT/sizeof(u##t)]; \
89 \
90 memset(&regs, 0, sizeof(regs)); \
91 cb710_read_regs_##t(chip->iobase, regs, select); \
92 cb710_dump_regs_##t(cb710_chip_dev(chip), regs, select); \
93}
94
95#define CB710_REG_ACCESS_TEMPLATES(t) \
96 CB710_READ_REGS_TEMPLATE(t) \
97 CB710_DUMP_REGS_TEMPLATE(t) \
98 CB710_READ_AND_DUMP_REGS_TEMPLATE(t)
99
100CB710_REG_ACCESS_TEMPLATES(8)
101CB710_REG_ACCESS_TEMPLATES(16)
102CB710_REG_ACCESS_TEMPLATES(32)
103
104void cb710_dump_regs(struct cb710_chip *chip, unsigned select)
105{
106 if (!(select & CB710_DUMP_REGS_MASK))
107 select = CB710_DUMP_REGS_ALL;
108 if (!(select & CB710_DUMP_ACCESS_MASK))
109 select |= CB710_DUMP_ACCESS_8;
110
111 if (select & CB710_DUMP_ACCESS_32)
112 cb710_read_and_dump_regs_32(chip, select);
113 if (select & CB710_DUMP_ACCESS_16)
114 cb710_read_and_dump_regs_16(chip, select);
115 if (select & CB710_DUMP_ACCESS_8)
116 cb710_read_and_dump_regs_8(chip, select);
117}
118EXPORT_SYMBOL_GPL(cb710_dump_regs);
119
diff --git a/drivers/misc/cb710/sgbuf2.c b/drivers/misc/cb710/sgbuf2.c
new file mode 100644
index 000000000000..d019746551f3
--- /dev/null
+++ b/drivers/misc/cb710/sgbuf2.c
@@ -0,0 +1,146 @@
1/*
2 * cb710/sgbuf2.c
3 *
4 * Copyright by Michał Mirosław, 2008-2009
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 version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/cb710.h>
13
14static bool sg_dwiter_next(struct sg_mapping_iter *miter)
15{
16 if (sg_miter_next(miter)) {
17 miter->consumed = 0;
18 return true;
19 } else
20 return false;
21}
22
23static bool sg_dwiter_is_at_end(struct sg_mapping_iter *miter)
24{
25 return miter->length == miter->consumed && !sg_dwiter_next(miter);
26}
27
28static uint32_t sg_dwiter_read_buffer(struct sg_mapping_iter *miter)
29{
30 size_t len, left = 4;
31 uint32_t data;
32 void *addr = &data;
33
34 do {
35 len = min(miter->length - miter->consumed, left);
36 memcpy(addr, miter->addr + miter->consumed, len);
37 miter->consumed += len;
38 left -= len;
39 if (!left)
40 return data;
41 addr += len;
42 } while (sg_dwiter_next(miter));
43
44 memset(addr, 0, left);
45 return data;
46}
47
48static inline bool needs_unaligned_copy(const void *ptr)
49{
50#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
51 return false;
52#else
53 return ((ptr - NULL) & 3) != 0;
54#endif
55}
56
57static bool sg_dwiter_get_next_block(struct sg_mapping_iter *miter, uint32_t **ptr)
58{
59 size_t len;
60
61 if (sg_dwiter_is_at_end(miter))
62 return true;
63
64 len = miter->length - miter->consumed;
65
66 if (likely(len >= 4 && !needs_unaligned_copy(
67 miter->addr + miter->consumed))) {
68 *ptr = miter->addr + miter->consumed;
69 miter->consumed += 4;
70 return true;
71 }
72
73 return false;
74}
75
76/**
77 * cb710_sg_dwiter_read_next_block() - get next 32-bit word from sg buffer
78 * @miter: sg mapping iterator used for reading
79 *
80 * Description:
81 * Returns 32-bit word starting at byte pointed to by @miter@
82 * handling any alignment issues. Bytes past the buffer's end
83 * are not accessed (read) but are returned as zeroes. @miter@
84 * is advanced by 4 bytes or to the end of buffer whichever is
85 * closer.
86 *
87 * Context:
88 * Same requirements as in sg_miter_next().
89 *
90 * Returns:
91 * 32-bit word just read.
92 */
93uint32_t cb710_sg_dwiter_read_next_block(struct sg_mapping_iter *miter)
94{
95 uint32_t *ptr = NULL;
96
97 if (likely(sg_dwiter_get_next_block(miter, &ptr)))
98 return ptr ? *ptr : 0;
99
100 return sg_dwiter_read_buffer(miter);
101}
102EXPORT_SYMBOL_GPL(cb710_sg_dwiter_read_next_block);
103
104static void sg_dwiter_write_slow(struct sg_mapping_iter *miter, uint32_t data)
105{
106 size_t len, left = 4;
107 void *addr = &data;
108
109 do {
110 len = min(miter->length - miter->consumed, left);
111 memcpy(miter->addr, addr, len);
112 miter->consumed += len;
113 left -= len;
114 if (!left)
115 return;
116 addr += len;
117 } while (sg_dwiter_next(miter));
118}
119
120/**
121 * cb710_sg_dwiter_write_next_block() - write next 32-bit word to sg buffer
122 * @miter: sg mapping iterator used for writing
123 *
124 * Description:
125 * Writes 32-bit word starting at byte pointed to by @miter@
126 * handling any alignment issues. Bytes which would be written
127 * past the buffer's end are silently discarded. @miter@ is
128 * advanced by 4 bytes or to the end of buffer whichever is closer.
129 *
130 * Context:
131 * Same requirements as in sg_miter_next().
132 */
133void cb710_sg_dwiter_write_next_block(struct sg_mapping_iter *miter, uint32_t data)
134{
135 uint32_t *ptr = NULL;
136
137 if (likely(sg_dwiter_get_next_block(miter, &ptr))) {
138 if (ptr)
139 *ptr = data;
140 else
141 return;
142 } else
143 sg_dwiter_write_slow(miter, data);
144}
145EXPORT_SYMBOL_GPL(cb710_sg_dwiter_write_next_block);
146
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 89fec052f3b4..9118613af321 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -48,6 +48,20 @@ config EEPROM_LEGACY
48 This driver can also be built as a module. If so, the module 48 This driver can also be built as a module. If so, the module
49 will be called eeprom. 49 will be called eeprom.
50 50
51config EEPROM_MAX6875
52 tristate "Maxim MAX6874/5 power supply supervisor"
53 depends on I2C && EXPERIMENTAL
54 help
55 If you say yes here you get read-only support for the user EEPROM of
56 the Maxim MAX6874/5 EEPROM-programmable, quad power-supply
57 sequencer/supervisor.
58
59 All other features of this chip should be accessed via i2c-dev.
60
61 This driver can also be built as a module. If so, the module
62 will be called max6875.
63
64
51config EEPROM_93CX6 65config EEPROM_93CX6
52 tristate "EEPROM 93CX6 support" 66 tristate "EEPROM 93CX6 support"
53 help 67 help
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 539dd8f88128..df3d68ffa9d1 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -1,4 +1,5 @@
1obj-$(CONFIG_EEPROM_AT24) += at24.o 1obj-$(CONFIG_EEPROM_AT24) += at24.o
2obj-$(CONFIG_EEPROM_AT25) += at25.o 2obj-$(CONFIG_EEPROM_AT25) += at25.o
3obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o 3obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
4obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
4obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o 5obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index b34cb5f79eea..2e535a0ccd5e 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -173,6 +173,7 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
173 unsigned segment; 173 unsigned segment;
174 unsigned offset = (unsigned) off; 174 unsigned offset = (unsigned) off;
175 u8 *cp = bounce + 1; 175 u8 *cp = bounce + 1;
176 int sr;
176 177
177 *cp = AT25_WREN; 178 *cp = AT25_WREN;
178 status = spi_write(at25->spi, cp, 1); 179 status = spi_write(at25->spi, cp, 1);
@@ -214,7 +215,6 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
214 timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT); 215 timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);
215 retries = 0; 216 retries = 0;
216 do { 217 do {
217 int sr;
218 218
219 sr = spi_w8r8(at25->spi, AT25_RDSR); 219 sr = spi_w8r8(at25->spi, AT25_RDSR);
220 if (sr < 0 || (sr & AT25_SR_nRDY)) { 220 if (sr < 0 || (sr & AT25_SR_nRDY)) {
@@ -228,7 +228,7 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
228 break; 228 break;
229 } while (retries++ < 3 || time_before_eq(jiffies, timeout)); 229 } while (retries++ < 3 || time_before_eq(jiffies, timeout));
230 230
231 if (time_after(jiffies, timeout)) { 231 if ((sr < 0) || (sr & AT25_SR_nRDY)) {
232 dev_err(&at25->spi->dev, 232 dev_err(&at25->spi->dev,
233 "write %d bytes offset %d, " 233 "write %d bytes offset %d, "
234 "timeout after %u msecs\n", 234 "timeout after %u msecs\n",
diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c
new file mode 100644
index 000000000000..3c0c58eed347
--- /dev/null
+++ b/drivers/misc/eeprom/max6875.c
@@ -0,0 +1,246 @@
1/*
2 max6875.c - driver for MAX6874/MAX6875
3
4 Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
5
6 Based on eeprom.c
7
8 The MAX6875 has a bank of registers and two banks of EEPROM.
9 Address ranges are defined as follows:
10 * 0x0000 - 0x0046 = configuration registers
11 * 0x8000 - 0x8046 = configuration EEPROM
12 * 0x8100 - 0x82FF = user EEPROM
13
14 This driver makes the user EEPROM available for read.
15
16 The registers & config EEPROM should be accessed via i2c-dev.
17
18 The MAX6875 ignores the lowest address bit, so each chip responds to
19 two addresses - 0x50/0x51 and 0x52/0x53.
20
21 Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
22 address, so this driver is destructive if loaded for the wrong EEPROM chip.
23
24 This program is free software; you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation; version 2 of the License.
27*/
28
29#include <linux/kernel.h>
30#include <linux/init.h>
31#include <linux/module.h>
32#include <linux/slab.h>
33#include <linux/i2c.h>
34#include <linux/mutex.h>
35
36/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
37static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
38
39/* Insmod parameters */
40I2C_CLIENT_INSMOD_1(max6875);
41
42/* The MAX6875 can only read/write 16 bytes at a time */
43#define SLICE_SIZE 16
44#define SLICE_BITS 4
45
46/* USER EEPROM is at addresses 0x8100 - 0x82FF */
47#define USER_EEPROM_BASE 0x8100
48#define USER_EEPROM_SIZE 0x0200
49#define USER_EEPROM_SLICES 32
50
51/* MAX6875 commands */
52#define MAX6875_CMD_BLK_READ 0x84
53
54/* Each client has this additional data */
55struct max6875_data {
56 struct i2c_client *fake_client;
57 struct mutex update_lock;
58
59 u32 valid;
60 u8 data[USER_EEPROM_SIZE];
61 unsigned long last_updated[USER_EEPROM_SLICES];
62};
63
64static void max6875_update_slice(struct i2c_client *client, int slice)
65{
66 struct max6875_data *data = i2c_get_clientdata(client);
67 int i, j, addr;
68 u8 *buf;
69
70 if (slice >= USER_EEPROM_SLICES)
71 return;
72
73 mutex_lock(&data->update_lock);
74
75 buf = &data->data[slice << SLICE_BITS];
76
77 if (!(data->valid & (1 << slice)) ||
78 time_after(jiffies, data->last_updated[slice])) {
79
80 dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
81
82 data->valid &= ~(1 << slice);
83
84 addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
85
86 /* select the eeprom address */
87 if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
88 dev_err(&client->dev, "address set failed\n");
89 goto exit_up;
90 }
91
92 if (i2c_check_functionality(client->adapter,
93 I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
94 if (i2c_smbus_read_i2c_block_data(client,
95 MAX6875_CMD_BLK_READ,
96 SLICE_SIZE,
97 buf) != SLICE_SIZE) {
98 goto exit_up;
99 }
100 } else {
101 for (i = 0; i < SLICE_SIZE; i++) {
102 j = i2c_smbus_read_byte(client);
103 if (j < 0) {
104 goto exit_up;
105 }
106 buf[i] = j;
107 }
108 }
109 data->last_updated[slice] = jiffies;
110 data->valid |= (1 << slice);
111 }
112exit_up:
113 mutex_unlock(&data->update_lock);
114}
115
116static ssize_t max6875_read(struct kobject *kobj,
117 struct bin_attribute *bin_attr,
118 char *buf, loff_t off, size_t count)
119{
120 struct i2c_client *client = kobj_to_i2c_client(kobj);
121 struct max6875_data *data = i2c_get_clientdata(client);
122 int slice, max_slice;
123
124 if (off > USER_EEPROM_SIZE)
125 return 0;
126
127 if (off + count > USER_EEPROM_SIZE)
128 count = USER_EEPROM_SIZE - off;
129
130 /* refresh slices which contain requested bytes */
131 max_slice = (off + count - 1) >> SLICE_BITS;
132 for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
133 max6875_update_slice(client, slice);
134
135 memcpy(buf, &data->data[off], count);
136
137 return count;
138}
139
140static struct bin_attribute user_eeprom_attr = {
141 .attr = {
142 .name = "eeprom",
143 .mode = S_IRUGO,
144 },
145 .size = USER_EEPROM_SIZE,
146 .read = max6875_read,
147};
148
149/* Return 0 if detection is successful, -ENODEV otherwise */
150static int max6875_detect(struct i2c_client *client, int kind,
151 struct i2c_board_info *info)
152{
153 struct i2c_adapter *adapter = client->adapter;
154
155 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
156 | I2C_FUNC_SMBUS_READ_BYTE))
157 return -ENODEV;
158
159 /* Only check even addresses */
160 if (client->addr & 1)
161 return -ENODEV;
162
163 strlcpy(info->type, "max6875", I2C_NAME_SIZE);
164
165 return 0;
166}
167
168static int max6875_probe(struct i2c_client *client,
169 const struct i2c_device_id *id)
170{
171 struct max6875_data *data;
172 int err;
173
174 if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
175 return -ENOMEM;
176
177 /* A fake client is created on the odd address */
178 data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1);
179 if (!data->fake_client) {
180 err = -ENOMEM;
181 goto exit_kfree;
182 }
183
184 /* Init real i2c_client */
185 i2c_set_clientdata(client, data);
186 mutex_init(&data->update_lock);
187
188 err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr);
189 if (err)
190 goto exit_remove_fake;
191
192 return 0;
193
194exit_remove_fake:
195 i2c_unregister_device(data->fake_client);
196exit_kfree:
197 kfree(data);
198 return err;
199}
200
201static int max6875_remove(struct i2c_client *client)
202{
203 struct max6875_data *data = i2c_get_clientdata(client);
204
205 i2c_unregister_device(data->fake_client);
206
207 sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
208 kfree(data);
209
210 return 0;
211}
212
213static const struct i2c_device_id max6875_id[] = {
214 { "max6875", 0 },
215 { }
216};
217
218static struct i2c_driver max6875_driver = {
219 .driver = {
220 .name = "max6875",
221 },
222 .probe = max6875_probe,
223 .remove = max6875_remove,
224 .id_table = max6875_id,
225
226 .detect = max6875_detect,
227 .address_data = &addr_data,
228};
229
230static int __init max6875_init(void)
231{
232 return i2c_add_driver(&max6875_driver);
233}
234
235static void __exit max6875_exit(void)
236{
237 i2c_del_driver(&max6875_driver);
238}
239
240
241MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
242MODULE_DESCRIPTION("MAX6875 driver");
243MODULE_LICENSE("GPL");
244
245module_init(max6875_init);
246module_exit(max6875_exit);
diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile
index bcd8136d2f98..7c4c306dfa8a 100644
--- a/drivers/misc/sgi-gru/Makefile
+++ b/drivers/misc/sgi-gru/Makefile
@@ -3,5 +3,5 @@ ifdef CONFIG_SGI_GRU_DEBUG
3endif 3endif
4 4
5obj-$(CONFIG_SGI_GRU) := gru.o 5obj-$(CONFIG_SGI_GRU) := gru.o
6gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o 6gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o grukdump.o
7 7
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h
index 3fde33c1e8f3..3c9c06618e6a 100644
--- a/drivers/misc/sgi-gru/gru_instructions.h
+++ b/drivers/misc/sgi-gru/gru_instructions.h
@@ -81,6 +81,8 @@ struct control_block_extended_exc_detail {
81 int exopc; 81 int exopc;
82 long exceptdet0; 82 long exceptdet0;
83 int exceptdet1; 83 int exceptdet1;
84 int cbrstate;
85 int cbrexecstatus;
84}; 86};
85 87
86/* 88/*
@@ -107,7 +109,8 @@ struct gru_instruction_bits {
107 unsigned char reserved2: 2; 109 unsigned char reserved2: 2;
108 unsigned char istatus: 2; 110 unsigned char istatus: 2;
109 unsigned char isubstatus:4; 111 unsigned char isubstatus:4;
110 unsigned char reserved3: 2; 112 unsigned char reserved3: 1;
113 unsigned char tlb_fault_color: 1;
111 /* DW 1 */ 114 /* DW 1 */
112 unsigned long idef4; /* 42 bits: TRi1, BufSize */ 115 unsigned long idef4; /* 42 bits: TRi1, BufSize */
113 /* DW 2-6 */ 116 /* DW 2-6 */
@@ -250,17 +253,37 @@ struct gru_instruction {
250#define CBE_CAUSE_HA_RESPONSE_FATAL (1 << 13) 253#define CBE_CAUSE_HA_RESPONSE_FATAL (1 << 13)
251#define CBE_CAUSE_HA_RESPONSE_NON_FATAL (1 << 14) 254#define CBE_CAUSE_HA_RESPONSE_NON_FATAL (1 << 14)
252#define CBE_CAUSE_ADDRESS_SPACE_DECODE_ERROR (1 << 15) 255#define CBE_CAUSE_ADDRESS_SPACE_DECODE_ERROR (1 << 15)
253#define CBE_CAUSE_RESPONSE_DATA_ERROR (1 << 16) 256#define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR (1 << 16)
254#define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR (1 << 17) 257#define CBE_CAUSE_RA_RESPONSE_DATA_ERROR (1 << 17)
258#define CBE_CAUSE_HA_RESPONSE_DATA_ERROR (1 << 18)
259
260/* CBE cbrexecstatus bits */
261#define CBR_EXS_ABORT_OCC_BIT 0
262#define CBR_EXS_INT_OCC_BIT 1
263#define CBR_EXS_PENDING_BIT 2
264#define CBR_EXS_QUEUED_BIT 3
265#define CBR_EXS_TLB_INVAL_BIT 4
266#define CBR_EXS_EXCEPTION_BIT 5
267
268#define CBR_EXS_ABORT_OCC (1 << CBR_EXS_ABORT_OCC_BIT)
269#define CBR_EXS_INT_OCC (1 << CBR_EXS_INT_OCC_BIT)
270#define CBR_EXS_PENDING (1 << CBR_EXS_PENDING_BIT)
271#define CBR_EXS_QUEUED (1 << CBR_EXS_QUEUED_BIT)
272#define CBR_TLB_INVAL (1 << CBR_EXS_TLB_INVAL_BIT)
273#define CBR_EXS_EXCEPTION (1 << CBR_EXS_EXCEPTION_BIT)
255 274
256/* 275/*
257 * Exceptions are retried for the following cases. If any OTHER bits are set 276 * Exceptions are retried for the following cases. If any OTHER bits are set
258 * in ecause, the exception is not retryable. 277 * in ecause, the exception is not retryable.
259 */ 278 */
260#define EXCEPTION_RETRY_BITS (CBE_CAUSE_RESPONSE_DATA_ERROR | \ 279#define EXCEPTION_RETRY_BITS (CBE_CAUSE_EXECUTION_HW_ERROR | \
261 CBE_CAUSE_RA_REQUEST_TIMEOUT | \
262 CBE_CAUSE_TLBHW_ERROR | \ 280 CBE_CAUSE_TLBHW_ERROR | \
263 CBE_CAUSE_HA_REQUEST_TIMEOUT) 281 CBE_CAUSE_RA_REQUEST_TIMEOUT | \
282 CBE_CAUSE_RA_RESPONSE_NON_FATAL | \
283 CBE_CAUSE_HA_RESPONSE_NON_FATAL | \
284 CBE_CAUSE_RA_RESPONSE_DATA_ERROR | \
285 CBE_CAUSE_HA_RESPONSE_DATA_ERROR \
286 )
264 287
265/* Message queue head structure */ 288/* Message queue head structure */
266union gru_mesqhead { 289union gru_mesqhead {
@@ -600,9 +623,11 @@ static inline int gru_get_cb_substatus(void *cb)
600 return cbs->isubstatus; 623 return cbs->isubstatus;
601} 624}
602 625
603/* Check the status of a CB. If the CB is in UPM mode, call the 626/*
604 * OS to handle the UPM status. 627 * User interface to check an instruction status. UPM and exceptions
605 * Returns the CB status field value (0 for normal completion) 628 * are handled automatically. However, this function does NOT wait
629 * for an active instruction to complete.
630 *
606 */ 631 */
607static inline int gru_check_status(void *cb) 632static inline int gru_check_status(void *cb)
608{ 633{
@@ -610,34 +635,31 @@ static inline int gru_check_status(void *cb)
610 int ret; 635 int ret;
611 636
612 ret = cbs->istatus; 637 ret = cbs->istatus;
613 if (ret == CBS_CALL_OS) 638 if (ret != CBS_ACTIVE)
614 ret = gru_check_status_proc(cb); 639 ret = gru_check_status_proc(cb);
615 return ret; 640 return ret;
616} 641}
617 642
618/* Wait for CB to complete. 643/*
619 * Returns the CB status field value (0 for normal completion) 644 * User interface (via inline function) to wait for an instruction
645 * to complete. Completion status (IDLE or EXCEPTION is returned
646 * to the user. Exception due to hardware errors are automatically
647 * retried before returning an exception.
648 *
620 */ 649 */
621static inline int gru_wait(void *cb) 650static inline int gru_wait(void *cb)
622{ 651{
623 struct gru_control_block_status *cbs = (void *)cb; 652 return gru_wait_proc(cb);
624 int ret = cbs->istatus;
625
626 if (ret != CBS_IDLE)
627 ret = gru_wait_proc(cb);
628 return ret;
629} 653}
630 654
631/* Wait for CB to complete. Aborts program if error. (Note: error does NOT 655/*
656 * Wait for CB to complete. Aborts program if error. (Note: error does NOT
632 * mean TLB mis - only fatal errors such as memory parity error or user 657 * mean TLB mis - only fatal errors such as memory parity error or user
633 * bugs will cause termination. 658 * bugs will cause termination.
634 */ 659 */
635static inline void gru_wait_abort(void *cb) 660static inline void gru_wait_abort(void *cb)
636{ 661{
637 struct gru_control_block_status *cbs = (void *)cb; 662 gru_wait_abort_proc(cb);
638
639 if (cbs->istatus != CBS_IDLE)
640 gru_wait_abort_proc(cb);
641} 663}
642 664
643 665
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index ab118558552e..679e01778286 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -166,7 +166,8 @@ static inline struct gru_state *irq_to_gru(int irq)
166 * the GRU, atomic operations must be used to clear bits. 166 * the GRU, atomic operations must be used to clear bits.
167 */ 167 */
168static void get_clear_fault_map(struct gru_state *gru, 168static void get_clear_fault_map(struct gru_state *gru,
169 struct gru_tlb_fault_map *map) 169 struct gru_tlb_fault_map *imap,
170 struct gru_tlb_fault_map *dmap)
170{ 171{
171 unsigned long i, k; 172 unsigned long i, k;
172 struct gru_tlb_fault_map *tfm; 173 struct gru_tlb_fault_map *tfm;
@@ -177,7 +178,11 @@ static void get_clear_fault_map(struct gru_state *gru,
177 k = tfm->fault_bits[i]; 178 k = tfm->fault_bits[i];
178 if (k) 179 if (k)
179 k = xchg(&tfm->fault_bits[i], 0UL); 180 k = xchg(&tfm->fault_bits[i], 0UL);
180 map->fault_bits[i] = k; 181 imap->fault_bits[i] = k;
182 k = tfm->done_bits[i];
183 if (k)
184 k = xchg(&tfm->done_bits[i], 0UL);
185 dmap->fault_bits[i] = k;
181 } 186 }
182 187
183 /* 188 /*
@@ -334,6 +339,12 @@ static int gru_try_dropin(struct gru_thread_state *gts,
334 * Might be a hardware race OR a stupid user. Ignore FMM because FMM 339 * Might be a hardware race OR a stupid user. Ignore FMM because FMM
335 * is a transient state. 340 * is a transient state.
336 */ 341 */
342 if (tfh->status != TFHSTATUS_EXCEPTION) {
343 gru_flush_cache(tfh);
344 if (tfh->status != TFHSTATUS_EXCEPTION)
345 goto failnoexception;
346 STAT(tfh_stale_on_fault);
347 }
337 if (tfh->state == TFHSTATE_IDLE) 348 if (tfh->state == TFHSTATE_IDLE)
338 goto failidle; 349 goto failidle;
339 if (tfh->state == TFHSTATE_MISS_FMM && cb) 350 if (tfh->state == TFHSTATE_MISS_FMM && cb)
@@ -401,8 +412,17 @@ failfmm:
401 gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state); 412 gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state);
402 return 0; 413 return 0;
403 414
415failnoexception:
416 /* TFH status did not show exception pending */
417 gru_flush_cache(tfh);
418 if (cb)
419 gru_flush_cache(cb);
420 STAT(tlb_dropin_fail_no_exception);
421 gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n", tfh, tfh->status, tfh->state);
422 return 0;
423
404failidle: 424failidle:
405 /* TFH was idle - no miss pending */ 425 /* TFH state was idle - no miss pending */
406 gru_flush_cache(tfh); 426 gru_flush_cache(tfh);
407 if (cb) 427 if (cb)
408 gru_flush_cache(cb); 428 gru_flush_cache(cb);
@@ -438,7 +458,7 @@ failactive:
438irqreturn_t gru_intr(int irq, void *dev_id) 458irqreturn_t gru_intr(int irq, void *dev_id)
439{ 459{
440 struct gru_state *gru; 460 struct gru_state *gru;
441 struct gru_tlb_fault_map map; 461 struct gru_tlb_fault_map imap, dmap;
442 struct gru_thread_state *gts; 462 struct gru_thread_state *gts;
443 struct gru_tlb_fault_handle *tfh = NULL; 463 struct gru_tlb_fault_handle *tfh = NULL;
444 int cbrnum, ctxnum; 464 int cbrnum, ctxnum;
@@ -451,11 +471,15 @@ irqreturn_t gru_intr(int irq, void *dev_id)
451 raw_smp_processor_id(), irq); 471 raw_smp_processor_id(), irq);
452 return IRQ_NONE; 472 return IRQ_NONE;
453 } 473 }
454 get_clear_fault_map(gru, &map); 474 get_clear_fault_map(gru, &imap, &dmap);
455 gru_dbg(grudev, "irq %d, gru %x, map 0x%lx\n", irq, gru->gs_gid, 475
456 map.fault_bits[0]); 476 for_each_cbr_in_tfm(cbrnum, dmap.fault_bits) {
477 complete(gru->gs_blade->bs_async_wq);
478 gru_dbg(grudev, "gid %d, cbr_done %d, done %d\n",
479 gru->gs_gid, cbrnum, gru->gs_blade->bs_async_wq->done);
480 }
457 481
458 for_each_cbr_in_tfm(cbrnum, map.fault_bits) { 482 for_each_cbr_in_tfm(cbrnum, imap.fault_bits) {
459 tfh = get_tfh_by_index(gru, cbrnum); 483 tfh = get_tfh_by_index(gru, cbrnum);
460 prefetchw(tfh); /* Helps on hdw, required for emulator */ 484 prefetchw(tfh); /* Helps on hdw, required for emulator */
461 485
@@ -472,7 +496,9 @@ irqreturn_t gru_intr(int irq, void *dev_id)
472 * This is running in interrupt context. Trylock the mmap_sem. 496 * This is running in interrupt context. Trylock the mmap_sem.
473 * If it fails, retry the fault in user context. 497 * If it fails, retry the fault in user context.
474 */ 498 */
475 if (down_read_trylock(&gts->ts_mm->mmap_sem)) { 499 if (!gts->ts_force_cch_reload &&
500 down_read_trylock(&gts->ts_mm->mmap_sem)) {
501 gts->ustats.fmm_tlbdropin++;
476 gru_try_dropin(gts, tfh, NULL); 502 gru_try_dropin(gts, tfh, NULL);
477 up_read(&gts->ts_mm->mmap_sem); 503 up_read(&gts->ts_mm->mmap_sem);
478 } else { 504 } else {
@@ -491,6 +517,7 @@ static int gru_user_dropin(struct gru_thread_state *gts,
491 struct gru_mm_struct *gms = gts->ts_gms; 517 struct gru_mm_struct *gms = gts->ts_gms;
492 int ret; 518 int ret;
493 519
520 gts->ustats.upm_tlbdropin++;
494 while (1) { 521 while (1) {
495 wait_event(gms->ms_wait_queue, 522 wait_event(gms->ms_wait_queue,
496 atomic_read(&gms->ms_range_active) == 0); 523 atomic_read(&gms->ms_range_active) == 0);
@@ -546,8 +573,8 @@ int gru_handle_user_call_os(unsigned long cb)
546 * CCH may contain stale data if ts_force_cch_reload is set. 573 * CCH may contain stale data if ts_force_cch_reload is set.
547 */ 574 */
548 if (gts->ts_gru && gts->ts_force_cch_reload) { 575 if (gts->ts_gru && gts->ts_force_cch_reload) {
549 gru_update_cch(gts, 0);
550 gts->ts_force_cch_reload = 0; 576 gts->ts_force_cch_reload = 0;
577 gru_update_cch(gts, 0);
551 } 578 }
552 579
553 ret = -EAGAIN; 580 ret = -EAGAIN;
@@ -589,20 +616,26 @@ int gru_get_exception_detail(unsigned long arg)
589 } else if (gts->ts_gru) { 616 } else if (gts->ts_gru) {
590 cbrnum = thread_cbr_number(gts, ucbnum); 617 cbrnum = thread_cbr_number(gts, ucbnum);
591 cbe = get_cbe_by_index(gts->ts_gru, cbrnum); 618 cbe = get_cbe_by_index(gts->ts_gru, cbrnum);
592 prefetchw(cbe);/* Harmless on hardware, required for emulator */ 619 gru_flush_cache(cbe); /* CBE not coherent */
593 excdet.opc = cbe->opccpy; 620 excdet.opc = cbe->opccpy;
594 excdet.exopc = cbe->exopccpy; 621 excdet.exopc = cbe->exopccpy;
595 excdet.ecause = cbe->ecause; 622 excdet.ecause = cbe->ecause;
596 excdet.exceptdet0 = cbe->idef1upd; 623 excdet.exceptdet0 = cbe->idef1upd;
597 excdet.exceptdet1 = cbe->idef3upd; 624 excdet.exceptdet1 = cbe->idef3upd;
625 excdet.cbrstate = cbe->cbrstate;
626 excdet.cbrexecstatus = cbe->cbrexecstatus;
627 gru_flush_cache(cbe);
598 ret = 0; 628 ret = 0;
599 } else { 629 } else {
600 ret = -EAGAIN; 630 ret = -EAGAIN;
601 } 631 }
602 gru_unlock_gts(gts); 632 gru_unlock_gts(gts);
603 633
604 gru_dbg(grudev, "address 0x%lx, ecause 0x%x\n", excdet.cb, 634 gru_dbg(grudev,
605 excdet.ecause); 635 "cb 0x%lx, op %d, exopc %d, cbrstate %d, cbrexecstatus 0x%x, ecause 0x%x, "
636 "exdet0 0x%lx, exdet1 0x%x\n",
637 excdet.cb, excdet.opc, excdet.exopc, excdet.cbrstate, excdet.cbrexecstatus,
638 excdet.ecause, excdet.exceptdet0, excdet.exceptdet1);
606 if (!ret && copy_to_user((void __user *)arg, &excdet, sizeof(excdet))) 639 if (!ret && copy_to_user((void __user *)arg, &excdet, sizeof(excdet)))
607 ret = -EFAULT; 640 ret = -EFAULT;
608 return ret; 641 return ret;
@@ -627,7 +660,7 @@ static int gru_unload_all_contexts(void)
627 if (gts && mutex_trylock(&gts->ts_ctxlock)) { 660 if (gts && mutex_trylock(&gts->ts_ctxlock)) {
628 spin_unlock(&gru->gs_lock); 661 spin_unlock(&gru->gs_lock);
629 gru_unload_context(gts, 1); 662 gru_unload_context(gts, 1);
630 gru_unlock_gts(gts); 663 mutex_unlock(&gts->ts_ctxlock);
631 spin_lock(&gru->gs_lock); 664 spin_lock(&gru->gs_lock);
632 } 665 }
633 } 666 }
@@ -669,6 +702,7 @@ int gru_user_flush_tlb(unsigned long arg)
669{ 702{
670 struct gru_thread_state *gts; 703 struct gru_thread_state *gts;
671 struct gru_flush_tlb_req req; 704 struct gru_flush_tlb_req req;
705 struct gru_mm_struct *gms;
672 706
673 STAT(user_flush_tlb); 707 STAT(user_flush_tlb);
674 if (copy_from_user(&req, (void __user *)arg, sizeof(req))) 708 if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
@@ -681,8 +715,34 @@ int gru_user_flush_tlb(unsigned long arg)
681 if (!gts) 715 if (!gts)
682 return -EINVAL; 716 return -EINVAL;
683 717
684 gru_flush_tlb_range(gts->ts_gms, req.vaddr, req.len); 718 gms = gts->ts_gms;
685 gru_unlock_gts(gts); 719 gru_unlock_gts(gts);
720 gru_flush_tlb_range(gms, req.vaddr, req.len);
721
722 return 0;
723}
724
725/*
726 * Fetch GSEG statisticss
727 */
728long gru_get_gseg_statistics(unsigned long arg)
729{
730 struct gru_thread_state *gts;
731 struct gru_get_gseg_statistics_req req;
732
733 if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
734 return -EFAULT;
735
736 gts = gru_find_lock_gts(req.gseg);
737 if (gts) {
738 memcpy(&req.stats, &gts->ustats, sizeof(gts->ustats));
739 gru_unlock_gts(gts);
740 } else {
741 memset(&req.stats, 0, sizeof(gts->ustats));
742 }
743
744 if (copy_to_user((void __user *)arg, &req, sizeof(req)))
745 return -EFAULT;
686 746
687 return 0; 747 return 0;
688} 748}
@@ -691,18 +751,34 @@ int gru_user_flush_tlb(unsigned long arg)
691 * Register the current task as the user of the GSEG slice. 751 * Register the current task as the user of the GSEG slice.
692 * Needed for TLB fault interrupt targeting. 752 * Needed for TLB fault interrupt targeting.
693 */ 753 */
694int gru_set_task_slice(long address) 754int gru_set_context_option(unsigned long arg)
695{ 755{
696 struct gru_thread_state *gts; 756 struct gru_thread_state *gts;
757 struct gru_set_context_option_req req;
758 int ret = 0;
759
760 STAT(set_context_option);
761 if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
762 return -EFAULT;
763 gru_dbg(grudev, "op %d, gseg 0x%lx, value1 0x%lx\n", req.op, req.gseg, req.val1);
697 764
698 STAT(set_task_slice); 765 gts = gru_alloc_locked_gts(req.gseg);
699 gru_dbg(grudev, "address 0x%lx\n", address);
700 gts = gru_alloc_locked_gts(address);
701 if (!gts) 766 if (!gts)
702 return -EINVAL; 767 return -EINVAL;
703 768
704 gts->ts_tgid_owner = current->tgid; 769 switch (req.op) {
770 case sco_gseg_owner:
771 /* Register the current task as the GSEG owner */
772 gts->ts_tgid_owner = current->tgid;
773 break;
774 case sco_cch_req_slice:
775 /* Set the CCH slice option */
776 gts->ts_cch_req_slice = req.val1 & 3;
777 break;
778 default:
779 ret = -EINVAL;
780 }
705 gru_unlock_gts(gts); 781 gru_unlock_gts(gts);
706 782
707 return 0; 783 return ret;
708} 784}
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index bbefe77c67a9..aed609832bc2 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -29,7 +29,6 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/mm.h> 30#include <linux/mm.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/smp_lock.h>
33#include <linux/spinlock.h> 32#include <linux/spinlock.h>
34#include <linux/device.h> 33#include <linux/device.h>
35#include <linux/miscdevice.h> 34#include <linux/miscdevice.h>
@@ -46,6 +45,7 @@
46 45
47struct gru_blade_state *gru_base[GRU_MAX_BLADES] __read_mostly; 46struct gru_blade_state *gru_base[GRU_MAX_BLADES] __read_mostly;
48unsigned long gru_start_paddr __read_mostly; 47unsigned long gru_start_paddr __read_mostly;
48void *gru_start_vaddr __read_mostly;
49unsigned long gru_end_paddr __read_mostly; 49unsigned long gru_end_paddr __read_mostly;
50unsigned int gru_max_gids __read_mostly; 50unsigned int gru_max_gids __read_mostly;
51struct gru_stats_s gru_stats; 51struct gru_stats_s gru_stats;
@@ -135,11 +135,9 @@ static int gru_create_new_context(unsigned long arg)
135 if (copy_from_user(&req, (void __user *)arg, sizeof(req))) 135 if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
136 return -EFAULT; 136 return -EFAULT;
137 137
138 if (req.data_segment_bytes == 0 || 138 if (req.data_segment_bytes > max_user_dsr_bytes)
139 req.data_segment_bytes > max_user_dsr_bytes)
140 return -EINVAL; 139 return -EINVAL;
141 if (!req.control_blocks || !req.maximum_thread_count || 140 if (req.control_blocks > max_user_cbrs || !req.maximum_thread_count)
142 req.control_blocks > max_user_cbrs)
143 return -EINVAL; 141 return -EINVAL;
144 142
145 if (!(req.options & GRU_OPT_MISS_MASK)) 143 if (!(req.options & GRU_OPT_MISS_MASK))
@@ -184,41 +182,6 @@ static long gru_get_config_info(unsigned long arg)
184} 182}
185 183
186/* 184/*
187 * Get GRU chiplet status
188 */
189static long gru_get_chiplet_status(unsigned long arg)
190{
191 struct gru_state *gru;
192 struct gru_chiplet_info info;
193
194 if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
195 return -EFAULT;
196
197 if (info.node == -1)
198 info.node = numa_node_id();
199 if (info.node >= num_possible_nodes() ||
200 info.chiplet >= GRU_CHIPLETS_PER_HUB ||
201 info.node < 0 || info.chiplet < 0)
202 return -EINVAL;
203
204 info.blade = uv_node_to_blade_id(info.node);
205 gru = get_gru(info.blade, info.chiplet);
206
207 info.total_dsr_bytes = GRU_NUM_DSR_BYTES;
208 info.total_cbr = GRU_NUM_CB;
209 info.total_user_dsr_bytes = GRU_NUM_DSR_BYTES -
210 gru->gs_reserved_dsr_bytes;
211 info.total_user_cbr = GRU_NUM_CB - gru->gs_reserved_cbrs;
212 info.free_user_dsr_bytes = hweight64(gru->gs_dsr_map) *
213 GRU_DSR_AU_BYTES;
214 info.free_user_cbr = hweight64(gru->gs_cbr_map) * GRU_CBR_AU_SIZE;
215
216 if (copy_to_user((void __user *)arg, &info, sizeof(info)))
217 return -EFAULT;
218 return 0;
219}
220
221/*
222 * gru_file_unlocked_ioctl 185 * gru_file_unlocked_ioctl
223 * 186 *
224 * Called to update file attributes via IOCTL calls. 187 * Called to update file attributes via IOCTL calls.
@@ -234,8 +197,8 @@ static long gru_file_unlocked_ioctl(struct file *file, unsigned int req,
234 case GRU_CREATE_CONTEXT: 197 case GRU_CREATE_CONTEXT:
235 err = gru_create_new_context(arg); 198 err = gru_create_new_context(arg);
236 break; 199 break;
237 case GRU_SET_TASK_SLICE: 200 case GRU_SET_CONTEXT_OPTION:
238 err = gru_set_task_slice(arg); 201 err = gru_set_context_option(arg);
239 break; 202 break;
240 case GRU_USER_GET_EXCEPTION_DETAIL: 203 case GRU_USER_GET_EXCEPTION_DETAIL:
241 err = gru_get_exception_detail(arg); 204 err = gru_get_exception_detail(arg);
@@ -243,18 +206,24 @@ static long gru_file_unlocked_ioctl(struct file *file, unsigned int req,
243 case GRU_USER_UNLOAD_CONTEXT: 206 case GRU_USER_UNLOAD_CONTEXT:
244 err = gru_user_unload_context(arg); 207 err = gru_user_unload_context(arg);
245 break; 208 break;
246 case GRU_GET_CHIPLET_STATUS:
247 err = gru_get_chiplet_status(arg);
248 break;
249 case GRU_USER_FLUSH_TLB: 209 case GRU_USER_FLUSH_TLB:
250 err = gru_user_flush_tlb(arg); 210 err = gru_user_flush_tlb(arg);
251 break; 211 break;
252 case GRU_USER_CALL_OS: 212 case GRU_USER_CALL_OS:
253 err = gru_handle_user_call_os(arg); 213 err = gru_handle_user_call_os(arg);
254 break; 214 break;
215 case GRU_GET_GSEG_STATISTICS:
216 err = gru_get_gseg_statistics(arg);
217 break;
218 case GRU_KTEST:
219 err = gru_ktest(arg);
220 break;
255 case GRU_GET_CONFIG_INFO: 221 case GRU_GET_CONFIG_INFO:
256 err = gru_get_config_info(arg); 222 err = gru_get_config_info(arg);
257 break; 223 break;
224 case GRU_DUMP_CHIPLET_STATE:
225 err = gru_dump_chiplet_request(arg);
226 break;
258 } 227 }
259 return err; 228 return err;
260} 229}
@@ -282,7 +251,6 @@ static void gru_init_chiplet(struct gru_state *gru, unsigned long paddr,
282 gru_dbg(grudev, "bid %d, nid %d, gid %d, vaddr %p (0x%lx)\n", 251 gru_dbg(grudev, "bid %d, nid %d, gid %d, vaddr %p (0x%lx)\n",
283 bid, nid, gru->gs_gid, gru->gs_gru_base_vaddr, 252 bid, nid, gru->gs_gid, gru->gs_gru_base_vaddr,
284 gru->gs_gru_base_paddr); 253 gru->gs_gru_base_paddr);
285 gru_kservices_init(gru);
286} 254}
287 255
288static int gru_init_tables(unsigned long gru_base_paddr, void *gru_base_vaddr) 256static int gru_init_tables(unsigned long gru_base_paddr, void *gru_base_vaddr)
@@ -302,13 +270,14 @@ static int gru_init_tables(unsigned long gru_base_paddr, void *gru_base_vaddr)
302 pnode = uv_node_to_pnode(nid); 270 pnode = uv_node_to_pnode(nid);
303 if (bid < 0 || gru_base[bid]) 271 if (bid < 0 || gru_base[bid])
304 continue; 272 continue;
305 page = alloc_pages_node(nid, GFP_KERNEL, order); 273 page = alloc_pages_exact_node(nid, GFP_KERNEL, order);
306 if (!page) 274 if (!page)
307 goto fail; 275 goto fail;
308 gru_base[bid] = page_address(page); 276 gru_base[bid] = page_address(page);
309 memset(gru_base[bid], 0, sizeof(struct gru_blade_state)); 277 memset(gru_base[bid], 0, sizeof(struct gru_blade_state));
310 gru_base[bid]->bs_lru_gru = &gru_base[bid]->bs_grus[0]; 278 gru_base[bid]->bs_lru_gru = &gru_base[bid]->bs_grus[0];
311 spin_lock_init(&gru_base[bid]->bs_lock); 279 spin_lock_init(&gru_base[bid]->bs_lock);
280 init_rwsem(&gru_base[bid]->bs_kgts_sema);
312 281
313 dsrbytes = 0; 282 dsrbytes = 0;
314 cbrs = 0; 283 cbrs = 0;
@@ -372,7 +341,6 @@ static int __init gru_init(void)
372{ 341{
373 int ret, irq, chip; 342 int ret, irq, chip;
374 char id[10]; 343 char id[10];
375 void *gru_start_vaddr;
376 344
377 if (!is_uv_system()) 345 if (!is_uv_system())
378 return 0; 346 return 0;
@@ -422,6 +390,7 @@ static int __init gru_init(void)
422 printk(KERN_ERR "%s: init tables failed\n", GRU_DRIVER_ID_STR); 390 printk(KERN_ERR "%s: init tables failed\n", GRU_DRIVER_ID_STR);
423 goto exit3; 391 goto exit3;
424 } 392 }
393 gru_kservices_init();
425 394
426 printk(KERN_INFO "%s: v%s\n", GRU_DRIVER_ID_STR, 395 printk(KERN_INFO "%s: v%s\n", GRU_DRIVER_ID_STR,
427 GRU_DRIVER_VERSION_STR); 396 GRU_DRIVER_VERSION_STR);
@@ -440,7 +409,7 @@ exit1:
440 409
441static void __exit gru_exit(void) 410static void __exit gru_exit(void)
442{ 411{
443 int i, bid, gid; 412 int i, bid;
444 int order = get_order(sizeof(struct gru_state) * 413 int order = get_order(sizeof(struct gru_state) *
445 GRU_CHIPLETS_PER_BLADE); 414 GRU_CHIPLETS_PER_BLADE);
446 415
@@ -449,10 +418,7 @@ static void __exit gru_exit(void)
449 418
450 for (i = 0; i < GRU_CHIPLETS_PER_BLADE; i++) 419 for (i = 0; i < GRU_CHIPLETS_PER_BLADE; i++)
451 free_irq(IRQ_GRU + i, NULL); 420 free_irq(IRQ_GRU + i, NULL);
452 421 gru_kservices_exit();
453 foreach_gid(gid)
454 gru_kservices_exit(GID_TO_GRU(gid));
455
456 for (bid = 0; bid < GRU_MAX_BLADES; bid++) 422 for (bid = 0; bid < GRU_MAX_BLADES; bid++)
457 free_pages((unsigned long)gru_base[bid], order); 423 free_pages((unsigned long)gru_base[bid], order);
458 424
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c
index 9b7ccb328697..37e7cfc53b9c 100644
--- a/drivers/misc/sgi-gru/gruhandles.c
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -57,7 +57,7 @@ static void start_instruction(void *h)
57static int wait_instruction_complete(void *h, enum mcs_op opc) 57static int wait_instruction_complete(void *h, enum mcs_op opc)
58{ 58{
59 int status; 59 int status;
60 cycles_t start_time = get_cycles(); 60 unsigned long start_time = get_cycles();
61 61
62 while (1) { 62 while (1) {
63 cpu_relax(); 63 cpu_relax();
@@ -65,25 +65,16 @@ static int wait_instruction_complete(void *h, enum mcs_op opc)
65 if (status != CCHSTATUS_ACTIVE) 65 if (status != CCHSTATUS_ACTIVE)
66 break; 66 break;
67 if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time)) 67 if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time))
68 panic("GRU %p is malfunctioning\n", h); 68 panic("GRU %p is malfunctioning: start %ld, end %ld\n",
69 h, start_time, (unsigned long)get_cycles());
69 } 70 }
70 if (gru_options & OPT_STATS) 71 if (gru_options & OPT_STATS)
71 update_mcs_stats(opc, get_cycles() - start_time); 72 update_mcs_stats(opc, get_cycles() - start_time);
72 return status; 73 return status;
73} 74}
74 75
75int cch_allocate(struct gru_context_configuration_handle *cch, 76int cch_allocate(struct gru_context_configuration_handle *cch)
76 int asidval, int sizeavail, unsigned long cbrmap,
77 unsigned long dsrmap)
78{ 77{
79 int i;
80
81 for (i = 0; i < 8; i++) {
82 cch->asid[i] = (asidval++);
83 cch->sizeavail[i] = sizeavail;
84 }
85 cch->dsr_allocation_map = dsrmap;
86 cch->cbr_allocation_map = cbrmap;
87 cch->opc = CCHOP_ALLOCATE; 78 cch->opc = CCHOP_ALLOCATE;
88 start_instruction(cch); 79 start_instruction(cch);
89 return wait_instruction_complete(cch, cchop_allocate); 80 return wait_instruction_complete(cch, cchop_allocate);
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h
index 1ed74d7508c8..f44112242d00 100644
--- a/drivers/misc/sgi-gru/gruhandles.h
+++ b/drivers/misc/sgi-gru/gruhandles.h
@@ -39,7 +39,6 @@
39#define GRU_NUM_CBE 128 39#define GRU_NUM_CBE 128
40#define GRU_NUM_TFH 128 40#define GRU_NUM_TFH 128
41#define GRU_NUM_CCH 16 41#define GRU_NUM_CCH 16
42#define GRU_NUM_GSH 1
43 42
44/* Maximum resource counts that can be reserved by user programs */ 43/* Maximum resource counts that can be reserved by user programs */
45#define GRU_NUM_USER_CBR GRU_NUM_CBE 44#define GRU_NUM_USER_CBR GRU_NUM_CBE
@@ -56,7 +55,6 @@
56#define GRU_CBE_BASE (GRU_MCS_BASE + 0x10000) 55#define GRU_CBE_BASE (GRU_MCS_BASE + 0x10000)
57#define GRU_TFH_BASE (GRU_MCS_BASE + 0x18000) 56#define GRU_TFH_BASE (GRU_MCS_BASE + 0x18000)
58#define GRU_CCH_BASE (GRU_MCS_BASE + 0x20000) 57#define GRU_CCH_BASE (GRU_MCS_BASE + 0x20000)
59#define GRU_GSH_BASE (GRU_MCS_BASE + 0x30000)
60 58
61/* User gseg constants */ 59/* User gseg constants */
62#define GRU_GSEG_STRIDE (4 * 1024 * 1024) 60#define GRU_GSEG_STRIDE (4 * 1024 * 1024)
@@ -251,15 +249,15 @@ struct gru_tlb_fault_handle {
251 unsigned int fill1:9; 249 unsigned int fill1:9;
252 250
253 unsigned int status:2; 251 unsigned int status:2;
254 unsigned int fill2:1; 252 unsigned int fill2:2;
255 unsigned int color:1;
256 unsigned int state:3; 253 unsigned int state:3;
257 unsigned int fill3:1; 254 unsigned int fill3:1;
258 255
259 unsigned int cause:7; /* DW 0 - high 32 */ 256 unsigned int cause:6;
257 unsigned int cb_int:1;
260 unsigned int fill4:1; 258 unsigned int fill4:1;
261 259
262 unsigned int indexway:12; 260 unsigned int indexway:12; /* DW 0 - high 32 */
263 unsigned int fill5:4; 261 unsigned int fill5:4;
264 262
265 unsigned int ctxnum:4; 263 unsigned int ctxnum:4;
@@ -457,21 +455,7 @@ enum gru_cbr_state {
457 CBRSTATE_BUSY_INTERRUPT, 455 CBRSTATE_BUSY_INTERRUPT,
458}; 456};
459 457
460/* CBE cbrexecstatus bits */ 458/* CBE cbrexecstatus bits - defined in gru_instructions.h*/
461#define CBR_EXS_ABORT_OCC_BIT 0
462#define CBR_EXS_INT_OCC_BIT 1
463#define CBR_EXS_PENDING_BIT 2
464#define CBR_EXS_QUEUED_BIT 3
465#define CBR_EXS_TLBHW_BIT 4
466#define CBR_EXS_EXCEPTION_BIT 5
467
468#define CBR_EXS_ABORT_OCC (1 << CBR_EXS_ABORT_OCC_BIT)
469#define CBR_EXS_INT_OCC (1 << CBR_EXS_INT_OCC_BIT)
470#define CBR_EXS_PENDING (1 << CBR_EXS_PENDING_BIT)
471#define CBR_EXS_QUEUED (1 << CBR_EXS_QUEUED_BIT)
472#define CBR_EXS_TLBHW (1 << CBR_EXS_TLBHW_BIT)
473#define CBR_EXS_EXCEPTION (1 << CBR_EXS_EXCEPTION_BIT)
474
475/* CBE ecause bits - defined in gru_instructions.h */ 459/* CBE ecause bits - defined in gru_instructions.h */
476 460
477/* 461/*
@@ -495,9 +479,7 @@ enum gru_cbr_state {
495/* minimum TLB purge count to ensure a full purge */ 479/* minimum TLB purge count to ensure a full purge */
496#define GRUMAXINVAL 1024UL 480#define GRUMAXINVAL 1024UL
497 481
498int cch_allocate(struct gru_context_configuration_handle *cch, 482int cch_allocate(struct gru_context_configuration_handle *cch);
499 int asidval, int sizeavail, unsigned long cbrmap, unsigned long dsrmap);
500
501int cch_start(struct gru_context_configuration_handle *cch); 483int cch_start(struct gru_context_configuration_handle *cch);
502int cch_interrupt(struct gru_context_configuration_handle *cch); 484int cch_interrupt(struct gru_context_configuration_handle *cch);
503int cch_deallocate(struct gru_context_configuration_handle *cch); 485int cch_deallocate(struct gru_context_configuration_handle *cch);
diff --git a/drivers/misc/sgi-gru/grukdump.c b/drivers/misc/sgi-gru/grukdump.c
new file mode 100644
index 000000000000..55eabfa85585
--- /dev/null
+++ b/drivers/misc/sgi-gru/grukdump.c
@@ -0,0 +1,232 @@
1/*
2 * SN Platform GRU Driver
3 *
4 * Dump GRU State
5 *
6 * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/spinlock.h>
26#include <linux/uaccess.h>
27#include <linux/delay.h>
28#include <linux/bitops.h>
29#include <asm/uv/uv_hub.h>
30#include "gru.h"
31#include "grutables.h"
32#include "gruhandles.h"
33#include "grulib.h"
34
35#define CCH_LOCK_ATTEMPTS 10
36
37static int gru_user_copy_handle(void __user **dp, void *s)
38{
39 if (copy_to_user(*dp, s, GRU_HANDLE_BYTES))
40 return -1;
41 *dp += GRU_HANDLE_BYTES;
42 return 0;
43}
44
45static int gru_dump_context_data(void *grubase,
46 struct gru_context_configuration_handle *cch,
47 void __user *ubuf, int ctxnum, int dsrcnt)
48{
49 void *cb, *cbe, *tfh, *gseg;
50 int i, scr;
51
52 gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
53 cb = gseg + GRU_CB_BASE;
54 cbe = grubase + GRU_CBE_BASE;
55 tfh = grubase + GRU_TFH_BASE;
56
57 for_each_cbr_in_allocation_map(i, &cch->cbr_allocation_map, scr) {
58 if (gru_user_copy_handle(&ubuf, cb))
59 goto fail;
60 if (gru_user_copy_handle(&ubuf, tfh + i * GRU_HANDLE_STRIDE))
61 goto fail;
62 if (gru_user_copy_handle(&ubuf, cbe + i * GRU_HANDLE_STRIDE))
63 goto fail;
64 cb += GRU_HANDLE_STRIDE;
65 }
66 if (dsrcnt)
67 memcpy(ubuf, gseg + GRU_DS_BASE, dsrcnt * GRU_HANDLE_STRIDE);
68 return 0;
69
70fail:
71 return -EFAULT;
72}
73
74static int gru_dump_tfm(struct gru_state *gru,
75 void __user *ubuf, void __user *ubufend)
76{
77 struct gru_tlb_fault_map *tfm;
78 int i, ret, bytes;
79
80 bytes = GRU_NUM_TFM * GRU_CACHE_LINE_BYTES;
81 if (bytes > ubufend - ubuf)
82 ret = -EFBIG;
83
84 for (i = 0; i < GRU_NUM_TFM; i++) {
85 tfm = get_tfm(gru->gs_gru_base_vaddr, i);
86 if (gru_user_copy_handle(&ubuf, tfm))
87 goto fail;
88 }
89 return GRU_NUM_TFM * GRU_CACHE_LINE_BYTES;
90
91fail:
92 return -EFAULT;
93}
94
95static int gru_dump_tgh(struct gru_state *gru,
96 void __user *ubuf, void __user *ubufend)
97{
98 struct gru_tlb_global_handle *tgh;
99 int i, ret, bytes;
100
101 bytes = GRU_NUM_TGH * GRU_CACHE_LINE_BYTES;
102 if (bytes > ubufend - ubuf)
103 ret = -EFBIG;
104
105 for (i = 0; i < GRU_NUM_TGH; i++) {
106 tgh = get_tgh(gru->gs_gru_base_vaddr, i);
107 if (gru_user_copy_handle(&ubuf, tgh))
108 goto fail;
109 }
110 return GRU_NUM_TGH * GRU_CACHE_LINE_BYTES;
111
112fail:
113 return -EFAULT;
114}
115
116static int gru_dump_context(struct gru_state *gru, int ctxnum,
117 void __user *ubuf, void __user *ubufend, char data_opt,
118 char lock_cch)
119{
120 struct gru_dump_context_header hdr;
121 struct gru_dump_context_header __user *uhdr = ubuf;
122 struct gru_context_configuration_handle *cch, *ubufcch;
123 struct gru_thread_state *gts;
124 int try, cch_locked, cbrcnt = 0, dsrcnt = 0, bytes = 0, ret = 0;
125 void *grubase;
126
127 memset(&hdr, 0, sizeof(hdr));
128 grubase = gru->gs_gru_base_vaddr;
129 cch = get_cch(grubase, ctxnum);
130 for (try = 0; try < CCH_LOCK_ATTEMPTS; try++) {
131 cch_locked = trylock_cch_handle(cch);
132 if (cch_locked)
133 break;
134 msleep(1);
135 }
136
137 ubuf += sizeof(hdr);
138 ubufcch = ubuf;
139 if (gru_user_copy_handle(&ubuf, cch))
140 goto fail;
141 if (cch_locked)
142 ubufcch->delresp = 0;
143 bytes = sizeof(hdr) + GRU_CACHE_LINE_BYTES;
144
145 if (cch_locked || !lock_cch) {
146 gts = gru->gs_gts[ctxnum];
147 if (gts && gts->ts_vma) {
148 hdr.pid = gts->ts_tgid_owner;
149 hdr.vaddr = gts->ts_vma->vm_start;
150 }
151 if (cch->state != CCHSTATE_INACTIVE) {
152 cbrcnt = hweight64(cch->cbr_allocation_map) *
153 GRU_CBR_AU_SIZE;
154 dsrcnt = data_opt ? hweight32(cch->dsr_allocation_map) *
155 GRU_DSR_AU_CL : 0;
156 }
157 bytes += (3 * cbrcnt + dsrcnt) * GRU_CACHE_LINE_BYTES;
158 if (bytes > ubufend - ubuf)
159 ret = -EFBIG;
160 else
161 ret = gru_dump_context_data(grubase, cch, ubuf, ctxnum,
162 dsrcnt);
163
164 }
165 if (cch_locked)
166 unlock_cch_handle(cch);
167 if (ret)
168 return ret;
169
170 hdr.magic = GRU_DUMP_MAGIC;
171 hdr.gid = gru->gs_gid;
172 hdr.ctxnum = ctxnum;
173 hdr.cbrcnt = cbrcnt;
174 hdr.dsrcnt = dsrcnt;
175 hdr.cch_locked = cch_locked;
176 if (!ret && copy_to_user((void __user *)uhdr, &hdr, sizeof(hdr)))
177 ret = -EFAULT;
178
179 return ret ? ret : bytes;
180
181fail:
182 unlock_cch_handle(cch);
183 return -EFAULT;
184}
185
186int gru_dump_chiplet_request(unsigned long arg)
187{
188 struct gru_state *gru;
189 struct gru_dump_chiplet_state_req req;
190 void __user *ubuf;
191 void __user *ubufend;
192 int ctxnum, ret, cnt = 0;
193
194 if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
195 return -EFAULT;
196
197 /* Currently, only dump by gid is implemented */
198 if (req.gid >= gru_max_gids || req.gid < 0)
199 return -EINVAL;
200
201 gru = GID_TO_GRU(req.gid);
202 ubuf = req.buf;
203 ubufend = req.buf + req.buflen;
204
205 ret = gru_dump_tfm(gru, ubuf, ubufend);
206 if (ret < 0)
207 goto fail;
208 ubuf += ret;
209
210 ret = gru_dump_tgh(gru, ubuf, ubufend);
211 if (ret < 0)
212 goto fail;
213 ubuf += ret;
214
215 for (ctxnum = 0; ctxnum < GRU_NUM_CCH; ctxnum++) {
216 if (req.ctxnum == ctxnum || req.ctxnum < 0) {
217 ret = gru_dump_context(gru, ctxnum, ubuf, ubufend,
218 req.data_opt, req.lock_cch);
219 if (ret < 0)
220 goto fail;
221 ubuf += ret;
222 cnt++;
223 }
224 }
225
226 if (copy_to_user((void __user *)arg, &req, sizeof(req)))
227 return -EFAULT;
228 return cnt;
229
230fail:
231 return ret;
232}
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index d8bd7d84a7cf..79689b10f937 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -24,13 +24,13 @@
24#include <linux/errno.h> 24#include <linux/errno.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/mm.h> 26#include <linux/mm.h>
27#include <linux/smp_lock.h>
28#include <linux/spinlock.h> 27#include <linux/spinlock.h>
29#include <linux/device.h> 28#include <linux/device.h>
30#include <linux/miscdevice.h> 29#include <linux/miscdevice.h>
31#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
32#include <linux/interrupt.h> 31#include <linux/interrupt.h>
33#include <linux/uaccess.h> 32#include <linux/uaccess.h>
33#include <linux/delay.h>
34#include "gru.h" 34#include "gru.h"
35#include "grulib.h" 35#include "grulib.h"
36#include "grutables.h" 36#include "grutables.h"
@@ -45,18 +45,66 @@
45 * resources. This will likely be replaced when we better understand the 45 * resources. This will likely be replaced when we better understand the
46 * kernel/user requirements. 46 * kernel/user requirements.
47 * 47 *
48 * At boot time, the kernel permanently reserves a fixed number of 48 * Blade percpu resources reserved for kernel use. These resources are
49 * CBRs/DSRs for each cpu to use. The resources are all taken from 49 * reserved whenever the the kernel context for the blade is loaded. Note
50 * the GRU chiplet 1 on the blade. This leaves the full set of resources 50 * that the kernel context is not guaranteed to be always available. It is
51 * of chiplet 0 available to be allocated to a single user. 51 * loaded on demand & can be stolen by a user if the user demand exceeds the
52 * kernel demand. The kernel can always reload the kernel context but
53 * a SLEEP may be required!!!.
54 *
55 * Async Overview:
56 *
57 * Each blade has one "kernel context" that owns GRU kernel resources
58 * located on the blade. Kernel drivers use GRU resources in this context
59 * for sending messages, zeroing memory, etc.
60 *
61 * The kernel context is dynamically loaded on demand. If it is not in
62 * use by the kernel, the kernel context can be unloaded & given to a user.
63 * The kernel context will be reloaded when needed. This may require that
64 * a context be stolen from a user.
65 * NOTE: frequent unloading/reloading of the kernel context is
66 * expensive. We are depending on batch schedulers, cpusets, sane
67 * drivers or some other mechanism to prevent the need for frequent
68 * stealing/reloading.
69 *
70 * The kernel context consists of two parts:
71 * - 1 CB & a few DSRs that are reserved for each cpu on the blade.
72 * Each cpu has it's own private resources & does not share them
73 * with other cpus. These resources are used serially, ie,
74 * locked, used & unlocked on each call to a function in
75 * grukservices.
76 * (Now that we have dynamic loading of kernel contexts, I
77 * may rethink this & allow sharing between cpus....)
78 *
79 * - Additional resources can be reserved long term & used directly
80 * by UV drivers located in the kernel. Drivers using these GRU
81 * resources can use asynchronous GRU instructions that send
82 * interrupts on completion.
83 * - these resources must be explicitly locked/unlocked
84 * - locked resources prevent (obviously) the kernel
85 * context from being unloaded.
86 * - drivers using these resource directly issue their own
87 * GRU instruction and must wait/check completion.
88 *
89 * When these resources are reserved, the caller can optionally
90 * associate a wait_queue with the resources and use asynchronous
91 * GRU instructions. When an async GRU instruction completes, the
92 * driver will do a wakeup on the event.
93 *
52 */ 94 */
53 95
54/* Blade percpu resources PERMANENTLY reserved for kernel use */ 96
97#define ASYNC_HAN_TO_BID(h) ((h) - 1)
98#define ASYNC_BID_TO_HAN(b) ((b) + 1)
99#define ASYNC_HAN_TO_BS(h) gru_base[ASYNC_HAN_TO_BID(h)]
100#define KCB_TO_GID(cb) ((cb - gru_start_vaddr) / \
101 (GRU_SIZE * GRU_CHIPLETS_PER_BLADE))
102#define KCB_TO_BS(cb) gru_base[KCB_TO_GID(cb)]
103
55#define GRU_NUM_KERNEL_CBR 1 104#define GRU_NUM_KERNEL_CBR 1
56#define GRU_NUM_KERNEL_DSR_BYTES 256 105#define GRU_NUM_KERNEL_DSR_BYTES 256
57#define GRU_NUM_KERNEL_DSR_CL (GRU_NUM_KERNEL_DSR_BYTES / \ 106#define GRU_NUM_KERNEL_DSR_CL (GRU_NUM_KERNEL_DSR_BYTES / \
58 GRU_CACHE_LINE_BYTES) 107 GRU_CACHE_LINE_BYTES)
59#define KERNEL_CTXNUM 15
60 108
61/* GRU instruction attributes for all instructions */ 109/* GRU instruction attributes for all instructions */
62#define IMA IMA_CB_DELAY 110#define IMA IMA_CB_DELAY
@@ -98,6 +146,108 @@ struct message_header {
98 146
99#define HSTATUS(mq, h) ((mq) + offsetof(struct message_queue, hstatus[h])) 147#define HSTATUS(mq, h) ((mq) + offsetof(struct message_queue, hstatus[h]))
100 148
149/*
150 * Reload the blade's kernel context into a GRU chiplet. Called holding
151 * the bs_kgts_sema for READ. Will steal user contexts if necessary.
152 */
153static void gru_load_kernel_context(struct gru_blade_state *bs, int blade_id)
154{
155 struct gru_state *gru;
156 struct gru_thread_state *kgts;
157 void *vaddr;
158 int ctxnum, ncpus;
159
160 up_read(&bs->bs_kgts_sema);
161 down_write(&bs->bs_kgts_sema);
162
163 if (!bs->bs_kgts)
164 bs->bs_kgts = gru_alloc_gts(NULL, 0, 0, 0, 0);
165 kgts = bs->bs_kgts;
166
167 if (!kgts->ts_gru) {
168 STAT(load_kernel_context);
169 ncpus = uv_blade_nr_possible_cpus(blade_id);
170 kgts->ts_cbr_au_count = GRU_CB_COUNT_TO_AU(
171 GRU_NUM_KERNEL_CBR * ncpus + bs->bs_async_cbrs);
172 kgts->ts_dsr_au_count = GRU_DS_BYTES_TO_AU(
173 GRU_NUM_KERNEL_DSR_BYTES * ncpus +
174 bs->bs_async_dsr_bytes);
175 while (!gru_assign_gru_context(kgts, blade_id)) {
176 msleep(1);
177 gru_steal_context(kgts, blade_id);
178 }
179 gru_load_context(kgts);
180 gru = bs->bs_kgts->ts_gru;
181 vaddr = gru->gs_gru_base_vaddr;
182 ctxnum = kgts->ts_ctxnum;
183 bs->kernel_cb = get_gseg_base_address_cb(vaddr, ctxnum, 0);
184 bs->kernel_dsr = get_gseg_base_address_ds(vaddr, ctxnum, 0);
185 }
186 downgrade_write(&bs->bs_kgts_sema);
187}
188
189/*
190 * Free all kernel contexts that are not currently in use.
191 * Returns 0 if all freed, else number of inuse context.
192 */
193static int gru_free_kernel_contexts(void)
194{
195 struct gru_blade_state *bs;
196 struct gru_thread_state *kgts;
197 int bid, ret = 0;
198
199 for (bid = 0; bid < GRU_MAX_BLADES; bid++) {
200 bs = gru_base[bid];
201 if (!bs)
202 continue;
203 if (down_write_trylock(&bs->bs_kgts_sema)) {
204 kgts = bs->bs_kgts;
205 if (kgts && kgts->ts_gru)
206 gru_unload_context(kgts, 0);
207 kfree(kgts);
208 bs->bs_kgts = NULL;
209 up_write(&bs->bs_kgts_sema);
210 } else {
211 ret++;
212 }
213 }
214 return ret;
215}
216
217/*
218 * Lock & load the kernel context for the specified blade.
219 */
220static struct gru_blade_state *gru_lock_kernel_context(int blade_id)
221{
222 struct gru_blade_state *bs;
223
224 STAT(lock_kernel_context);
225 bs = gru_base[blade_id];
226
227 down_read(&bs->bs_kgts_sema);
228 if (!bs->bs_kgts || !bs->bs_kgts->ts_gru)
229 gru_load_kernel_context(bs, blade_id);
230 return bs;
231
232}
233
234/*
235 * Unlock the kernel context for the specified blade. Context is not
236 * unloaded but may be stolen before next use.
237 */
238static void gru_unlock_kernel_context(int blade_id)
239{
240 struct gru_blade_state *bs;
241
242 bs = gru_base[blade_id];
243 up_read(&bs->bs_kgts_sema);
244 STAT(unlock_kernel_context);
245}
246
247/*
248 * Reserve & get pointers to the DSR/CBRs reserved for the current cpu.
249 * - returns with preemption disabled
250 */
101static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr) 251static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr)
102{ 252{
103 struct gru_blade_state *bs; 253 struct gru_blade_state *bs;
@@ -105,30 +255,148 @@ static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr)
105 255
106 BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES); 256 BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES);
107 preempt_disable(); 257 preempt_disable();
108 bs = gru_base[uv_numa_blade_id()]; 258 bs = gru_lock_kernel_context(uv_numa_blade_id());
109 lcpu = uv_blade_processor_id(); 259 lcpu = uv_blade_processor_id();
110 *cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE; 260 *cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE;
111 *dsr = bs->kernel_dsr + lcpu * GRU_NUM_KERNEL_DSR_BYTES; 261 *dsr = bs->kernel_dsr + lcpu * GRU_NUM_KERNEL_DSR_BYTES;
112 return 0; 262 return 0;
113} 263}
114 264
265/*
266 * Free the current cpus reserved DSR/CBR resources.
267 */
115static void gru_free_cpu_resources(void *cb, void *dsr) 268static void gru_free_cpu_resources(void *cb, void *dsr)
116{ 269{
270 gru_unlock_kernel_context(uv_numa_blade_id());
117 preempt_enable(); 271 preempt_enable();
118} 272}
119 273
274/*
275 * Reserve GRU resources to be used asynchronously.
276 * Note: currently supports only 1 reservation per blade.
277 *
278 * input:
279 * blade_id - blade on which resources should be reserved
280 * cbrs - number of CBRs
281 * dsr_bytes - number of DSR bytes needed
282 * output:
283 * handle to identify resource
284 * (0 = async resources already reserved)
285 */
286unsigned long gru_reserve_async_resources(int blade_id, int cbrs, int dsr_bytes,
287 struct completion *cmp)
288{
289 struct gru_blade_state *bs;
290 struct gru_thread_state *kgts;
291 int ret = 0;
292
293 bs = gru_base[blade_id];
294
295 down_write(&bs->bs_kgts_sema);
296
297 /* Verify no resources already reserved */
298 if (bs->bs_async_dsr_bytes + bs->bs_async_cbrs)
299 goto done;
300 bs->bs_async_dsr_bytes = dsr_bytes;
301 bs->bs_async_cbrs = cbrs;
302 bs->bs_async_wq = cmp;
303 kgts = bs->bs_kgts;
304
305 /* Resources changed. Unload context if already loaded */
306 if (kgts && kgts->ts_gru)
307 gru_unload_context(kgts, 0);
308 ret = ASYNC_BID_TO_HAN(blade_id);
309
310done:
311 up_write(&bs->bs_kgts_sema);
312 return ret;
313}
314
315/*
316 * Release async resources previously reserved.
317 *
318 * input:
319 * han - handle to identify resources
320 */
321void gru_release_async_resources(unsigned long han)
322{
323 struct gru_blade_state *bs = ASYNC_HAN_TO_BS(han);
324
325 down_write(&bs->bs_kgts_sema);
326 bs->bs_async_dsr_bytes = 0;
327 bs->bs_async_cbrs = 0;
328 bs->bs_async_wq = NULL;
329 up_write(&bs->bs_kgts_sema);
330}
331
332/*
333 * Wait for async GRU instructions to complete.
334 *
335 * input:
336 * han - handle to identify resources
337 */
338void gru_wait_async_cbr(unsigned long han)
339{
340 struct gru_blade_state *bs = ASYNC_HAN_TO_BS(han);
341
342 wait_for_completion(bs->bs_async_wq);
343 mb();
344}
345
346/*
347 * Lock previous reserved async GRU resources
348 *
349 * input:
350 * han - handle to identify resources
351 * output:
352 * cb - pointer to first CBR
353 * dsr - pointer to first DSR
354 */
355void gru_lock_async_resource(unsigned long han, void **cb, void **dsr)
356{
357 struct gru_blade_state *bs = ASYNC_HAN_TO_BS(han);
358 int blade_id = ASYNC_HAN_TO_BID(han);
359 int ncpus;
360
361 gru_lock_kernel_context(blade_id);
362 ncpus = uv_blade_nr_possible_cpus(blade_id);
363 if (cb)
364 *cb = bs->kernel_cb + ncpus * GRU_HANDLE_STRIDE;
365 if (dsr)
366 *dsr = bs->kernel_dsr + ncpus * GRU_NUM_KERNEL_DSR_BYTES;
367}
368
369/*
370 * Unlock previous reserved async GRU resources
371 *
372 * input:
373 * han - handle to identify resources
374 */
375void gru_unlock_async_resource(unsigned long han)
376{
377 int blade_id = ASYNC_HAN_TO_BID(han);
378
379 gru_unlock_kernel_context(blade_id);
380}
381
382/*----------------------------------------------------------------------*/
120int gru_get_cb_exception_detail(void *cb, 383int gru_get_cb_exception_detail(void *cb,
121 struct control_block_extended_exc_detail *excdet) 384 struct control_block_extended_exc_detail *excdet)
122{ 385{
123 struct gru_control_block_extended *cbe; 386 struct gru_control_block_extended *cbe;
387 struct gru_blade_state *bs;
388 int cbrnum;
124 389
125 cbe = get_cbe(GRUBASE(cb), get_cb_number(cb)); 390 bs = KCB_TO_BS(cb);
126 prefetchw(cbe); /* Harmless on hardware, required for emulator */ 391 cbrnum = thread_cbr_number(bs->bs_kgts, get_cb_number(cb));
392 cbe = get_cbe(GRUBASE(cb), cbrnum);
393 gru_flush_cache(cbe); /* CBE not coherent */
127 excdet->opc = cbe->opccpy; 394 excdet->opc = cbe->opccpy;
128 excdet->exopc = cbe->exopccpy; 395 excdet->exopc = cbe->exopccpy;
129 excdet->ecause = cbe->ecause; 396 excdet->ecause = cbe->ecause;
130 excdet->exceptdet0 = cbe->idef1upd; 397 excdet->exceptdet0 = cbe->idef1upd;
131 excdet->exceptdet1 = cbe->idef3upd; 398 excdet->exceptdet1 = cbe->idef3upd;
399 gru_flush_cache(cbe);
132 return 0; 400 return 0;
133} 401}
134 402
@@ -167,13 +435,13 @@ static int gru_retry_exception(void *cb)
167 int retry = EXCEPTION_RETRY_LIMIT; 435 int retry = EXCEPTION_RETRY_LIMIT;
168 436
169 while (1) { 437 while (1) {
170 if (gru_get_cb_message_queue_substatus(cb))
171 break;
172 if (gru_wait_idle_or_exception(gen) == CBS_IDLE) 438 if (gru_wait_idle_or_exception(gen) == CBS_IDLE)
173 return CBS_IDLE; 439 return CBS_IDLE;
174 440 if (gru_get_cb_message_queue_substatus(cb))
441 return CBS_EXCEPTION;
175 gru_get_cb_exception_detail(cb, &excdet); 442 gru_get_cb_exception_detail(cb, &excdet);
176 if (excdet.ecause & ~EXCEPTION_RETRY_BITS) 443 if ((excdet.ecause & ~EXCEPTION_RETRY_BITS) ||
444 (excdet.cbrexecstatus & CBR_EXS_ABORT_OCC))
177 break; 445 break;
178 if (retry-- == 0) 446 if (retry-- == 0)
179 break; 447 break;
@@ -416,6 +684,29 @@ static void send_message_queue_interrupt(struct gru_message_queue_desc *mqd)
416 mqd->interrupt_vector); 684 mqd->interrupt_vector);
417} 685}
418 686
687/*
688 * Handle a PUT failure. Note: if message was a 2-line message, one of the
689 * lines might have successfully have been written. Before sending the
690 * message, "present" must be cleared in BOTH lines to prevent the receiver
691 * from prematurely seeing the full message.
692 */
693static int send_message_put_nacked(void *cb, struct gru_message_queue_desc *mqd,
694 void *mesg, int lines)
695{
696 unsigned long m;
697
698 m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6);
699 if (lines == 2) {
700 gru_vset(cb, m, 0, XTYPE_CL, lines, 1, IMA);
701 if (gru_wait(cb) != CBS_IDLE)
702 return MQE_UNEXPECTED_CB_ERR;
703 }
704 gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
705 if (gru_wait(cb) != CBS_IDLE)
706 return MQE_UNEXPECTED_CB_ERR;
707 send_message_queue_interrupt(mqd);
708 return MQE_OK;
709}
419 710
420/* 711/*
421 * Handle a gru_mesq failure. Some of these failures are software recoverable 712 * Handle a gru_mesq failure. Some of these failures are software recoverable
@@ -425,7 +716,6 @@ static int send_message_failure(void *cb, struct gru_message_queue_desc *mqd,
425 void *mesg, int lines) 716 void *mesg, int lines)
426{ 717{
427 int substatus, ret = 0; 718 int substatus, ret = 0;
428 unsigned long m;
429 719
430 substatus = gru_get_cb_message_queue_substatus(cb); 720 substatus = gru_get_cb_message_queue_substatus(cb);
431 switch (substatus) { 721 switch (substatus) {
@@ -447,14 +737,7 @@ static int send_message_failure(void *cb, struct gru_message_queue_desc *mqd,
447 break; 737 break;
448 case CBSS_PUT_NACKED: 738 case CBSS_PUT_NACKED:
449 STAT(mesq_send_put_nacked); 739 STAT(mesq_send_put_nacked);
450 m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6); 740 ret = send_message_put_nacked(cb, mqd, mesg, lines);
451 gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
452 if (gru_wait(cb) == CBS_IDLE) {
453 ret = MQE_OK;
454 send_message_queue_interrupt(mqd);
455 } else {
456 ret = MQE_UNEXPECTED_CB_ERR;
457 }
458 break; 741 break;
459 default: 742 default:
460 BUG(); 743 BUG();
@@ -597,115 +880,177 @@ EXPORT_SYMBOL_GPL(gru_copy_gpa);
597 880
598/* ------------------- KERNEL QUICKTESTS RUN AT STARTUP ----------------*/ 881/* ------------------- KERNEL QUICKTESTS RUN AT STARTUP ----------------*/
599/* Temp - will delete after we gain confidence in the GRU */ 882/* Temp - will delete after we gain confidence in the GRU */
600static __cacheline_aligned unsigned long word0;
601static __cacheline_aligned unsigned long word1;
602 883
603static int quicktest(struct gru_state *gru) 884static int quicktest0(unsigned long arg)
604{ 885{
886 unsigned long word0;
887 unsigned long word1;
605 void *cb; 888 void *cb;
606 void *ds; 889 void *dsr;
607 unsigned long *p; 890 unsigned long *p;
891 int ret = -EIO;
608 892
609 cb = get_gseg_base_address_cb(gru->gs_gru_base_vaddr, KERNEL_CTXNUM, 0); 893 if (gru_get_cpu_resources(GRU_CACHE_LINE_BYTES, &cb, &dsr))
610 ds = get_gseg_base_address_ds(gru->gs_gru_base_vaddr, KERNEL_CTXNUM, 0); 894 return MQE_BUG_NO_RESOURCES;
611 p = ds; 895 p = dsr;
612 word0 = MAGIC; 896 word0 = MAGIC;
897 word1 = 0;
613 898
614 gru_vload(cb, uv_gpa(&word0), 0, XTYPE_DW, 1, 1, IMA); 899 gru_vload(cb, uv_gpa(&word0), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
615 if (gru_wait(cb) != CBS_IDLE) 900 if (gru_wait(cb) != CBS_IDLE) {
616 BUG(); 901 printk(KERN_DEBUG "GRU quicktest0: CBR failure 1\n");
902 goto done;
903 }
617 904
618 if (*(unsigned long *)ds != MAGIC) 905 if (*p != MAGIC) {
619 BUG(); 906 printk(KERN_DEBUG "GRU: quicktest0 bad magic 0x%lx\n", *p);
620 gru_vstore(cb, uv_gpa(&word1), 0, XTYPE_DW, 1, 1, IMA); 907 goto done;
621 if (gru_wait(cb) != CBS_IDLE) 908 }
622 BUG(); 909 gru_vstore(cb, uv_gpa(&word1), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
910 if (gru_wait(cb) != CBS_IDLE) {
911 printk(KERN_DEBUG "GRU quicktest0: CBR failure 2\n");
912 goto done;
913 }
623 914
624 if (word0 != word1 || word0 != MAGIC) { 915 if (word0 != word1 || word1 != MAGIC) {
625 printk 916 printk(KERN_DEBUG
626 ("GRU quicktest err: gid %d, found 0x%lx, expected 0x%lx\n", 917 "GRU quicktest0 err: found 0x%lx, expected 0x%lx\n",
627 gru->gs_gid, word1, MAGIC); 918 word1, MAGIC);
628 BUG(); /* ZZZ should not be fatal */ 919 goto done;
629 } 920 }
921 ret = 0;
630 922
631 return 0; 923done:
924 gru_free_cpu_resources(cb, dsr);
925 return ret;
632} 926}
633 927
928#define ALIGNUP(p, q) ((void *)(((unsigned long)(p) + (q) - 1) & ~(q - 1)))
634 929
635int gru_kservices_init(struct gru_state *gru) 930static int quicktest1(unsigned long arg)
636{ 931{
637 struct gru_blade_state *bs; 932 struct gru_message_queue_desc mqd;
638 struct gru_context_configuration_handle *cch; 933 void *p, *mq;
639 unsigned long cbr_map, dsr_map; 934 unsigned long *dw;
640 int err, num, cpus_possible; 935 int i, ret = -EIO;
641 936 char mes[GRU_CACHE_LINE_BYTES], *m;
642 /* 937
643 * Currently, resources are reserved ONLY on the second chiplet 938 /* Need 1K cacheline aligned that does not cross page boundary */
644 * on each blade. This leaves ALL resources on chiplet 0 available 939 p = kmalloc(4096, 0);
645 * for user code. 940 mq = ALIGNUP(p, 1024);
646 */ 941 memset(mes, 0xee, sizeof(mes));
647 bs = gru->gs_blade; 942 dw = mq;
648 if (gru != &bs->bs_grus[1]) 943
649 return 0; 944 gru_create_message_queue(&mqd, mq, 8 * GRU_CACHE_LINE_BYTES, 0, 0, 0);
650 945 for (i = 0; i < 6; i++) {
651 cpus_possible = uv_blade_nr_possible_cpus(gru->gs_blade_id); 946 mes[8] = i;
652 947 do {
653 num = GRU_NUM_KERNEL_CBR * cpus_possible; 948 ret = gru_send_message_gpa(&mqd, mes, sizeof(mes));
654 cbr_map = gru_reserve_cb_resources(gru, GRU_CB_COUNT_TO_AU(num), NULL); 949 } while (ret == MQE_CONGESTION);
655 gru->gs_reserved_cbrs += num; 950 if (ret)
656 951 break;
657 num = GRU_NUM_KERNEL_DSR_BYTES * cpus_possible;
658 dsr_map = gru_reserve_ds_resources(gru, GRU_DS_BYTES_TO_AU(num), NULL);
659 gru->gs_reserved_dsr_bytes += num;
660
661 gru->gs_active_contexts++;
662 __set_bit(KERNEL_CTXNUM, &gru->gs_context_map);
663 cch = get_cch(gru->gs_gru_base_vaddr, KERNEL_CTXNUM);
664
665 bs->kernel_cb = get_gseg_base_address_cb(gru->gs_gru_base_vaddr,
666 KERNEL_CTXNUM, 0);
667 bs->kernel_dsr = get_gseg_base_address_ds(gru->gs_gru_base_vaddr,
668 KERNEL_CTXNUM, 0);
669
670 lock_cch_handle(cch);
671 cch->tfm_fault_bit_enable = 0;
672 cch->tlb_int_enable = 0;
673 cch->tfm_done_bit_enable = 0;
674 cch->unmap_enable = 1;
675 err = cch_allocate(cch, 0, 0, cbr_map, dsr_map);
676 if (err) {
677 gru_dbg(grudev,
678 "Unable to allocate kernel CCH: gid %d, err %d\n",
679 gru->gs_gid, err);
680 BUG();
681 } 952 }
682 if (cch_start(cch)) { 953 if (ret != MQE_QUEUE_FULL || i != 4)
683 gru_dbg(grudev, "Unable to start kernel CCH: gid %d, err %d\n", 954 goto done;
684 gru->gs_gid, err); 955
685 BUG(); 956 for (i = 0; i < 6; i++) {
957 m = gru_get_next_message(&mqd);
958 if (!m || m[8] != i)
959 break;
960 gru_free_message(&mqd, m);
686 } 961 }
687 unlock_cch_handle(cch); 962 ret = (i == 4) ? 0 : -EIO;
688 963
689 if (gru_options & GRU_QUICKLOOK) 964done:
690 quicktest(gru); 965 kfree(p);
691 return 0; 966 return ret;
692} 967}
693 968
694void gru_kservices_exit(struct gru_state *gru) 969static int quicktest2(unsigned long arg)
695{ 970{
696 struct gru_context_configuration_handle *cch; 971 static DECLARE_COMPLETION(cmp);
697 struct gru_blade_state *bs; 972 unsigned long han;
973 int blade_id = 0;
974 int numcb = 4;
975 int ret = 0;
976 unsigned long *buf;
977 void *cb0, *cb;
978 int i, k, istatus, bytes;
979
980 bytes = numcb * 4 * 8;
981 buf = kmalloc(bytes, GFP_KERNEL);
982 if (!buf)
983 return -ENOMEM;
984
985 ret = -EBUSY;
986 han = gru_reserve_async_resources(blade_id, numcb, 0, &cmp);
987 if (!han)
988 goto done;
989
990 gru_lock_async_resource(han, &cb0, NULL);
991 memset(buf, 0xee, bytes);
992 for (i = 0; i < numcb; i++)
993 gru_vset(cb0 + i * GRU_HANDLE_STRIDE, uv_gpa(&buf[i * 4]), 0,
994 XTYPE_DW, 4, 1, IMA_INTERRUPT);
995
996 ret = 0;
997 for (k = 0; k < numcb; k++) {
998 gru_wait_async_cbr(han);
999 for (i = 0; i < numcb; i++) {
1000 cb = cb0 + i * GRU_HANDLE_STRIDE;
1001 istatus = gru_check_status(cb);
1002 if (istatus == CBS_ACTIVE)
1003 continue;
1004 if (istatus == CBS_EXCEPTION)
1005 ret = -EFAULT;
1006 else if (buf[i] || buf[i + 1] || buf[i + 2] ||
1007 buf[i + 3])
1008 ret = -EIO;
1009 }
1010 }
1011 BUG_ON(cmp.done);
698 1012
699 bs = gru->gs_blade; 1013 gru_unlock_async_resource(han);
700 if (gru != &bs->bs_grus[1]) 1014 gru_release_async_resources(han);
701 return; 1015done:
1016 kfree(buf);
1017 return ret;
1018}
702 1019
703 cch = get_cch(gru->gs_gru_base_vaddr, KERNEL_CTXNUM); 1020/*
704 lock_cch_handle(cch); 1021 * Debugging only. User hook for various kernel tests
705 if (cch_interrupt_sync(cch)) 1022 * of driver & gru.
706 BUG(); 1023 */
707 if (cch_deallocate(cch)) 1024int gru_ktest(unsigned long arg)
1025{
1026 int ret = -EINVAL;
1027
1028 switch (arg & 0xff) {
1029 case 0:
1030 ret = quicktest0(arg);
1031 break;
1032 case 1:
1033 ret = quicktest1(arg);
1034 break;
1035 case 2:
1036 ret = quicktest2(arg);
1037 break;
1038 case 99:
1039 ret = gru_free_kernel_contexts();
1040 break;
1041 }
1042 return ret;
1043
1044}
1045
1046int gru_kservices_init(void)
1047{
1048 return 0;
1049}
1050
1051void gru_kservices_exit(void)
1052{
1053 if (gru_free_kernel_contexts())
708 BUG(); 1054 BUG();
709 unlock_cch_handle(cch);
710} 1055}
711 1056
diff --git a/drivers/misc/sgi-gru/grukservices.h b/drivers/misc/sgi-gru/grukservices.h
index 747ed315d56f..d60d34bca44d 100644
--- a/drivers/misc/sgi-gru/grukservices.h
+++ b/drivers/misc/sgi-gru/grukservices.h
@@ -146,4 +146,55 @@ extern void *gru_get_next_message(struct gru_message_queue_desc *mqd);
146extern int gru_copy_gpa(unsigned long dest_gpa, unsigned long src_gpa, 146extern int gru_copy_gpa(unsigned long dest_gpa, unsigned long src_gpa,
147 unsigned int bytes); 147 unsigned int bytes);
148 148
149/*
150 * Reserve GRU resources to be used asynchronously.
151 *
152 * input:
153 * blade_id - blade on which resources should be reserved
154 * cbrs - number of CBRs
155 * dsr_bytes - number of DSR bytes needed
156 * cmp - completion structure for waiting for
157 * async completions
158 * output:
159 * handle to identify resource
160 * (0 = no resources)
161 */
162extern unsigned long gru_reserve_async_resources(int blade_id, int cbrs, int dsr_bytes,
163 struct completion *cmp);
164
165/*
166 * Release async resources previously reserved.
167 *
168 * input:
169 * han - handle to identify resources
170 */
171extern void gru_release_async_resources(unsigned long han);
172
173/*
174 * Wait for async GRU instructions to complete.
175 *
176 * input:
177 * han - handle to identify resources
178 */
179extern void gru_wait_async_cbr(unsigned long han);
180
181/*
182 * Lock previous reserved async GRU resources
183 *
184 * input:
185 * han - handle to identify resources
186 * output:
187 * cb - pointer to first CBR
188 * dsr - pointer to first DSR
189 */
190extern void gru_lock_async_resource(unsigned long han, void **cb, void **dsr);
191
192/*
193 * Unlock previous reserved async GRU resources
194 *
195 * input:
196 * han - handle to identify resources
197 */
198extern void gru_unlock_async_resource(unsigned long han);
199
149#endif /* __GRU_KSERVICES_H_ */ 200#endif /* __GRU_KSERVICES_H_ */
diff --git a/drivers/misc/sgi-gru/grulib.h b/drivers/misc/sgi-gru/grulib.h
index e56e196a6998..889bc442a3e8 100644
--- a/drivers/misc/sgi-gru/grulib.h
+++ b/drivers/misc/sgi-gru/grulib.h
@@ -32,8 +32,8 @@
32/* Set Number of Request Blocks */ 32/* Set Number of Request Blocks */
33#define GRU_CREATE_CONTEXT _IOWR(GRU_IOCTL_NUM, 1, void *) 33#define GRU_CREATE_CONTEXT _IOWR(GRU_IOCTL_NUM, 1, void *)
34 34
35/* Register task as using the slice */ 35/* Set Context Options */
36#define GRU_SET_TASK_SLICE _IOWR(GRU_IOCTL_NUM, 5, void *) 36#define GRU_SET_CONTEXT_OPTION _IOWR(GRU_IOCTL_NUM, 4, void *)
37 37
38/* Fetch exception detail */ 38/* Fetch exception detail */
39#define GRU_USER_GET_EXCEPTION_DETAIL _IOWR(GRU_IOCTL_NUM, 6, void *) 39#define GRU_USER_GET_EXCEPTION_DETAIL _IOWR(GRU_IOCTL_NUM, 6, void *)
@@ -44,8 +44,11 @@
44/* For user unload context */ 44/* For user unload context */
45#define GRU_USER_UNLOAD_CONTEXT _IOWR(GRU_IOCTL_NUM, 9, void *) 45#define GRU_USER_UNLOAD_CONTEXT _IOWR(GRU_IOCTL_NUM, 9, void *)
46 46
47/* For fetching GRU chiplet status */ 47/* For dumpping GRU chiplet state */
48#define GRU_GET_CHIPLET_STATUS _IOWR(GRU_IOCTL_NUM, 10, void *) 48#define GRU_DUMP_CHIPLET_STATE _IOWR(GRU_IOCTL_NUM, 11, void *)
49
50/* For getting gseg statistics */
51#define GRU_GET_GSEG_STATISTICS _IOWR(GRU_IOCTL_NUM, 12, void *)
49 52
50/* For user TLB flushing (primarily for tests) */ 53/* For user TLB flushing (primarily for tests) */
51#define GRU_USER_FLUSH_TLB _IOWR(GRU_IOCTL_NUM, 50, void *) 54#define GRU_USER_FLUSH_TLB _IOWR(GRU_IOCTL_NUM, 50, void *)
@@ -53,8 +56,26 @@
53/* Get some config options (primarily for tests & emulator) */ 56/* Get some config options (primarily for tests & emulator) */
54#define GRU_GET_CONFIG_INFO _IOWR(GRU_IOCTL_NUM, 51, void *) 57#define GRU_GET_CONFIG_INFO _IOWR(GRU_IOCTL_NUM, 51, void *)
55 58
59/* Various kernel self-tests */
60#define GRU_KTEST _IOWR(GRU_IOCTL_NUM, 52, void *)
61
56#define CONTEXT_WINDOW_BYTES(th) (GRU_GSEG_PAGESIZE * (th)) 62#define CONTEXT_WINDOW_BYTES(th) (GRU_GSEG_PAGESIZE * (th))
57#define THREAD_POINTER(p, th) (p + GRU_GSEG_PAGESIZE * (th)) 63#define THREAD_POINTER(p, th) (p + GRU_GSEG_PAGESIZE * (th))
64#define GSEG_START(cb) ((void *)((unsigned long)(cb) & ~(GRU_GSEG_PAGESIZE - 1)))
65
66/*
67 * Statictics kept on a per-GTS basis.
68 */
69struct gts_statistics {
70 unsigned long fmm_tlbdropin;
71 unsigned long upm_tlbdropin;
72 unsigned long context_stolen;
73};
74
75struct gru_get_gseg_statistics_req {
76 unsigned long gseg;
77 struct gts_statistics stats;
78};
58 79
59/* 80/*
60 * Structure used to pass TLB flush parameters to the driver 81 * Structure used to pass TLB flush parameters to the driver
@@ -75,6 +96,16 @@ struct gru_unload_context_req {
75}; 96};
76 97
77/* 98/*
99 * Structure used to set context options
100 */
101enum {sco_gseg_owner, sco_cch_req_slice};
102struct gru_set_context_option_req {
103 unsigned long gseg;
104 int op;
105 unsigned long val1;
106};
107
108/*
78 * Structure used to pass TLB flush parameters to the driver 109 * Structure used to pass TLB flush parameters to the driver
79 */ 110 */
80struct gru_flush_tlb_req { 111struct gru_flush_tlb_req {
@@ -84,6 +115,36 @@ struct gru_flush_tlb_req {
84}; 115};
85 116
86/* 117/*
118 * Structure used to pass TLB flush parameters to the driver
119 */
120enum {dcs_pid, dcs_gid};
121struct gru_dump_chiplet_state_req {
122 unsigned int op;
123 unsigned int gid;
124 int ctxnum;
125 char data_opt;
126 char lock_cch;
127 pid_t pid;
128 void *buf;
129 size_t buflen;
130 /* ---- output --- */
131 unsigned int num_contexts;
132};
133
134#define GRU_DUMP_MAGIC 0x3474ab6c
135struct gru_dump_context_header {
136 unsigned int magic;
137 unsigned int gid;
138 unsigned char ctxnum;
139 unsigned char cbrcnt;
140 unsigned char dsrcnt;
141 pid_t pid;
142 unsigned long vaddr;
143 int cch_locked;
144 unsigned long data[0];
145};
146
147/*
87 * GRU configuration info (temp - for testing) 148 * GRU configuration info (temp - for testing)
88 */ 149 */
89struct gru_config_info { 150struct gru_config_info {
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index ec3f7a17d221..3bc643dad606 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -3,11 +3,21 @@
3 * 3 *
4 * DRIVER TABLE MANAGER + GRU CONTEXT LOAD/UNLOAD 4 * DRIVER TABLE MANAGER + GRU CONTEXT LOAD/UNLOAD
5 * 5 *
6 * This file is subject to the terms and conditions of the GNU General Public 6 * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 * 7 *
10 * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11 */ 21 */
12 22
13#include <linux/kernel.h> 23#include <linux/kernel.h>
@@ -96,7 +106,7 @@ static int gru_reset_asid_limit(struct gru_state *gru, int asid)
96 gid = gru->gs_gid; 106 gid = gru->gs_gid;
97again: 107again:
98 for (i = 0; i < GRU_NUM_CCH; i++) { 108 for (i = 0; i < GRU_NUM_CCH; i++) {
99 if (!gru->gs_gts[i]) 109 if (!gru->gs_gts[i] || is_kernel_context(gru->gs_gts[i]))
100 continue; 110 continue;
101 inuse_asid = gru->gs_gts[i]->ts_gms->ms_asids[gid].mt_asid; 111 inuse_asid = gru->gs_gts[i]->ts_gms->ms_asids[gid].mt_asid;
102 gru_dbg(grudev, "gid %d, gts %p, gms %p, inuse 0x%x, cxt %d\n", 112 gru_dbg(grudev, "gid %d, gts %p, gms %p, inuse 0x%x, cxt %d\n",
@@ -150,7 +160,7 @@ static unsigned long reserve_resources(unsigned long *p, int n, int mmax,
150 unsigned long bits = 0; 160 unsigned long bits = 0;
151 int i; 161 int i;
152 162
153 do { 163 while (n--) {
154 i = find_first_bit(p, mmax); 164 i = find_first_bit(p, mmax);
155 if (i == mmax) 165 if (i == mmax)
156 BUG(); 166 BUG();
@@ -158,7 +168,7 @@ static unsigned long reserve_resources(unsigned long *p, int n, int mmax,
158 __set_bit(i, &bits); 168 __set_bit(i, &bits);
159 if (idx) 169 if (idx)
160 *idx++ = i; 170 *idx++ = i;
161 } while (--n); 171 }
162 return bits; 172 return bits;
163} 173}
164 174
@@ -299,38 +309,39 @@ static struct gru_thread_state *gru_find_current_gts_nolock(struct gru_vma_data
299/* 309/*
300 * Allocate a thread state structure. 310 * Allocate a thread state structure.
301 */ 311 */
302static struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, 312struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
303 struct gru_vma_data *vdata, 313 int cbr_au_count, int dsr_au_count, int options, int tsid)
304 int tsid)
305{ 314{
306 struct gru_thread_state *gts; 315 struct gru_thread_state *gts;
307 int bytes; 316 int bytes;
308 317
309 bytes = DSR_BYTES(vdata->vd_dsr_au_count) + 318 bytes = DSR_BYTES(dsr_au_count) + CBR_BYTES(cbr_au_count);
310 CBR_BYTES(vdata->vd_cbr_au_count);
311 bytes += sizeof(struct gru_thread_state); 319 bytes += sizeof(struct gru_thread_state);
312 gts = kzalloc(bytes, GFP_KERNEL); 320 gts = kmalloc(bytes, GFP_KERNEL);
313 if (!gts) 321 if (!gts)
314 return NULL; 322 return NULL;
315 323
316 STAT(gts_alloc); 324 STAT(gts_alloc);
325 memset(gts, 0, sizeof(struct gru_thread_state)); /* zero out header */
317 atomic_set(&gts->ts_refcnt, 1); 326 atomic_set(&gts->ts_refcnt, 1);
318 mutex_init(&gts->ts_ctxlock); 327 mutex_init(&gts->ts_ctxlock);
319 gts->ts_cbr_au_count = vdata->vd_cbr_au_count; 328 gts->ts_cbr_au_count = cbr_au_count;
320 gts->ts_dsr_au_count = vdata->vd_dsr_au_count; 329 gts->ts_dsr_au_count = dsr_au_count;
321 gts->ts_user_options = vdata->vd_user_options; 330 gts->ts_user_options = options;
322 gts->ts_tsid = tsid; 331 gts->ts_tsid = tsid;
323 gts->ts_user_options = vdata->vd_user_options;
324 gts->ts_ctxnum = NULLCTX; 332 gts->ts_ctxnum = NULLCTX;
325 gts->ts_mm = current->mm;
326 gts->ts_vma = vma;
327 gts->ts_tlb_int_select = -1; 333 gts->ts_tlb_int_select = -1;
328 gts->ts_gms = gru_register_mmu_notifier(); 334 gts->ts_cch_req_slice = -1;
329 gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT); 335 gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT);
330 if (!gts->ts_gms) 336 if (vma) {
331 goto err; 337 gts->ts_mm = current->mm;
338 gts->ts_vma = vma;
339 gts->ts_gms = gru_register_mmu_notifier();
340 if (!gts->ts_gms)
341 goto err;
342 }
332 343
333 gru_dbg(grudev, "alloc vdata %p, new gts %p\n", vdata, gts); 344 gru_dbg(grudev, "alloc gts %p\n", gts);
334 return gts; 345 return gts;
335 346
336err: 347err:
@@ -381,7 +392,8 @@ struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct *vma,
381 struct gru_vma_data *vdata = vma->vm_private_data; 392 struct gru_vma_data *vdata = vma->vm_private_data;
382 struct gru_thread_state *gts, *ngts; 393 struct gru_thread_state *gts, *ngts;
383 394
384 gts = gru_alloc_gts(vma, vdata, tsid); 395 gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count, vdata->vd_dsr_au_count,
396 vdata->vd_user_options, tsid);
385 if (!gts) 397 if (!gts)
386 return NULL; 398 return NULL;
387 399
@@ -458,7 +470,8 @@ static void gru_prefetch_context(void *gseg, void *cb, void *cbe,
458} 470}
459 471
460static void gru_load_context_data(void *save, void *grubase, int ctxnum, 472static void gru_load_context_data(void *save, void *grubase, int ctxnum,
461 unsigned long cbrmap, unsigned long dsrmap) 473 unsigned long cbrmap, unsigned long dsrmap,
474 int data_valid)
462{ 475{
463 void *gseg, *cb, *cbe; 476 void *gseg, *cb, *cbe;
464 unsigned long length; 477 unsigned long length;
@@ -471,12 +484,22 @@ static void gru_load_context_data(void *save, void *grubase, int ctxnum,
471 gru_prefetch_context(gseg, cb, cbe, cbrmap, length); 484 gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
472 485
473 for_each_cbr_in_allocation_map(i, &cbrmap, scr) { 486 for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
474 save += gru_copy_handle(cb, save); 487 if (data_valid) {
475 save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save); 488 save += gru_copy_handle(cb, save);
489 save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE,
490 save);
491 } else {
492 memset(cb, 0, GRU_CACHE_LINE_BYTES);
493 memset(cbe + i * GRU_HANDLE_STRIDE, 0,
494 GRU_CACHE_LINE_BYTES);
495 }
476 cb += GRU_HANDLE_STRIDE; 496 cb += GRU_HANDLE_STRIDE;
477 } 497 }
478 498
479 memcpy(gseg + GRU_DS_BASE, save, length); 499 if (data_valid)
500 memcpy(gseg + GRU_DS_BASE, save, length);
501 else
502 memset(gseg + GRU_DS_BASE, 0, length);
480} 503}
481 504
482static void gru_unload_context_data(void *save, void *grubase, int ctxnum, 505static void gru_unload_context_data(void *save, void *grubase, int ctxnum,
@@ -506,7 +529,8 @@ void gru_unload_context(struct gru_thread_state *gts, int savestate)
506 struct gru_context_configuration_handle *cch; 529 struct gru_context_configuration_handle *cch;
507 int ctxnum = gts->ts_ctxnum; 530 int ctxnum = gts->ts_ctxnum;
508 531
509 zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE); 532 if (!is_kernel_context(gts))
533 zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
510 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum); 534 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
511 535
512 gru_dbg(grudev, "gts %p\n", gts); 536 gru_dbg(grudev, "gts %p\n", gts);
@@ -514,11 +538,14 @@ void gru_unload_context(struct gru_thread_state *gts, int savestate)
514 if (cch_interrupt_sync(cch)) 538 if (cch_interrupt_sync(cch))
515 BUG(); 539 BUG();
516 540
517 gru_unload_mm_tracker(gru, gts); 541 if (!is_kernel_context(gts))
518 if (savestate) 542 gru_unload_mm_tracker(gru, gts);
543 if (savestate) {
519 gru_unload_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr, 544 gru_unload_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr,
520 ctxnum, gts->ts_cbr_map, 545 ctxnum, gts->ts_cbr_map,
521 gts->ts_dsr_map); 546 gts->ts_dsr_map);
547 gts->ts_data_valid = 1;
548 }
522 549
523 if (cch_deallocate(cch)) 550 if (cch_deallocate(cch))
524 BUG(); 551 BUG();
@@ -526,24 +553,22 @@ void gru_unload_context(struct gru_thread_state *gts, int savestate)
526 unlock_cch_handle(cch); 553 unlock_cch_handle(cch);
527 554
528 gru_free_gru_context(gts); 555 gru_free_gru_context(gts);
529 STAT(unload_context);
530} 556}
531 557
532/* 558/*
533 * Load a GRU context by copying it from the thread data structure in memory 559 * Load a GRU context by copying it from the thread data structure in memory
534 * to the GRU. 560 * to the GRU.
535 */ 561 */
536static void gru_load_context(struct gru_thread_state *gts) 562void gru_load_context(struct gru_thread_state *gts)
537{ 563{
538 struct gru_state *gru = gts->ts_gru; 564 struct gru_state *gru = gts->ts_gru;
539 struct gru_context_configuration_handle *cch; 565 struct gru_context_configuration_handle *cch;
540 int err, asid, ctxnum = gts->ts_ctxnum; 566 int i, err, asid, ctxnum = gts->ts_ctxnum;
541 567
542 gru_dbg(grudev, "gts %p\n", gts); 568 gru_dbg(grudev, "gts %p\n", gts);
543 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum); 569 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
544 570
545 lock_cch_handle(cch); 571 lock_cch_handle(cch);
546 asid = gru_load_mm_tracker(gru, gts);
547 cch->tfm_fault_bit_enable = 572 cch->tfm_fault_bit_enable =
548 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL 573 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
549 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR); 574 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
@@ -552,9 +577,32 @@ static void gru_load_context(struct gru_thread_state *gts)
552 gts->ts_tlb_int_select = gru_cpu_fault_map_id(); 577 gts->ts_tlb_int_select = gru_cpu_fault_map_id();
553 cch->tlb_int_select = gts->ts_tlb_int_select; 578 cch->tlb_int_select = gts->ts_tlb_int_select;
554 } 579 }
580 if (gts->ts_cch_req_slice >= 0) {
581 cch->req_slice_set_enable = 1;
582 cch->req_slice = gts->ts_cch_req_slice;
583 } else {
584 cch->req_slice_set_enable =0;
585 }
555 cch->tfm_done_bit_enable = 0; 586 cch->tfm_done_bit_enable = 0;
556 err = cch_allocate(cch, asid, gts->ts_sizeavail, gts->ts_cbr_map, 587 cch->dsr_allocation_map = gts->ts_dsr_map;
557 gts->ts_dsr_map); 588 cch->cbr_allocation_map = gts->ts_cbr_map;
589
590 if (is_kernel_context(gts)) {
591 cch->unmap_enable = 1;
592 cch->tfm_done_bit_enable = 1;
593 cch->cb_int_enable = 1;
594 } else {
595 cch->unmap_enable = 0;
596 cch->tfm_done_bit_enable = 0;
597 cch->cb_int_enable = 0;
598 asid = gru_load_mm_tracker(gru, gts);
599 for (i = 0; i < 8; i++) {
600 cch->asid[i] = asid + i;
601 cch->sizeavail[i] = gts->ts_sizeavail;
602 }
603 }
604
605 err = cch_allocate(cch);
558 if (err) { 606 if (err) {
559 gru_dbg(grudev, 607 gru_dbg(grudev,
560 "err %d: cch %p, gts %p, cbr 0x%lx, dsr 0x%lx\n", 608 "err %d: cch %p, gts %p, cbr 0x%lx, dsr 0x%lx\n",
@@ -563,13 +611,11 @@ static void gru_load_context(struct gru_thread_state *gts)
563 } 611 }
564 612
565 gru_load_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr, ctxnum, 613 gru_load_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr, ctxnum,
566 gts->ts_cbr_map, gts->ts_dsr_map); 614 gts->ts_cbr_map, gts->ts_dsr_map, gts->ts_data_valid);
567 615
568 if (cch_start(cch)) 616 if (cch_start(cch))
569 BUG(); 617 BUG();
570 unlock_cch_handle(cch); 618 unlock_cch_handle(cch);
571
572 STAT(load_context);
573} 619}
574 620
575/* 621/*
@@ -599,6 +645,9 @@ int gru_update_cch(struct gru_thread_state *gts, int force_unload)
599 cch->sizeavail[i] = gts->ts_sizeavail; 645 cch->sizeavail[i] = gts->ts_sizeavail;
600 gts->ts_tlb_int_select = gru_cpu_fault_map_id(); 646 gts->ts_tlb_int_select = gru_cpu_fault_map_id();
601 cch->tlb_int_select = gru_cpu_fault_map_id(); 647 cch->tlb_int_select = gru_cpu_fault_map_id();
648 cch->tfm_fault_bit_enable =
649 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
650 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
602 } else { 651 } else {
603 for (i = 0; i < 8; i++) 652 for (i = 0; i < 8; i++)
604 cch->asid[i] = 0; 653 cch->asid[i] = 0;
@@ -642,7 +691,28 @@ static int gru_retarget_intr(struct gru_thread_state *gts)
642#define next_gru(b, g) (((g) < &(b)->bs_grus[GRU_CHIPLETS_PER_BLADE - 1]) ? \ 691#define next_gru(b, g) (((g) < &(b)->bs_grus[GRU_CHIPLETS_PER_BLADE - 1]) ? \
643 ((g)+1) : &(b)->bs_grus[0]) 692 ((g)+1) : &(b)->bs_grus[0])
644 693
645static void gru_steal_context(struct gru_thread_state *gts) 694static int is_gts_stealable(struct gru_thread_state *gts,
695 struct gru_blade_state *bs)
696{
697 if (is_kernel_context(gts))
698 return down_write_trylock(&bs->bs_kgts_sema);
699 else
700 return mutex_trylock(&gts->ts_ctxlock);
701}
702
703static void gts_stolen(struct gru_thread_state *gts,
704 struct gru_blade_state *bs)
705{
706 if (is_kernel_context(gts)) {
707 up_write(&bs->bs_kgts_sema);
708 STAT(steal_kernel_context);
709 } else {
710 mutex_unlock(&gts->ts_ctxlock);
711 STAT(steal_user_context);
712 }
713}
714
715void gru_steal_context(struct gru_thread_state *gts, int blade_id)
646{ 716{
647 struct gru_blade_state *blade; 717 struct gru_blade_state *blade;
648 struct gru_state *gru, *gru0; 718 struct gru_state *gru, *gru0;
@@ -652,8 +722,7 @@ static void gru_steal_context(struct gru_thread_state *gts)
652 cbr = gts->ts_cbr_au_count; 722 cbr = gts->ts_cbr_au_count;
653 dsr = gts->ts_dsr_au_count; 723 dsr = gts->ts_dsr_au_count;
654 724
655 preempt_disable(); 725 blade = gru_base[blade_id];
656 blade = gru_base[uv_numa_blade_id()];
657 spin_lock(&blade->bs_lock); 726 spin_lock(&blade->bs_lock);
658 727
659 ctxnum = next_ctxnum(blade->bs_lru_ctxnum); 728 ctxnum = next_ctxnum(blade->bs_lru_ctxnum);
@@ -676,7 +745,7 @@ static void gru_steal_context(struct gru_thread_state *gts)
676 * success are high. If trylock fails, try to steal a 745 * success are high. If trylock fails, try to steal a
677 * different GSEG. 746 * different GSEG.
678 */ 747 */
679 if (ngts && mutex_trylock(&ngts->ts_ctxlock)) 748 if (ngts && is_gts_stealable(ngts, blade))
680 break; 749 break;
681 ngts = NULL; 750 ngts = NULL;
682 flag = 1; 751 flag = 1;
@@ -690,13 +759,12 @@ static void gru_steal_context(struct gru_thread_state *gts)
690 blade->bs_lru_gru = gru; 759 blade->bs_lru_gru = gru;
691 blade->bs_lru_ctxnum = ctxnum; 760 blade->bs_lru_ctxnum = ctxnum;
692 spin_unlock(&blade->bs_lock); 761 spin_unlock(&blade->bs_lock);
693 preempt_enable();
694 762
695 if (ngts) { 763 if (ngts) {
696 STAT(steal_context); 764 gts->ustats.context_stolen++;
697 ngts->ts_steal_jiffies = jiffies; 765 ngts->ts_steal_jiffies = jiffies;
698 gru_unload_context(ngts, 1); 766 gru_unload_context(ngts, is_kernel_context(ngts) ? 0 : 1);
699 mutex_unlock(&ngts->ts_ctxlock); 767 gts_stolen(ngts, blade);
700 } else { 768 } else {
701 STAT(steal_context_failed); 769 STAT(steal_context_failed);
702 } 770 }
@@ -710,17 +778,17 @@ static void gru_steal_context(struct gru_thread_state *gts)
710/* 778/*
711 * Scan the GRUs on the local blade & assign a GRU context. 779 * Scan the GRUs on the local blade & assign a GRU context.
712 */ 780 */
713static struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts) 781struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts,
782 int blade)
714{ 783{
715 struct gru_state *gru, *grux; 784 struct gru_state *gru, *grux;
716 int i, max_active_contexts; 785 int i, max_active_contexts;
717 786
718 preempt_disable();
719 787
720again: 788again:
721 gru = NULL; 789 gru = NULL;
722 max_active_contexts = GRU_NUM_CCH; 790 max_active_contexts = GRU_NUM_CCH;
723 for_each_gru_on_blade(grux, uv_numa_blade_id(), i) { 791 for_each_gru_on_blade(grux, blade, i) {
724 if (check_gru_resources(grux, gts->ts_cbr_au_count, 792 if (check_gru_resources(grux, gts->ts_cbr_au_count,
725 gts->ts_dsr_au_count, 793 gts->ts_dsr_au_count,
726 max_active_contexts)) { 794 max_active_contexts)) {
@@ -760,7 +828,6 @@ again:
760 STAT(assign_context_failed); 828 STAT(assign_context_failed);
761 } 829 }
762 830
763 preempt_enable();
764 return gru; 831 return gru;
765} 832}
766 833
@@ -775,6 +842,7 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
775{ 842{
776 struct gru_thread_state *gts; 843 struct gru_thread_state *gts;
777 unsigned long paddr, vaddr; 844 unsigned long paddr, vaddr;
845 int blade_id;
778 846
779 vaddr = (unsigned long)vmf->virtual_address; 847 vaddr = (unsigned long)vmf->virtual_address;
780 gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n", 848 gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n",
@@ -789,8 +857,10 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
789again: 857again:
790 mutex_lock(&gts->ts_ctxlock); 858 mutex_lock(&gts->ts_ctxlock);
791 preempt_disable(); 859 preempt_disable();
860 blade_id = uv_numa_blade_id();
861
792 if (gts->ts_gru) { 862 if (gts->ts_gru) {
793 if (gts->ts_gru->gs_blade_id != uv_numa_blade_id()) { 863 if (gts->ts_gru->gs_blade_id != blade_id) {
794 STAT(migrated_nopfn_unload); 864 STAT(migrated_nopfn_unload);
795 gru_unload_context(gts, 1); 865 gru_unload_context(gts, 1);
796 } else { 866 } else {
@@ -800,12 +870,15 @@ again:
800 } 870 }
801 871
802 if (!gts->ts_gru) { 872 if (!gts->ts_gru) {
803 if (!gru_assign_gru_context(gts)) { 873 STAT(load_user_context);
804 mutex_unlock(&gts->ts_ctxlock); 874 if (!gru_assign_gru_context(gts, blade_id)) {
805 preempt_enable(); 875 preempt_enable();
876 mutex_unlock(&gts->ts_ctxlock);
877 set_current_state(TASK_INTERRUPTIBLE);
806 schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */ 878 schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */
879 blade_id = uv_numa_blade_id();
807 if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies) 880 if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies)
808 gru_steal_context(gts); 881 gru_steal_context(gts, blade_id);
809 goto again; 882 goto again;
810 } 883 }
811 gru_load_context(gts); 884 gru_load_context(gts);
@@ -815,8 +888,8 @@ again:
815 vma->vm_page_prot); 888 vma->vm_page_prot);
816 } 889 }
817 890
818 mutex_unlock(&gts->ts_ctxlock);
819 preempt_enable(); 891 preempt_enable();
892 mutex_unlock(&gts->ts_ctxlock);
820 893
821 return VM_FAULT_NOPAGE; 894 return VM_FAULT_NOPAGE;
822} 895}
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c
index ee74821b171c..9cbf95bedce6 100644
--- a/drivers/misc/sgi-gru/gruprocfs.c
+++ b/drivers/misc/sgi-gru/gruprocfs.c
@@ -51,9 +51,12 @@ static int statistics_show(struct seq_file *s, void *p)
51 printstat(s, assign_context); 51 printstat(s, assign_context);
52 printstat(s, assign_context_failed); 52 printstat(s, assign_context_failed);
53 printstat(s, free_context); 53 printstat(s, free_context);
54 printstat(s, load_context); 54 printstat(s, load_user_context);
55 printstat(s, unload_context); 55 printstat(s, load_kernel_context);
56 printstat(s, steal_context); 56 printstat(s, lock_kernel_context);
57 printstat(s, unlock_kernel_context);
58 printstat(s, steal_user_context);
59 printstat(s, steal_kernel_context);
57 printstat(s, steal_context_failed); 60 printstat(s, steal_context_failed);
58 printstat(s, nopfn); 61 printstat(s, nopfn);
59 printstat(s, break_cow); 62 printstat(s, break_cow);
@@ -70,7 +73,7 @@ static int statistics_show(struct seq_file *s, void *p)
70 printstat(s, user_flush_tlb); 73 printstat(s, user_flush_tlb);
71 printstat(s, user_unload_context); 74 printstat(s, user_unload_context);
72 printstat(s, user_exception); 75 printstat(s, user_exception);
73 printstat(s, set_task_slice); 76 printstat(s, set_context_option);
74 printstat(s, migrate_check); 77 printstat(s, migrate_check);
75 printstat(s, migrated_retarget); 78 printstat(s, migrated_retarget);
76 printstat(s, migrated_unload); 79 printstat(s, migrated_unload);
@@ -84,6 +87,9 @@ static int statistics_show(struct seq_file *s, void *p)
84 printstat(s, tlb_dropin_fail_range_active); 87 printstat(s, tlb_dropin_fail_range_active);
85 printstat(s, tlb_dropin_fail_idle); 88 printstat(s, tlb_dropin_fail_idle);
86 printstat(s, tlb_dropin_fail_fmm); 89 printstat(s, tlb_dropin_fail_fmm);
90 printstat(s, tlb_dropin_fail_no_exception);
91 printstat(s, tlb_dropin_fail_no_exception_war);
92 printstat(s, tfh_stale_on_fault);
87 printstat(s, mmu_invalidate_range); 93 printstat(s, mmu_invalidate_range);
88 printstat(s, mmu_invalidate_page); 94 printstat(s, mmu_invalidate_page);
89 printstat(s, mmu_clear_flush_young); 95 printstat(s, mmu_clear_flush_young);
@@ -158,8 +164,7 @@ static ssize_t options_write(struct file *file, const char __user *userbuf,
158 unsigned long val; 164 unsigned long val;
159 char buf[80]; 165 char buf[80];
160 166
161 if (copy_from_user 167 if (strncpy_from_user(buf, userbuf, sizeof(buf) - 1) < 0)
162 (buf, userbuf, count < sizeof(buf) ? count : sizeof(buf)))
163 return -EFAULT; 168 return -EFAULT;
164 buf[count - 1] = '\0'; 169 buf[count - 1] = '\0';
165 if (!strict_strtoul(buf, 10, &val)) 170 if (!strict_strtoul(buf, 10, &val))
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index bf1eeb7553ed..34ab3d453919 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -148,11 +148,13 @@
148#include <linux/wait.h> 148#include <linux/wait.h>
149#include <linux/mmu_notifier.h> 149#include <linux/mmu_notifier.h>
150#include "gru.h" 150#include "gru.h"
151#include "grulib.h"
151#include "gruhandles.h" 152#include "gruhandles.h"
152 153
153extern struct gru_stats_s gru_stats; 154extern struct gru_stats_s gru_stats;
154extern struct gru_blade_state *gru_base[]; 155extern struct gru_blade_state *gru_base[];
155extern unsigned long gru_start_paddr, gru_end_paddr; 156extern unsigned long gru_start_paddr, gru_end_paddr;
157extern void *gru_start_vaddr;
156extern unsigned int gru_max_gids; 158extern unsigned int gru_max_gids;
157 159
158#define GRU_MAX_BLADES MAX_NUMNODES 160#define GRU_MAX_BLADES MAX_NUMNODES
@@ -174,9 +176,12 @@ struct gru_stats_s {
174 atomic_long_t assign_context; 176 atomic_long_t assign_context;
175 atomic_long_t assign_context_failed; 177 atomic_long_t assign_context_failed;
176 atomic_long_t free_context; 178 atomic_long_t free_context;
177 atomic_long_t load_context; 179 atomic_long_t load_user_context;
178 atomic_long_t unload_context; 180 atomic_long_t load_kernel_context;
179 atomic_long_t steal_context; 181 atomic_long_t lock_kernel_context;
182 atomic_long_t unlock_kernel_context;
183 atomic_long_t steal_user_context;
184 atomic_long_t steal_kernel_context;
180 atomic_long_t steal_context_failed; 185 atomic_long_t steal_context_failed;
181 atomic_long_t nopfn; 186 atomic_long_t nopfn;
182 atomic_long_t break_cow; 187 atomic_long_t break_cow;
@@ -193,7 +198,7 @@ struct gru_stats_s {
193 atomic_long_t user_flush_tlb; 198 atomic_long_t user_flush_tlb;
194 atomic_long_t user_unload_context; 199 atomic_long_t user_unload_context;
195 atomic_long_t user_exception; 200 atomic_long_t user_exception;
196 atomic_long_t set_task_slice; 201 atomic_long_t set_context_option;
197 atomic_long_t migrate_check; 202 atomic_long_t migrate_check;
198 atomic_long_t migrated_retarget; 203 atomic_long_t migrated_retarget;
199 atomic_long_t migrated_unload; 204 atomic_long_t migrated_unload;
@@ -207,6 +212,9 @@ struct gru_stats_s {
207 atomic_long_t tlb_dropin_fail_range_active; 212 atomic_long_t tlb_dropin_fail_range_active;
208 atomic_long_t tlb_dropin_fail_idle; 213 atomic_long_t tlb_dropin_fail_idle;
209 atomic_long_t tlb_dropin_fail_fmm; 214 atomic_long_t tlb_dropin_fail_fmm;
215 atomic_long_t tlb_dropin_fail_no_exception;
216 atomic_long_t tlb_dropin_fail_no_exception_war;
217 atomic_long_t tfh_stale_on_fault;
210 atomic_long_t mmu_invalidate_range; 218 atomic_long_t mmu_invalidate_range;
211 atomic_long_t mmu_invalidate_page; 219 atomic_long_t mmu_invalidate_page;
212 atomic_long_t mmu_clear_flush_young; 220 atomic_long_t mmu_clear_flush_young;
@@ -253,7 +261,6 @@ extern struct mcs_op_statistic mcs_op_statistics[mcsop_last];
253 261
254#define OPT_DPRINT 1 262#define OPT_DPRINT 1
255#define OPT_STATS 2 263#define OPT_STATS 2
256#define GRU_QUICKLOOK 4
257 264
258 265
259#define IRQ_GRU 110 /* Starting IRQ number for interrupts */ 266#define IRQ_GRU 110 /* Starting IRQ number for interrupts */
@@ -373,6 +380,7 @@ struct gru_thread_state {
373 required for contest */ 380 required for contest */
374 unsigned char ts_cbr_au_count;/* Number of CBR resources 381 unsigned char ts_cbr_au_count;/* Number of CBR resources
375 required for contest */ 382 required for contest */
383 char ts_cch_req_slice;/* CCH packet slice */
376 char ts_blade; /* If >= 0, migrate context if 384 char ts_blade; /* If >= 0, migrate context if
377 ref from diferent blade */ 385 ref from diferent blade */
378 char ts_force_cch_reload; 386 char ts_force_cch_reload;
@@ -380,6 +388,9 @@ struct gru_thread_state {
380 after migration */ 388 after migration */
381 char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each 389 char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each
382 allocated CB */ 390 allocated CB */
391 int ts_data_valid; /* Indicates if ts_gdata has
392 valid data */
393 struct gts_statistics ustats; /* User statistics */
383 unsigned long ts_gdata[0]; /* save area for GRU data (CB, 394 unsigned long ts_gdata[0]; /* save area for GRU data (CB,
384 DS, CBE) */ 395 DS, CBE) */
385}; 396};
@@ -452,6 +463,14 @@ struct gru_blade_state {
452 reserved cb */ 463 reserved cb */
453 void *kernel_dsr; /* First kernel 464 void *kernel_dsr; /* First kernel
454 reserved DSR */ 465 reserved DSR */
466 struct rw_semaphore bs_kgts_sema; /* lock for kgts */
467 struct gru_thread_state *bs_kgts; /* GTS for kernel use */
468
469 /* ---- the following are used for managing kernel async GRU CBRs --- */
470 int bs_async_dsr_bytes; /* DSRs for async */
471 int bs_async_cbrs; /* CBRs AU for async */
472 struct completion *bs_async_wq;
473
455 /* ---- the following are protected by the bs_lock spinlock ---- */ 474 /* ---- the following are protected by the bs_lock spinlock ---- */
456 spinlock_t bs_lock; /* lock used for 475 spinlock_t bs_lock; /* lock used for
457 stealing contexts */ 476 stealing contexts */
@@ -552,6 +571,12 @@ struct gru_blade_state {
552 571
553/* Lock hierarchy checking enabled only in emulator */ 572/* Lock hierarchy checking enabled only in emulator */
554 573
574/* 0 = lock failed, 1 = locked */
575static inline int __trylock_handle(void *h)
576{
577 return !test_and_set_bit(1, h);
578}
579
555static inline void __lock_handle(void *h) 580static inline void __lock_handle(void *h)
556{ 581{
557 while (test_and_set_bit(1, h)) 582 while (test_and_set_bit(1, h))
@@ -563,6 +588,11 @@ static inline void __unlock_handle(void *h)
563 clear_bit(1, h); 588 clear_bit(1, h);
564} 589}
565 590
591static inline int trylock_cch_handle(struct gru_context_configuration_handle *cch)
592{
593 return __trylock_handle(cch);
594}
595
566static inline void lock_cch_handle(struct gru_context_configuration_handle *cch) 596static inline void lock_cch_handle(struct gru_context_configuration_handle *cch)
567{ 597{
568 __lock_handle(cch); 598 __lock_handle(cch);
@@ -584,6 +614,11 @@ static inline void unlock_tgh_handle(struct gru_tlb_global_handle *tgh)
584 __unlock_handle(tgh); 614 __unlock_handle(tgh);
585} 615}
586 616
617static inline int is_kernel_context(struct gru_thread_state *gts)
618{
619 return !gts->ts_mm;
620}
621
587/*----------------------------------------------------------------------------- 622/*-----------------------------------------------------------------------------
588 * Function prototypes & externs 623 * Function prototypes & externs
589 */ 624 */
@@ -598,24 +633,32 @@ extern struct gru_thread_state *gru_find_thread_state(struct vm_area_struct
598 *vma, int tsid); 633 *vma, int tsid);
599extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct 634extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct
600 *vma, int tsid); 635 *vma, int tsid);
636extern struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts,
637 int blade);
638extern void gru_load_context(struct gru_thread_state *gts);
639extern void gru_steal_context(struct gru_thread_state *gts, int blade_id);
601extern void gru_unload_context(struct gru_thread_state *gts, int savestate); 640extern void gru_unload_context(struct gru_thread_state *gts, int savestate);
602extern int gru_update_cch(struct gru_thread_state *gts, int force_unload); 641extern int gru_update_cch(struct gru_thread_state *gts, int force_unload);
603extern void gts_drop(struct gru_thread_state *gts); 642extern void gts_drop(struct gru_thread_state *gts);
604extern void gru_tgh_flush_init(struct gru_state *gru); 643extern void gru_tgh_flush_init(struct gru_state *gru);
605extern int gru_kservices_init(struct gru_state *gru); 644extern int gru_kservices_init(void);
606extern void gru_kservices_exit(struct gru_state *gru); 645extern void gru_kservices_exit(void);
646extern int gru_dump_chiplet_request(unsigned long arg);
647extern long gru_get_gseg_statistics(unsigned long arg);
607extern irqreturn_t gru_intr(int irq, void *dev_id); 648extern irqreturn_t gru_intr(int irq, void *dev_id);
608extern int gru_handle_user_call_os(unsigned long address); 649extern int gru_handle_user_call_os(unsigned long address);
609extern int gru_user_flush_tlb(unsigned long arg); 650extern int gru_user_flush_tlb(unsigned long arg);
610extern int gru_user_unload_context(unsigned long arg); 651extern int gru_user_unload_context(unsigned long arg);
611extern int gru_get_exception_detail(unsigned long arg); 652extern int gru_get_exception_detail(unsigned long arg);
612extern int gru_set_task_slice(long address); 653extern int gru_set_context_option(unsigned long address);
613extern int gru_cpu_fault_map_id(void); 654extern int gru_cpu_fault_map_id(void);
614extern struct vm_area_struct *gru_find_vma(unsigned long vaddr); 655extern struct vm_area_struct *gru_find_vma(unsigned long vaddr);
615extern void gru_flush_all_tlb(struct gru_state *gru); 656extern void gru_flush_all_tlb(struct gru_state *gru);
616extern int gru_proc_init(void); 657extern int gru_proc_init(void);
617extern void gru_proc_exit(void); 658extern void gru_proc_exit(void);
618 659
660extern struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
661 int cbr_au_count, int dsr_au_count, int options, int tsid);
619extern unsigned long gru_reserve_cb_resources(struct gru_state *gru, 662extern unsigned long gru_reserve_cb_resources(struct gru_state *gru,
620 int cbr_au_count, char *cbmap); 663 int cbr_au_count, char *cbmap);
621extern unsigned long gru_reserve_ds_resources(struct gru_state *gru, 664extern unsigned long gru_reserve_ds_resources(struct gru_state *gru,
@@ -624,6 +667,7 @@ extern int gru_fault(struct vm_area_struct *, struct vm_fault *vmf);
624extern struct gru_mm_struct *gru_register_mmu_notifier(void); 667extern struct gru_mm_struct *gru_register_mmu_notifier(void);
625extern void gru_drop_mmu_notifier(struct gru_mm_struct *gms); 668extern void gru_drop_mmu_notifier(struct gru_mm_struct *gms);
626 669
670extern int gru_ktest(unsigned long arg);
627extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start, 671extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start,
628 unsigned long len); 672 unsigned long len);
629 673
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 9172fcdee4e2..c76677afda1b 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -232,7 +232,7 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
232 mq->mmr_blade = uv_cpu_to_blade_id(cpu); 232 mq->mmr_blade = uv_cpu_to_blade_id(cpu);
233 233
234 nid = cpu_to_node(cpu); 234 nid = cpu_to_node(cpu);
235 page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, 235 page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
236 pg_order); 236 pg_order);
237 if (page == NULL) { 237 if (page == NULL) {
238 dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " 238 dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 6faefcffcb53..5d778ec8cdb2 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -235,7 +235,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
235 skb->ip_summed = CHECKSUM_UNNECESSARY; 235 skb->ip_summed = CHECKSUM_UNNECESSARY;
236 236
237 dev_dbg(xpnet, "passing skb to network layer\n" 237 dev_dbg(xpnet, "passing skb to network layer\n"
238 KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p " 238 "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
239 "skb->end=0x%p skb->len=%d\n", 239 "skb->end=0x%p skb->len=%d\n",
240 (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb), 240 (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
241 skb_end_pointer(skb), skb->len); 241 skb_end_pointer(skb), skb->len);
@@ -399,7 +399,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg,
399 msg->buf_pa = xp_pa((void *)start_addr); 399 msg->buf_pa = xp_pa((void *)start_addr);
400 400
401 dev_dbg(xpnet, "sending XPC message to %d:%d\n" 401 dev_dbg(xpnet, "sending XPC message to %d:%d\n"
402 KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, " 402 "msg->buf_pa=0x%lx, msg->size=%u, "
403 "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n", 403 "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
404 dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size, 404 dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
405 msg->leadin_ignore, msg->tailout_ignore); 405 msg->leadin_ignore, msg->tailout_ignore);
@@ -450,7 +450,8 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
450 "packet\n", sizeof(struct xpnet_pending_msg)); 450 "packet\n", sizeof(struct xpnet_pending_msg));
451 451
452 dev->stats.tx_errors++; 452 dev->stats.tx_errors++;
453 return -ENOMEM; 453 dev_kfree_skb(skb);
454 return NETDEV_TX_OK;
454 } 455 }
455 456
456 /* get the beginning of the first cacheline and end of last */ 457 /* get the beginning of the first cacheline and end of last */