diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/dma-mapping.h | 18 | ||||
-rw-r--r-- | arch/sparc/include/asm/pgtable_64.h | 4 | ||||
-rw-r--r-- | arch/sparc/kernel/ds.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/iommu.c | 10 | ||||
-rw-r--r-- | arch/sparc/kernel/ioport.c | 18 | ||||
-rw-r--r-- | arch/sparc/kernel/leon_kernel.c | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/leon_pci.c | 13 | ||||
-rw-r--r-- | arch/sparc/kernel/leon_smp.c | 3 | ||||
-rw-r--r-- | arch/sparc/kernel/pci_sun4v.c | 9 | ||||
-rw-r--r-- | arch/sparc/kernel/rtrap_64.S | 7 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc_64.c | 7 | ||||
-rw-r--r-- | arch/sparc/mm/fault_32.c | 37 | ||||
-rw-r--r-- | arch/sparc/mm/fault_64.c | 37 |
13 files changed, 103 insertions, 68 deletions
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h index 8c0e4f7bb204..48a7c65731d2 100644 --- a/arch/sparc/include/asm/dma-mapping.h +++ b/arch/sparc/include/asm/dma-mapping.h | |||
@@ -26,24 +26,30 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev) | |||
26 | 26 | ||
27 | #include <asm-generic/dma-mapping-common.h> | 27 | #include <asm-generic/dma-mapping-common.h> |
28 | 28 | ||
29 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, | 29 | #define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL) |
30 | dma_addr_t *dma_handle, gfp_t flag) | 30 | |
31 | static inline void *dma_alloc_attrs(struct device *dev, size_t size, | ||
32 | dma_addr_t *dma_handle, gfp_t flag, | ||
33 | struct dma_attrs *attrs) | ||
31 | { | 34 | { |
32 | struct dma_map_ops *ops = get_dma_ops(dev); | 35 | struct dma_map_ops *ops = get_dma_ops(dev); |
33 | void *cpu_addr; | 36 | void *cpu_addr; |
34 | 37 | ||
35 | cpu_addr = ops->alloc_coherent(dev, size, dma_handle, flag); | 38 | cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs); |
36 | debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr); | 39 | debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr); |
37 | return cpu_addr; | 40 | return cpu_addr; |
38 | } | 41 | } |
39 | 42 | ||
40 | static inline void dma_free_coherent(struct device *dev, size_t size, | 43 | #define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL) |
41 | void *cpu_addr, dma_addr_t dma_handle) | 44 | |
45 | static inline void dma_free_attrs(struct device *dev, size_t size, | ||
46 | void *cpu_addr, dma_addr_t dma_handle, | ||
47 | struct dma_attrs *attrs) | ||
42 | { | 48 | { |
43 | struct dma_map_ops *ops = get_dma_ops(dev); | 49 | struct dma_map_ops *ops = get_dma_ops(dev); |
44 | 50 | ||
45 | debug_dma_free_coherent(dev, size, cpu_addr, dma_handle); | 51 | debug_dma_free_coherent(dev, size, cpu_addr, dma_handle); |
46 | ops->free_coherent(dev, size, cpu_addr, dma_handle); | 52 | ops->free(dev, size, cpu_addr, dma_handle, attrs); |
47 | } | 53 | } |
48 | 54 | ||
49 | static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | 55 | static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) |
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 6fa2f7980e6b..76e4a52aa85e 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -12,8 +12,6 @@ | |||
12 | * the SpitFire page tables. | 12 | * the SpitFire page tables. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <asm-generic/pgtable-nopud.h> | ||
16 | |||
17 | #include <linux/compiler.h> | 15 | #include <linux/compiler.h> |
18 | #include <linux/const.h> | 16 | #include <linux/const.h> |
19 | #include <asm/types.h> | 17 | #include <asm/types.h> |
@@ -22,6 +20,8 @@ | |||
22 | #include <asm/page.h> | 20 | #include <asm/page.h> |
23 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
24 | 22 | ||
23 | #include <asm-generic/pgtable-nopud.h> | ||
24 | |||
25 | /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). | 25 | /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). |
26 | * The page copy blockops can use 0x6000000 to 0x8000000. | 26 | * The page copy blockops can use 0x6000000 to 0x8000000. |
27 | * The TSB is mapped in the 0x8000000 to 0xa000000 range. | 27 | * The TSB is mapped in the 0x8000000 to 0xa000000 range. |
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index fea13c7b1aee..b93c2c9ccb1d 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c | |||
@@ -1264,4 +1264,4 @@ static int __init ds_init(void) | |||
1264 | return vio_register_driver(&ds_driver); | 1264 | return vio_register_driver(&ds_driver); |
1265 | } | 1265 | } |
1266 | 1266 | ||
1267 | subsys_initcall(ds_init); | 1267 | fs_initcall(ds_init); |
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 4643d68713fa..070ed141aac7 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c | |||
@@ -280,7 +280,8 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx) | |||
280 | } | 280 | } |
281 | 281 | ||
282 | static void *dma_4u_alloc_coherent(struct device *dev, size_t size, | 282 | static void *dma_4u_alloc_coherent(struct device *dev, size_t size, |
283 | dma_addr_t *dma_addrp, gfp_t gfp) | 283 | dma_addr_t *dma_addrp, gfp_t gfp, |
284 | struct dma_attrs *attrs) | ||
284 | { | 285 | { |
285 | unsigned long flags, order, first_page; | 286 | unsigned long flags, order, first_page; |
286 | struct iommu *iommu; | 287 | struct iommu *iommu; |
@@ -330,7 +331,8 @@ static void *dma_4u_alloc_coherent(struct device *dev, size_t size, | |||
330 | } | 331 | } |
331 | 332 | ||
332 | static void dma_4u_free_coherent(struct device *dev, size_t size, | 333 | static void dma_4u_free_coherent(struct device *dev, size_t size, |
333 | void *cpu, dma_addr_t dvma) | 334 | void *cpu, dma_addr_t dvma, |
335 | struct dma_attrs *attrs) | ||
334 | { | 336 | { |
335 | struct iommu *iommu; | 337 | struct iommu *iommu; |
336 | unsigned long flags, order, npages; | 338 | unsigned long flags, order, npages; |
@@ -825,8 +827,8 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev, | |||
825 | } | 827 | } |
826 | 828 | ||
827 | static struct dma_map_ops sun4u_dma_ops = { | 829 | static struct dma_map_ops sun4u_dma_ops = { |
828 | .alloc_coherent = dma_4u_alloc_coherent, | 830 | .alloc = dma_4u_alloc_coherent, |
829 | .free_coherent = dma_4u_free_coherent, | 831 | .free = dma_4u_free_coherent, |
830 | .map_page = dma_4u_map_page, | 832 | .map_page = dma_4u_map_page, |
831 | .unmap_page = dma_4u_unmap_page, | 833 | .unmap_page = dma_4u_unmap_page, |
832 | .map_sg = dma_4u_map_sg, | 834 | .map_sg = dma_4u_map_sg, |
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index d0479e2163fa..21bd73943f7f 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c | |||
@@ -261,7 +261,8 @@ EXPORT_SYMBOL(sbus_set_sbus64); | |||
261 | * CPU may access them without any explicit flushing. | 261 | * CPU may access them without any explicit flushing. |
262 | */ | 262 | */ |
263 | static void *sbus_alloc_coherent(struct device *dev, size_t len, | 263 | static void *sbus_alloc_coherent(struct device *dev, size_t len, |
264 | dma_addr_t *dma_addrp, gfp_t gfp) | 264 | dma_addr_t *dma_addrp, gfp_t gfp, |
265 | struct dma_attrs *attrs) | ||
265 | { | 266 | { |
266 | struct platform_device *op = to_platform_device(dev); | 267 | struct platform_device *op = to_platform_device(dev); |
267 | unsigned long len_total = PAGE_ALIGN(len); | 268 | unsigned long len_total = PAGE_ALIGN(len); |
@@ -315,7 +316,7 @@ err_nopages: | |||
315 | } | 316 | } |
316 | 317 | ||
317 | static void sbus_free_coherent(struct device *dev, size_t n, void *p, | 318 | static void sbus_free_coherent(struct device *dev, size_t n, void *p, |
318 | dma_addr_t ba) | 319 | dma_addr_t ba, struct dma_attrs *attrs) |
319 | { | 320 | { |
320 | struct resource *res; | 321 | struct resource *res; |
321 | struct page *pgv; | 322 | struct page *pgv; |
@@ -407,8 +408,8 @@ static void sbus_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | |||
407 | } | 408 | } |
408 | 409 | ||
409 | struct dma_map_ops sbus_dma_ops = { | 410 | struct dma_map_ops sbus_dma_ops = { |
410 | .alloc_coherent = sbus_alloc_coherent, | 411 | .alloc = sbus_alloc_coherent, |
411 | .free_coherent = sbus_free_coherent, | 412 | .free = sbus_free_coherent, |
412 | .map_page = sbus_map_page, | 413 | .map_page = sbus_map_page, |
413 | .unmap_page = sbus_unmap_page, | 414 | .unmap_page = sbus_unmap_page, |
414 | .map_sg = sbus_map_sg, | 415 | .map_sg = sbus_map_sg, |
@@ -436,7 +437,8 @@ arch_initcall(sparc_register_ioport); | |||
436 | * hwdev should be valid struct pci_dev pointer for PCI devices. | 437 | * hwdev should be valid struct pci_dev pointer for PCI devices. |
437 | */ | 438 | */ |
438 | static void *pci32_alloc_coherent(struct device *dev, size_t len, | 439 | static void *pci32_alloc_coherent(struct device *dev, size_t len, |
439 | dma_addr_t *pba, gfp_t gfp) | 440 | dma_addr_t *pba, gfp_t gfp, |
441 | struct dma_attrs *attrs) | ||
440 | { | 442 | { |
441 | unsigned long len_total = PAGE_ALIGN(len); | 443 | unsigned long len_total = PAGE_ALIGN(len); |
442 | void *va; | 444 | void *va; |
@@ -489,7 +491,7 @@ err_nopages: | |||
489 | * past this call are illegal. | 491 | * past this call are illegal. |
490 | */ | 492 | */ |
491 | static void pci32_free_coherent(struct device *dev, size_t n, void *p, | 493 | static void pci32_free_coherent(struct device *dev, size_t n, void *p, |
492 | dma_addr_t ba) | 494 | dma_addr_t ba, struct dma_attrs *attrs) |
493 | { | 495 | { |
494 | struct resource *res; | 496 | struct resource *res; |
495 | 497 | ||
@@ -645,8 +647,8 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist * | |||
645 | } | 647 | } |
646 | 648 | ||
647 | struct dma_map_ops pci32_dma_ops = { | 649 | struct dma_map_ops pci32_dma_ops = { |
648 | .alloc_coherent = pci32_alloc_coherent, | 650 | .alloc = pci32_alloc_coherent, |
649 | .free_coherent = pci32_free_coherent, | 651 | .free = pci32_free_coherent, |
650 | .map_page = pci32_map_page, | 652 | .map_page = pci32_map_page, |
651 | .unmap_page = pci32_unmap_page, | 653 | .unmap_page = pci32_unmap_page, |
652 | .map_sg = pci32_map_sg, | 654 | .map_sg = pci32_map_sg, |
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index a19c8a063683..35e43673c453 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -104,11 +104,11 @@ static int irq_choose_cpu(const struct cpumask *affinity) | |||
104 | { | 104 | { |
105 | cpumask_t mask; | 105 | cpumask_t mask; |
106 | 106 | ||
107 | cpus_and(mask, cpu_online_map, *affinity); | 107 | cpumask_and(&mask, cpu_online_mask, affinity); |
108 | if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask)) | 108 | if (cpumask_equal(&mask, cpu_online_mask) || cpumask_empty(&mask)) |
109 | return boot_cpu_id; | 109 | return boot_cpu_id; |
110 | else | 110 | else |
111 | return first_cpu(mask); | 111 | return cpumask_first(&mask); |
112 | } | 112 | } |
113 | #else | 113 | #else |
114 | #define irq_choose_cpu(affinity) boot_cpu_id | 114 | #define irq_choose_cpu(affinity) boot_cpu_id |
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c index aba6b958b2a5..19f56058742b 100644 --- a/arch/sparc/kernel/leon_pci.c +++ b/arch/sparc/kernel/leon_pci.c | |||
@@ -45,7 +45,6 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info) | |||
45 | 45 | ||
46 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) | 46 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) |
47 | { | 47 | { |
48 | struct leon_pci_info *info = pbus->sysdata; | ||
49 | struct pci_dev *dev; | 48 | struct pci_dev *dev; |
50 | int i, has_io, has_mem; | 49 | int i, has_io, has_mem; |
51 | u16 cmd; | 50 | u16 cmd; |
@@ -111,18 +110,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
111 | return pci_enable_resources(dev, mask); | 110 | return pci_enable_resources(dev, mask); |
112 | } | 111 | } |
113 | 112 | ||
114 | struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) | ||
115 | { | ||
116 | /* | ||
117 | * Currently the OpenBoot nodes are not connected with the PCI device, | ||
118 | * this is because the LEON PROM does not create PCI nodes. Eventually | ||
119 | * this will change and the same approach as pcic.c can be used to | ||
120 | * match PROM nodes with pci devices. | ||
121 | */ | ||
122 | return NULL; | ||
123 | } | ||
124 | EXPORT_SYMBOL(pci_device_to_OF_node); | ||
125 | |||
126 | void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) | 113 | void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) |
127 | { | 114 | { |
128 | #ifdef CONFIG_PCI_DEBUG | 115 | #ifdef CONFIG_PCI_DEBUG |
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 1210fde18740..160cac9c4036 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/pm.h> | 23 | #include <linux/pm.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/gfp.h> | 25 | #include <linux/gfp.h> |
26 | #include <linux/cpu.h> | ||
26 | 27 | ||
27 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
28 | #include <asm/tlbflush.h> | 29 | #include <asm/tlbflush.h> |
@@ -78,6 +79,8 @@ void __cpuinit leon_callin(void) | |||
78 | local_flush_tlb_all(); | 79 | local_flush_tlb_all(); |
79 | leon_configure_cache_smp(); | 80 | leon_configure_cache_smp(); |
80 | 81 | ||
82 | notify_cpu_starting(cpuid); | ||
83 | |||
81 | /* Get our local ticker going. */ | 84 | /* Get our local ticker going. */ |
82 | smp_setup_percpu_timer(); | 85 | smp_setup_percpu_timer(); |
83 | 86 | ||
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index af5755d20fbe..7661e84a05a0 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c | |||
@@ -128,7 +128,8 @@ static inline long iommu_batch_end(void) | |||
128 | } | 128 | } |
129 | 129 | ||
130 | static void *dma_4v_alloc_coherent(struct device *dev, size_t size, | 130 | static void *dma_4v_alloc_coherent(struct device *dev, size_t size, |
131 | dma_addr_t *dma_addrp, gfp_t gfp) | 131 | dma_addr_t *dma_addrp, gfp_t gfp, |
132 | struct dma_attrs *attrs) | ||
132 | { | 133 | { |
133 | unsigned long flags, order, first_page, npages, n; | 134 | unsigned long flags, order, first_page, npages, n; |
134 | struct iommu *iommu; | 135 | struct iommu *iommu; |
@@ -198,7 +199,7 @@ range_alloc_fail: | |||
198 | } | 199 | } |
199 | 200 | ||
200 | static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu, | 201 | static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu, |
201 | dma_addr_t dvma) | 202 | dma_addr_t dvma, struct dma_attrs *attrs) |
202 | { | 203 | { |
203 | struct pci_pbm_info *pbm; | 204 | struct pci_pbm_info *pbm; |
204 | struct iommu *iommu; | 205 | struct iommu *iommu; |
@@ -527,8 +528,8 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist, | |||
527 | } | 528 | } |
528 | 529 | ||
529 | static struct dma_map_ops sun4v_dma_ops = { | 530 | static struct dma_map_ops sun4v_dma_ops = { |
530 | .alloc_coherent = dma_4v_alloc_coherent, | 531 | .alloc = dma_4v_alloc_coherent, |
531 | .free_coherent = dma_4v_free_coherent, | 532 | .free = dma_4v_free_coherent, |
532 | .map_page = dma_4v_map_page, | 533 | .map_page = dma_4v_map_page, |
533 | .unmap_page = dma_4v_unmap_page, | 534 | .unmap_page = dma_4v_unmap_page, |
534 | .map_sg = dma_4v_map_sg, | 535 | .map_sg = dma_4v_map_sg, |
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 77f1b95e0806..9171fc238def 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S | |||
@@ -20,11 +20,6 @@ | |||
20 | 20 | ||
21 | .text | 21 | .text |
22 | .align 32 | 22 | .align 32 |
23 | __handle_softirq: | ||
24 | call do_softirq | ||
25 | nop | ||
26 | ba,a,pt %xcc, __handle_softirq_continue | ||
27 | nop | ||
28 | __handle_preemption: | 23 | __handle_preemption: |
29 | call schedule | 24 | call schedule |
30 | wrpr %g0, RTRAP_PSTATE, %pstate | 25 | wrpr %g0, RTRAP_PSTATE, %pstate |
@@ -89,9 +84,7 @@ rtrap: | |||
89 | cmp %l1, 0 | 84 | cmp %l1, 0 |
90 | 85 | ||
91 | /* mm/ultra.S:xcall_report_regs KNOWS about this load. */ | 86 | /* mm/ultra.S:xcall_report_regs KNOWS about this load. */ |
92 | bne,pn %icc, __handle_softirq | ||
93 | ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 | 87 | ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 |
94 | __handle_softirq_continue: | ||
95 | rtrap_xcall: | 88 | rtrap_xcall: |
96 | sethi %hi(0xf << 20), %l4 | 89 | sethi %hi(0xf << 20), %l4 |
97 | and %l1, %l4, %l4 | 90 | and %l1, %l4, %l4 |
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 232df9949530..3ee51f189a55 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c | |||
@@ -566,15 +566,10 @@ out: | |||
566 | 566 | ||
567 | SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len) | 567 | SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len) |
568 | { | 568 | { |
569 | long ret; | ||
570 | |||
571 | if (invalid_64bit_range(addr, len)) | 569 | if (invalid_64bit_range(addr, len)) |
572 | return -EINVAL; | 570 | return -EINVAL; |
573 | 571 | ||
574 | down_write(¤t->mm->mmap_sem); | 572 | return vm_munmap(addr, len); |
575 | ret = do_munmap(current->mm, addr, len); | ||
576 | up_write(¤t->mm->mmap_sem); | ||
577 | return ret; | ||
578 | } | 573 | } |
579 | 574 | ||
580 | extern unsigned long do_mremap(unsigned long addr, | 575 | extern unsigned long do_mremap(unsigned long addr, |
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index 7705c6731e28..df3155a17991 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c | |||
@@ -225,6 +225,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
225 | unsigned long g2; | 225 | unsigned long g2; |
226 | int from_user = !(regs->psr & PSR_PS); | 226 | int from_user = !(regs->psr & PSR_PS); |
227 | int fault, code; | 227 | int fault, code; |
228 | unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | ||
229 | (write ? FAULT_FLAG_WRITE : 0)); | ||
228 | 230 | ||
229 | if(text_fault) | 231 | if(text_fault) |
230 | address = regs->pc; | 232 | address = regs->pc; |
@@ -251,6 +253,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
251 | 253 | ||
252 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 254 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); |
253 | 255 | ||
256 | retry: | ||
254 | down_read(&mm->mmap_sem); | 257 | down_read(&mm->mmap_sem); |
255 | 258 | ||
256 | /* | 259 | /* |
@@ -289,7 +292,11 @@ good_area: | |||
289 | * make sure we exit gracefully rather than endlessly redo | 292 | * make sure we exit gracefully rather than endlessly redo |
290 | * the fault. | 293 | * the fault. |
291 | */ | 294 | */ |
292 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); | 295 | fault = handle_mm_fault(mm, vma, address, flags); |
296 | |||
297 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
298 | return; | ||
299 | |||
293 | if (unlikely(fault & VM_FAULT_ERROR)) { | 300 | if (unlikely(fault & VM_FAULT_ERROR)) { |
294 | if (fault & VM_FAULT_OOM) | 301 | if (fault & VM_FAULT_OOM) |
295 | goto out_of_memory; | 302 | goto out_of_memory; |
@@ -297,13 +304,29 @@ good_area: | |||
297 | goto do_sigbus; | 304 | goto do_sigbus; |
298 | BUG(); | 305 | BUG(); |
299 | } | 306 | } |
300 | if (fault & VM_FAULT_MAJOR) { | 307 | |
301 | current->maj_flt++; | 308 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
302 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address); | 309 | if (fault & VM_FAULT_MAJOR) { |
303 | } else { | 310 | current->maj_flt++; |
304 | current->min_flt++; | 311 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, |
305 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address); | 312 | 1, regs, address); |
313 | } else { | ||
314 | current->min_flt++; | ||
315 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, | ||
316 | 1, regs, address); | ||
317 | } | ||
318 | if (fault & VM_FAULT_RETRY) { | ||
319 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
320 | |||
321 | /* No need to up_read(&mm->mmap_sem) as we would | ||
322 | * have already released it in __lock_page_or_retry | ||
323 | * in mm/filemap.c. | ||
324 | */ | ||
325 | |||
326 | goto retry; | ||
327 | } | ||
306 | } | 328 | } |
329 | |||
307 | up_read(&mm->mmap_sem); | 330 | up_read(&mm->mmap_sem); |
308 | return; | 331 | return; |
309 | 332 | ||
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 504c0622f729..1fe0429b6314 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -279,6 +279,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
279 | unsigned int insn = 0; | 279 | unsigned int insn = 0; |
280 | int si_code, fault_code, fault; | 280 | int si_code, fault_code, fault; |
281 | unsigned long address, mm_rss; | 281 | unsigned long address, mm_rss; |
282 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | ||
282 | 283 | ||
283 | fault_code = get_thread_fault_code(); | 284 | fault_code = get_thread_fault_code(); |
284 | 285 | ||
@@ -333,6 +334,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
333 | insn = get_fault_insn(regs, insn); | 334 | insn = get_fault_insn(regs, insn); |
334 | goto handle_kernel_fault; | 335 | goto handle_kernel_fault; |
335 | } | 336 | } |
337 | |||
338 | retry: | ||
336 | down_read(&mm->mmap_sem); | 339 | down_read(&mm->mmap_sem); |
337 | } | 340 | } |
338 | 341 | ||
@@ -423,7 +426,12 @@ good_area: | |||
423 | goto bad_area; | 426 | goto bad_area; |
424 | } | 427 | } |
425 | 428 | ||
426 | fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0); | 429 | flags |= ((fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0); |
430 | fault = handle_mm_fault(mm, vma, address, flags); | ||
431 | |||
432 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
433 | return; | ||
434 | |||
427 | if (unlikely(fault & VM_FAULT_ERROR)) { | 435 | if (unlikely(fault & VM_FAULT_ERROR)) { |
428 | if (fault & VM_FAULT_OOM) | 436 | if (fault & VM_FAULT_OOM) |
429 | goto out_of_memory; | 437 | goto out_of_memory; |
@@ -431,12 +439,27 @@ good_area: | |||
431 | goto do_sigbus; | 439 | goto do_sigbus; |
432 | BUG(); | 440 | BUG(); |
433 | } | 441 | } |
434 | if (fault & VM_FAULT_MAJOR) { | 442 | |
435 | current->maj_flt++; | 443 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
436 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address); | 444 | if (fault & VM_FAULT_MAJOR) { |
437 | } else { | 445 | current->maj_flt++; |
438 | current->min_flt++; | 446 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, |
439 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address); | 447 | 1, regs, address); |
448 | } else { | ||
449 | current->min_flt++; | ||
450 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, | ||
451 | 1, regs, address); | ||
452 | } | ||
453 | if (fault & VM_FAULT_RETRY) { | ||
454 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
455 | |||
456 | /* No need to up_read(&mm->mmap_sem) as we would | ||
457 | * have already released it in __lock_page_or_retry | ||
458 | * in mm/filemap.c. | ||
459 | */ | ||
460 | |||
461 | goto retry; | ||
462 | } | ||
440 | } | 463 | } |
441 | up_read(&mm->mmap_sem); | 464 | up_read(&mm->mmap_sem); |
442 | 465 | ||