diff options
author | Jack Steiner <steiner@sgi.com> | 2008-10-16 01:05:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 14:21:51 -0400 |
commit | 923f7f6970bd448b8e88b9e4be10fd01fc7106a4 (patch) | |
tree | 5e9f5646f547eaa345068f177815ebadd6a95454 /drivers | |
parent | ebf3f09c634906d371f2bfd71b41c7e0c52efe7e (diff) |
GRU driver: minor updates
A few minor updates for the GRU driver.
- documentation changes found in code reviews
- changes to #ifdefs to make them recognized by "unifdef"
(used in simulator testing)
- change GRU context load/unload to prefetch data
[akpm@linux-foundation.org: fix typo in comment]
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/sgi-gru/gru.h | 4 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/gru_instructions.h | 10 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grufault.c | 11 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grufile.c | 8 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/gruhandles.h | 5 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 1 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grumain.c | 29 |
7 files changed, 39 insertions, 29 deletions
diff --git a/drivers/misc/sgi-gru/gru.h b/drivers/misc/sgi-gru/gru.h index 40df7cb3f0a5..f93f03a9e6e9 100644 --- a/drivers/misc/sgi-gru/gru.h +++ b/drivers/misc/sgi-gru/gru.h | |||
@@ -30,9 +30,9 @@ | |||
30 | /* | 30 | /* |
31 | * Size used to map GRU GSeg | 31 | * Size used to map GRU GSeg |
32 | */ | 32 | */ |
33 | #if defined CONFIG_IA64 | 33 | #if defined(CONFIG_IA64) |
34 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) | 34 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) |
35 | #elif defined CONFIG_X86_64 | 35 | #elif defined(CONFIG_X86_64) |
36 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) /* ZZZ 2MB ??? */ | 36 | #define GRU_GSEG_PAGESIZE (256 * 1024UL) /* ZZZ 2MB ??? */ |
37 | #else | 37 | #else |
38 | #error "Unsupported architecture" | 38 | #error "Unsupported architecture" |
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h index 0dc36225c7c6..48762e7b98be 100644 --- a/drivers/misc/sgi-gru/gru_instructions.h +++ b/drivers/misc/sgi-gru/gru_instructions.h | |||
@@ -26,7 +26,7 @@ | |||
26 | * Architecture dependent functions | 26 | * Architecture dependent functions |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #if defined CONFIG_IA64 | 29 | #if defined(CONFIG_IA64) |
30 | #include <linux/compiler.h> | 30 | #include <linux/compiler.h> |
31 | #include <asm/intrinsics.h> | 31 | #include <asm/intrinsics.h> |
32 | #define __flush_cache(p) ia64_fc(p) | 32 | #define __flush_cache(p) ia64_fc(p) |
@@ -36,7 +36,7 @@ | |||
36 | barrier(); \ | 36 | barrier(); \ |
37 | *((volatile int *)(p)) = v; /* force st.rel */ \ | 37 | *((volatile int *)(p)) = v; /* force st.rel */ \ |
38 | } while (0) | 38 | } while (0) |
39 | #elif defined CONFIG_X86_64 | 39 | #elif defined(CONFIG_X86_64) |
40 | #define __flush_cache(p) clflush(p) | 40 | #define __flush_cache(p) clflush(p) |
41 | #define gru_ordered_store_int(p,v) \ | 41 | #define gru_ordered_store_int(p,v) \ |
42 | do { \ | 42 | do { \ |
@@ -299,6 +299,7 @@ static inline void gru_flush_cache(void *p) | |||
299 | static inline void gru_start_instruction(struct gru_instruction *ins, int op32) | 299 | static inline void gru_start_instruction(struct gru_instruction *ins, int op32) |
300 | { | 300 | { |
301 | gru_ordered_store_int(ins, op32); | 301 | gru_ordered_store_int(ins, op32); |
302 | gru_flush_cache(ins); | ||
302 | } | 303 | } |
303 | 304 | ||
304 | 305 | ||
@@ -604,8 +605,9 @@ static inline int gru_get_cb_substatus(void *cb) | |||
604 | static inline int gru_check_status(void *cb) | 605 | static inline int gru_check_status(void *cb) |
605 | { | 606 | { |
606 | struct gru_control_block_status *cbs = (void *)cb; | 607 | struct gru_control_block_status *cbs = (void *)cb; |
607 | int ret = cbs->istatus; | 608 | int ret; |
608 | 609 | ||
610 | ret = cbs->istatus; | ||
609 | if (ret == CBS_CALL_OS) | 611 | if (ret == CBS_CALL_OS) |
610 | ret = gru_check_status_proc(cb); | 612 | ret = gru_check_status_proc(cb); |
611 | return ret; | 613 | return ret; |
@@ -617,7 +619,7 @@ static inline int gru_check_status(void *cb) | |||
617 | static inline int gru_wait(void *cb) | 619 | static inline int gru_wait(void *cb) |
618 | { | 620 | { |
619 | struct gru_control_block_status *cbs = (void *)cb; | 621 | struct gru_control_block_status *cbs = (void *)cb; |
620 | int ret = cbs->istatus;; | 622 | int ret = cbs->istatus; |
621 | 623 | ||
622 | if (ret != CBS_IDLE) | 624 | if (ret != CBS_IDLE) |
623 | ret = gru_wait_proc(cb); | 625 | ret = gru_wait_proc(cb); |
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c index 3d33015bbf31..8c389d606c30 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c | |||
@@ -214,12 +214,14 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma, | |||
214 | } | 214 | } |
215 | 215 | ||
216 | /* | 216 | /* |
217 | * | ||
218 | * atomic_pte_lookup | 217 | * atomic_pte_lookup |
219 | * | 218 | * |
220 | * Convert a user virtual address to a physical address | 219 | * Convert a user virtual address to a physical address |
221 | * Only supports Intel large pages (2MB only) on x86_64. | 220 | * Only supports Intel large pages (2MB only) on x86_64. |
222 | * ZZZ - hugepage support is incomplete | 221 | * ZZZ - hugepage support is incomplete |
222 | * | ||
223 | * NOTE: mmap_sem is already held on entry to this function. This | ||
224 | * guarantees existence of the page tables. | ||
223 | */ | 225 | */ |
224 | static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, | 226 | static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, |
225 | int write, unsigned long *paddr, int *pageshift) | 227 | int write, unsigned long *paddr, int *pageshift) |
@@ -229,9 +231,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, | |||
229 | pud_t *pudp; | 231 | pud_t *pudp; |
230 | pte_t pte; | 232 | pte_t pte; |
231 | 233 | ||
232 | WARN_ON(irqs_disabled()); /* ZZZ debug */ | ||
233 | |||
234 | local_irq_disable(); | ||
235 | pgdp = pgd_offset(vma->vm_mm, vaddr); | 234 | pgdp = pgd_offset(vma->vm_mm, vaddr); |
236 | if (unlikely(pgd_none(*pgdp))) | 235 | if (unlikely(pgd_none(*pgdp))) |
237 | goto err; | 236 | goto err; |
@@ -250,8 +249,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, | |||
250 | #endif | 249 | #endif |
251 | pte = *pte_offset_kernel(pmdp, vaddr); | 250 | pte = *pte_offset_kernel(pmdp, vaddr); |
252 | 251 | ||
253 | local_irq_enable(); | ||
254 | |||
255 | if (unlikely(!pte_present(pte) || | 252 | if (unlikely(!pte_present(pte) || |
256 | (write && (!pte_write(pte) || !pte_dirty(pte))))) | 253 | (write && (!pte_write(pte) || !pte_dirty(pte))))) |
257 | return 1; | 254 | return 1; |
@@ -324,6 +321,7 @@ static int gru_try_dropin(struct gru_thread_state *gts, | |||
324 | * Atomic lookup is faster & usually works even if called in non-atomic | 321 | * Atomic lookup is faster & usually works even if called in non-atomic |
325 | * context. | 322 | * context. |
326 | */ | 323 | */ |
324 | rmb(); /* Must/check ms_range_active before loading PTEs */ | ||
327 | ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &pageshift); | 325 | ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &pageshift); |
328 | if (ret) { | 326 | if (ret) { |
329 | if (!cb) | 327 | if (!cb) |
@@ -543,6 +541,7 @@ int gru_get_exception_detail(unsigned long arg) | |||
543 | ucbnum = get_cb_number((void *)excdet.cb); | 541 | ucbnum = get_cb_number((void *)excdet.cb); |
544 | cbrnum = thread_cbr_number(gts, ucbnum); | 542 | cbrnum = thread_cbr_number(gts, ucbnum); |
545 | cbe = get_cbe_by_index(gts->ts_gru, cbrnum); | 543 | cbe = get_cbe_by_index(gts->ts_gru, cbrnum); |
544 | prefetchw(cbe); /* Harmless on hardware, required for emulator */ | ||
546 | excdet.opc = cbe->opccpy; | 545 | excdet.opc = cbe->opccpy; |
547 | excdet.exopc = cbe->exopccpy; | 546 | excdet.exopc = cbe->exopccpy; |
548 | excdet.ecause = cbe->ecause; | 547 | excdet.ecause = cbe->ecause; |
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index d61cee796efd..5c027b6b4e5a 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c | |||
@@ -113,7 +113,7 @@ static int gru_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
113 | return -EPERM; | 113 | return -EPERM; |
114 | 114 | ||
115 | if (vma->vm_start & (GRU_GSEG_PAGESIZE - 1) || | 115 | if (vma->vm_start & (GRU_GSEG_PAGESIZE - 1) || |
116 | vma->vm_end & (GRU_GSEG_PAGESIZE - 1)) | 116 | vma->vm_end & (GRU_GSEG_PAGESIZE - 1)) |
117 | return -EINVAL; | 117 | return -EINVAL; |
118 | 118 | ||
119 | vma->vm_flags |= | 119 | vma->vm_flags |= |
@@ -398,6 +398,12 @@ static int __init gru_init(void) | |||
398 | irq = get_base_irq(); | 398 | irq = get_base_irq(); |
399 | for (chip = 0; chip < GRU_CHIPLETS_PER_BLADE; chip++) { | 399 | for (chip = 0; chip < GRU_CHIPLETS_PER_BLADE; chip++) { |
400 | ret = request_irq(irq + chip, gru_intr, 0, id, NULL); | 400 | ret = request_irq(irq + chip, gru_intr, 0, id, NULL); |
401 | /* TODO: fix irq handling on x86. For now ignore failures because | ||
402 | * interrupts are not required & not yet fully supported */ | ||
403 | if (ret) { | ||
404 | printk("!!!WARNING: GRU ignoring request failure!!!\n"); | ||
405 | ret = 0; | ||
406 | } | ||
401 | if (ret) { | 407 | if (ret) { |
402 | printk(KERN_ERR "%s: request_irq failed\n", | 408 | printk(KERN_ERR "%s: request_irq failed\n", |
403 | GRU_DRIVER_ID_STR); | 409 | GRU_DRIVER_ID_STR); |
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h index d16031d62673..b63018d60fe1 100644 --- a/drivers/misc/sgi-gru/gruhandles.h +++ b/drivers/misc/sgi-gru/gruhandles.h | |||
@@ -91,12 +91,7 @@ | |||
91 | #define GSEGPOFF(h) ((h) & (GRU_SIZE - 1)) | 91 | #define GSEGPOFF(h) ((h) & (GRU_SIZE - 1)) |
92 | 92 | ||
93 | /* Convert an arbitrary handle address to the beginning of the GRU segment */ | 93 | /* Convert an arbitrary handle address to the beginning of the GRU segment */ |
94 | #ifndef __PLUGIN__ | ||
95 | #define GRUBASE(h) ((void *)((unsigned long)(h) & ~(GRU_SIZE - 1))) | 94 | #define GRUBASE(h) ((void *)((unsigned long)(h) & ~(GRU_SIZE - 1))) |
96 | #else | ||
97 | extern void *gmu_grubase(void *h); | ||
98 | #define GRUBASE(h) gmu_grubase(h) | ||
99 | #endif | ||
100 | 95 | ||
101 | /* General addressing macros. */ | 96 | /* General addressing macros. */ |
102 | static inline void *get_gseg_base_address(void *base, int ctxnum) | 97 | static inline void *get_gseg_base_address(void *base, int ctxnum) |
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index 08d29cd756b4..880c55dfb662 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c | |||
@@ -122,6 +122,7 @@ int gru_get_cb_exception_detail(void *cb, | |||
122 | struct gru_control_block_extended *cbe; | 122 | struct gru_control_block_extended *cbe; |
123 | 123 | ||
124 | cbe = get_cbe(GRUBASE(cb), get_cb_number(cb)); | 124 | cbe = get_cbe(GRUBASE(cb), get_cb_number(cb)); |
125 | prefetchw(cbe); /* Harmless on hardware, required for emulator */ | ||
125 | excdet->opc = cbe->opccpy; | 126 | excdet->opc = cbe->opccpy; |
126 | excdet->exopc = cbe->exopccpy; | 127 | excdet->exopc = cbe->exopccpy; |
127 | excdet->ecause = cbe->ecause; | 128 | excdet->ecause = cbe->ecause; |
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c index 0eeb8dddd2f5..e11e1ac50900 100644 --- a/drivers/misc/sgi-gru/grumain.c +++ b/drivers/misc/sgi-gru/grumain.c | |||
@@ -432,29 +432,35 @@ static inline long gru_copy_handle(void *d, void *s) | |||
432 | return GRU_HANDLE_BYTES; | 432 | return GRU_HANDLE_BYTES; |
433 | } | 433 | } |
434 | 434 | ||
435 | /* rewrite in assembly & use lots of prefetch */ | 435 | static void gru_prefetch_context(void *gseg, void *cb, void *cbe, unsigned long cbrmap, |
436 | static void gru_load_context_data(void *save, void *grubase, int ctxnum, | 436 | unsigned long length) |
437 | unsigned long cbrmap, unsigned long dsrmap) | ||
438 | { | 437 | { |
439 | void *gseg, *cb, *cbe; | ||
440 | unsigned long length; | ||
441 | int i, scr; | 438 | int i, scr; |
442 | 439 | ||
443 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; | ||
444 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
445 | prefetch_data(gseg + GRU_DS_BASE, length / GRU_CACHE_LINE_BYTES, | 440 | prefetch_data(gseg + GRU_DS_BASE, length / GRU_CACHE_LINE_BYTES, |
446 | GRU_CACHE_LINE_BYTES); | 441 | GRU_CACHE_LINE_BYTES); |
447 | 442 | ||
448 | cb = gseg + GRU_CB_BASE; | ||
449 | cbe = grubase + GRU_CBE_BASE; | ||
450 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { | 443 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |
451 | prefetch_data(cb, 1, GRU_CACHE_LINE_BYTES); | 444 | prefetch_data(cb, 1, GRU_CACHE_LINE_BYTES); |
452 | prefetch_data(cbe + i * GRU_HANDLE_STRIDE, 1, | 445 | prefetch_data(cbe + i * GRU_HANDLE_STRIDE, 1, |
453 | GRU_CACHE_LINE_BYTES); | 446 | GRU_CACHE_LINE_BYTES); |
454 | cb += GRU_HANDLE_STRIDE; | 447 | cb += GRU_HANDLE_STRIDE; |
455 | } | 448 | } |
449 | } | ||
450 | |||
451 | static void gru_load_context_data(void *save, void *grubase, int ctxnum, | ||
452 | unsigned long cbrmap, unsigned long dsrmap) | ||
453 | { | ||
454 | void *gseg, *cb, *cbe; | ||
455 | unsigned long length; | ||
456 | int i, scr; | ||
456 | 457 | ||
458 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; | ||
457 | cb = gseg + GRU_CB_BASE; | 459 | cb = gseg + GRU_CB_BASE; |
460 | cbe = grubase + GRU_CBE_BASE; | ||
461 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
462 | gru_prefetch_context(gseg, cb, cbe, cbrmap, length); | ||
463 | |||
458 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { | 464 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |
459 | save += gru_copy_handle(cb, save); | 465 | save += gru_copy_handle(cb, save); |
460 | save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save); | 466 | save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save); |
@@ -472,15 +478,16 @@ static void gru_unload_context_data(void *save, void *grubase, int ctxnum, | |||
472 | int i, scr; | 478 | int i, scr; |
473 | 479 | ||
474 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; | 480 | gseg = grubase + ctxnum * GRU_GSEG_STRIDE; |
475 | |||
476 | cb = gseg + GRU_CB_BASE; | 481 | cb = gseg + GRU_CB_BASE; |
477 | cbe = grubase + GRU_CBE_BASE; | 482 | cbe = grubase + GRU_CBE_BASE; |
483 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
484 | gru_prefetch_context(gseg, cb, cbe, cbrmap, length); | ||
485 | |||
478 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { | 486 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |
479 | save += gru_copy_handle(save, cb); | 487 | save += gru_copy_handle(save, cb); |
480 | save += gru_copy_handle(save, cbe + i * GRU_HANDLE_STRIDE); | 488 | save += gru_copy_handle(save, cbe + i * GRU_HANDLE_STRIDE); |
481 | cb += GRU_HANDLE_STRIDE; | 489 | cb += GRU_HANDLE_STRIDE; |
482 | } | 490 | } |
483 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | ||
484 | memcpy(save, gseg + GRU_DS_BASE, length); | 491 | memcpy(save, gseg + GRU_DS_BASE, length); |
485 | } | 492 | } |
486 | 493 | ||