Annotation of /trunk/kernel26-alx/patches-2.6.20-r5/0111-2.6.20.11-all-fixes.patch
Parent Directory | Revision Log
Revision 199 -
(hide annotations)
(download)
Fri May 18 11:04:36 2007 UTC (17 years, 4 months ago) by niro
File size: 64264 byte(s)
Fri May 18 11:04:36 2007 UTC (17 years, 4 months ago) by niro
File size: 64264 byte(s)
-import
1 | niro | 199 | diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S |
2 | index 2c5b5cc..8143c95 100644 | ||
3 | --- a/arch/i386/boot/video.S | ||
4 | +++ b/arch/i386/boot/video.S | ||
5 | @@ -571,6 +571,16 @@ setr1: lodsw | ||
6 | jmp _m_s | ||
7 | |||
8 | check_vesa: | ||
9 | +#ifdef CONFIG_FIRMWARE_EDID | ||
10 | + leaw modelist+1024, %di | ||
11 | + movw $0x4f00, %ax | ||
12 | + int $0x10 | ||
13 | + cmpw $0x004f, %ax | ||
14 | + jnz setbad | ||
15 | + | ||
16 | + movw 4(%di), %ax | ||
17 | + movw %ax, vbe_version | ||
18 | +#endif | ||
19 | leaw modelist+1024, %di | ||
20 | subb $VIDEO_FIRST_VESA>>8, %bh | ||
21 | movw %bx, %cx # Get mode information structure | ||
22 | @@ -1945,6 +1955,9 @@ store_edid: | ||
23 | rep | ||
24 | stosl | ||
25 | |||
26 | + cmpw $0x0200, vbe_version # only do EDID on >= VBE2.0 | ||
27 | + jl no_edid | ||
28 | + | ||
29 | pushw %es # save ES | ||
30 | xorw %di, %di # Report Capability | ||
31 | pushw %di | ||
32 | @@ -1987,6 +2000,7 @@ do_restore: .byte 0 # Screen contents altered during mode change | ||
33 | svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes | ||
34 | graphic_mode: .byte 0 # Graphic mode with a linear frame buffer | ||
35 | dac_size: .byte 6 # DAC bit depth | ||
36 | +vbe_version: .word 0 # VBE bios version | ||
37 | |||
38 | # Status messages | ||
39 | keymsg: .ascii "Press <RETURN> to see video modes available, " | ||
40 | diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c | ||
41 | index 2e7f142..7aca0f3 100644 | ||
42 | --- a/arch/sparc64/kernel/pci_iommu.c | ||
43 | +++ b/arch/sparc64/kernel/pci_iommu.c | ||
44 | @@ -64,7 +64,7 @@ static void __iommu_flushall(struct pci_iommu *iommu) | ||
45 | #define IOPTE_IS_DUMMY(iommu, iopte) \ | ||
46 | ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa) | ||
47 | |||
48 | -static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) | ||
49 | +static inline void iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) | ||
50 | { | ||
51 | unsigned long val = iopte_val(*iopte); | ||
52 | |||
53 | diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c | ||
54 | index 01d6d86..14f78fb 100644 | ||
55 | --- a/arch/sparc64/kernel/sbus.c | ||
56 | +++ b/arch/sparc64/kernel/sbus.c | ||
57 | @@ -24,48 +24,25 @@ | ||
58 | |||
59 | #include "iommu_common.h" | ||
60 | |||
61 | -/* These should be allocated on an SMP_CACHE_BYTES | ||
62 | - * aligned boundary for optimal performance. | ||
63 | - * | ||
64 | - * On SYSIO, using an 8K page size we have 1GB of SBUS | ||
65 | - * DMA space mapped. We divide this space into equally | ||
66 | - * sized clusters. We allocate a DMA mapping from the | ||
67 | - * cluster that matches the order of the allocation, or | ||
68 | - * if the order is greater than the number of clusters, | ||
69 | - * we try to allocate from the last cluster. | ||
70 | - */ | ||
71 | - | ||
72 | -#define NCLUSTERS 8UL | ||
73 | -#define ONE_GIG (1UL * 1024UL * 1024UL * 1024UL) | ||
74 | -#define CLUSTER_SIZE (ONE_GIG / NCLUSTERS) | ||
75 | -#define CLUSTER_MASK (CLUSTER_SIZE - 1) | ||
76 | -#define CLUSTER_NPAGES (CLUSTER_SIZE >> IO_PAGE_SHIFT) | ||
77 | #define MAP_BASE ((u32)0xc0000000) | ||
78 | |||
79 | +struct sbus_iommu_arena { | ||
80 | + unsigned long *map; | ||
81 | + unsigned int hint; | ||
82 | + unsigned int limit; | ||
83 | +}; | ||
84 | + | ||
85 | struct sbus_iommu { | ||
86 | -/*0x00*/spinlock_t lock; | ||
87 | + spinlock_t lock; | ||
88 | |||
89 | -/*0x08*/iopte_t *page_table; | ||
90 | -/*0x10*/unsigned long strbuf_regs; | ||
91 | -/*0x18*/unsigned long iommu_regs; | ||
92 | -/*0x20*/unsigned long sbus_control_reg; | ||
93 | + struct sbus_iommu_arena arena; | ||
94 | |||
95 | -/*0x28*/volatile unsigned long strbuf_flushflag; | ||
96 | + iopte_t *page_table; | ||
97 | + unsigned long strbuf_regs; | ||
98 | + unsigned long iommu_regs; | ||
99 | + unsigned long sbus_control_reg; | ||
100 | |||
101 | - /* If NCLUSTERS is ever decresed to 4 or lower, | ||
102 | - * you must increase the size of the type of | ||
103 | - * these counters. You have been duly warned. -DaveM | ||
104 | - */ | ||
105 | -/*0x30*/struct { | ||
106 | - u16 next; | ||
107 | - u16 flush; | ||
108 | - } alloc_info[NCLUSTERS]; | ||
109 | - | ||
110 | - /* The lowest used consistent mapping entry. Since | ||
111 | - * we allocate consistent maps out of cluster 0 this | ||
112 | - * is relative to the beginning of closter 0. | ||
113 | - */ | ||
114 | -/*0x50*/u32 lowest_consistent_map; | ||
115 | + volatile unsigned long strbuf_flushflag; | ||
116 | }; | ||
117 | |||
118 | /* Offsets from iommu_regs */ | ||
119 | @@ -91,19 +68,6 @@ static void __iommu_flushall(struct sbus_iommu *iommu) | ||
120 | tag += 8UL; | ||
121 | } | ||
122 | upa_readq(iommu->sbus_control_reg); | ||
123 | - | ||
124 | - for (entry = 0; entry < NCLUSTERS; entry++) { | ||
125 | - iommu->alloc_info[entry].flush = | ||
126 | - iommu->alloc_info[entry].next; | ||
127 | - } | ||
128 | -} | ||
129 | - | ||
130 | -static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) | ||
131 | -{ | ||
132 | - while (npages--) | ||
133 | - upa_writeq(base + (npages << IO_PAGE_SHIFT), | ||
134 | - iommu->iommu_regs + IOMMU_FLUSH); | ||
135 | - upa_readq(iommu->sbus_control_reg); | ||
136 | } | ||
137 | |||
138 | /* Offsets from strbuf_regs */ | ||
139 | @@ -156,178 +120,115 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long | ||
140 | base, npages); | ||
141 | } | ||
142 | |||
143 | -static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) | ||
144 | +/* Based largely upon the ppc64 iommu allocator. */ | ||
145 | +static long sbus_arena_alloc(struct sbus_iommu *iommu, unsigned long npages) | ||
146 | { | ||
147 | - iopte_t *iopte, *limit, *first, *cluster; | ||
148 | - unsigned long cnum, ent, nent, flush_point, found; | ||
149 | - | ||
150 | - cnum = 0; | ||
151 | - nent = 1; | ||
152 | - while ((1UL << cnum) < npages) | ||
153 | - cnum++; | ||
154 | - if(cnum >= NCLUSTERS) { | ||
155 | - nent = 1UL << (cnum - NCLUSTERS); | ||
156 | - cnum = NCLUSTERS - 1; | ||
157 | - } | ||
158 | - iopte = iommu->page_table + (cnum * CLUSTER_NPAGES); | ||
159 | - | ||
160 | - if (cnum == 0) | ||
161 | - limit = (iommu->page_table + | ||
162 | - iommu->lowest_consistent_map); | ||
163 | - else | ||
164 | - limit = (iopte + CLUSTER_NPAGES); | ||
165 | - | ||
166 | - iopte += ((ent = iommu->alloc_info[cnum].next) << cnum); | ||
167 | - flush_point = iommu->alloc_info[cnum].flush; | ||
168 | - | ||
169 | - first = iopte; | ||
170 | - cluster = NULL; | ||
171 | - found = 0; | ||
172 | - for (;;) { | ||
173 | - if (iopte_val(*iopte) == 0UL) { | ||
174 | - found++; | ||
175 | - if (!cluster) | ||
176 | - cluster = iopte; | ||
177 | + struct sbus_iommu_arena *arena = &iommu->arena; | ||
178 | + unsigned long n, i, start, end, limit; | ||
179 | + int pass; | ||
180 | + | ||
181 | + limit = arena->limit; | ||
182 | + start = arena->hint; | ||
183 | + pass = 0; | ||
184 | + | ||
185 | +again: | ||
186 | + n = find_next_zero_bit(arena->map, limit, start); | ||
187 | + end = n + npages; | ||
188 | + if (unlikely(end >= limit)) { | ||
189 | + if (likely(pass < 1)) { | ||
190 | + limit = start; | ||
191 | + start = 0; | ||
192 | + __iommu_flushall(iommu); | ||
193 | + pass++; | ||
194 | + goto again; | ||
195 | } else { | ||
196 | - /* Used cluster in the way */ | ||
197 | - cluster = NULL; | ||
198 | - found = 0; | ||
199 | + /* Scanned the whole thing, give up. */ | ||
200 | + return -1; | ||
201 | } | ||
202 | + } | ||
203 | |||
204 | - if (found == nent) | ||
205 | - break; | ||
206 | - | ||
207 | - iopte += (1 << cnum); | ||
208 | - ent++; | ||
209 | - if (iopte >= limit) { | ||
210 | - iopte = (iommu->page_table + (cnum * CLUSTER_NPAGES)); | ||
211 | - ent = 0; | ||
212 | - | ||
213 | - /* Multiple cluster allocations must not wrap */ | ||
214 | - cluster = NULL; | ||
215 | - found = 0; | ||
216 | + for (i = n; i < end; i++) { | ||
217 | + if (test_bit(i, arena->map)) { | ||
218 | + start = i + 1; | ||
219 | + goto again; | ||
220 | } | ||
221 | - if (ent == flush_point) | ||
222 | - __iommu_flushall(iommu); | ||
223 | - if (iopte == first) | ||
224 | - goto bad; | ||
225 | } | ||
226 | |||
227 | - /* ent/iopte points to the last cluster entry we're going to use, | ||
228 | - * so save our place for the next allocation. | ||
229 | - */ | ||
230 | - if ((iopte + (1 << cnum)) >= limit) | ||
231 | - ent = 0; | ||
232 | - else | ||
233 | - ent = ent + 1; | ||
234 | - iommu->alloc_info[cnum].next = ent; | ||
235 | - if (ent == flush_point) | ||
236 | - __iommu_flushall(iommu); | ||
237 | - | ||
238 | - /* I've got your streaming cluster right here buddy boy... */ | ||
239 | - return cluster; | ||
240 | - | ||
241 | -bad: | ||
242 | - printk(KERN_EMERG "sbus: alloc_streaming_cluster of npages(%ld) failed!\n", | ||
243 | - npages); | ||
244 | - return NULL; | ||
245 | + for (i = n; i < end; i++) | ||
246 | + __set_bit(i, arena->map); | ||
247 | + | ||
248 | + arena->hint = end; | ||
249 | + | ||
250 | + return n; | ||
251 | } | ||
252 | |||
253 | -static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) | ||
254 | +static void sbus_arena_free(struct sbus_iommu_arena *arena, unsigned long base, unsigned long npages) | ||
255 | { | ||
256 | - unsigned long cnum, ent, nent; | ||
257 | - iopte_t *iopte; | ||
258 | + unsigned long i; | ||
259 | |||
260 | - cnum = 0; | ||
261 | - nent = 1; | ||
262 | - while ((1UL << cnum) < npages) | ||
263 | - cnum++; | ||
264 | - if(cnum >= NCLUSTERS) { | ||
265 | - nent = 1UL << (cnum - NCLUSTERS); | ||
266 | - cnum = NCLUSTERS - 1; | ||
267 | - } | ||
268 | - ent = (base & CLUSTER_MASK) >> (IO_PAGE_SHIFT + cnum); | ||
269 | - iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); | ||
270 | - do { | ||
271 | - iopte_val(*iopte) = 0UL; | ||
272 | - iopte += 1 << cnum; | ||
273 | - } while(--nent); | ||
274 | - | ||
275 | - /* If the global flush might not have caught this entry, | ||
276 | - * adjust the flush point such that we will flush before | ||
277 | - * ever trying to reuse it. | ||
278 | - */ | ||
279 | -#define between(X,Y,Z) (((Z) - (Y)) >= ((X) - (Y))) | ||
280 | - if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush)) | ||
281 | - iommu->alloc_info[cnum].flush = ent; | ||
282 | -#undef between | ||
283 | + for (i = base; i < (base + npages); i++) | ||
284 | + __clear_bit(i, arena->map); | ||
285 | } | ||
286 | |||
287 | -/* We allocate consistent mappings from the end of cluster zero. */ | ||
288 | -static iopte_t *alloc_consistent_cluster(struct sbus_iommu *iommu, unsigned long npages) | ||
289 | +static void sbus_iommu_table_init(struct sbus_iommu *iommu, unsigned int tsbsize) | ||
290 | { | ||
291 | - iopte_t *iopte; | ||
292 | + unsigned long tsbbase, order, sz, num_tsb_entries; | ||
293 | |||
294 | - iopte = iommu->page_table + (1 * CLUSTER_NPAGES); | ||
295 | - while (iopte > iommu->page_table) { | ||
296 | - iopte--; | ||
297 | - if (!(iopte_val(*iopte) & IOPTE_VALID)) { | ||
298 | - unsigned long tmp = npages; | ||
299 | + num_tsb_entries = tsbsize / sizeof(iopte_t); | ||
300 | |||
301 | - while (--tmp) { | ||
302 | - iopte--; | ||
303 | - if (iopte_val(*iopte) & IOPTE_VALID) | ||
304 | - break; | ||
305 | - } | ||
306 | - if (tmp == 0) { | ||
307 | - u32 entry = (iopte - iommu->page_table); | ||
308 | + /* Setup initial software IOMMU state. */ | ||
309 | + spin_lock_init(&iommu->lock); | ||
310 | |||
311 | - if (entry < iommu->lowest_consistent_map) | ||
312 | - iommu->lowest_consistent_map = entry; | ||
313 | - return iopte; | ||
314 | - } | ||
315 | - } | ||
316 | + /* Allocate and initialize the free area map. */ | ||
317 | + sz = num_tsb_entries / 8; | ||
318 | + sz = (sz + 7UL) & ~7UL; | ||
319 | + iommu->arena.map = kzalloc(sz, GFP_KERNEL); | ||
320 | + if (!iommu->arena.map) { | ||
321 | + prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); | ||
322 | + prom_halt(); | ||
323 | + } | ||
324 | + iommu->arena.limit = num_tsb_entries; | ||
325 | + | ||
326 | + /* Now allocate and setup the IOMMU page table itself. */ | ||
327 | + order = get_order(tsbsize); | ||
328 | + tsbbase = __get_free_pages(GFP_KERNEL, order); | ||
329 | + if (!tsbbase) { | ||
330 | + prom_printf("IOMMU: Error, gfp(tsb) failed.\n"); | ||
331 | + prom_halt(); | ||
332 | } | ||
333 | - return NULL; | ||
334 | + iommu->page_table = (iopte_t *)tsbbase; | ||
335 | + memset(iommu->page_table, 0, tsbsize); | ||
336 | } | ||
337 | |||
338 | -static void free_consistent_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) | ||
339 | +static inline iopte_t *alloc_npages(struct sbus_iommu *iommu, unsigned long npages) | ||
340 | { | ||
341 | - iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); | ||
342 | + long entry; | ||
343 | |||
344 | - if ((iopte - iommu->page_table) == iommu->lowest_consistent_map) { | ||
345 | - iopte_t *walk = iopte + npages; | ||
346 | - iopte_t *limit; | ||
347 | + entry = sbus_arena_alloc(iommu, npages); | ||
348 | + if (unlikely(entry < 0)) | ||
349 | + return NULL; | ||
350 | |||
351 | - limit = iommu->page_table + CLUSTER_NPAGES; | ||
352 | - while (walk < limit) { | ||
353 | - if (iopte_val(*walk) != 0UL) | ||
354 | - break; | ||
355 | - walk++; | ||
356 | - } | ||
357 | - iommu->lowest_consistent_map = | ||
358 | - (walk - iommu->page_table); | ||
359 | - } | ||
360 | + return iommu->page_table + entry; | ||
361 | +} | ||
362 | |||
363 | - while (npages--) | ||
364 | - *iopte++ = __iopte(0UL); | ||
365 | +static inline void free_npages(struct sbus_iommu *iommu, dma_addr_t base, unsigned long npages) | ||
366 | +{ | ||
367 | + sbus_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages); | ||
368 | } | ||
369 | |||
370 | void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr) | ||
371 | { | ||
372 | - unsigned long order, first_page, flags; | ||
373 | struct sbus_iommu *iommu; | ||
374 | iopte_t *iopte; | ||
375 | + unsigned long flags, order, first_page; | ||
376 | void *ret; | ||
377 | int npages; | ||
378 | |||
379 | - if (size <= 0 || sdev == NULL || dvma_addr == NULL) | ||
380 | - return NULL; | ||
381 | - | ||
382 | size = IO_PAGE_ALIGN(size); | ||
383 | order = get_order(size); | ||
384 | if (order >= 10) | ||
385 | return NULL; | ||
386 | + | ||
387 | first_page = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); | ||
388 | if (first_page == 0UL) | ||
389 | return NULL; | ||
390 | @@ -336,108 +237,121 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma | ||
391 | iommu = sdev->bus->iommu; | ||
392 | |||
393 | spin_lock_irqsave(&iommu->lock, flags); | ||
394 | - iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT); | ||
395 | - if (iopte == NULL) { | ||
396 | - spin_unlock_irqrestore(&iommu->lock, flags); | ||
397 | + iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT); | ||
398 | + spin_unlock_irqrestore(&iommu->lock, flags); | ||
399 | + | ||
400 | + if (unlikely(iopte == NULL)) { | ||
401 | free_pages(first_page, order); | ||
402 | return NULL; | ||
403 | } | ||
404 | |||
405 | - /* Ok, we're committed at this point. */ | ||
406 | - *dvma_addr = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); | ||
407 | + *dvma_addr = (MAP_BASE + | ||
408 | + ((iopte - iommu->page_table) << IO_PAGE_SHIFT)); | ||
409 | ret = (void *) first_page; | ||
410 | npages = size >> IO_PAGE_SHIFT; | ||
411 | + first_page = __pa(first_page); | ||
412 | while (npages--) { | ||
413 | - *iopte++ = __iopte(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | | ||
414 | - (__pa(first_page) & IOPTE_PAGE)); | ||
415 | + iopte_val(*iopte) = (IOPTE_VALID | IOPTE_CACHE | | ||
416 | + IOPTE_WRITE | | ||
417 | + (first_page & IOPTE_PAGE)); | ||
418 | + iopte++; | ||
419 | first_page += IO_PAGE_SIZE; | ||
420 | } | ||
421 | - iommu_flush(iommu, *dvma_addr, size >> IO_PAGE_SHIFT); | ||
422 | - spin_unlock_irqrestore(&iommu->lock, flags); | ||
423 | |||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma) | ||
428 | { | ||
429 | - unsigned long order, npages; | ||
430 | struct sbus_iommu *iommu; | ||
431 | - | ||
432 | - if (size <= 0 || sdev == NULL || cpu == NULL) | ||
433 | - return; | ||
434 | + iopte_t *iopte; | ||
435 | + unsigned long flags, order, npages; | ||
436 | |||
437 | npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; | ||
438 | iommu = sdev->bus->iommu; | ||
439 | + iopte = iommu->page_table + | ||
440 | + ((dvma - MAP_BASE) >> IO_PAGE_SHIFT); | ||
441 | + | ||
442 | + spin_lock_irqsave(&iommu->lock, flags); | ||
443 | + | ||
444 | + free_npages(iommu, dvma - MAP_BASE, npages); | ||
445 | |||
446 | - spin_lock_irq(&iommu->lock); | ||
447 | - free_consistent_cluster(iommu, dvma, npages); | ||
448 | - iommu_flush(iommu, dvma, npages); | ||
449 | - spin_unlock_irq(&iommu->lock); | ||
450 | + spin_unlock_irqrestore(&iommu->lock, flags); | ||
451 | |||
452 | order = get_order(size); | ||
453 | if (order < 10) | ||
454 | free_pages((unsigned long)cpu, order); | ||
455 | } | ||
456 | |||
457 | -dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int dir) | ||
458 | +dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int direction) | ||
459 | { | ||
460 | - struct sbus_iommu *iommu = sdev->bus->iommu; | ||
461 | - unsigned long npages, pbase, flags; | ||
462 | - iopte_t *iopte; | ||
463 | - u32 dma_base, offset; | ||
464 | - unsigned long iopte_bits; | ||
465 | + struct sbus_iommu *iommu; | ||
466 | + iopte_t *base; | ||
467 | + unsigned long flags, npages, oaddr; | ||
468 | + unsigned long i, base_paddr; | ||
469 | + u32 bus_addr, ret; | ||
470 | + unsigned long iopte_protection; | ||
471 | + | ||
472 | + iommu = sdev->bus->iommu; | ||
473 | |||
474 | - if (dir == SBUS_DMA_NONE) | ||
475 | + if (unlikely(direction == SBUS_DMA_NONE)) | ||
476 | BUG(); | ||
477 | |||
478 | - pbase = (unsigned long) ptr; | ||
479 | - offset = (u32) (pbase & ~IO_PAGE_MASK); | ||
480 | - size = (IO_PAGE_ALIGN(pbase + size) - (pbase & IO_PAGE_MASK)); | ||
481 | - pbase = (unsigned long) __pa(pbase & IO_PAGE_MASK); | ||
482 | + oaddr = (unsigned long)ptr; | ||
483 | + npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK); | ||
484 | + npages >>= IO_PAGE_SHIFT; | ||
485 | |||
486 | spin_lock_irqsave(&iommu->lock, flags); | ||
487 | - npages = size >> IO_PAGE_SHIFT; | ||
488 | - iopte = alloc_streaming_cluster(iommu, npages); | ||
489 | - if (iopte == NULL) | ||
490 | - goto bad; | ||
491 | - dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); | ||
492 | - npages = size >> IO_PAGE_SHIFT; | ||
493 | - iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; | ||
494 | - if (dir != SBUS_DMA_TODEVICE) | ||
495 | - iopte_bits |= IOPTE_WRITE; | ||
496 | - while (npages--) { | ||
497 | - *iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE)); | ||
498 | - pbase += IO_PAGE_SIZE; | ||
499 | - } | ||
500 | - npages = size >> IO_PAGE_SHIFT; | ||
501 | + base = alloc_npages(iommu, npages); | ||
502 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
503 | |||
504 | - return (dma_base | offset); | ||
505 | + if (unlikely(!base)) | ||
506 | + BUG(); | ||
507 | |||
508 | -bad: | ||
509 | - spin_unlock_irqrestore(&iommu->lock, flags); | ||
510 | - BUG(); | ||
511 | - return 0; | ||
512 | + bus_addr = (MAP_BASE + | ||
513 | + ((base - iommu->page_table) << IO_PAGE_SHIFT)); | ||
514 | + ret = bus_addr | (oaddr & ~IO_PAGE_MASK); | ||
515 | + base_paddr = __pa(oaddr & IO_PAGE_MASK); | ||
516 | + | ||
517 | + iopte_protection = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; | ||
518 | + if (direction != SBUS_DMA_TODEVICE) | ||
519 | + iopte_protection |= IOPTE_WRITE; | ||
520 | + | ||
521 | + for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE) | ||
522 | + iopte_val(*base) = iopte_protection | base_paddr; | ||
523 | + | ||
524 | + return ret; | ||
525 | } | ||
526 | |||
527 | -void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction) | ||
528 | +void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction) | ||
529 | { | ||
530 | struct sbus_iommu *iommu = sdev->bus->iommu; | ||
531 | - u32 dma_base = dma_addr & IO_PAGE_MASK; | ||
532 | - unsigned long flags; | ||
533 | + iopte_t *base; | ||
534 | + unsigned long flags, npages, i; | ||
535 | + | ||
536 | + if (unlikely(direction == SBUS_DMA_NONE)) | ||
537 | + BUG(); | ||
538 | + | ||
539 | + npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); | ||
540 | + npages >>= IO_PAGE_SHIFT; | ||
541 | + base = iommu->page_table + | ||
542 | + ((bus_addr - MAP_BASE) >> IO_PAGE_SHIFT); | ||
543 | |||
544 | - size = (IO_PAGE_ALIGN(dma_addr + size) - dma_base); | ||
545 | + bus_addr &= IO_PAGE_MASK; | ||
546 | |||
547 | spin_lock_irqsave(&iommu->lock, flags); | ||
548 | - free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); | ||
549 | - sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction); | ||
550 | + sbus_strbuf_flush(iommu, bus_addr, npages, direction); | ||
551 | + for (i = 0; i < npages; i++) | ||
552 | + iopte_val(base[i]) = 0UL; | ||
553 | + free_npages(iommu, bus_addr - MAP_BASE, npages); | ||
554 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
555 | } | ||
556 | |||
557 | #define SG_ENT_PHYS_ADDRESS(SG) \ | ||
558 | (__pa(page_address((SG)->page)) + (SG)->offset) | ||
559 | |||
560 | -static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, int nelems, unsigned long iopte_bits) | ||
561 | +static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | ||
562 | + int nused, int nelems, unsigned long iopte_protection) | ||
563 | { | ||
564 | struct scatterlist *dma_sg = sg; | ||
565 | struct scatterlist *sg_end = sg + nelems; | ||
566 | @@ -462,7 +376,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, in | ||
567 | for (;;) { | ||
568 | unsigned long tmp; | ||
569 | |||
570 | - tmp = (unsigned long) SG_ENT_PHYS_ADDRESS(sg); | ||
571 | + tmp = SG_ENT_PHYS_ADDRESS(sg); | ||
572 | len = sg->length; | ||
573 | if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { | ||
574 | pteval = tmp & IO_PAGE_MASK; | ||
575 | @@ -478,7 +392,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, in | ||
576 | sg++; | ||
577 | } | ||
578 | |||
579 | - pteval = ((pteval & IOPTE_PAGE) | iopte_bits); | ||
580 | + pteval = iopte_protection | (pteval & IOPTE_PAGE); | ||
581 | while (len > 0) { | ||
582 | *iopte++ = __iopte(pteval); | ||
583 | pteval += IO_PAGE_SIZE; | ||
584 | @@ -509,103 +423,111 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, in | ||
585 | } | ||
586 | } | ||
587 | |||
588 | -int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int dir) | ||
589 | +int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction) | ||
590 | { | ||
591 | - struct sbus_iommu *iommu = sdev->bus->iommu; | ||
592 | - unsigned long flags, npages; | ||
593 | - iopte_t *iopte; | ||
594 | + struct sbus_iommu *iommu; | ||
595 | + unsigned long flags, npages, iopte_protection; | ||
596 | + iopte_t *base; | ||
597 | u32 dma_base; | ||
598 | struct scatterlist *sgtmp; | ||
599 | int used; | ||
600 | - unsigned long iopte_bits; | ||
601 | - | ||
602 | - if (dir == SBUS_DMA_NONE) | ||
603 | - BUG(); | ||
604 | |||
605 | /* Fast path single entry scatterlists. */ | ||
606 | - if (nents == 1) { | ||
607 | - sg->dma_address = | ||
608 | + if (nelems == 1) { | ||
609 | + sglist->dma_address = | ||
610 | sbus_map_single(sdev, | ||
611 | - (page_address(sg->page) + sg->offset), | ||
612 | - sg->length, dir); | ||
613 | - sg->dma_length = sg->length; | ||
614 | + (page_address(sglist->page) + sglist->offset), | ||
615 | + sglist->length, direction); | ||
616 | + sglist->dma_length = sglist->length; | ||
617 | return 1; | ||
618 | } | ||
619 | |||
620 | - npages = prepare_sg(sg, nents); | ||
621 | + iommu = sdev->bus->iommu; | ||
622 | + | ||
623 | + if (unlikely(direction == SBUS_DMA_NONE)) | ||
624 | + BUG(); | ||
625 | + | ||
626 | + npages = prepare_sg(sglist, nelems); | ||
627 | |||
628 | spin_lock_irqsave(&iommu->lock, flags); | ||
629 | - iopte = alloc_streaming_cluster(iommu, npages); | ||
630 | - if (iopte == NULL) | ||
631 | - goto bad; | ||
632 | - dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); | ||
633 | + base = alloc_npages(iommu, npages); | ||
634 | + spin_unlock_irqrestore(&iommu->lock, flags); | ||
635 | + | ||
636 | + if (unlikely(base == NULL)) | ||
637 | + BUG(); | ||
638 | + | ||
639 | + dma_base = MAP_BASE + | ||
640 | + ((base - iommu->page_table) << IO_PAGE_SHIFT); | ||
641 | |||
642 | /* Normalize DVMA addresses. */ | ||
643 | - sgtmp = sg; | ||
644 | - used = nents; | ||
645 | + used = nelems; | ||
646 | |||
647 | + sgtmp = sglist; | ||
648 | while (used && sgtmp->dma_length) { | ||
649 | sgtmp->dma_address += dma_base; | ||
650 | sgtmp++; | ||
651 | used--; | ||
652 | } | ||
653 | - used = nents - used; | ||
654 | + used = nelems - used; | ||
655 | |||
656 | - iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; | ||
657 | - if (dir != SBUS_DMA_TODEVICE) | ||
658 | - iopte_bits |= IOPTE_WRITE; | ||
659 | + iopte_protection = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; | ||
660 | + if (direction != SBUS_DMA_TODEVICE) | ||
661 | + iopte_protection |= IOPTE_WRITE; | ||
662 | + | ||
663 | + fill_sg(base, sglist, used, nelems, iopte_protection); | ||
664 | |||
665 | - fill_sg(iopte, sg, used, nents, iopte_bits); | ||
666 | #ifdef VERIFY_SG | ||
667 | - verify_sglist(sg, nents, iopte, npages); | ||
668 | + verify_sglist(sglist, nelems, base, npages); | ||
669 | #endif | ||
670 | - spin_unlock_irqrestore(&iommu->lock, flags); | ||
671 | |||
672 | return used; | ||
673 | - | ||
674 | -bad: | ||
675 | - spin_unlock_irqrestore(&iommu->lock, flags); | ||
676 | - BUG(); | ||
677 | - return 0; | ||
678 | } | ||
679 | |||
680 | -void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction) | ||
681 | +void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction) | ||
682 | { | ||
683 | - unsigned long size, flags; | ||
684 | struct sbus_iommu *iommu; | ||
685 | - u32 dvma_base; | ||
686 | - int i; | ||
687 | + iopte_t *base; | ||
688 | + unsigned long flags, i, npages; | ||
689 | + u32 bus_addr; | ||
690 | |||
691 | - /* Fast path single entry scatterlists. */ | ||
692 | - if (nents == 1) { | ||
693 | - sbus_unmap_single(sdev, sg->dma_address, sg->dma_length, direction); | ||
694 | - return; | ||
695 | - } | ||
696 | + if (unlikely(direction == SBUS_DMA_NONE)) | ||
697 | + BUG(); | ||
698 | + | ||
699 | + iommu = sdev->bus->iommu; | ||
700 | + | ||
701 | + bus_addr = sglist->dma_address & IO_PAGE_MASK; | ||
702 | |||
703 | - dvma_base = sg[0].dma_address & IO_PAGE_MASK; | ||
704 | - for (i = 0; i < nents; i++) { | ||
705 | - if (sg[i].dma_length == 0) | ||
706 | + for (i = 1; i < nelems; i++) | ||
707 | + if (sglist[i].dma_length == 0) | ||
708 | break; | ||
709 | - } | ||
710 | i--; | ||
711 | - size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - dvma_base; | ||
712 | + npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - | ||
713 | + bus_addr) >> IO_PAGE_SHIFT; | ||
714 | + | ||
715 | + base = iommu->page_table + | ||
716 | + ((bus_addr - MAP_BASE) >> IO_PAGE_SHIFT); | ||
717 | |||
718 | - iommu = sdev->bus->iommu; | ||
719 | spin_lock_irqsave(&iommu->lock, flags); | ||
720 | - free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); | ||
721 | - sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction); | ||
722 | + sbus_strbuf_flush(iommu, bus_addr, npages, direction); | ||
723 | + for (i = 0; i < npages; i++) | ||
724 | + iopte_val(base[i]) = 0UL; | ||
725 | + free_npages(iommu, bus_addr - MAP_BASE, npages); | ||
726 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
727 | } | ||
728 | |||
729 | -void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t size, int direction) | ||
730 | +void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction) | ||
731 | { | ||
732 | - struct sbus_iommu *iommu = sdev->bus->iommu; | ||
733 | - unsigned long flags; | ||
734 | + struct sbus_iommu *iommu; | ||
735 | + unsigned long flags, npages; | ||
736 | + | ||
737 | + iommu = sdev->bus->iommu; | ||
738 | |||
739 | - size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); | ||
740 | + npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); | ||
741 | + npages >>= IO_PAGE_SHIFT; | ||
742 | + bus_addr &= IO_PAGE_MASK; | ||
743 | |||
744 | spin_lock_irqsave(&iommu->lock, flags); | ||
745 | - sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction); | ||
746 | + sbus_strbuf_flush(iommu, bus_addr, npages, direction); | ||
747 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
748 | } | ||
749 | |||
750 | @@ -613,23 +535,25 @@ void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t base, siz | ||
751 | { | ||
752 | } | ||
753 | |||
754 | -void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction) | ||
755 | +void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction) | ||
756 | { | ||
757 | - struct sbus_iommu *iommu = sdev->bus->iommu; | ||
758 | - unsigned long flags, size; | ||
759 | - u32 base; | ||
760 | - int i; | ||
761 | + struct sbus_iommu *iommu; | ||
762 | + unsigned long flags, npages, i; | ||
763 | + u32 bus_addr; | ||
764 | + | ||
765 | + iommu = sdev->bus->iommu; | ||
766 | |||
767 | - base = sg[0].dma_address & IO_PAGE_MASK; | ||
768 | - for (i = 0; i < nents; i++) { | ||
769 | - if (sg[i].dma_length == 0) | ||
770 | + bus_addr = sglist[0].dma_address & IO_PAGE_MASK; | ||
771 | + for (i = 0; i < nelems; i++) { | ||
772 | + if (!sglist[i].dma_length) | ||
773 | break; | ||
774 | } | ||
775 | i--; | ||
776 | - size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; | ||
777 | + npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) | ||
778 | + - bus_addr) >> IO_PAGE_SHIFT; | ||
779 | |||
780 | spin_lock_irqsave(&iommu->lock, flags); | ||
781 | - sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction); | ||
782 | + sbus_strbuf_flush(iommu, bus_addr, npages, direction); | ||
783 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
784 | } | ||
785 | |||
786 | @@ -1104,7 +1028,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | ||
787 | struct linux_prom64_registers *pr; | ||
788 | struct device_node *dp; | ||
789 | struct sbus_iommu *iommu; | ||
790 | - unsigned long regs, tsb_base; | ||
791 | + unsigned long regs; | ||
792 | u64 control; | ||
793 | int i; | ||
794 | |||
795 | @@ -1132,14 +1056,6 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | ||
796 | |||
797 | memset(iommu, 0, sizeof(*iommu)); | ||
798 | |||
799 | - /* We start with no consistent mappings. */ | ||
800 | - iommu->lowest_consistent_map = CLUSTER_NPAGES; | ||
801 | - | ||
802 | - for (i = 0; i < NCLUSTERS; i++) { | ||
803 | - iommu->alloc_info[i].flush = 0; | ||
804 | - iommu->alloc_info[i].next = 0; | ||
805 | - } | ||
806 | - | ||
807 | /* Setup spinlock. */ | ||
808 | spin_lock_init(&iommu->lock); | ||
809 | |||
810 | @@ -1159,25 +1075,13 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | ||
811 | sbus->portid, regs); | ||
812 | |||
813 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ | ||
814 | + sbus_iommu_table_init(iommu, IO_TSB_SIZE); | ||
815 | + | ||
816 | control = upa_readq(iommu->iommu_regs + IOMMU_CONTROL); | ||
817 | control = ((7UL << 16UL) | | ||
818 | (0UL << 2UL) | | ||
819 | (1UL << 1UL) | | ||
820 | (1UL << 0UL)); | ||
821 | - | ||
822 | - /* Using the above configuration we need 1MB iommu page | ||
823 | - * table (128K ioptes * 8 bytes per iopte). This is | ||
824 | - * page order 7 on UltraSparc. | ||
825 | - */ | ||
826 | - tsb_base = __get_free_pages(GFP_ATOMIC, get_order(IO_TSB_SIZE)); | ||
827 | - if (tsb_base == 0UL) { | ||
828 | - prom_printf("sbus_iommu_init: Fatal error, cannot alloc TSB table.\n"); | ||
829 | - prom_halt(); | ||
830 | - } | ||
831 | - | ||
832 | - iommu->page_table = (iopte_t *) tsb_base; | ||
833 | - memset(iommu->page_table, 0, IO_TSB_SIZE); | ||
834 | - | ||
835 | upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL); | ||
836 | |||
837 | /* Clean out any cruft in the IOMMU using | ||
838 | @@ -1195,7 +1099,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | ||
839 | upa_readq(iommu->sbus_control_reg); | ||
840 | |||
841 | /* Give the TSB to SYSIO. */ | ||
842 | - upa_writeq(__pa(tsb_base), iommu->iommu_regs + IOMMU_TSBBASE); | ||
843 | + upa_writeq(__pa(iommu->page_table), iommu->iommu_regs + IOMMU_TSBBASE); | ||
844 | |||
845 | /* Setup streaming buffer, DE=1 SB_EN=1 */ | ||
846 | control = (1UL << 1UL) | (1UL << 0UL); | ||
847 | diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S | ||
848 | index c09ab4b..010a737 100644 | ||
849 | --- a/arch/sparc64/kernel/sys32.S | ||
850 | +++ b/arch/sparc64/kernel/sys32.S | ||
851 | @@ -91,7 +91,6 @@ SIGN1(sys32_select, compat_sys_select, %o0) | ||
852 | SIGN1(sys32_mkdir, sys_mkdir, %o1) | ||
853 | SIGN3(sys32_futex, compat_sys_futex, %o1, %o2, %o5) | ||
854 | SIGN1(sys32_sysfs, compat_sys_sysfs, %o0) | ||
855 | -SIGN3(sys32_ipc, compat_sys_ipc, %o1, %o2, %o3) | ||
856 | SIGN2(sys32_sendfile, compat_sys_sendfile, %o0, %o1) | ||
857 | SIGN2(sys32_sendfile64, compat_sys_sendfile64, %o0, %o1) | ||
858 | SIGN1(sys32_prctl, sys_prctl, %o0) | ||
859 | diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S | ||
860 | index 9a80267..46f870b 100644 | ||
861 | --- a/arch/sparc64/kernel/systbls.S | ||
862 | +++ b/arch/sparc64/kernel/systbls.S | ||
863 | @@ -62,7 +62,7 @@ sys_call_table32: | ||
864 | /*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir | ||
865 | .word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64 | ||
866 | /*210*/ .word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, sys32_sysinfo | ||
867 | - .word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex | ||
868 | + .word compat_sys_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex | ||
869 | /*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid | ||
870 | .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16 | ||
871 | /*230*/ .word sys32_select, compat_sys_time, sys32_splice, compat_sys_stime, compat_sys_statfs64 | ||
872 | diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S | ||
873 | index d6ff88f..6090516 100644 | ||
874 | --- a/arch/x86_64/boot/video.S | ||
875 | +++ b/arch/x86_64/boot/video.S | ||
876 | @@ -571,6 +571,16 @@ setr1: lodsw | ||
877 | jmp _m_s | ||
878 | |||
879 | check_vesa: | ||
880 | +#ifdef CONFIG_FIRMWARE_EDID | ||
881 | + leaw modelist+1024, %di | ||
882 | + movw $0x4f00, %ax | ||
883 | + int $0x10 | ||
884 | + cmpw $0x004f, %ax | ||
885 | + jnz setbad | ||
886 | + | ||
887 | + movw 4(%di), %ax | ||
888 | + movw %ax, vbe_version | ||
889 | +#endif | ||
890 | leaw modelist+1024, %di | ||
891 | subb $VIDEO_FIRST_VESA>>8, %bh | ||
892 | movw %bx, %cx # Get mode information structure | ||
893 | @@ -1945,6 +1955,9 @@ store_edid: | ||
894 | rep | ||
895 | stosl | ||
896 | |||
897 | + cmpw $0x0200, vbe_version # only do EDID on >= VBE2.0 | ||
898 | + jl no_edid | ||
899 | + | ||
900 | pushw %es # save ES | ||
901 | xorw %di, %di # Report Capability | ||
902 | pushw %di | ||
903 | @@ -1987,6 +2000,7 @@ do_restore: .byte 0 # Screen contents altered during mode change | ||
904 | svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes | ||
905 | graphic_mode: .byte 0 # Graphic mode with a linear frame buffer | ||
906 | dac_size: .byte 6 # DAC bit depth | ||
907 | +vbe_version: .word 0 # VBE bios version | ||
908 | |||
909 | # Status messages | ||
910 | keymsg: .ascii "Press <RETURN> to see video modes available, " | ||
911 | diff --git a/arch/x86_64/kernel/k8.c b/arch/x86_64/kernel/k8.c | ||
912 | index 6416682..bc11b32 100644 | ||
913 | --- a/arch/x86_64/kernel/k8.c | ||
914 | +++ b/arch/x86_64/kernel/k8.c | ||
915 | @@ -61,8 +61,8 @@ int cache_k8_northbridges(void) | ||
916 | dev = NULL; | ||
917 | i = 0; | ||
918 | while ((dev = next_k8_northbridge(dev)) != NULL) { | ||
919 | - k8_northbridges[i++] = dev; | ||
920 | - pci_read_config_dword(dev, 0x9c, &flush_words[i]); | ||
921 | + k8_northbridges[i] = dev; | ||
922 | + pci_read_config_dword(dev, 0x9c, &flush_words[i++]); | ||
923 | } | ||
924 | k8_northbridges[i] = NULL; | ||
925 | return 0; | ||
926 | diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c | ||
927 | index 07b7062..0280fe6 100644 | ||
928 | --- a/block/cfq-iosched.c | ||
929 | +++ b/block/cfq-iosched.c | ||
930 | @@ -462,6 +462,12 @@ static void cfq_add_rq_rb(struct request *rq) | ||
931 | |||
932 | if (!cfq_cfqq_on_rr(cfqq)) | ||
933 | cfq_add_cfqq_rr(cfqd, cfqq); | ||
934 | + | ||
935 | + /* | ||
936 | + * check if this request is a better next-serve candidate | ||
937 | + */ | ||
938 | + cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq); | ||
939 | + BUG_ON(!cfqq->next_rq); | ||
940 | } | ||
941 | |||
942 | static inline void | ||
943 | @@ -1623,12 +1629,6 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
944 | cfqq->meta_pending++; | ||
945 | |||
946 | /* | ||
947 | - * check if this request is a better next-serve candidate)) { | ||
948 | - */ | ||
949 | - cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq); | ||
950 | - BUG_ON(!cfqq->next_rq); | ||
951 | - | ||
952 | - /* | ||
953 | * we never wait for an async request and we don't allow preemption | ||
954 | * of an async request. so just return early | ||
955 | */ | ||
956 | diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c | ||
957 | index 84787ce..ed1d380 100644 | ||
958 | --- a/drivers/char/agp/intel-agp.c | ||
959 | +++ b/drivers/char/agp/intel-agp.c | ||
960 | @@ -405,9 +405,8 @@ static void intel_i830_init_gtt_entries(void) | ||
961 | |||
962 | if (IS_I965) { | ||
963 | u32 pgetbl_ctl; | ||
964 | + pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL); | ||
965 | |||
966 | - pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL, | ||
967 | - &pgetbl_ctl); | ||
968 | /* The 965 has a field telling us the size of the GTT, | ||
969 | * which may be larger than what is necessary to map the | ||
970 | * aperture. | ||
971 | diff --git a/drivers/char/mem.c b/drivers/char/mem.c | ||
972 | index f5c160c..5f06696 100644 | ||
973 | --- a/drivers/char/mem.c | ||
974 | +++ b/drivers/char/mem.c | ||
975 | @@ -248,7 +248,7 @@ static unsigned long get_unmapped_area_mem(struct file *file, | ||
976 | { | ||
977 | if (!valid_mmap_phys_addr_range(pgoff, len)) | ||
978 | return (unsigned long) -EINVAL; | ||
979 | - return pgoff; | ||
980 | + return pgoff << PAGE_SHIFT; | ||
981 | } | ||
982 | |||
983 | /* can't do an in-place private mapping if there's no MMU */ | ||
984 | diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c | ||
985 | index dc8368e..60740a1 100644 | ||
986 | --- a/drivers/char/vt_ioctl.c | ||
987 | +++ b/drivers/char/vt_ioctl.c | ||
988 | @@ -1038,10 +1038,22 @@ int vt_waitactive(int vt) | ||
989 | |||
990 | add_wait_queue(&vt_activate_queue, &wait); | ||
991 | for (;;) { | ||
992 | - set_current_state(TASK_INTERRUPTIBLE); | ||
993 | retval = 0; | ||
994 | - if (vt == fg_console) | ||
995 | + | ||
996 | + /* | ||
997 | + * Synchronize with redraw_screen(). By acquiring the console | ||
998 | + * semaphore we make sure that the console switch is completed | ||
999 | + * before we return. If we didn't wait for the semaphore, we | ||
1000 | + * could return at a point where fg_console has already been | ||
1001 | + * updated, but the console switch hasn't been completed. | ||
1002 | + */ | ||
1003 | + acquire_console_sem(); | ||
1004 | + set_current_state(TASK_INTERRUPTIBLE); | ||
1005 | + if (vt == fg_console) { | ||
1006 | + release_console_sem(); | ||
1007 | break; | ||
1008 | + } | ||
1009 | + release_console_sem(); | ||
1010 | retval = -EINTR; | ||
1011 | if (signal_pending(current)) | ||
1012 | break; | ||
1013 | diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c | ||
1014 | index 1ecad3e..f6fb5b3 100644 | ||
1015 | --- a/drivers/hid/hid-core.c | ||
1016 | +++ b/drivers/hid/hid-core.c | ||
1017 | @@ -876,10 +876,6 @@ static void hid_output_field(struct hid_field *field, __u8 *data) | ||
1018 | unsigned size = field->report_size; | ||
1019 | unsigned n; | ||
1020 | |||
1021 | - /* make sure the unused bits in the last byte are zeros */ | ||
1022 | - if (count > 0 && size > 0) | ||
1023 | - data[(count*size-1)/8] = 0; | ||
1024 | - | ||
1025 | for (n = 0; n < count; n++) { | ||
1026 | if (field->logical_minimum < 0) /* signed values */ | ||
1027 | implement(data, offset + n * size, size, s32ton(field->value[n], size)); | ||
1028 | diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c | ||
1029 | index 212a155..b9d5dd4 100644 | ||
1030 | --- a/drivers/hwmon/w83627ehf.c | ||
1031 | +++ b/drivers/hwmon/w83627ehf.c | ||
1032 | @@ -389,7 +389,7 @@ static void w83627ehf_write_fan_div(struct i2c_client *client, int nr) | ||
1033 | break; | ||
1034 | case 4: | ||
1035 | reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73) | ||
1036 | - | ((data->fan_div[4] & 0x03) << 3) | ||
1037 | + | ((data->fan_div[4] & 0x03) << 2) | ||
1038 | | ((data->fan_div[4] & 0x04) << 5); | ||
1039 | w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg); | ||
1040 | break; | ||
1041 | @@ -453,9 +453,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | ||
1042 | time */ | ||
1043 | if (data->fan[i] == 0xff | ||
1044 | && data->fan_div[i] < 0x07) { | ||
1045 | - dev_dbg(&client->dev, "Increasing fan %d " | ||
1046 | + dev_dbg(&client->dev, "Increasing fan%d " | ||
1047 | "clock divider from %u to %u\n", | ||
1048 | - i, div_from_reg(data->fan_div[i]), | ||
1049 | + i + 1, div_from_reg(data->fan_div[i]), | ||
1050 | div_from_reg(data->fan_div[i] + 1)); | ||
1051 | data->fan_div[i]++; | ||
1052 | w83627ehf_write_fan_div(client, i); | ||
1053 | diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c | ||
1054 | index f71ffa8..58012ac 100644 | ||
1055 | --- a/drivers/infiniband/hw/mthca/mthca_mr.c | ||
1056 | +++ b/drivers/infiniband/hw/mthca/mthca_mr.c | ||
1057 | @@ -751,6 +751,7 @@ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr) | ||
1058 | |||
1059 | key = arbel_key_to_hw_index(fmr->ibmr.lkey); | ||
1060 | key &= dev->limits.num_mpts - 1; | ||
1061 | + key = adjust_key(dev, key); | ||
1062 | fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key); | ||
1063 | |||
1064 | fmr->maps = 0; | ||
1065 | diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c | ||
1066 | index 22c426c..1b5e189 100644 | ||
1067 | --- a/drivers/kvm/mmu.c | ||
1068 | +++ b/drivers/kvm/mmu.c | ||
1069 | @@ -131,7 +131,7 @@ static int dbg = 1; | ||
1070 | (((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1)) | ||
1071 | |||
1072 | |||
1073 | -#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK) | ||
1074 | +#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1)) | ||
1075 | #define PT64_DIR_BASE_ADDR_MASK \ | ||
1076 | (PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1)) | ||
1077 | |||
1078 | @@ -406,8 +406,8 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn) | ||
1079 | spte = desc->shadow_ptes[0]; | ||
1080 | } | ||
1081 | BUG_ON(!spte); | ||
1082 | - BUG_ON((*spte & PT64_BASE_ADDR_MASK) != | ||
1083 | - page_to_pfn(page) << PAGE_SHIFT); | ||
1084 | + BUG_ON((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT | ||
1085 | + != page_to_pfn(page)); | ||
1086 | BUG_ON(!(*spte & PT_PRESENT_MASK)); | ||
1087 | BUG_ON(!(*spte & PT_WRITABLE_MASK)); | ||
1088 | rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte); | ||
1089 | @@ -1093,22 +1093,40 @@ out: | ||
1090 | return r; | ||
1091 | } | ||
1092 | |||
1093 | +static void mmu_pre_write_zap_pte(struct kvm_vcpu *vcpu, | ||
1094 | + struct kvm_mmu_page *page, | ||
1095 | + u64 *spte) | ||
1096 | +{ | ||
1097 | + u64 pte; | ||
1098 | + struct kvm_mmu_page *child; | ||
1099 | + | ||
1100 | + pte = *spte; | ||
1101 | + if (is_present_pte(pte)) { | ||
1102 | + if (page->role.level == PT_PAGE_TABLE_LEVEL) | ||
1103 | + rmap_remove(vcpu, spte); | ||
1104 | + else { | ||
1105 | + child = page_header(pte & PT64_BASE_ADDR_MASK); | ||
1106 | + mmu_page_remove_parent_pte(vcpu, child, spte); | ||
1107 | + } | ||
1108 | + } | ||
1109 | + *spte = 0; | ||
1110 | +} | ||
1111 | + | ||
1112 | void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes) | ||
1113 | { | ||
1114 | gfn_t gfn = gpa >> PAGE_SHIFT; | ||
1115 | struct kvm_mmu_page *page; | ||
1116 | - struct kvm_mmu_page *child; | ||
1117 | struct hlist_node *node, *n; | ||
1118 | struct hlist_head *bucket; | ||
1119 | unsigned index; | ||
1120 | u64 *spte; | ||
1121 | - u64 pte; | ||
1122 | unsigned offset = offset_in_page(gpa); | ||
1123 | unsigned pte_size; | ||
1124 | unsigned page_offset; | ||
1125 | unsigned misaligned; | ||
1126 | int level; | ||
1127 | int flooded = 0; | ||
1128 | + int npte; | ||
1129 | |||
1130 | pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes); | ||
1131 | if (gfn == vcpu->last_pt_write_gfn) { | ||
1132 | @@ -1144,22 +1162,27 @@ void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes) | ||
1133 | } | ||
1134 | page_offset = offset; | ||
1135 | level = page->role.level; | ||
1136 | + npte = 1; | ||
1137 | if (page->role.glevels == PT32_ROOT_LEVEL) { | ||
1138 | - page_offset <<= 1; /* 32->64 */ | ||
1139 | + page_offset <<= 1; /* 32->64 */ | ||
1140 | + /* | ||
1141 | + * A 32-bit pde maps 4MB while the shadow pdes map | ||
1142 | + * only 2MB. So we need to double the offset again | ||
1143 | + * and zap two pdes instead of one. | ||
1144 | + */ | ||
1145 | + if (level == PT32_ROOT_LEVEL) { | ||
1146 | + page_offset &= ~7; /* kill rounding error */ | ||
1147 | + page_offset <<= 1; | ||
1148 | + npte = 2; | ||
1149 | + } | ||
1150 | page_offset &= ~PAGE_MASK; | ||
1151 | } | ||
1152 | spte = __va(page->page_hpa); | ||
1153 | spte += page_offset / sizeof(*spte); | ||
1154 | - pte = *spte; | ||
1155 | - if (is_present_pte(pte)) { | ||
1156 | - if (level == PT_PAGE_TABLE_LEVEL) | ||
1157 | - rmap_remove(vcpu, spte); | ||
1158 | - else { | ||
1159 | - child = page_header(pte & PT64_BASE_ADDR_MASK); | ||
1160 | - mmu_page_remove_parent_pte(vcpu, child, spte); | ||
1161 | - } | ||
1162 | + while (npte--) { | ||
1163 | + mmu_pre_write_zap_pte(vcpu, page, spte); | ||
1164 | + ++spte; | ||
1165 | } | ||
1166 | - *spte = 0; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c | ||
1171 | index 0252ef9..0e0401d 100644 | ||
1172 | --- a/drivers/pci/probe.c | ||
1173 | +++ b/drivers/pci/probe.c | ||
1174 | @@ -639,34 +639,7 @@ static void pci_read_irq(struct pci_dev *dev) | ||
1175 | dev->irq = irq; | ||
1176 | } | ||
1177 | |||
1178 | -static void change_legacy_io_resource(struct pci_dev * dev, unsigned index, | ||
1179 | - unsigned start, unsigned end) | ||
1180 | -{ | ||
1181 | - unsigned base = start & PCI_BASE_ADDRESS_IO_MASK; | ||
1182 | - unsigned len = (end | ~PCI_BASE_ADDRESS_IO_MASK) - base + 1; | ||
1183 | - | ||
1184 | - /* | ||
1185 | - * Some X versions get confused when the BARs reported through | ||
1186 | - * /sys or /proc differ from those seen in config space, thus | ||
1187 | - * try to update the config space values, too. | ||
1188 | - */ | ||
1189 | - if (!(pci_resource_flags(dev, index) & IORESOURCE_IO)) | ||
1190 | - printk(KERN_WARNING "%s: cannot adjust BAR%u (not I/O)\n", | ||
1191 | - pci_name(dev), index); | ||
1192 | - else if (pci_resource_len(dev, index) != len) | ||
1193 | - printk(KERN_WARNING "%s: cannot adjust BAR%u (size %04X)\n", | ||
1194 | - pci_name(dev), index, (unsigned)pci_resource_len(dev, index)); | ||
1195 | - else { | ||
1196 | - printk(KERN_INFO "%s: trying to change BAR%u from %04X to %04X\n", | ||
1197 | - pci_name(dev), index, | ||
1198 | - (unsigned)pci_resource_start(dev, index), base); | ||
1199 | - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + index * 4, base); | ||
1200 | - } | ||
1201 | - pci_resource_start(dev, index) = start; | ||
1202 | - pci_resource_end(dev, index) = end; | ||
1203 | - pci_resource_flags(dev, index) = | ||
1204 | - IORESOURCE_IO | IORESOURCE_PCI_FIXED | PCI_BASE_ADDRESS_SPACE_IO; | ||
1205 | -} | ||
1206 | +#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) | ||
1207 | |||
1208 | /** | ||
1209 | * pci_setup_device - fill in class and map information of a device | ||
1210 | @@ -719,12 +692,20 @@ static int pci_setup_device(struct pci_dev * dev) | ||
1211 | u8 progif; | ||
1212 | pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); | ||
1213 | if ((progif & 1) == 0) { | ||
1214 | - change_legacy_io_resource(dev, 0, 0x1F0, 0x1F7); | ||
1215 | - change_legacy_io_resource(dev, 1, 0x3F6, 0x3F6); | ||
1216 | + dev->resource[0].start = 0x1F0; | ||
1217 | + dev->resource[0].end = 0x1F7; | ||
1218 | + dev->resource[0].flags = LEGACY_IO_RESOURCE; | ||
1219 | + dev->resource[1].start = 0x3F6; | ||
1220 | + dev->resource[1].end = 0x3F6; | ||
1221 | + dev->resource[1].flags = LEGACY_IO_RESOURCE; | ||
1222 | } | ||
1223 | if ((progif & 4) == 0) { | ||
1224 | - change_legacy_io_resource(dev, 2, 0x170, 0x177); | ||
1225 | - change_legacy_io_resource(dev, 3, 0x376, 0x376); | ||
1226 | + dev->resource[2].start = 0x170; | ||
1227 | + dev->resource[2].end = 0x177; | ||
1228 | + dev->resource[2].flags = LEGACY_IO_RESOURCE; | ||
1229 | + dev->resource[3].start = 0x376; | ||
1230 | + dev->resource[3].end = 0x376; | ||
1231 | + dev->resource[3].flags = LEGACY_IO_RESOURCE; | ||
1232 | } | ||
1233 | } | ||
1234 | break; | ||
1235 | diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c | ||
1236 | index e1b44d6..2981ceb 100644 | ||
1237 | --- a/drivers/scsi/3w-xxxx.c | ||
1238 | +++ b/drivers/scsi/3w-xxxx.c | ||
1239 | @@ -1864,10 +1864,17 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) | ||
1240 | /* This function will handle the request sense scsi command */ | ||
1241 | static int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id) | ||
1242 | { | ||
1243 | + char request_buffer[18]; | ||
1244 | + | ||
1245 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n"); | ||
1246 | |||
1247 | - /* For now we just zero the request buffer */ | ||
1248 | - memset(tw_dev->srb[request_id]->request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); | ||
1249 | + memset(request_buffer, 0, sizeof(request_buffer)); | ||
1250 | + request_buffer[0] = 0x70; /* Immediate fixed format */ | ||
1251 | + request_buffer[7] = 10; /* minimum size per SPC: 18 bytes */ | ||
1252 | + /* leave all other fields zero, giving effectively NO_SENSE return */ | ||
1253 | + tw_transfer_internal(tw_dev, request_id, request_buffer, | ||
1254 | + sizeof(request_buffer)); | ||
1255 | + | ||
1256 | tw_dev->state[request_id] = TW_S_COMPLETED; | ||
1257 | tw_state_request_finish(tw_dev, request_id); | ||
1258 | |||
1259 | diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c | ||
1260 | index 9b827ce..9f10689 100644 | ||
1261 | --- a/drivers/scsi/qlogicpti.c | ||
1262 | +++ b/drivers/scsi/qlogicpti.c | ||
1263 | @@ -1281,7 +1281,7 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti) | ||
1264 | (struct scatterlist *)Cmnd->request_buffer, | ||
1265 | Cmnd->use_sg, | ||
1266 | Cmnd->sc_data_direction); | ||
1267 | - } else { | ||
1268 | + } else if (Cmnd->request_bufflen) { | ||
1269 | sbus_unmap_single(qpti->sdev, | ||
1270 | (__u32)((unsigned long)Cmnd->SCp.ptr), | ||
1271 | Cmnd->request_bufflen, | ||
1272 | diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c | ||
1273 | index 5261f0a..2e542b9 100644 | ||
1274 | --- a/drivers/serial/8250.c | ||
1275 | +++ b/drivers/serial/8250.c | ||
1276 | @@ -1289,7 +1289,8 @@ static unsigned int check_modem_status(struct uart_8250_port *up) | ||
1277 | { | ||
1278 | unsigned int status = serial_in(up, UART_MSR); | ||
1279 | |||
1280 | - if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI) { | ||
1281 | + if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && | ||
1282 | + up->port.info != NULL) { | ||
1283 | if (status & UART_MSR_TERI) | ||
1284 | up->port.icount.rng++; | ||
1285 | if (status & UART_MSR_DDSR) | ||
1286 | diff --git a/fs/exec.c b/fs/exec.c | ||
1287 | index 11fe93f..0f8573a 100644 | ||
1288 | --- a/fs/exec.c | ||
1289 | +++ b/fs/exec.c | ||
1290 | @@ -1246,13 +1246,17 @@ EXPORT_SYMBOL(set_binfmt); | ||
1291 | * name into corename, which must have space for at least | ||
1292 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. | ||
1293 | */ | ||
1294 | -static void format_corename(char *corename, const char *pattern, long signr) | ||
1295 | +static int format_corename(char *corename, const char *pattern, long signr) | ||
1296 | { | ||
1297 | const char *pat_ptr = pattern; | ||
1298 | char *out_ptr = corename; | ||
1299 | char *const out_end = corename + CORENAME_MAX_SIZE; | ||
1300 | int rc; | ||
1301 | int pid_in_pattern = 0; | ||
1302 | + int ispipe = 0; | ||
1303 | + | ||
1304 | + if (*pattern == '|') | ||
1305 | + ispipe = 1; | ||
1306 | |||
1307 | /* Repeat as long as we have more pattern to process and more output | ||
1308 | space */ | ||
1309 | @@ -1343,8 +1347,8 @@ static void format_corename(char *corename, const char *pattern, long signr) | ||
1310 | * | ||
1311 | * If core_pattern does not include a %p (as is the default) | ||
1312 | * and core_uses_pid is set, then .%pid will be appended to | ||
1313 | - * the filename */ | ||
1314 | - if (!pid_in_pattern | ||
1315 | + * the filename. Do not do this for piped commands. */ | ||
1316 | + if (!ispipe && !pid_in_pattern | ||
1317 | && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { | ||
1318 | rc = snprintf(out_ptr, out_end - out_ptr, | ||
1319 | ".%d", current->tgid); | ||
1320 | @@ -1352,8 +1356,9 @@ static void format_corename(char *corename, const char *pattern, long signr) | ||
1321 | goto out; | ||
1322 | out_ptr += rc; | ||
1323 | } | ||
1324 | - out: | ||
1325 | +out: | ||
1326 | *out_ptr = 0; | ||
1327 | + return ispipe; | ||
1328 | } | ||
1329 | |||
1330 | static void zap_process(struct task_struct *start) | ||
1331 | @@ -1504,16 +1509,15 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | ||
1332 | * uses lock_kernel() | ||
1333 | */ | ||
1334 | lock_kernel(); | ||
1335 | - format_corename(corename, core_pattern, signr); | ||
1336 | + ispipe = format_corename(corename, core_pattern, signr); | ||
1337 | unlock_kernel(); | ||
1338 | - if (corename[0] == '|') { | ||
1339 | + if (ispipe) { | ||
1340 | /* SIGPIPE can happen, but it's just never processed */ | ||
1341 | if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) { | ||
1342 | printk(KERN_INFO "Core dump to %s pipe failed\n", | ||
1343 | corename); | ||
1344 | goto fail_unlock; | ||
1345 | } | ||
1346 | - ispipe = 1; | ||
1347 | } else | ||
1348 | file = filp_open(corename, | ||
1349 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | ||
1350 | diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c | ||
1351 | index d9ba8cb..80b4264 100644 | ||
1352 | --- a/fs/nfs/dir.c | ||
1353 | +++ b/fs/nfs/dir.c | ||
1354 | @@ -1659,7 +1659,8 @@ go_ahead: | ||
1355 | * ... prune child dentries and writebacks if needed. | ||
1356 | */ | ||
1357 | if (atomic_read(&old_dentry->d_count) > 1) { | ||
1358 | - nfs_wb_all(old_inode); | ||
1359 | + if (S_ISREG(old_inode->i_mode)) | ||
1360 | + nfs_wb_all(old_inode); | ||
1361 | shrink_dcache_parent(old_dentry); | ||
1362 | } | ||
1363 | nfs_inode_return_delegation(old_inode); | ||
1364 | diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c | ||
1365 | index 5a83e8d..e8cacef 100644 | ||
1366 | --- a/fs/nfs/inode.c | ||
1367 | +++ b/fs/nfs/inode.c | ||
1368 | @@ -334,8 +334,10 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | ||
1369 | lock_kernel(); | ||
1370 | nfs_begin_data_update(inode); | ||
1371 | /* Write all dirty data */ | ||
1372 | - filemap_write_and_wait(inode->i_mapping); | ||
1373 | - nfs_wb_all(inode); | ||
1374 | + if (S_ISREG(inode->i_mode)) { | ||
1375 | + filemap_write_and_wait(inode->i_mapping); | ||
1376 | + nfs_wb_all(inode); | ||
1377 | + } | ||
1378 | /* | ||
1379 | * Return any delegations if we're going to change ACLs | ||
1380 | */ | ||
1381 | diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c | ||
1382 | index f01389f..c8178b7 100644 | ||
1383 | --- a/fs/reiserfs/xattr.c | ||
1384 | +++ b/fs/reiserfs/xattr.c | ||
1385 | @@ -54,82 +54,48 @@ | ||
1386 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | ||
1387 | *prefix); | ||
1388 | |||
1389 | -static struct dentry *create_xa_root(struct super_block *sb) | ||
1390 | +/* Returns the dentry referring to the root of the extended attribute | ||
1391 | + * directory tree. If it has already been retrieved, it is used. If it | ||
1392 | + * hasn't been created and the flags indicate creation is allowed, we | ||
1393 | + * attempt to create it. On error, we return a pointer-encoded error. | ||
1394 | + */ | ||
1395 | +static struct dentry *get_xa_root(struct super_block *sb, int flags) | ||
1396 | { | ||
1397 | struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); | ||
1398 | struct dentry *xaroot; | ||
1399 | |||
1400 | /* This needs to be created at mount-time */ | ||
1401 | if (!privroot) | ||
1402 | - return ERR_PTR(-EOPNOTSUPP); | ||
1403 | + return ERR_PTR(-ENODATA); | ||
1404 | |||
1405 | - xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | ||
1406 | - if (IS_ERR(xaroot)) { | ||
1407 | + mutex_lock(&privroot->d_inode->i_mutex); | ||
1408 | + if (REISERFS_SB(sb)->xattr_root) { | ||
1409 | + xaroot = dget(REISERFS_SB(sb)->xattr_root); | ||
1410 | goto out; | ||
1411 | - } else if (!xaroot->d_inode) { | ||
1412 | - int err; | ||
1413 | - mutex_lock(&privroot->d_inode->i_mutex); | ||
1414 | - err = | ||
1415 | - privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot, | ||
1416 | - 0700); | ||
1417 | - mutex_unlock(&privroot->d_inode->i_mutex); | ||
1418 | - | ||
1419 | - if (err) { | ||
1420 | - dput(xaroot); | ||
1421 | - dput(privroot); | ||
1422 | - return ERR_PTR(err); | ||
1423 | - } | ||
1424 | - REISERFS_SB(sb)->xattr_root = dget(xaroot); | ||
1425 | } | ||
1426 | |||
1427 | - out: | ||
1428 | - dput(privroot); | ||
1429 | - return xaroot; | ||
1430 | -} | ||
1431 | - | ||
1432 | -/* This will return a dentry, or error, refering to the xa root directory. | ||
1433 | - * If the xa root doesn't exist yet, the dentry will be returned without | ||
1434 | - * an associated inode. This dentry can be used with ->mkdir to create | ||
1435 | - * the xa directory. */ | ||
1436 | -static struct dentry *__get_xa_root(struct super_block *s) | ||
1437 | -{ | ||
1438 | - struct dentry *privroot = dget(REISERFS_SB(s)->priv_root); | ||
1439 | - struct dentry *xaroot = NULL; | ||
1440 | - | ||
1441 | - if (IS_ERR(privroot) || !privroot) | ||
1442 | - return privroot; | ||
1443 | - | ||
1444 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | ||
1445 | if (IS_ERR(xaroot)) { | ||
1446 | goto out; | ||
1447 | } else if (!xaroot->d_inode) { | ||
1448 | - dput(xaroot); | ||
1449 | - xaroot = NULL; | ||
1450 | - goto out; | ||
1451 | + int err = -ENODATA; | ||
1452 | + if (flags == 0 || flags & XATTR_CREATE) | ||
1453 | + err = privroot->d_inode->i_op->mkdir(privroot->d_inode, | ||
1454 | + xaroot, 0700); | ||
1455 | + if (err) { | ||
1456 | + dput(xaroot); | ||
1457 | + xaroot = ERR_PTR(err); | ||
1458 | + goto out; | ||
1459 | + } | ||
1460 | } | ||
1461 | - | ||
1462 | - REISERFS_SB(s)->xattr_root = dget(xaroot); | ||
1463 | + REISERFS_SB(sb)->xattr_root = dget(xaroot); | ||
1464 | |||
1465 | out: | ||
1466 | + mutex_unlock(&privroot->d_inode->i_mutex); | ||
1467 | dput(privroot); | ||
1468 | return xaroot; | ||
1469 | } | ||
1470 | |||
1471 | -/* Returns the dentry (or NULL) referring to the root of the extended | ||
1472 | - * attribute directory tree. If it has already been retrieved, it is used. | ||
1473 | - * Otherwise, we attempt to retrieve it from disk. It may also return | ||
1474 | - * a pointer-encoded error. | ||
1475 | - */ | ||
1476 | -static inline struct dentry *get_xa_root(struct super_block *s) | ||
1477 | -{ | ||
1478 | - struct dentry *dentry = dget(REISERFS_SB(s)->xattr_root); | ||
1479 | - | ||
1480 | - if (!dentry) | ||
1481 | - dentry = __get_xa_root(s); | ||
1482 | - | ||
1483 | - return dentry; | ||
1484 | -} | ||
1485 | - | ||
1486 | /* Opens the directory corresponding to the inode's extended attribute store. | ||
1487 | * If flags allow, the tree to the directory may be created. If creation is | ||
1488 | * prohibited, -ENODATA is returned. */ | ||
1489 | @@ -138,21 +104,11 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags) | ||
1490 | struct dentry *xaroot, *xadir; | ||
1491 | char namebuf[17]; | ||
1492 | |||
1493 | - xaroot = get_xa_root(inode->i_sb); | ||
1494 | - if (IS_ERR(xaroot)) { | ||
1495 | + xaroot = get_xa_root(inode->i_sb, flags); | ||
1496 | + if (IS_ERR(xaroot)) | ||
1497 | return xaroot; | ||
1498 | - } else if (!xaroot) { | ||
1499 | - if (flags == 0 || flags & XATTR_CREATE) { | ||
1500 | - xaroot = create_xa_root(inode->i_sb); | ||
1501 | - if (IS_ERR(xaroot)) | ||
1502 | - return xaroot; | ||
1503 | - } | ||
1504 | - if (!xaroot) | ||
1505 | - return ERR_PTR(-ENODATA); | ||
1506 | - } | ||
1507 | |||
1508 | /* ok, we have xaroot open */ | ||
1509 | - | ||
1510 | snprintf(namebuf, sizeof(namebuf), "%X.%X", | ||
1511 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), | ||
1512 | inode->i_generation); | ||
1513 | @@ -821,7 +777,7 @@ int reiserfs_delete_xattrs(struct inode *inode) | ||
1514 | |||
1515 | /* Leftovers besides . and .. -- that's not good. */ | ||
1516 | if (dir->d_inode->i_nlink <= 2) { | ||
1517 | - root = get_xa_root(inode->i_sb); | ||
1518 | + root = get_xa_root(inode->i_sb, XATTR_REPLACE); | ||
1519 | reiserfs_write_lock_xattrs(inode->i_sb); | ||
1520 | err = vfs_rmdir(root->d_inode, dir); | ||
1521 | reiserfs_write_unlock_xattrs(inode->i_sb); | ||
1522 | diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h | ||
1523 | index 3fced47..a46104a 100644 | ||
1524 | --- a/include/linux/taskstats.h | ||
1525 | +++ b/include/linux/taskstats.h | ||
1526 | @@ -31,7 +31,7 @@ | ||
1527 | */ | ||
1528 | |||
1529 | |||
1530 | -#define TASKSTATS_VERSION 3 | ||
1531 | +#define TASKSTATS_VERSION 4 | ||
1532 | #define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN | ||
1533 | * in linux/sched.h */ | ||
1534 | |||
1535 | @@ -66,7 +66,7 @@ struct taskstats { | ||
1536 | /* Delay waiting for cpu, while runnable | ||
1537 | * count, delay_total NOT updated atomically | ||
1538 | */ | ||
1539 | - __u64 cpu_count; | ||
1540 | + __u64 cpu_count __attribute__((aligned(8))); | ||
1541 | __u64 cpu_delay_total; | ||
1542 | |||
1543 | /* Following four fields atomically updated using task->delays->lock */ | ||
1544 | @@ -101,14 +101,17 @@ struct taskstats { | ||
1545 | |||
1546 | /* Basic Accounting Fields start */ | ||
1547 | char ac_comm[TS_COMM_LEN]; /* Command name */ | ||
1548 | - __u8 ac_sched; /* Scheduling discipline */ | ||
1549 | + __u8 ac_sched __attribute__((aligned(8))); | ||
1550 | + /* Scheduling discipline */ | ||
1551 | __u8 ac_pad[3]; | ||
1552 | - __u32 ac_uid; /* User ID */ | ||
1553 | + __u32 ac_uid __attribute__((aligned(8))); | ||
1554 | + /* User ID */ | ||
1555 | __u32 ac_gid; /* Group ID */ | ||
1556 | __u32 ac_pid; /* Process ID */ | ||
1557 | __u32 ac_ppid; /* Parent process ID */ | ||
1558 | __u32 ac_btime; /* Begin time [sec since 1970] */ | ||
1559 | - __u64 ac_etime; /* Elapsed time [usec] */ | ||
1560 | + __u64 ac_etime __attribute__((aligned(8))); | ||
1561 | + /* Elapsed time [usec] */ | ||
1562 | __u64 ac_utime; /* User CPU time [usec] */ | ||
1563 | __u64 ac_stime; /* SYstem CPU time [usec] */ | ||
1564 | __u64 ac_minflt; /* Minor Page Fault Count */ | ||
1565 | diff --git a/mm/madvise.c b/mm/madvise.c | ||
1566 | index 77916e9..603c525 100644 | ||
1567 | --- a/mm/madvise.c | ||
1568 | +++ b/mm/madvise.c | ||
1569 | @@ -159,9 +159,10 @@ static long madvise_remove(struct vm_area_struct *vma, | ||
1570 | unsigned long start, unsigned long end) | ||
1571 | { | ||
1572 | struct address_space *mapping; | ||
1573 | - loff_t offset, endoff; | ||
1574 | + loff_t offset, endoff; | ||
1575 | + int error; | ||
1576 | |||
1577 | - *prev = vma; | ||
1578 | + *prev = NULL; /* tell sys_madvise we drop mmap_sem */ | ||
1579 | |||
1580 | if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB)) | ||
1581 | return -EINVAL; | ||
1582 | @@ -180,7 +181,12 @@ static long madvise_remove(struct vm_area_struct *vma, | ||
1583 | + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); | ||
1584 | endoff = (loff_t)(end - vma->vm_start - 1) | ||
1585 | + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); | ||
1586 | - return vmtruncate_range(mapping->host, offset, endoff); | ||
1587 | + | ||
1588 | + /* vmtruncate_range needs to take i_mutex and i_alloc_sem */ | ||
1589 | + up_write(¤t->mm->mmap_sem); | ||
1590 | + error = vmtruncate_range(mapping->host, offset, endoff); | ||
1591 | + down_write(¤t->mm->mmap_sem); | ||
1592 | + return error; | ||
1593 | } | ||
1594 | |||
1595 | static long | ||
1596 | @@ -315,12 +321,15 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior) | ||
1597 | if (error) | ||
1598 | goto out; | ||
1599 | start = tmp; | ||
1600 | - if (start < prev->vm_end) | ||
1601 | + if (prev && start < prev->vm_end) | ||
1602 | start = prev->vm_end; | ||
1603 | error = unmapped_error; | ||
1604 | if (start >= end) | ||
1605 | goto out; | ||
1606 | - vma = prev->vm_next; | ||
1607 | + if (prev) | ||
1608 | + vma = prev->vm_next; | ||
1609 | + else /* madvise_remove dropped mmap_sem */ | ||
1610 | + vma = find_vma(current->mm, start); | ||
1611 | } | ||
1612 | out: | ||
1613 | up_write(¤t->mm->mmap_sem); | ||
1614 | diff --git a/mm/migrate.c b/mm/migrate.c | ||
1615 | index e9b161b..4372d6b 100644 | ||
1616 | --- a/mm/migrate.c | ||
1617 | +++ b/mm/migrate.c | ||
1618 | @@ -297,7 +297,7 @@ static int migrate_page_move_mapping(struct address_space *mapping, | ||
1619 | void **pslot; | ||
1620 | |||
1621 | if (!mapping) { | ||
1622 | - /* Anonymous page */ | ||
1623 | + /* Anonymous page without mapping */ | ||
1624 | if (page_count(page) != 1) | ||
1625 | return -EAGAIN; | ||
1626 | return 0; | ||
1627 | @@ -333,6 +333,19 @@ static int migrate_page_move_mapping(struct address_space *mapping, | ||
1628 | */ | ||
1629 | __put_page(page); | ||
1630 | |||
1631 | + /* | ||
1632 | + * If moved to a different zone then also account | ||
1633 | + * the page for that zone. Other VM counters will be | ||
1634 | + * taken care of when we establish references to the | ||
1635 | + * new page and drop references to the old page. | ||
1636 | + * | ||
1637 | + * Note that anonymous pages are accounted for | ||
1638 | + * via NR_FILE_PAGES and NR_ANON_PAGES if they | ||
1639 | + * are mapped to swap space. | ||
1640 | + */ | ||
1641 | + __dec_zone_page_state(page, NR_FILE_PAGES); | ||
1642 | + __inc_zone_page_state(newpage, NR_FILE_PAGES); | ||
1643 | + | ||
1644 | write_unlock_irq(&mapping->tree_lock); | ||
1645 | |||
1646 | return 0; | ||
1647 | diff --git a/mm/oom_kill.c b/mm/oom_kill.c | ||
1648 | index 2f39169..223add3 100644 | ||
1649 | --- a/mm/oom_kill.c | ||
1650 | +++ b/mm/oom_kill.c | ||
1651 | @@ -176,6 +176,8 @@ static inline int constrained_alloc(struct zonelist *zonelist, gfp_t gfp_mask) | ||
1652 | struct zone **z; | ||
1653 | nodemask_t nodes; | ||
1654 | int node; | ||
1655 | + | ||
1656 | + nodes_clear(nodes); | ||
1657 | /* node has memory ? */ | ||
1658 | for_each_online_node(node) | ||
1659 | if (NODE_DATA(node)->node_present_pages) | ||
1660 | diff --git a/mm/shmem.c b/mm/shmem.c | ||
1661 | index 70da7a0..fc30c59 100644 | ||
1662 | --- a/mm/shmem.c | ||
1663 | +++ b/mm/shmem.c | ||
1664 | @@ -402,26 +402,38 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long | ||
1665 | /* | ||
1666 | * shmem_free_swp - free some swap entries in a directory | ||
1667 | * | ||
1668 | - * @dir: pointer to the directory | ||
1669 | - * @edir: pointer after last entry of the directory | ||
1670 | + * @dir: pointer to the directory | ||
1671 | + * @edir: pointer after last entry of the directory | ||
1672 | + * @punch_lock: pointer to spinlock when needed for the holepunch case | ||
1673 | */ | ||
1674 | -static int shmem_free_swp(swp_entry_t *dir, swp_entry_t *edir) | ||
1675 | +static int shmem_free_swp(swp_entry_t *dir, swp_entry_t *edir, | ||
1676 | + spinlock_t *punch_lock) | ||
1677 | { | ||
1678 | + spinlock_t *punch_unlock = NULL; | ||
1679 | swp_entry_t *ptr; | ||
1680 | int freed = 0; | ||
1681 | |||
1682 | for (ptr = dir; ptr < edir; ptr++) { | ||
1683 | if (ptr->val) { | ||
1684 | + if (unlikely(punch_lock)) { | ||
1685 | + punch_unlock = punch_lock; | ||
1686 | + punch_lock = NULL; | ||
1687 | + spin_lock(punch_unlock); | ||
1688 | + if (!ptr->val) | ||
1689 | + continue; | ||
1690 | + } | ||
1691 | free_swap_and_cache(*ptr); | ||
1692 | *ptr = (swp_entry_t){0}; | ||
1693 | freed++; | ||
1694 | } | ||
1695 | } | ||
1696 | + if (punch_unlock) | ||
1697 | + spin_unlock(punch_unlock); | ||
1698 | return freed; | ||
1699 | } | ||
1700 | |||
1701 | -static int shmem_map_and_free_swp(struct page *subdir, | ||
1702 | - int offset, int limit, struct page ***dir) | ||
1703 | +static int shmem_map_and_free_swp(struct page *subdir, int offset, | ||
1704 | + int limit, struct page ***dir, spinlock_t *punch_lock) | ||
1705 | { | ||
1706 | swp_entry_t *ptr; | ||
1707 | int freed = 0; | ||
1708 | @@ -431,7 +443,8 @@ static int shmem_map_and_free_swp(struct page *subdir, | ||
1709 | int size = limit - offset; | ||
1710 | if (size > LATENCY_LIMIT) | ||
1711 | size = LATENCY_LIMIT; | ||
1712 | - freed += shmem_free_swp(ptr+offset, ptr+offset+size); | ||
1713 | + freed += shmem_free_swp(ptr+offset, ptr+offset+size, | ||
1714 | + punch_lock); | ||
1715 | if (need_resched()) { | ||
1716 | shmem_swp_unmap(ptr); | ||
1717 | if (*dir) { | ||
1718 | @@ -481,7 +494,10 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) | ||
1719 | long nr_swaps_freed = 0; | ||
1720 | int offset; | ||
1721 | int freed; | ||
1722 | - int punch_hole = 0; | ||
1723 | + int punch_hole; | ||
1724 | + spinlock_t *needs_lock; | ||
1725 | + spinlock_t *punch_lock; | ||
1726 | + unsigned long upper_limit; | ||
1727 | |||
1728 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | ||
1729 | idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
1730 | @@ -492,11 +508,20 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) | ||
1731 | info->flags |= SHMEM_TRUNCATE; | ||
1732 | if (likely(end == (loff_t) -1)) { | ||
1733 | limit = info->next_index; | ||
1734 | + upper_limit = SHMEM_MAX_INDEX; | ||
1735 | info->next_index = idx; | ||
1736 | + needs_lock = NULL; | ||
1737 | + punch_hole = 0; | ||
1738 | } else { | ||
1739 | - limit = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
1740 | - if (limit > info->next_index) | ||
1741 | - limit = info->next_index; | ||
1742 | + if (end + 1 >= inode->i_size) { /* we may free a little more */ | ||
1743 | + limit = (inode->i_size + PAGE_CACHE_SIZE - 1) >> | ||
1744 | + PAGE_CACHE_SHIFT; | ||
1745 | + upper_limit = SHMEM_MAX_INDEX; | ||
1746 | + } else { | ||
1747 | + limit = (end + 1) >> PAGE_CACHE_SHIFT; | ||
1748 | + upper_limit = limit; | ||
1749 | + } | ||
1750 | + needs_lock = &info->lock; | ||
1751 | punch_hole = 1; | ||
1752 | } | ||
1753 | |||
1754 | @@ -513,17 +538,30 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) | ||
1755 | size = limit; | ||
1756 | if (size > SHMEM_NR_DIRECT) | ||
1757 | size = SHMEM_NR_DIRECT; | ||
1758 | - nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size); | ||
1759 | + nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size, needs_lock); | ||
1760 | } | ||
1761 | |||
1762 | /* | ||
1763 | * If there are no indirect blocks or we are punching a hole | ||
1764 | * below indirect blocks, nothing to be done. | ||
1765 | */ | ||
1766 | - if (!topdir || (punch_hole && (limit <= SHMEM_NR_DIRECT))) | ||
1767 | + if (!topdir || limit <= SHMEM_NR_DIRECT) | ||
1768 | goto done2; | ||
1769 | |||
1770 | - BUG_ON(limit <= SHMEM_NR_DIRECT); | ||
1771 | + /* | ||
1772 | + * The truncation case has already dropped info->lock, and we're safe | ||
1773 | + * because i_size and next_index have already been lowered, preventing | ||
1774 | + * access beyond. But in the punch_hole case, we still need to take | ||
1775 | + * the lock when updating the swap directory, because there might be | ||
1776 | + * racing accesses by shmem_getpage(SGP_CACHE), shmem_unuse_inode or | ||
1777 | + * shmem_writepage. However, whenever we find we can remove a whole | ||
1778 | + * directory page (not at the misaligned start or end of the range), | ||
1779 | + * we first NULLify its pointer in the level above, and then have no | ||
1780 | + * need to take the lock when updating its contents: needs_lock and | ||
1781 | + * punch_lock (either pointing to info->lock or NULL) manage this. | ||
1782 | + */ | ||
1783 | + | ||
1784 | + upper_limit -= SHMEM_NR_DIRECT; | ||
1785 | limit -= SHMEM_NR_DIRECT; | ||
1786 | idx = (idx > SHMEM_NR_DIRECT)? (idx - SHMEM_NR_DIRECT): 0; | ||
1787 | offset = idx % ENTRIES_PER_PAGE; | ||
1788 | @@ -543,8 +581,14 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) | ||
1789 | if (*dir) { | ||
1790 | diroff = ((idx - ENTRIES_PER_PAGEPAGE/2) % | ||
1791 | ENTRIES_PER_PAGEPAGE) / ENTRIES_PER_PAGE; | ||
1792 | - if (!diroff && !offset) { | ||
1793 | - *dir = NULL; | ||
1794 | + if (!diroff && !offset && upper_limit >= stage) { | ||
1795 | + if (needs_lock) { | ||
1796 | + spin_lock(needs_lock); | ||
1797 | + *dir = NULL; | ||
1798 | + spin_unlock(needs_lock); | ||
1799 | + needs_lock = NULL; | ||
1800 | + } else | ||
1801 | + *dir = NULL; | ||
1802 | nr_pages_to_free++; | ||
1803 | list_add(&middir->lru, &pages_to_free); | ||
1804 | } | ||
1805 | @@ -570,39 +614,55 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) | ||
1806 | } | ||
1807 | stage = idx + ENTRIES_PER_PAGEPAGE; | ||
1808 | middir = *dir; | ||
1809 | - *dir = NULL; | ||
1810 | - nr_pages_to_free++; | ||
1811 | - list_add(&middir->lru, &pages_to_free); | ||
1812 | + if (punch_hole) | ||
1813 | + needs_lock = &info->lock; | ||
1814 | + if (upper_limit >= stage) { | ||
1815 | + if (needs_lock) { | ||
1816 | + spin_lock(needs_lock); | ||
1817 | + *dir = NULL; | ||
1818 | + spin_unlock(needs_lock); | ||
1819 | + needs_lock = NULL; | ||
1820 | + } else | ||
1821 | + *dir = NULL; | ||
1822 | + nr_pages_to_free++; | ||
1823 | + list_add(&middir->lru, &pages_to_free); | ||
1824 | + } | ||
1825 | shmem_dir_unmap(dir); | ||
1826 | cond_resched(); | ||
1827 | dir = shmem_dir_map(middir); | ||
1828 | diroff = 0; | ||
1829 | } | ||
1830 | + punch_lock = needs_lock; | ||
1831 | subdir = dir[diroff]; | ||
1832 | - if (subdir && page_private(subdir)) { | ||
1833 | + if (subdir && !offset && upper_limit-idx >= ENTRIES_PER_PAGE) { | ||
1834 | + if (needs_lock) { | ||
1835 | + spin_lock(needs_lock); | ||
1836 | + dir[diroff] = NULL; | ||
1837 | + spin_unlock(needs_lock); | ||
1838 | + punch_lock = NULL; | ||
1839 | + } else | ||
1840 | + dir[diroff] = NULL; | ||
1841 | + nr_pages_to_free++; | ||
1842 | + list_add(&subdir->lru, &pages_to_free); | ||
1843 | + } | ||
1844 | + if (subdir && page_private(subdir) /* has swap entries */) { | ||
1845 | size = limit - idx; | ||
1846 | if (size > ENTRIES_PER_PAGE) | ||
1847 | size = ENTRIES_PER_PAGE; | ||
1848 | freed = shmem_map_and_free_swp(subdir, | ||
1849 | - offset, size, &dir); | ||
1850 | + offset, size, &dir, punch_lock); | ||
1851 | if (!dir) | ||
1852 | dir = shmem_dir_map(middir); | ||
1853 | nr_swaps_freed += freed; | ||
1854 | - if (offset) | ||
1855 | + if (offset || punch_lock) { | ||
1856 | spin_lock(&info->lock); | ||
1857 | - set_page_private(subdir, page_private(subdir) - freed); | ||
1858 | - if (offset) | ||
1859 | + set_page_private(subdir, | ||
1860 | + page_private(subdir) - freed); | ||
1861 | spin_unlock(&info->lock); | ||
1862 | - if (!punch_hole) | ||
1863 | - BUG_ON(page_private(subdir) > offset); | ||
1864 | - } | ||
1865 | - if (offset) | ||
1866 | - offset = 0; | ||
1867 | - else if (subdir && !page_private(subdir)) { | ||
1868 | - dir[diroff] = NULL; | ||
1869 | - nr_pages_to_free++; | ||
1870 | - list_add(&subdir->lru, &pages_to_free); | ||
1871 | + } else | ||
1872 | + BUG_ON(page_private(subdir) != freed); | ||
1873 | } | ||
1874 | + offset = 0; | ||
1875 | } | ||
1876 | done1: | ||
1877 | shmem_dir_unmap(dir); | ||
1878 | @@ -614,8 +674,16 @@ done2: | ||
1879 | * generic_delete_inode did it, before we lowered next_index. | ||
1880 | * Also, though shmem_getpage checks i_size before adding to | ||
1881 | * cache, no recheck after: so fix the narrow window there too. | ||
1882 | + * | ||
1883 | + * Recalling truncate_inode_pages_range and unmap_mapping_range | ||
1884 | + * every time for punch_hole (which never got a chance to clear | ||
1885 | + * SHMEM_PAGEIN at the start of vmtruncate_range) is expensive, | ||
1886 | + * yet hardly ever necessary: try to optimize them out later. | ||
1887 | */ | ||
1888 | truncate_inode_pages_range(inode->i_mapping, start, end); | ||
1889 | + if (punch_hole) | ||
1890 | + unmap_mapping_range(inode->i_mapping, start, | ||
1891 | + end - start, 1); | ||
1892 | } | ||
1893 | |||
1894 | spin_lock(&info->lock); | ||
1895 | diff --git a/net/core/netpoll.c b/net/core/netpoll.c | ||
1896 | index 823215d..522e441 100644 | ||
1897 | --- a/net/core/netpoll.c | ||
1898 | +++ b/net/core/netpoll.c | ||
1899 | @@ -471,6 +471,13 @@ int __netpoll_rx(struct sk_buff *skb) | ||
1900 | if (skb->len < len || len < iph->ihl*4) | ||
1901 | goto out; | ||
1902 | |||
1903 | + /* | ||
1904 | + * Our transport medium may have padded the buffer out. | ||
1905 | + * Now We trim to the true length of the frame. | ||
1906 | + */ | ||
1907 | + if (pskb_trim_rcsum(skb, len)) | ||
1908 | + goto out; | ||
1909 | + | ||
1910 | if (iph->protocol != IPPROTO_UDP) | ||
1911 | goto out; | ||
1912 | |||
1913 | diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c | ||
1914 | index ebe9d0d..4a71b31 100644 | ||
1915 | --- a/net/ipv4/tcp.c | ||
1916 | +++ b/net/ipv4/tcp.c | ||
1917 | @@ -2457,11 +2457,18 @@ void __init tcp_init(void) | ||
1918 | sysctl_max_syn_backlog = 128; | ||
1919 | } | ||
1920 | |||
1921 | - /* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */ | ||
1922 | - sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order; | ||
1923 | - sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3; | ||
1924 | + /* Set the pressure threshold to be a fraction of global memory that | ||
1925 | + * is up to 1/2 at 256 MB, decreasing toward zero with the amount of | ||
1926 | + * memory, with a floor of 128 pages. | ||
1927 | + */ | ||
1928 | + limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); | ||
1929 | + limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); | ||
1930 | + limit = max(limit, 128UL); | ||
1931 | + sysctl_tcp_mem[0] = limit / 4 * 3; | ||
1932 | + sysctl_tcp_mem[1] = limit; | ||
1933 | sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2; | ||
1934 | |||
1935 | + /* Set per-socket limits to no more than 1/128 the pressure threshold */ | ||
1936 | limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7); | ||
1937 | max_share = min(4UL*1024*1024, limit); | ||
1938 | |||
1939 | diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c | ||
1940 | index 7e1aea8..b296c1b 100644 | ||
1941 | --- a/net/irda/af_irda.c | ||
1942 | +++ b/net/irda/af_irda.c | ||
1943 | @@ -138,7 +138,6 @@ static void irda_disconnect_indication(void *instance, void *sap, | ||
1944 | sk->sk_shutdown |= SEND_SHUTDOWN; | ||
1945 | |||
1946 | sk->sk_state_change(sk); | ||
1947 | - sock_orphan(sk); | ||
1948 | release_sock(sk); | ||
1949 | |||
1950 | /* Close our TSAP. | ||
1951 | @@ -1446,7 +1445,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | ||
1952 | */ | ||
1953 | ret = sock_error(sk); | ||
1954 | if (ret) | ||
1955 | - break; | ||
1956 | + ; | ||
1957 | else if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
1958 | ; | ||
1959 | else if (noblock) | ||
1960 | diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c | ||
1961 | index 0d1e8fb..a568f9f 100644 | ||
1962 | --- a/net/sunrpc/svcauth_unix.c | ||
1963 | +++ b/net/sunrpc/svcauth_unix.c | ||
1964 | @@ -383,7 +383,10 @@ void svcauth_unix_purge(void) | ||
1965 | static inline struct ip_map * | ||
1966 | ip_map_cached_get(struct svc_rqst *rqstp) | ||
1967 | { | ||
1968 | - struct ip_map *ipm = rqstp->rq_sock->sk_info_authunix; | ||
1969 | + struct ip_map *ipm; | ||
1970 | + struct svc_sock *svsk = rqstp->rq_sock; | ||
1971 | + spin_lock_bh(&svsk->sk_defer_lock); | ||
1972 | + ipm = svsk->sk_info_authunix; | ||
1973 | if (ipm != NULL) { | ||
1974 | if (!cache_valid(&ipm->h)) { | ||
1975 | /* | ||
1976 | @@ -391,12 +394,14 @@ ip_map_cached_get(struct svc_rqst *rqstp) | ||
1977 | * remembered, e.g. by a second mount from the | ||
1978 | * same IP address. | ||
1979 | */ | ||
1980 | - rqstp->rq_sock->sk_info_authunix = NULL; | ||
1981 | + svsk->sk_info_authunix = NULL; | ||
1982 | + spin_unlock_bh(&svsk->sk_defer_lock); | ||
1983 | cache_put(&ipm->h, &ip_map_cache); | ||
1984 | return NULL; | ||
1985 | } | ||
1986 | cache_get(&ipm->h); | ||
1987 | } | ||
1988 | + spin_unlock_bh(&svsk->sk_defer_lock); | ||
1989 | return ipm; | ||
1990 | } | ||
1991 | |||
1992 | @@ -405,9 +410,15 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) | ||
1993 | { | ||
1994 | struct svc_sock *svsk = rqstp->rq_sock; | ||
1995 | |||
1996 | - if (svsk->sk_sock->type == SOCK_STREAM && svsk->sk_info_authunix == NULL) | ||
1997 | - svsk->sk_info_authunix = ipm; /* newly cached, keep the reference */ | ||
1998 | - else | ||
1999 | + spin_lock_bh(&svsk->sk_defer_lock); | ||
2000 | + if (svsk->sk_sock->type == SOCK_STREAM && | ||
2001 | + svsk->sk_info_authunix == NULL) { | ||
2002 | + /* newly cached, keep the reference */ | ||
2003 | + svsk->sk_info_authunix = ipm; | ||
2004 | + ipm = NULL; | ||
2005 | + } | ||
2006 | + spin_unlock_bh(&svsk->sk_defer_lock); | ||
2007 | + if (ipm) | ||
2008 | cache_put(&ipm->h, &ip_map_cache); | ||
2009 | } | ||
2010 | |||
2011 | diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c | ||
2012 | index 30aaa60..6dc6b77 100644 | ||
2013 | --- a/sound/pci/intel8x0.c | ||
2014 | +++ b/sound/pci/intel8x0.c | ||
2015 | @@ -2489,7 +2489,10 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) | ||
2016 | } | ||
2017 | pci_disable_device(pci); | ||
2018 | pci_save_state(pci); | ||
2019 | - pci_set_power_state(pci, pci_choose_state(pci, state)); | ||
2020 | + /* The call below may disable built-in speaker on some laptops | ||
2021 | + * after S2RAM. So, don't touch it. | ||
2022 | + */ | ||
2023 | + /* pci_set_power_state(pci, pci_choose_state(pci, state)); */ | ||
2024 | return 0; | ||
2025 | } | ||
2026 |