diff options
| author | Jack Steiner <steiner@sgi.com> | 2009-04-02 19:59:06 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:05:06 -0400 |
| commit | a24e5e1caf4875bbe09f328b5f4daef6d25ebcc4 (patch) | |
| tree | 3b9214880d848c1b4b071fcf00eb39a8ef8cb47b /drivers/misc | |
| parent | 438846043af39fef286f68b197d42bd75f49898e (diff) | |
sgi-gru: change GRU CCH commands from inline functions to outofline functions
Change the GRU instructions that manage contexts from inline functions to
out-of-line functions. This simplifies adding statistics & error checking
to these functions.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc')
| -rw-r--r-- | drivers/misc/sgi-gru/Makefile | 2 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/gruhandles.c | 197 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/gruhandles.h | 176 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/grutables.h | 3 |
4 files changed, 218 insertions, 160 deletions
diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile index 9e9170b3599a..bcd8136d2f98 100644 --- a/drivers/misc/sgi-gru/Makefile +++ b/drivers/misc/sgi-gru/Makefile | |||
| @@ -3,5 +3,5 @@ ifdef CONFIG_SGI_GRU_DEBUG | |||
| 3 | endif | 3 | endif |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_SGI_GRU) := gru.o | 5 | obj-$(CONFIG_SGI_GRU) := gru.o |
| 6 | gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o | 6 | gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o |
| 7 | 7 | ||
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c new file mode 100644 index 000000000000..5b82e7def16d --- /dev/null +++ b/drivers/misc/sgi-gru/gruhandles.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | /* | ||
| 2 | * GRU KERNEL MCS INSTRUCTIONS | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include "gru.h" | ||
| 23 | #include "grulib.h" | ||
| 24 | #include "grutables.h" | ||
| 25 | |||
| 26 | /* 10 sec */ | ||
| 27 | #ifdef CONFIG_IA64 | ||
| 28 | #include <asm/processor.h> | ||
| 29 | #define GRU_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10) | ||
| 30 | #else | ||
| 31 | #include <asm/tsc.h> | ||
| 32 | #define GRU_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) | ||
| 33 | #endif | ||
| 34 | |||
| 35 | /* Extract the status field from a kernel handle */ | ||
| 36 | #define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3) | ||
| 37 | |||
| 38 | static void start_instruction(void *h) | ||
| 39 | { | ||
| 40 | unsigned long *w0 = h; | ||
| 41 | |||
| 42 | wmb(); /* setting CMD bit must be last */ | ||
| 43 | *w0 = *w0 | 1; | ||
| 44 | gru_flush_cache(h); | ||
| 45 | } | ||
| 46 | |||
| 47 | static int wait_instruction_complete(void *h, enum mcs_op opc) | ||
| 48 | { | ||
| 49 | int status; | ||
| 50 | cycles_t start_time = get_cycles(); | ||
| 51 | |||
| 52 | while (1) { | ||
| 53 | cpu_relax(); | ||
| 54 | status = GET_MSEG_HANDLE_STATUS(h); | ||
| 55 | if (status != CCHSTATUS_ACTIVE) | ||
| 56 | break; | ||
| 57 | if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time)) | ||
| 58 | panic("GRU %p is malfunctioning\n", h); | ||
| 59 | } | ||
| 60 | return status; | ||
| 61 | } | ||
| 62 | |||
| 63 | #if defined CONFIG_IA64 | ||
| 64 | static void cch_allocate_set_asids( | ||
| 65 | struct gru_context_configuration_handle *cch, int asidval) | ||
| 66 | { | ||
| 67 | int i; | ||
| 68 | |||
| 69 | for (i = 0; i < 8; i++) { | ||
| 70 | cch->asid[i] = (asidval++); | ||
| 71 | #if 0 | ||
| 72 | /* ZZZ hugepages not supported yet */ | ||
| 73 | if (i == RGN_HPAGE) | ||
| 74 | cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift); | ||
| 75 | else | ||
| 76 | #endif | ||
| 77 | cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | #elif defined CONFIG_X86_64 | ||
| 81 | static void cch_allocate_set_asids( | ||
| 82 | struct gru_context_configuration_handle *cch, int asidval) | ||
| 83 | { | ||
| 84 | int i; | ||
| 85 | |||
| 86 | for (i = 0; i < 8; i++) { | ||
| 87 | cch->asid[i] = asidval++; | ||
| 88 | cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) | | ||
| 89 | GRU_SIZEAVAIL(21); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | #endif | ||
| 93 | |||
| 94 | int cch_allocate(struct gru_context_configuration_handle *cch, | ||
| 95 | int asidval, unsigned long cbrmap, | ||
| 96 | unsigned long dsrmap) | ||
| 97 | { | ||
| 98 | cch_allocate_set_asids(cch, asidval); | ||
| 99 | cch->dsr_allocation_map = dsrmap; | ||
| 100 | cch->cbr_allocation_map = cbrmap; | ||
| 101 | cch->opc = CCHOP_ALLOCATE; | ||
| 102 | start_instruction(cch); | ||
| 103 | return wait_instruction_complete(cch, cchop_allocate); | ||
| 104 | } | ||
| 105 | |||
| 106 | int cch_start(struct gru_context_configuration_handle *cch) | ||
| 107 | { | ||
| 108 | cch->opc = CCHOP_START; | ||
| 109 | start_instruction(cch); | ||
| 110 | return wait_instruction_complete(cch, cchop_start); | ||
| 111 | } | ||
| 112 | |||
| 113 | int cch_interrupt(struct gru_context_configuration_handle *cch) | ||
| 114 | { | ||
| 115 | cch->opc = CCHOP_INTERRUPT; | ||
| 116 | start_instruction(cch); | ||
| 117 | return wait_instruction_complete(cch, cchop_interrupt); | ||
| 118 | } | ||
| 119 | |||
| 120 | int cch_deallocate(struct gru_context_configuration_handle *cch) | ||
| 121 | { | ||
| 122 | cch->opc = CCHOP_DEALLOCATE; | ||
| 123 | start_instruction(cch); | ||
| 124 | return wait_instruction_complete(cch, cchop_deallocate); | ||
| 125 | } | ||
| 126 | |||
| 127 | int cch_interrupt_sync(struct gru_context_configuration_handle | ||
| 128 | *cch) | ||
| 129 | { | ||
| 130 | cch->opc = CCHOP_INTERRUPT_SYNC; | ||
| 131 | start_instruction(cch); | ||
| 132 | return wait_instruction_complete(cch, cchop_interrupt_sync); | ||
| 133 | } | ||
| 134 | |||
| 135 | int tgh_invalidate(struct gru_tlb_global_handle *tgh, | ||
| 136 | unsigned long vaddr, unsigned long vaddrmask, | ||
| 137 | int asid, int pagesize, int global, int n, | ||
| 138 | unsigned short ctxbitmap) | ||
| 139 | { | ||
| 140 | tgh->vaddr = vaddr; | ||
| 141 | tgh->asid = asid; | ||
| 142 | tgh->pagesize = pagesize; | ||
| 143 | tgh->n = n; | ||
| 144 | tgh->global = global; | ||
| 145 | tgh->vaddrmask = vaddrmask; | ||
| 146 | tgh->ctxbitmap = ctxbitmap; | ||
| 147 | tgh->opc = TGHOP_TLBINV; | ||
| 148 | start_instruction(tgh); | ||
| 149 | return wait_instruction_complete(tgh, tghop_invalidate); | ||
| 150 | } | ||
| 151 | |||
| 152 | void tfh_write_only(struct gru_tlb_fault_handle *tfh, | ||
| 153 | unsigned long pfn, unsigned long vaddr, | ||
| 154 | int asid, int dirty, int pagesize) | ||
| 155 | { | ||
| 156 | tfh->fillasid = asid; | ||
| 157 | tfh->fillvaddr = vaddr; | ||
| 158 | tfh->pfn = pfn; | ||
| 159 | tfh->dirty = dirty; | ||
| 160 | tfh->pagesize = pagesize; | ||
| 161 | tfh->opc = TFHOP_WRITE_ONLY; | ||
| 162 | start_instruction(tfh); | ||
| 163 | } | ||
| 164 | |||
| 165 | void tfh_write_restart(struct gru_tlb_fault_handle *tfh, | ||
| 166 | unsigned long paddr, int gaa, | ||
| 167 | unsigned long vaddr, int asid, int dirty, | ||
| 168 | int pagesize) | ||
| 169 | { | ||
| 170 | tfh->fillasid = asid; | ||
| 171 | tfh->fillvaddr = vaddr; | ||
| 172 | tfh->pfn = paddr >> GRU_PADDR_SHIFT; | ||
| 173 | tfh->gaa = gaa; | ||
| 174 | tfh->dirty = dirty; | ||
| 175 | tfh->pagesize = pagesize; | ||
| 176 | tfh->opc = TFHOP_WRITE_RESTART; | ||
| 177 | start_instruction(tfh); | ||
| 178 | } | ||
| 179 | |||
| 180 | void tfh_restart(struct gru_tlb_fault_handle *tfh) | ||
| 181 | { | ||
| 182 | tfh->opc = TFHOP_RESTART; | ||
| 183 | start_instruction(tfh); | ||
| 184 | } | ||
| 185 | |||
| 186 | void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh) | ||
| 187 | { | ||
| 188 | tfh->opc = TFHOP_USER_POLLING_MODE; | ||
| 189 | start_instruction(tfh); | ||
| 190 | } | ||
| 191 | |||
| 192 | void tfh_exception(struct gru_tlb_fault_handle *tfh) | ||
| 193 | { | ||
| 194 | tfh->opc = TFHOP_EXCEPTION; | ||
| 195 | start_instruction(tfh); | ||
| 196 | } | ||
| 197 | |||
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h index fb72a52a34a8..dfce8ea5da24 100644 --- a/drivers/misc/sgi-gru/gruhandles.h +++ b/drivers/misc/sgi-gru/gruhandles.h | |||
| @@ -495,164 +495,22 @@ enum gru_cbr_state { | |||
| 495 | /* minimum TLB purge count to ensure a full purge */ | 495 | /* minimum TLB purge count to ensure a full purge */ |
| 496 | #define GRUMAXINVAL 1024UL | 496 | #define GRUMAXINVAL 1024UL |
| 497 | 497 | ||
| 498 | 498 | int cch_allocate(struct gru_context_configuration_handle *cch, | |
| 499 | /* Extract the status field from a kernel handle */ | 499 | int asidval, unsigned long cbrmap, unsigned long dsrmap); |
| 500 | #define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3) | 500 | |
| 501 | 501 | int cch_start(struct gru_context_configuration_handle *cch); | |
| 502 | static inline void start_instruction(void *h) | 502 | int cch_interrupt(struct gru_context_configuration_handle *cch); |
| 503 | { | 503 | int cch_deallocate(struct gru_context_configuration_handle *cch); |
| 504 | unsigned long *w0 = h; | 504 | int cch_interrupt_sync(struct gru_context_configuration_handle *cch); |
| 505 | 505 | int tgh_invalidate(struct gru_tlb_global_handle *tgh, unsigned long vaddr, | |
| 506 | wmb(); /* setting CMD bit must be last */ | 506 | unsigned long vaddrmask, int asid, int pagesize, int global, int n, |
| 507 | *w0 = *w0 | 1; | 507 | unsigned short ctxbitmap); |
| 508 | gru_flush_cache(h); | 508 | void tfh_write_only(struct gru_tlb_fault_handle *tfh, unsigned long pfn, |
| 509 | } | 509 | unsigned long vaddr, int asid, int dirty, int pagesize); |
| 510 | 510 | void tfh_write_restart(struct gru_tlb_fault_handle *tfh, unsigned long paddr, | |
| 511 | static inline int wait_instruction_complete(void *h) | 511 | int gaa, unsigned long vaddr, int asid, int dirty, int pagesize); |
| 512 | { | 512 | void tfh_restart(struct gru_tlb_fault_handle *tfh); |
| 513 | int status; | 513 | void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh); |
| 514 | 514 | void tfh_exception(struct gru_tlb_fault_handle *tfh); | |
| 515 | do { | ||
| 516 | cpu_relax(); | ||
| 517 | barrier(); | ||
| 518 | status = GET_MSEG_HANDLE_STATUS(h); | ||
| 519 | } while (status == CCHSTATUS_ACTIVE); | ||
| 520 | return status; | ||
| 521 | } | ||
| 522 | |||
| 523 | #if defined CONFIG_IA64 | ||
| 524 | static inline void cch_allocate_set_asids( | ||
| 525 | struct gru_context_configuration_handle *cch, int asidval) | ||
| 526 | { | ||
| 527 | int i; | ||
| 528 | |||
| 529 | for (i = 0; i <= RGN_HPAGE; i++) { /* assume HPAGE is last region */ | ||
| 530 | cch->asid[i] = (asidval++); | ||
| 531 | #if 0 | ||
| 532 | /* ZZZ hugepages not supported yet */ | ||
| 533 | if (i == RGN_HPAGE) | ||
| 534 | cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift); | ||
| 535 | else | ||
| 536 | #endif | ||
| 537 | cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT); | ||
| 538 | } | ||
| 539 | } | ||
| 540 | #elif defined CONFIG_X86_64 | ||
| 541 | static inline void cch_allocate_set_asids( | ||
| 542 | struct gru_context_configuration_handle *cch, int asidval) | ||
| 543 | { | ||
| 544 | int i; | ||
| 545 | |||
| 546 | for (i = 0; i < 8; i++) { | ||
| 547 | cch->asid[i] = asidval++; | ||
| 548 | cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) | | ||
| 549 | GRU_SIZEAVAIL(21); | ||
| 550 | } | ||
| 551 | } | ||
| 552 | #endif | ||
| 553 | |||
| 554 | static inline int cch_allocate(struct gru_context_configuration_handle *cch, | ||
| 555 | int asidval, unsigned long cbrmap, | ||
| 556 | unsigned long dsrmap) | ||
| 557 | { | ||
| 558 | cch_allocate_set_asids(cch, asidval); | ||
| 559 | cch->dsr_allocation_map = dsrmap; | ||
| 560 | cch->cbr_allocation_map = cbrmap; | ||
| 561 | cch->opc = CCHOP_ALLOCATE; | ||
| 562 | start_instruction(cch); | ||
| 563 | return wait_instruction_complete(cch); | ||
| 564 | } | ||
| 565 | |||
| 566 | static inline int cch_start(struct gru_context_configuration_handle *cch) | ||
| 567 | { | ||
| 568 | cch->opc = CCHOP_START; | ||
| 569 | start_instruction(cch); | ||
| 570 | return wait_instruction_complete(cch); | ||
| 571 | } | ||
| 572 | |||
| 573 | static inline int cch_interrupt(struct gru_context_configuration_handle *cch) | ||
| 574 | { | ||
| 575 | cch->opc = CCHOP_INTERRUPT; | ||
| 576 | start_instruction(cch); | ||
| 577 | return wait_instruction_complete(cch); | ||
| 578 | } | ||
| 579 | |||
| 580 | static inline int cch_deallocate(struct gru_context_configuration_handle *cch) | ||
| 581 | { | ||
| 582 | cch->opc = CCHOP_DEALLOCATE; | ||
| 583 | start_instruction(cch); | ||
| 584 | return wait_instruction_complete(cch); | ||
| 585 | } | ||
| 586 | |||
| 587 | static inline int cch_interrupt_sync(struct gru_context_configuration_handle | ||
| 588 | *cch) | ||
| 589 | { | ||
| 590 | cch->opc = CCHOP_INTERRUPT_SYNC; | ||
| 591 | start_instruction(cch); | ||
| 592 | return wait_instruction_complete(cch); | ||
| 593 | } | ||
| 594 | |||
| 595 | static inline int tgh_invalidate(struct gru_tlb_global_handle *tgh, | ||
| 596 | unsigned long vaddr, unsigned long vaddrmask, | ||
| 597 | int asid, int pagesize, int global, int n, | ||
| 598 | unsigned short ctxbitmap) | ||
| 599 | { | ||
| 600 | tgh->vaddr = vaddr; | ||
| 601 | tgh->asid = asid; | ||
| 602 | tgh->pagesize = pagesize; | ||
| 603 | tgh->n = n; | ||
| 604 | tgh->global = global; | ||
| 605 | tgh->vaddrmask = vaddrmask; | ||
| 606 | tgh->ctxbitmap = ctxbitmap; | ||
| 607 | tgh->opc = TGHOP_TLBINV; | ||
| 608 | start_instruction(tgh); | ||
| 609 | return wait_instruction_complete(tgh); | ||
| 610 | } | ||
| 611 | |||
| 612 | static inline void tfh_write_only(struct gru_tlb_fault_handle *tfh, | ||
| 613 | unsigned long pfn, unsigned long vaddr, | ||
| 614 | int asid, int dirty, int pagesize) | ||
| 615 | { | ||
| 616 | tfh->fillasid = asid; | ||
| 617 | tfh->fillvaddr = vaddr; | ||
| 618 | tfh->pfn = pfn; | ||
| 619 | tfh->dirty = dirty; | ||
| 620 | tfh->pagesize = pagesize; | ||
| 621 | tfh->opc = TFHOP_WRITE_ONLY; | ||
| 622 | start_instruction(tfh); | ||
| 623 | } | ||
| 624 | |||
| 625 | static inline void tfh_write_restart(struct gru_tlb_fault_handle *tfh, | ||
| 626 | unsigned long paddr, int gaa, | ||
| 627 | unsigned long vaddr, int asid, int dirty, | ||
| 628 | int pagesize) | ||
| 629 | { | ||
| 630 | tfh->fillasid = asid; | ||
| 631 | tfh->fillvaddr = vaddr; | ||
| 632 | tfh->pfn = paddr >> GRU_PADDR_SHIFT; | ||
| 633 | tfh->gaa = gaa; | ||
| 634 | tfh->dirty = dirty; | ||
| 635 | tfh->pagesize = pagesize; | ||
| 636 | tfh->opc = TFHOP_WRITE_RESTART; | ||
| 637 | start_instruction(tfh); | ||
| 638 | } | ||
| 639 | |||
| 640 | static inline void tfh_restart(struct gru_tlb_fault_handle *tfh) | ||
| 641 | { | ||
| 642 | tfh->opc = TFHOP_RESTART; | ||
| 643 | start_instruction(tfh); | ||
| 644 | } | ||
| 645 | |||
| 646 | static inline void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh) | ||
| 647 | { | ||
| 648 | tfh->opc = TFHOP_USER_POLLING_MODE; | ||
| 649 | start_instruction(tfh); | ||
| 650 | } | ||
| 651 | |||
| 652 | static inline void tfh_exception(struct gru_tlb_fault_handle *tfh) | ||
| 653 | { | ||
| 654 | tfh->opc = TFHOP_EXCEPTION; | ||
| 655 | start_instruction(tfh); | ||
| 656 | } | ||
| 657 | 515 | ||
| 658 | #endif /* __GRUHANDLES_H__ */ | 516 | #endif /* __GRUHANDLES_H__ */ |
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h index cc0fc734405e..378a0894198e 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h | |||
| @@ -239,6 +239,9 @@ struct gru_stats_s { | |||
| 239 | 239 | ||
| 240 | }; | 240 | }; |
| 241 | 241 | ||
| 242 | enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync, | ||
| 243 | cchop_deallocate, tghop_invalidate, mcsop_last}; | ||
| 244 | |||
| 242 | #define OPT_DPRINT 1 | 245 | #define OPT_DPRINT 1 |
| 243 | #define OPT_STATS 2 | 246 | #define OPT_STATS 2 |
| 244 | #define GRU_QUICKLOOK 4 | 247 | #define GRU_QUICKLOOK 4 |
