diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 15:56:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 15:56:01 -0400 |
commit | aabded9c3aab5160ae2ca3dd1fa0fa37f3d510e4 (patch) | |
tree | 8544d546735bcb975b8dec296eb9b6dc6531fb2a /arch/powerpc/platforms | |
parent | 9a9136e270af14da506f66bcafcc506b86a86498 (diff) | |
parent | f1a1eb299a8422c3e8d41753095bec44b2493398 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
[POWERPC] Further fixes for the removal of 4level-fixup hack from ppc32
[POWERPC] EEH: log all PCI-X and PCI-E AER registers
[POWERPC] EEH: capture and log pci state on error
[POWERPC] EEH: Split up long error msg
[POWERPC] EEH: log error only after driver notification.
[POWERPC] fsl_soc: Make mac_addr const in fs_enet_of_init().
[POWERPC] Don't use SLAB/SLUB for PTE pages
[POWERPC] Spufs support for 64K LS mappings on 4K kernels
[POWERPC] Add ability to 4K kernel to hash in 64K pages
[POWERPC] Introduce address space "slices"
[POWERPC] Small fixes & cleanups in segment page size demotion
[POWERPC] iSeries: Make HVC_ISERIES the default
[POWERPC] iSeries: suppress build warning in lparmap.c
[POWERPC] Mark pages that don't exist as nosave
[POWERPC] swsusp: Introduce register_nosave_region_late
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/86xx/mpc86xx_smp.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/Kconfig | 15 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 80 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/lscsa_alloc.c | 181 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/switch.c | 28 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/Kconfig | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 87 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_driver.c | 14 |
11 files changed, 377 insertions, 49 deletions
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c index 7ef0c6854799..ba55b0ff0f74 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c | |||
@@ -15,8 +15,8 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | 17 | ||
18 | #include <asm/pgtable.h> | ||
19 | #include <asm/page.h> | 18 | #include <asm/page.h> |
19 | #include <asm/pgtable.h> | ||
20 | #include <asm/pci-bridge.h> | 20 | #include <asm/pci-bridge.h> |
21 | #include <asm-powerpc/mpic.h> | 21 | #include <asm-powerpc/mpic.h> |
22 | #include <asm/mpc86xx.h> | 22 | #include <asm/mpc86xx.h> |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 82551770917c..9b2b386ccf48 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -35,6 +35,21 @@ config SPU_FS | |||
35 | Units on machines implementing the Broadband Processor | 35 | Units on machines implementing the Broadband Processor |
36 | Architecture. | 36 | Architecture. |
37 | 37 | ||
38 | config SPU_FS_64K_LS | ||
39 | bool "Use 64K pages to map SPE local store" | ||
40 | # we depend on PPC_MM_SLICES for now rather than selecting | ||
41 | # it because we depend on hugetlbfs hooks being present. We | ||
42 | # will fix that when the generic code has been improved to | ||
43 | # not require hijacking hugetlbfs hooks. | ||
44 | depends on SPU_FS && PPC_MM_SLICES && !PPC_64K_PAGES | ||
45 | default y | ||
46 | select PPC_HAS_HASH_64K | ||
47 | help | ||
48 | This option causes SPE local stores to be mapped in process | ||
49 | address spaces using 64K pages while the rest of the kernel | ||
50 | uses 4K pages. This can improve performances of applications | ||
51 | using multiple SPEs by lowering the TLB pressure on them. | ||
52 | |||
38 | config SPU_BASE | 53 | config SPU_BASE |
39 | bool | 54 | bool |
40 | default n | 55 | default n |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index fec51525252e..a7f5a7653c62 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -144,12 +144,11 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
144 | 144 | ||
145 | switch(REGION_ID(ea)) { | 145 | switch(REGION_ID(ea)) { |
146 | case USER_REGION_ID: | 146 | case USER_REGION_ID: |
147 | #ifdef CONFIG_HUGETLB_PAGE | 147 | #ifdef CONFIG_PPC_MM_SLICES |
148 | if (in_hugepage_area(mm->context, ea)) | 148 | psize = get_slice_psize(mm, ea); |
149 | psize = mmu_huge_psize; | 149 | #else |
150 | else | 150 | psize = mm->context.user_psize; |
151 | #endif | 151 | #endif |
152 | psize = mm->context.user_psize; | ||
153 | vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | | 152 | vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | |
154 | SLB_VSID_USER; | 153 | SLB_VSID_USER; |
155 | break; | 154 | break; |
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index 2cd89c11af5a..328afcf89503 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-y += switch.o fault.o | 1 | obj-y += switch.o fault.o lscsa_alloc.o |
2 | 2 | ||
3 | obj-$(CONFIG_SPU_FS) += spufs.o | 3 | obj-$(CONFIG_SPU_FS) += spufs.o |
4 | spufs-y += inode.o file.o context.o syscalls.o coredump.o | 4 | spufs-y += inode.o file.o context.o syscalls.o coredump.o |
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index a87d9ca3dba2..8654749e317b 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -36,10 +36,8 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) | |||
36 | /* Binding to physical processor deferred | 36 | /* Binding to physical processor deferred |
37 | * until spu_activate(). | 37 | * until spu_activate(). |
38 | */ | 38 | */ |
39 | spu_init_csa(&ctx->csa); | 39 | if (spu_init_csa(&ctx->csa)) |
40 | if (!ctx->csa.lscsa) { | ||
41 | goto out_free; | 40 | goto out_free; |
42 | } | ||
43 | spin_lock_init(&ctx->mmio_lock); | 41 | spin_lock_init(&ctx->mmio_lock); |
44 | spin_lock_init(&ctx->mapping_lock); | 42 | spin_lock_init(&ctx->mapping_lock); |
45 | kref_init(&ctx->kref); | 43 | kref_init(&ctx->kref); |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index d010b2464a98..45614c73c784 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -118,14 +118,32 @@ spufs_mem_write(struct file *file, const char __user *buffer, | |||
118 | static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma, | 118 | static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma, |
119 | unsigned long address) | 119 | unsigned long address) |
120 | { | 120 | { |
121 | struct spu_context *ctx = vma->vm_file->private_data; | 121 | struct spu_context *ctx = vma->vm_file->private_data; |
122 | unsigned long pfn, offset = address - vma->vm_start; | 122 | unsigned long pfn, offset, addr0 = address; |
123 | 123 | #ifdef CONFIG_SPU_FS_64K_LS | |
124 | offset += vma->vm_pgoff << PAGE_SHIFT; | 124 | struct spu_state *csa = &ctx->csa; |
125 | int psize; | ||
126 | |||
127 | /* Check what page size we are using */ | ||
128 | psize = get_slice_psize(vma->vm_mm, address); | ||
129 | |||
130 | /* Some sanity checking */ | ||
131 | BUG_ON(csa->use_big_pages != (psize == MMU_PAGE_64K)); | ||
132 | |||
133 | /* Wow, 64K, cool, we need to align the address though */ | ||
134 | if (csa->use_big_pages) { | ||
135 | BUG_ON(vma->vm_start & 0xffff); | ||
136 | address &= ~0xfffful; | ||
137 | } | ||
138 | #endif /* CONFIG_SPU_FS_64K_LS */ | ||
125 | 139 | ||
140 | offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); | ||
126 | if (offset >= LS_SIZE) | 141 | if (offset >= LS_SIZE) |
127 | return NOPFN_SIGBUS; | 142 | return NOPFN_SIGBUS; |
128 | 143 | ||
144 | pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n", | ||
145 | addr0, address, offset); | ||
146 | |||
129 | spu_acquire(ctx); | 147 | spu_acquire(ctx); |
130 | 148 | ||
131 | if (ctx->state == SPU_STATE_SAVED) { | 149 | if (ctx->state == SPU_STATE_SAVED) { |
@@ -149,9 +167,24 @@ static struct vm_operations_struct spufs_mem_mmap_vmops = { | |||
149 | .nopfn = spufs_mem_mmap_nopfn, | 167 | .nopfn = spufs_mem_mmap_nopfn, |
150 | }; | 168 | }; |
151 | 169 | ||
152 | static int | 170 | static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) |
153 | spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) | 171 | { |
154 | { | 172 | #ifdef CONFIG_SPU_FS_64K_LS |
173 | struct spu_context *ctx = file->private_data; | ||
174 | struct spu_state *csa = &ctx->csa; | ||
175 | |||
176 | /* Sanity check VMA alignment */ | ||
177 | if (csa->use_big_pages) { | ||
178 | pr_debug("spufs_mem_mmap 64K, start=0x%lx, end=0x%lx," | ||
179 | " pgoff=0x%lx\n", vma->vm_start, vma->vm_end, | ||
180 | vma->vm_pgoff); | ||
181 | if (vma->vm_start & 0xffff) | ||
182 | return -EINVAL; | ||
183 | if (vma->vm_pgoff & 0xf) | ||
184 | return -EINVAL; | ||
185 | } | ||
186 | #endif /* CONFIG_SPU_FS_64K_LS */ | ||
187 | |||
155 | if (!(vma->vm_flags & VM_SHARED)) | 188 | if (!(vma->vm_flags & VM_SHARED)) |
156 | return -EINVAL; | 189 | return -EINVAL; |
157 | 190 | ||
@@ -163,13 +196,34 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) | |||
163 | return 0; | 196 | return 0; |
164 | } | 197 | } |
165 | 198 | ||
199 | #ifdef CONFIG_SPU_FS_64K_LS | ||
200 | unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, | ||
201 | unsigned long len, unsigned long pgoff, | ||
202 | unsigned long flags) | ||
203 | { | ||
204 | struct spu_context *ctx = file->private_data; | ||
205 | struct spu_state *csa = &ctx->csa; | ||
206 | |||
207 | /* If not using big pages, fallback to normal MM g_u_a */ | ||
208 | if (!csa->use_big_pages) | ||
209 | return current->mm->get_unmapped_area(file, addr, len, | ||
210 | pgoff, flags); | ||
211 | |||
212 | /* Else, try to obtain a 64K pages slice */ | ||
213 | return slice_get_unmapped_area(addr, len, flags, | ||
214 | MMU_PAGE_64K, 1, 0); | ||
215 | } | ||
216 | #endif /* CONFIG_SPU_FS_64K_LS */ | ||
217 | |||
166 | static const struct file_operations spufs_mem_fops = { | 218 | static const struct file_operations spufs_mem_fops = { |
167 | .open = spufs_mem_open, | 219 | .open = spufs_mem_open, |
168 | .release = spufs_mem_release, | 220 | .read = spufs_mem_read, |
169 | .read = spufs_mem_read, | 221 | .write = spufs_mem_write, |
170 | .write = spufs_mem_write, | 222 | .llseek = generic_file_llseek, |
171 | .llseek = generic_file_llseek, | 223 | .mmap = spufs_mem_mmap, |
172 | .mmap = spufs_mem_mmap, | 224 | #ifdef CONFIG_SPU_FS_64K_LS |
225 | .get_unmapped_area = spufs_get_unmapped_area, | ||
226 | #endif | ||
173 | }; | 227 | }; |
174 | 228 | ||
175 | static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | 229 | static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, |
diff --git a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c new file mode 100644 index 000000000000..f4b3c052dabf --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * SPU local store allocation routines | ||
3 | * | ||
4 | * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. | ||
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, or (at your option) | ||
9 | * 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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #undef DEBUG | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/vmalloc.h> | ||
26 | |||
27 | #include <asm/spu.h> | ||
28 | #include <asm/spu_csa.h> | ||
29 | #include <asm/mmu.h> | ||
30 | |||
31 | static int spu_alloc_lscsa_std(struct spu_state *csa) | ||
32 | { | ||
33 | struct spu_lscsa *lscsa; | ||
34 | unsigned char *p; | ||
35 | |||
36 | lscsa = vmalloc(sizeof(struct spu_lscsa)); | ||
37 | if (!lscsa) | ||
38 | return -ENOMEM; | ||
39 | memset(lscsa, 0, sizeof(struct spu_lscsa)); | ||
40 | csa->lscsa = lscsa; | ||
41 | |||
42 | /* Set LS pages reserved to allow for user-space mapping. */ | ||
43 | for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE) | ||
44 | SetPageReserved(vmalloc_to_page(p)); | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void spu_free_lscsa_std(struct spu_state *csa) | ||
50 | { | ||
51 | /* Clear reserved bit before vfree. */ | ||
52 | unsigned char *p; | ||
53 | |||
54 | if (csa->lscsa == NULL) | ||
55 | return; | ||
56 | |||
57 | for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) | ||
58 | ClearPageReserved(vmalloc_to_page(p)); | ||
59 | |||
60 | vfree(csa->lscsa); | ||
61 | } | ||
62 | |||
63 | #ifdef CONFIG_SPU_FS_64K_LS | ||
64 | |||
65 | #define SPU_64K_PAGE_SHIFT 16 | ||
66 | #define SPU_64K_PAGE_ORDER (SPU_64K_PAGE_SHIFT - PAGE_SHIFT) | ||
67 | #define SPU_64K_PAGE_COUNT (1ul << SPU_64K_PAGE_ORDER) | ||
68 | |||
69 | int spu_alloc_lscsa(struct spu_state *csa) | ||
70 | { | ||
71 | struct page **pgarray; | ||
72 | unsigned char *p; | ||
73 | int i, j, n_4k; | ||
74 | |||
75 | /* Check availability of 64K pages */ | ||
76 | if (mmu_psize_defs[MMU_PAGE_64K].shift == 0) | ||
77 | goto fail; | ||
78 | |||
79 | csa->use_big_pages = 1; | ||
80 | |||
81 | pr_debug("spu_alloc_lscsa(csa=0x%p), trying to allocate 64K pages\n", | ||
82 | csa); | ||
83 | |||
84 | /* First try to allocate our 64K pages. We need 5 of them | ||
85 | * with the current implementation. In the future, we should try | ||
86 | * to separate the lscsa with the actual local store image, thus | ||
87 | * allowing us to require only 4 64K pages per context | ||
88 | */ | ||
89 | for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) { | ||
90 | /* XXX This is likely to fail, we should use a special pool | ||
91 | * similiar to what hugetlbfs does. | ||
92 | */ | ||
93 | csa->lscsa_pages[i] = alloc_pages(GFP_KERNEL, | ||
94 | SPU_64K_PAGE_ORDER); | ||
95 | if (csa->lscsa_pages[i] == NULL) | ||
96 | goto fail; | ||
97 | } | ||
98 | |||
99 | pr_debug(" success ! creating vmap...\n"); | ||
100 | |||
101 | /* Now we need to create a vmalloc mapping of these for the kernel | ||
102 | * and SPU context switch code to use. Currently, we stick to a | ||
103 | * normal kernel vmalloc mapping, which in our case will be 4K | ||
104 | */ | ||
105 | n_4k = SPU_64K_PAGE_COUNT * SPU_LSCSA_NUM_BIG_PAGES; | ||
106 | pgarray = kmalloc(sizeof(struct page *) * n_4k, GFP_KERNEL); | ||
107 | if (pgarray == NULL) | ||
108 | goto fail; | ||
109 | for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) | ||
110 | for (j = 0; j < SPU_64K_PAGE_COUNT; j++) | ||
111 | /* We assume all the struct page's are contiguous | ||
112 | * which should be hopefully the case for an order 4 | ||
113 | * allocation.. | ||
114 | */ | ||
115 | pgarray[i * SPU_64K_PAGE_COUNT + j] = | ||
116 | csa->lscsa_pages[i] + j; | ||
117 | csa->lscsa = vmap(pgarray, n_4k, VM_USERMAP, PAGE_KERNEL); | ||
118 | kfree(pgarray); | ||
119 | if (csa->lscsa == NULL) | ||
120 | goto fail; | ||
121 | |||
122 | memset(csa->lscsa, 0, sizeof(struct spu_lscsa)); | ||
123 | |||
124 | /* Set LS pages reserved to allow for user-space mapping. | ||
125 | * | ||
126 | * XXX isn't that a bit obsolete ? I think we should just | ||
127 | * make sure the page count is high enough. Anyway, won't harm | ||
128 | * for now | ||
129 | */ | ||
130 | for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) | ||
131 | SetPageReserved(vmalloc_to_page(p)); | ||
132 | |||
133 | pr_debug(" all good !\n"); | ||
134 | |||
135 | return 0; | ||
136 | fail: | ||
137 | pr_debug("spufs: failed to allocate lscsa 64K pages, falling back\n"); | ||
138 | spu_free_lscsa(csa); | ||
139 | return spu_alloc_lscsa_std(csa); | ||
140 | } | ||
141 | |||
142 | void spu_free_lscsa(struct spu_state *csa) | ||
143 | { | ||
144 | unsigned char *p; | ||
145 | int i; | ||
146 | |||
147 | if (!csa->use_big_pages) { | ||
148 | spu_free_lscsa_std(csa); | ||
149 | return; | ||
150 | } | ||
151 | csa->use_big_pages = 0; | ||
152 | |||
153 | if (csa->lscsa == NULL) | ||
154 | goto free_pages; | ||
155 | |||
156 | for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) | ||
157 | ClearPageReserved(vmalloc_to_page(p)); | ||
158 | |||
159 | vunmap(csa->lscsa); | ||
160 | csa->lscsa = NULL; | ||
161 | |||
162 | free_pages: | ||
163 | |||
164 | for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) | ||
165 | if (csa->lscsa_pages[i]) | ||
166 | __free_pages(csa->lscsa_pages[i], SPU_64K_PAGE_ORDER); | ||
167 | } | ||
168 | |||
169 | #else /* CONFIG_SPU_FS_64K_LS */ | ||
170 | |||
171 | int spu_alloc_lscsa(struct spu_state *csa) | ||
172 | { | ||
173 | return spu_alloc_lscsa_std(csa); | ||
174 | } | ||
175 | |||
176 | void spu_free_lscsa(struct spu_state *csa) | ||
177 | { | ||
178 | spu_free_lscsa_std(csa); | ||
179 | } | ||
180 | |||
181 | #endif /* !defined(CONFIG_SPU_FS_64K_LS) */ | ||
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 29dc59cefc38..71a0b41adb8c 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
@@ -2188,40 +2188,30 @@ static void init_priv2(struct spu_state *csa) | |||
2188 | * as it is by far the largest of the context save regions, | 2188 | * as it is by far the largest of the context save regions, |
2189 | * and may need to be pinned or otherwise specially aligned. | 2189 | * and may need to be pinned or otherwise specially aligned. |
2190 | */ | 2190 | */ |
2191 | void spu_init_csa(struct spu_state *csa) | 2191 | int spu_init_csa(struct spu_state *csa) |
2192 | { | 2192 | { |
2193 | struct spu_lscsa *lscsa; | 2193 | int rc; |
2194 | unsigned char *p; | ||
2195 | 2194 | ||
2196 | if (!csa) | 2195 | if (!csa) |
2197 | return; | 2196 | return -EINVAL; |
2198 | memset(csa, 0, sizeof(struct spu_state)); | 2197 | memset(csa, 0, sizeof(struct spu_state)); |
2199 | 2198 | ||
2200 | lscsa = vmalloc(sizeof(struct spu_lscsa)); | 2199 | rc = spu_alloc_lscsa(csa); |
2201 | if (!lscsa) | 2200 | if (rc) |
2202 | return; | 2201 | return rc; |
2203 | 2202 | ||
2204 | memset(lscsa, 0, sizeof(struct spu_lscsa)); | ||
2205 | csa->lscsa = lscsa; | ||
2206 | spin_lock_init(&csa->register_lock); | 2203 | spin_lock_init(&csa->register_lock); |
2207 | 2204 | ||
2208 | /* Set LS pages reserved to allow for user-space mapping. */ | ||
2209 | for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE) | ||
2210 | SetPageReserved(vmalloc_to_page(p)); | ||
2211 | |||
2212 | init_prob(csa); | 2205 | init_prob(csa); |
2213 | init_priv1(csa); | 2206 | init_priv1(csa); |
2214 | init_priv2(csa); | 2207 | init_priv2(csa); |
2208 | |||
2209 | return 0; | ||
2215 | } | 2210 | } |
2216 | EXPORT_SYMBOL_GPL(spu_init_csa); | 2211 | EXPORT_SYMBOL_GPL(spu_init_csa); |
2217 | 2212 | ||
2218 | void spu_fini_csa(struct spu_state *csa) | 2213 | void spu_fini_csa(struct spu_state *csa) |
2219 | { | 2214 | { |
2220 | /* Clear reserved bit before vfree. */ | 2215 | spu_free_lscsa(csa); |
2221 | unsigned char *p; | ||
2222 | for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE) | ||
2223 | ClearPageReserved(vmalloc_to_page(p)); | ||
2224 | |||
2225 | vfree(csa->lscsa); | ||
2226 | } | 2216 | } |
2227 | EXPORT_SYMBOL_GPL(spu_fini_csa); | 2217 | EXPORT_SYMBOL_GPL(spu_fini_csa); |
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig index 46c3a8e7c3a8..761d9e971fc4 100644 --- a/arch/powerpc/platforms/iseries/Kconfig +++ b/arch/powerpc/platforms/iseries/Kconfig | |||
@@ -7,7 +7,9 @@ menu "iSeries device drivers" | |||
7 | depends on PPC_ISERIES | 7 | depends on PPC_ISERIES |
8 | 8 | ||
9 | config VIOCONS | 9 | config VIOCONS |
10 | tristate "iSeries Virtual Console Support (Obsolete)" | 10 | bool "iSeries Virtual Console Support (Obsolete)" |
11 | depends on !HVC_ISERIES | ||
12 | default n | ||
11 | help | 13 | help |
12 | This is the old virtual console driver for legacy iSeries. | 14 | This is the old virtual console driver for legacy iSeries. |
13 | You should use the iSeries Hypervisor Virtual Console | 15 | You should use the iSeries Hypervisor Virtual Console |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 63e23062e982..093438b93bd9 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -100,6 +100,9 @@ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; | |||
100 | static DEFINE_SPINLOCK(slot_errbuf_lock); | 100 | static DEFINE_SPINLOCK(slot_errbuf_lock); |
101 | static int eeh_error_buf_size; | 101 | static int eeh_error_buf_size; |
102 | 102 | ||
103 | #define EEH_PCI_REGS_LOG_LEN 4096 | ||
104 | static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN]; | ||
105 | |||
103 | /* System monitoring statistics */ | 106 | /* System monitoring statistics */ |
104 | static unsigned long no_device; | 107 | static unsigned long no_device; |
105 | static unsigned long no_dn; | 108 | static unsigned long no_dn; |
@@ -115,7 +118,8 @@ static unsigned long slot_resets; | |||
115 | /* --------------------------------------------------------------- */ | 118 | /* --------------------------------------------------------------- */ |
116 | /* Below lies the EEH event infrastructure */ | 119 | /* Below lies the EEH event infrastructure */ |
117 | 120 | ||
118 | void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | 121 | static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, |
122 | char *driver_log, size_t loglen) | ||
119 | { | 123 | { |
120 | int config_addr; | 124 | int config_addr; |
121 | unsigned long flags; | 125 | unsigned long flags; |
@@ -133,7 +137,8 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | |||
133 | rc = rtas_call(ibm_slot_error_detail, | 137 | rc = rtas_call(ibm_slot_error_detail, |
134 | 8, 1, NULL, config_addr, | 138 | 8, 1, NULL, config_addr, |
135 | BUID_HI(pdn->phb->buid), | 139 | BUID_HI(pdn->phb->buid), |
136 | BUID_LO(pdn->phb->buid), NULL, 0, | 140 | BUID_LO(pdn->phb->buid), |
141 | virt_to_phys(driver_log), loglen, | ||
137 | virt_to_phys(slot_errbuf), | 142 | virt_to_phys(slot_errbuf), |
138 | eeh_error_buf_size, | 143 | eeh_error_buf_size, |
139 | severity); | 144 | severity); |
@@ -144,6 +149,84 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | |||
144 | } | 149 | } |
145 | 150 | ||
146 | /** | 151 | /** |
152 | * gather_pci_data - copy assorted PCI config space registers to buff | ||
153 | * @pdn: device to report data for | ||
154 | * @buf: point to buffer in which to log | ||
155 | * @len: amount of room in buffer | ||
156 | * | ||
157 | * This routine captures assorted PCI configuration space data, | ||
158 | * and puts them into a buffer for RTAS error logging. | ||
159 | */ | ||
160 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | ||
161 | { | ||
162 | u32 cfg; | ||
163 | int cap, i; | ||
164 | int n = 0; | ||
165 | |||
166 | n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name); | ||
167 | printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name); | ||
168 | |||
169 | rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg); | ||
170 | n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); | ||
171 | printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); | ||
172 | |||
173 | rtas_read_config(pdn, PCI_COMMAND, 4, &cfg); | ||
174 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); | ||
175 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); | ||
176 | |||
177 | /* Dump out the PCI-X command and status regs */ | ||
178 | cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX); | ||
179 | if (cap) { | ||
180 | rtas_read_config(pdn, cap, 4, &cfg); | ||
181 | n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); | ||
182 | printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); | ||
183 | |||
184 | rtas_read_config(pdn, cap+4, 4, &cfg); | ||
185 | n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); | ||
186 | printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); | ||
187 | } | ||
188 | |||
189 | /* If PCI-E capable, dump PCI-E cap 10, and the AER */ | ||
190 | cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_EXP); | ||
191 | if (cap) { | ||
192 | n += scnprintf(buf+n, len-n, "pci-e cap10:\n"); | ||
193 | printk(KERN_WARNING | ||
194 | "EEH: PCI-E capabilities and status follow:\n"); | ||
195 | |||
196 | for (i=0; i<=8; i++) { | ||
197 | rtas_read_config(pdn, cap+4*i, 4, &cfg); | ||
198 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | ||
199 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); | ||
200 | } | ||
201 | |||
202 | cap = pci_find_ext_capability(pdn->pcidev,PCI_EXT_CAP_ID_ERR); | ||
203 | if (cap) { | ||
204 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); | ||
205 | printk(KERN_WARNING | ||
206 | "EEH: PCI-E AER capability register set follows:\n"); | ||
207 | |||
208 | for (i=0; i<14; i++) { | ||
209 | rtas_read_config(pdn, cap+4*i, 4, &cfg); | ||
210 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | ||
211 | printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | return n; | ||
216 | } | ||
217 | |||
218 | void eeh_slot_error_detail(struct pci_dn *pdn, int severity) | ||
219 | { | ||
220 | size_t loglen = 0; | ||
221 | memset(pci_regs_buf, 0, EEH_PCI_REGS_LOG_LEN); | ||
222 | |||
223 | rtas_pci_enable(pdn, EEH_THAW_MMIO); | ||
224 | loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN); | ||
225 | |||
226 | rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen); | ||
227 | } | ||
228 | |||
229 | /** | ||
147 | * read_slot_reset_state - Read the reset state of a device node's slot | 230 | * read_slot_reset_state - Read the reset state of a device node's slot |
148 | * @dn: device node to read | 231 | * @dn: device node to read |
149 | * @rets: array to return results in | 232 | * @rets: array to return results in |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 3170e003f76a..f07d849cfc84 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -361,11 +361,12 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) | |||
361 | goto hard_fail; | 361 | goto hard_fail; |
362 | } | 362 | } |
363 | 363 | ||
364 | eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); | ||
365 | printk(KERN_WARNING | 364 | printk(KERN_WARNING |
366 | "EEH: This PCI device has failed %d times since last reboot: " | 365 | "EEH: This PCI device has failed %d times in the last hour:\n", |
367 | "location=%s driver=%s pci addr=%s\n", | 366 | frozen_pdn->eeh_freeze_count); |
368 | frozen_pdn->eeh_freeze_count, location, drv_str, pci_str); | 367 | printk(KERN_WARNING |
368 | "EEH: location=%s driver=%s pci addr=%s\n", | ||
369 | location, drv_str, pci_str); | ||
369 | 370 | ||
370 | /* Walk the various device drivers attached to this slot through | 371 | /* Walk the various device drivers attached to this slot through |
371 | * a reset sequence, giving each an opportunity to do what it needs | 372 | * a reset sequence, giving each an opportunity to do what it needs |
@@ -375,6 +376,11 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) | |||
375 | */ | 376 | */ |
376 | pci_walk_bus(frozen_bus, eeh_report_error, &result); | 377 | pci_walk_bus(frozen_bus, eeh_report_error, &result); |
377 | 378 | ||
379 | /* Since rtas may enable MMIO when posting the error log, | ||
380 | * don't post the error log until after all dev drivers | ||
381 | * have been informed. */ | ||
382 | eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); | ||
383 | |||
378 | /* If all device drivers were EEH-unaware, then shut | 384 | /* If all device drivers were EEH-unaware, then shut |
379 | * down all of the device drivers, and hope they | 385 | * down all of the device drivers, and hope they |
380 | * go down willingly, without panicing the system. | 386 | * go down willingly, without panicing the system. |