diff options
31 files changed, 222 insertions, 65 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4fd479059d65..10a0a5488a44 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -385,9 +385,15 @@ config NUMA | |||
385 | 385 | ||
386 | config NODES_SHIFT | 386 | config NODES_SHIFT |
387 | int | 387 | int |
388 | default "8" if PPC64 | ||
388 | default "4" | 389 | default "4" |
389 | depends on NEED_MULTIPLE_NODES | 390 | depends on NEED_MULTIPLE_NODES |
390 | 391 | ||
392 | config MAX_ACTIVE_REGIONS | ||
393 | int | ||
394 | default "256" if PPC64 | ||
395 | default "32" | ||
396 | |||
391 | config ARCH_SELECT_MEMORY_MODEL | 397 | config ARCH_SELECT_MEMORY_MODEL |
392 | def_bool y | 398 | def_bool y |
393 | depends on PPC64 | 399 | depends on PPC64 |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index aacf629c1a9f..1a54a3b3a3fa 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -164,6 +164,17 @@ PHONY += $(BOOT_TARGETS) | |||
164 | 164 | ||
165 | boot := arch/$(ARCH)/boot | 165 | boot := arch/$(ARCH)/boot |
166 | 166 | ||
167 | ifeq ($(CONFIG_RELOCATABLE),y) | ||
168 | quiet_cmd_relocs_check = CALL $< | ||
169 | cmd_relocs_check = perl $< "$(OBJDUMP)" "$(obj)/vmlinux" | ||
170 | |||
171 | PHONY += relocs_check | ||
172 | relocs_check: arch/powerpc/relocs_check.pl vmlinux | ||
173 | $(call cmd,relocs_check) | ||
174 | |||
175 | zImage: relocs_check | ||
176 | endif | ||
177 | |||
167 | $(BOOT_TARGETS): vmlinux | 178 | $(BOOT_TARGETS): vmlinux |
168 | $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@) | 179 | $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@) |
169 | 180 | ||
diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h index 9dade15d1ab4..6d94d27ed850 100644 --- a/arch/powerpc/include/asm/device.h +++ b/arch/powerpc/include/asm/device.h | |||
@@ -15,7 +15,16 @@ struct dev_archdata { | |||
15 | 15 | ||
16 | /* DMA operations on that device */ | 16 | /* DMA operations on that device */ |
17 | struct dma_map_ops *dma_ops; | 17 | struct dma_map_ops *dma_ops; |
18 | void *dma_data; | 18 | |
19 | /* | ||
20 | * When an iommu is in use, dma_data is used as a ptr to the base of the | ||
21 | * iommu_table. Otherwise, it is a simple numerical offset. | ||
22 | */ | ||
23 | union { | ||
24 | dma_addr_t dma_offset; | ||
25 | void *iommu_table_base; | ||
26 | } dma_data; | ||
27 | |||
19 | #ifdef CONFIG_SWIOTLB | 28 | #ifdef CONFIG_SWIOTLB |
20 | dma_addr_t max_direct_dma_addr; | 29 | dma_addr_t max_direct_dma_addr; |
21 | #endif | 30 | #endif |
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index cb2ca41dd526..e281daebddca 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h | |||
@@ -26,7 +26,6 @@ extern void *dma_direct_alloc_coherent(struct device *dev, size_t size, | |||
26 | extern void dma_direct_free_coherent(struct device *dev, size_t size, | 26 | extern void dma_direct_free_coherent(struct device *dev, size_t size, |
27 | void *vaddr, dma_addr_t dma_handle); | 27 | void *vaddr, dma_addr_t dma_handle); |
28 | 28 | ||
29 | extern unsigned long get_dma_direct_offset(struct device *dev); | ||
30 | 29 | ||
31 | #ifdef CONFIG_NOT_COHERENT_CACHE | 30 | #ifdef CONFIG_NOT_COHERENT_CACHE |
32 | /* | 31 | /* |
@@ -90,6 +89,28 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) | |||
90 | dev->archdata.dma_ops = ops; | 89 | dev->archdata.dma_ops = ops; |
91 | } | 90 | } |
92 | 91 | ||
92 | /* | ||
93 | * get_dma_offset() | ||
94 | * | ||
95 | * Get the dma offset on configurations where the dma address can be determined | ||
96 | * from the physical address by looking at a simple offset. Direct dma and | ||
97 | * swiotlb use this function, but it is typically not used by implementations | ||
98 | * with an iommu. | ||
99 | */ | ||
100 | static inline dma_addr_t get_dma_offset(struct device *dev) | ||
101 | { | ||
102 | if (dev) | ||
103 | return dev->archdata.dma_data.dma_offset; | ||
104 | |||
105 | return PCI_DRAM_OFFSET; | ||
106 | } | ||
107 | |||
108 | static inline void set_dma_offset(struct device *dev, dma_addr_t off) | ||
109 | { | ||
110 | if (dev) | ||
111 | dev->archdata.dma_data.dma_offset = off; | ||
112 | } | ||
113 | |||
93 | /* this will be removed soon */ | 114 | /* this will be removed soon */ |
94 | #define flush_write_buffers() | 115 | #define flush_write_buffers() |
95 | 116 | ||
@@ -181,12 +202,12 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | |||
181 | 202 | ||
182 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 203 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
183 | { | 204 | { |
184 | return paddr + get_dma_direct_offset(dev); | 205 | return paddr + get_dma_offset(dev); |
185 | } | 206 | } |
186 | 207 | ||
187 | static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) | 208 | static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) |
188 | { | 209 | { |
189 | return daddr - get_dma_direct_offset(dev); | 210 | return daddr - get_dma_offset(dev); |
190 | } | 211 | } |
191 | 212 | ||
192 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | 213 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) |
diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 7464c0daddd1..edfc9803ec91 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h | |||
@@ -70,6 +70,16 @@ struct iommu_table { | |||
70 | 70 | ||
71 | struct scatterlist; | 71 | struct scatterlist; |
72 | 72 | ||
73 | static inline void set_iommu_table_base(struct device *dev, void *base) | ||
74 | { | ||
75 | dev->archdata.dma_data.iommu_table_base = base; | ||
76 | } | ||
77 | |||
78 | static inline void *get_iommu_table_base(struct device *dev) | ||
79 | { | ||
80 | return dev->archdata.dma_data.iommu_table_base; | ||
81 | } | ||
82 | |||
73 | /* Frees table for an individual device node */ | 83 | /* Frees table for an individual device node */ |
74 | extern void iommu_free_table(struct iommu_table *tbl, const char *node_name); | 84 | extern void iommu_free_table(struct iommu_table *tbl, const char *node_name); |
75 | 85 | ||
diff --git a/arch/powerpc/include/asm/pmc.h b/arch/powerpc/include/asm/pmc.h index ccc68b50d05d..5a9ede4962cb 100644 --- a/arch/powerpc/include/asm/pmc.h +++ b/arch/powerpc/include/asm/pmc.h | |||
@@ -29,7 +29,7 @@ int reserve_pmc_hardware(perf_irq_t new_perf_irq); | |||
29 | void release_pmc_hardware(void); | 29 | void release_pmc_hardware(void); |
30 | void ppc_enable_pmcs(void); | 30 | void ppc_enable_pmcs(void); |
31 | 31 | ||
32 | #ifdef CONFIG_PPC64 | 32 | #ifdef CONFIG_PPC_BOOK3S_64 |
33 | #include <asm/lppaca.h> | 33 | #include <asm/lppaca.h> |
34 | 34 | ||
35 | static inline void ppc_set_pmu_inuse(int inuse) | 35 | static inline void ppc_set_pmu_inuse(int inuse) |
diff --git a/arch/powerpc/include/asm/pte-40x.h b/arch/powerpc/include/asm/pte-40x.h index 6c3e1f4378d4..ec0b0b0d1df9 100644 --- a/arch/powerpc/include/asm/pte-40x.h +++ b/arch/powerpc/include/asm/pte-40x.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */ | 43 | #define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */ |
44 | #define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */ | 44 | #define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */ |
45 | #define _PAGE_USER 0x010 /* matches one of the zone permission bits */ | 45 | #define _PAGE_USER 0x010 /* matches one of the zone permission bits */ |
46 | #define _PAGE_SPECIAL 0x020 /* software: Special page */ | ||
46 | #define _PAGE_RW 0x040 /* software: Writes permitted */ | 47 | #define _PAGE_RW 0x040 /* software: Writes permitted */ |
47 | #define _PAGE_DIRTY 0x080 /* software: dirty page */ | 48 | #define _PAGE_DIRTY 0x080 /* software: dirty page */ |
48 | #define _PAGE_HWWRITE 0x100 /* hardware: Dirty & RW, set in exception */ | 49 | #define _PAGE_HWWRITE 0x100 /* hardware: Dirty & RW, set in exception */ |
diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h index 94e979718dcf..dd5ea95fe61e 100644 --- a/arch/powerpc/include/asm/pte-8xx.h +++ b/arch/powerpc/include/asm/pte-8xx.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define _PAGE_FILE 0x0002 /* when !present: nonlinear file mapping */ | 32 | #define _PAGE_FILE 0x0002 /* when !present: nonlinear file mapping */ |
33 | #define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */ | 33 | #define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */ |
34 | #define _PAGE_SHARED 0x0004 /* No ASID (context) compare */ | 34 | #define _PAGE_SHARED 0x0004 /* No ASID (context) compare */ |
35 | #define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */ | ||
35 | 36 | ||
36 | /* These five software bits must be masked out when the entry is loaded | 37 | /* These five software bits must be masked out when the entry is loaded |
37 | * into the TLB. | 38 | * into the TLB. |
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h index c3b65076a263..f2b370180a09 100644 --- a/arch/powerpc/include/asm/pte-common.h +++ b/arch/powerpc/include/asm/pte-common.h | |||
@@ -25,9 +25,6 @@ | |||
25 | #ifndef _PAGE_WRITETHRU | 25 | #ifndef _PAGE_WRITETHRU |
26 | #define _PAGE_WRITETHRU 0 | 26 | #define _PAGE_WRITETHRU 0 |
27 | #endif | 27 | #endif |
28 | #ifndef _PAGE_SPECIAL | ||
29 | #define _PAGE_SPECIAL 0 | ||
30 | #endif | ||
31 | #ifndef _PAGE_4K_PFN | 28 | #ifndef _PAGE_4K_PFN |
32 | #define _PAGE_4K_PFN 0 | 29 | #define _PAGE_4K_PFN 0 |
33 | #endif | 30 | #endif |
@@ -179,7 +176,5 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); | |||
179 | #define HAVE_PAGE_AGP | 176 | #define HAVE_PAGE_AGP |
180 | 177 | ||
181 | /* Advertise support for _PAGE_SPECIAL */ | 178 | /* Advertise support for _PAGE_SPECIAL */ |
182 | #ifdef _PAGE_SPECIAL | ||
183 | #define __HAVE_ARCH_PTE_SPECIAL | 179 | #define __HAVE_ARCH_PTE_SPECIAL |
184 | #endif | ||
185 | 180 | ||
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 87ddb3fb948c..37771a518119 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c | |||
@@ -18,7 +18,7 @@ | |||
18 | static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, | 18 | static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, |
19 | dma_addr_t *dma_handle, gfp_t flag) | 19 | dma_addr_t *dma_handle, gfp_t flag) |
20 | { | 20 | { |
21 | return iommu_alloc_coherent(dev, dev->archdata.dma_data, size, | 21 | return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size, |
22 | dma_handle, device_to_mask(dev), flag, | 22 | dma_handle, device_to_mask(dev), flag, |
23 | dev_to_node(dev)); | 23 | dev_to_node(dev)); |
24 | } | 24 | } |
@@ -26,7 +26,7 @@ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, | |||
26 | static void dma_iommu_free_coherent(struct device *dev, size_t size, | 26 | static void dma_iommu_free_coherent(struct device *dev, size_t size, |
27 | void *vaddr, dma_addr_t dma_handle) | 27 | void *vaddr, dma_addr_t dma_handle) |
28 | { | 28 | { |
29 | iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle); | 29 | iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle); |
30 | } | 30 | } |
31 | 31 | ||
32 | /* Creates TCEs for a user provided buffer. The user buffer must be | 32 | /* Creates TCEs for a user provided buffer. The user buffer must be |
@@ -39,8 +39,8 @@ static dma_addr_t dma_iommu_map_page(struct device *dev, struct page *page, | |||
39 | enum dma_data_direction direction, | 39 | enum dma_data_direction direction, |
40 | struct dma_attrs *attrs) | 40 | struct dma_attrs *attrs) |
41 | { | 41 | { |
42 | return iommu_map_page(dev, dev->archdata.dma_data, page, offset, size, | 42 | return iommu_map_page(dev, get_iommu_table_base(dev), page, offset, |
43 | device_to_mask(dev), direction, attrs); | 43 | size, device_to_mask(dev), direction, attrs); |
44 | } | 44 | } |
45 | 45 | ||
46 | 46 | ||
@@ -48,7 +48,7 @@ static void dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle, | |||
48 | size_t size, enum dma_data_direction direction, | 48 | size_t size, enum dma_data_direction direction, |
49 | struct dma_attrs *attrs) | 49 | struct dma_attrs *attrs) |
50 | { | 50 | { |
51 | iommu_unmap_page(dev->archdata.dma_data, dma_handle, size, direction, | 51 | iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size, direction, |
52 | attrs); | 52 | attrs); |
53 | } | 53 | } |
54 | 54 | ||
@@ -57,7 +57,7 @@ static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist, | |||
57 | int nelems, enum dma_data_direction direction, | 57 | int nelems, enum dma_data_direction direction, |
58 | struct dma_attrs *attrs) | 58 | struct dma_attrs *attrs) |
59 | { | 59 | { |
60 | return iommu_map_sg(dev, dev->archdata.dma_data, sglist, nelems, | 60 | return iommu_map_sg(dev, get_iommu_table_base(dev), sglist, nelems, |
61 | device_to_mask(dev), direction, attrs); | 61 | device_to_mask(dev), direction, attrs); |
62 | } | 62 | } |
63 | 63 | ||
@@ -65,14 +65,14 @@ static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist, | |||
65 | int nelems, enum dma_data_direction direction, | 65 | int nelems, enum dma_data_direction direction, |
66 | struct dma_attrs *attrs) | 66 | struct dma_attrs *attrs) |
67 | { | 67 | { |
68 | iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction, | 68 | iommu_unmap_sg(get_iommu_table_base(dev), sglist, nelems, direction, |
69 | attrs); | 69 | attrs); |
70 | } | 70 | } |
71 | 71 | ||
72 | /* We support DMA to/from any memory page via the iommu */ | 72 | /* We support DMA to/from any memory page via the iommu */ |
73 | static int dma_iommu_dma_supported(struct device *dev, u64 mask) | 73 | static int dma_iommu_dma_supported(struct device *dev, u64 mask) |
74 | { | 74 | { |
75 | struct iommu_table *tbl = dev->archdata.dma_data; | 75 | struct iommu_table *tbl = get_iommu_table_base(dev); |
76 | 76 | ||
77 | if (!tbl || tbl->it_offset > mask) { | 77 | if (!tbl || tbl->it_offset > mask) { |
78 | printk(KERN_INFO | 78 | printk(KERN_INFO |
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 21b784d7e7d0..6215062caf8c 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c | |||
@@ -21,13 +21,6 @@ | |||
21 | * default the offset is PCI_DRAM_OFFSET. | 21 | * default the offset is PCI_DRAM_OFFSET. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | unsigned long get_dma_direct_offset(struct device *dev) | ||
25 | { | ||
26 | if (dev) | ||
27 | return (unsigned long)dev->archdata.dma_data; | ||
28 | |||
29 | return PCI_DRAM_OFFSET; | ||
30 | } | ||
31 | 24 | ||
32 | void *dma_direct_alloc_coherent(struct device *dev, size_t size, | 25 | void *dma_direct_alloc_coherent(struct device *dev, size_t size, |
33 | dma_addr_t *dma_handle, gfp_t flag) | 26 | dma_addr_t *dma_handle, gfp_t flag) |
@@ -37,7 +30,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size, | |||
37 | ret = __dma_alloc_coherent(dev, size, dma_handle, flag); | 30 | ret = __dma_alloc_coherent(dev, size, dma_handle, flag); |
38 | if (ret == NULL) | 31 | if (ret == NULL) |
39 | return NULL; | 32 | return NULL; |
40 | *dma_handle += get_dma_direct_offset(dev); | 33 | *dma_handle += get_dma_offset(dev); |
41 | return ret; | 34 | return ret; |
42 | #else | 35 | #else |
43 | struct page *page; | 36 | struct page *page; |
@@ -51,7 +44,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size, | |||
51 | return NULL; | 44 | return NULL; |
52 | ret = page_address(page); | 45 | ret = page_address(page); |
53 | memset(ret, 0, size); | 46 | memset(ret, 0, size); |
54 | *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev); | 47 | *dma_handle = virt_to_abs(ret) + get_dma_offset(dev); |
55 | 48 | ||
56 | return ret; | 49 | return ret; |
57 | #endif | 50 | #endif |
@@ -75,7 +68,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, | |||
75 | int i; | 68 | int i; |
76 | 69 | ||
77 | for_each_sg(sgl, sg, nents, i) { | 70 | for_each_sg(sgl, sg, nents, i) { |
78 | sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev); | 71 | sg->dma_address = sg_phys(sg) + get_dma_offset(dev); |
79 | sg->dma_length = sg->length; | 72 | sg->dma_length = sg->length; |
80 | __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction); | 73 | __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction); |
81 | } | 74 | } |
@@ -110,7 +103,7 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev, | |||
110 | { | 103 | { |
111 | BUG_ON(dir == DMA_NONE); | 104 | BUG_ON(dir == DMA_NONE); |
112 | __dma_sync_page(page, offset, size, dir); | 105 | __dma_sync_page(page, offset, size, dir); |
113 | return page_to_phys(page) + offset + get_dma_direct_offset(dev); | 106 | return page_to_phys(page) + offset + get_dma_offset(dev); |
114 | } | 107 | } |
115 | 108 | ||
116 | static inline void dma_direct_unmap_page(struct device *dev, | 109 | static inline void dma_direct_unmap_page(struct device *dev, |
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 9048f96237f6..24dcc0ecf246 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <asm/cputable.h> | 17 | #include <asm/cputable.h> |
18 | #include <asm/setup.h> | 18 | #include <asm/setup.h> |
19 | #include <asm/thread_info.h> | 19 | #include <asm/thread_info.h> |
20 | #include <asm/reg.h> | ||
21 | #include <asm/exception-64e.h> | 20 | #include <asm/exception-64e.h> |
22 | #include <asm/bug.h> | 21 | #include <asm/bug.h> |
23 | #include <asm/irqflags.h> | 22 | #include <asm/irqflags.h> |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index e9f4840096b3..bb8209e34931 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -1117,7 +1117,7 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) | |||
1117 | 1117 | ||
1118 | /* Hook up default DMA ops */ | 1118 | /* Hook up default DMA ops */ |
1119 | sd->dma_ops = pci_dma_ops; | 1119 | sd->dma_ops = pci_dma_ops; |
1120 | sd->dma_data = (void *)PCI_DRAM_OFFSET; | 1120 | set_dma_offset(&dev->dev, PCI_DRAM_OFFSET); |
1121 | 1121 | ||
1122 | /* Additional platform DMA/iommu setup */ | 1122 | /* Additional platform DMA/iommu setup */ |
1123 | if (ppc_md.pci_dma_dev_setup) | 1123 | if (ppc_md.pci_dma_dev_setup) |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 0a3216433051..1168c5f440ab 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -1165,7 +1165,22 @@ static inline unsigned long brk_rnd(void) | |||
1165 | 1165 | ||
1166 | unsigned long arch_randomize_brk(struct mm_struct *mm) | 1166 | unsigned long arch_randomize_brk(struct mm_struct *mm) |
1167 | { | 1167 | { |
1168 | unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); | 1168 | unsigned long base = mm->brk; |
1169 | unsigned long ret; | ||
1170 | |||
1171 | #ifdef CONFIG_PPC64 | ||
1172 | /* | ||
1173 | * If we are using 1TB segments and we are allowed to randomise | ||
1174 | * the heap, we can put it above 1TB so it is backed by a 1TB | ||
1175 | * segment. Otherwise the heap will be in the bottom 1TB | ||
1176 | * which always uses 256MB segments and this may result in a | ||
1177 | * performance penalty. | ||
1178 | */ | ||
1179 | if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T)) | ||
1180 | base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T); | ||
1181 | #endif | ||
1182 | |||
1183 | ret = PAGE_ALIGN(base + brk_rnd()); | ||
1169 | 1184 | ||
1170 | if (ret < mm->brk) | 1185 | if (ret < mm->brk) |
1171 | return mm->brk; | 1186 | return mm->brk; |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 864334b337a3..bafac2e41ae1 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -800,7 +800,7 @@ static void __init prom_send_capabilities(void) | |||
800 | root = call_prom("open", 1, 1, ADDR("/")); | 800 | root = call_prom("open", 1, 1, ADDR("/")); |
801 | if (root != 0) { | 801 | if (root != 0) { |
802 | /* try calling the ibm,client-architecture-support method */ | 802 | /* try calling the ibm,client-architecture-support method */ |
803 | prom_printf("Calling ibm,client-architecture..."); | 803 | prom_printf("Calling ibm,client-architecture-support..."); |
804 | if (call_prom_ret("call-method", 3, 2, &ret, | 804 | if (call_prom_ret("call-method", 3, 2, &ret, |
805 | ADDR("ibm,client-architecture-support"), | 805 | ADDR("ibm,client-architecture-support"), |
806 | root, | 806 | root, |
@@ -814,6 +814,7 @@ static void __init prom_send_capabilities(void) | |||
814 | return; | 814 | return; |
815 | } | 815 | } |
816 | call_prom("close", 1, 0, root); | 816 | call_prom("close", 1, 0, root); |
817 | prom_printf(" not implemented\n"); | ||
817 | } | 818 | } |
818 | 819 | ||
819 | /* no ibm,client-architecture-support call, try the old way */ | 820 | /* no ibm,client-architecture-support call, try the old way */ |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 3faaf29bdb29..94e2df3cae07 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -241,6 +241,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
241 | } | 241 | } |
242 | 242 | ||
243 | /* | 243 | /* |
244 | * Put vDSO base into mm struct. We need to do this before calling | ||
245 | * install_special_mapping or the perf counter mmap tracking code | ||
246 | * will fail to recognise it as a vDSO (since arch_vma_name fails). | ||
247 | */ | ||
248 | current->mm->context.vdso_base = vdso_base; | ||
249 | |||
250 | /* | ||
244 | * our vma flags don't have VM_WRITE so by default, the process isn't | 251 | * our vma flags don't have VM_WRITE so by default, the process isn't |
245 | * allowed to write those pages. | 252 | * allowed to write those pages. |
246 | * gdb can break that with ptrace interface, and thus trigger COW on | 253 | * gdb can break that with ptrace interface, and thus trigger COW on |
@@ -260,11 +267,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
260 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| | 267 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| |
261 | VM_ALWAYSDUMP, | 268 | VM_ALWAYSDUMP, |
262 | vdso_pagelist); | 269 | vdso_pagelist); |
263 | if (rc) | 270 | if (rc) { |
271 | current->mm->context.vdso_base = 0; | ||
264 | goto fail_mmapsem; | 272 | goto fail_mmapsem; |
265 | 273 | } | |
266 | /* Put vDSO base into mm struct */ | ||
267 | current->mm->context.vdso_base = vdso_base; | ||
268 | 274 | ||
269 | up_write(&mm->mmap_sem); | 275 | up_write(&mm->mmap_sem); |
270 | return 0; | 276 | return 0; |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index bc7b41edbdfc..77f64218abf3 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -1054,6 +1054,8 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) | |||
1054 | return NULL; | 1054 | return NULL; |
1055 | 1055 | ||
1056 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); | 1056 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); |
1057 | if (tbl == NULL) | ||
1058 | return NULL; | ||
1057 | 1059 | ||
1058 | of_parse_dma_window(dev->dev.archdata.of_node, dma_window, | 1060 | of_parse_dma_window(dev->dev.archdata.of_node, dma_window, |
1059 | &tbl->it_index, &offset, &size); | 1061 | &tbl->it_index, &offset, &size); |
@@ -1233,7 +1235,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1233 | vio_cmo_set_dma_ops(viodev); | 1235 | vio_cmo_set_dma_ops(viodev); |
1234 | else | 1236 | else |
1235 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; | 1237 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; |
1236 | viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev); | 1238 | set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev)); |
1237 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); | 1239 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); |
1238 | 1240 | ||
1239 | /* init generic 'struct device' fields: */ | 1241 | /* init generic 'struct device' fields: */ |
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 83f1551ec2c9..53040931de32 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <asm/tlbflush.h> | 30 | #include <asm/tlbflush.h> |
31 | #include <asm/tlb.h> | 31 | #include <asm/tlb.h> |
32 | 32 | ||
33 | #include "mmu_decl.h" | ||
34 | |||
33 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 35 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
34 | 36 | ||
35 | #ifdef CONFIG_SMP | 37 | #ifdef CONFIG_SMP |
@@ -166,7 +168,7 @@ struct page * maybe_pte_to_page(pte_t pte) | |||
166 | * support falls into the same category. | 168 | * support falls into the same category. |
167 | */ | 169 | */ |
168 | 170 | ||
169 | static pte_t set_pte_filter(pte_t pte) | 171 | static pte_t set_pte_filter(pte_t pte, unsigned long addr) |
170 | { | 172 | { |
171 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); | 173 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); |
172 | if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || | 174 | if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || |
@@ -175,6 +177,17 @@ static pte_t set_pte_filter(pte_t pte) | |||
175 | if (!pg) | 177 | if (!pg) |
176 | return pte; | 178 | return pte; |
177 | if (!test_bit(PG_arch_1, &pg->flags)) { | 179 | if (!test_bit(PG_arch_1, &pg->flags)) { |
180 | #ifdef CONFIG_8xx | ||
181 | /* On 8xx, cache control instructions (particularly | ||
182 | * "dcbst" from flush_dcache_icache) fault as write | ||
183 | * operation if there is an unpopulated TLB entry | ||
184 | * for the address in question. To workaround that, | ||
185 | * we invalidate the TLB here, thus avoiding dcbst | ||
186 | * misbehaviour. | ||
187 | */ | ||
188 | /* 8xx doesn't care about PID, size or ind args */ | ||
189 | _tlbil_va(addr, 0, 0, 0); | ||
190 | #endif /* CONFIG_8xx */ | ||
178 | flush_dcache_icache_page(pg); | 191 | flush_dcache_icache_page(pg); |
179 | set_bit(PG_arch_1, &pg->flags); | 192 | set_bit(PG_arch_1, &pg->flags); |
180 | } | 193 | } |
@@ -194,7 +207,7 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | |||
194 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so | 207 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so |
195 | * instead we "filter out" the exec permission for non clean pages. | 208 | * instead we "filter out" the exec permission for non clean pages. |
196 | */ | 209 | */ |
197 | static pte_t set_pte_filter(pte_t pte) | 210 | static pte_t set_pte_filter(pte_t pte, unsigned long addr) |
198 | { | 211 | { |
199 | struct page *pg; | 212 | struct page *pg; |
200 | 213 | ||
@@ -276,7 +289,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |||
276 | * this context might not have been activated yet when this | 289 | * this context might not have been activated yet when this |
277 | * is called. | 290 | * is called. |
278 | */ | 291 | */ |
279 | pte = set_pte_filter(pte); | 292 | pte = set_pte_filter(pte, addr); |
280 | 293 | ||
281 | /* Perform the setting of the PTE */ | 294 | /* Perform the setting of the PTE */ |
282 | __set_pte_at(mm, addr, ptep, pte, 0); | 295 | __set_pte_at(mm, addr, ptep, pte, 0); |
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S index ef1cccf71173..f288279e679d 100644 --- a/arch/powerpc/mm/tlb_low_64e.S +++ b/arch/powerpc/mm/tlb_low_64e.S | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/asm-offsets.h> | 18 | #include <asm/asm-offsets.h> |
19 | #include <asm/cputable.h> | 19 | #include <asm/cputable.h> |
20 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
21 | #include <asm/reg.h> | ||
22 | #include <asm/exception-64e.h> | 21 | #include <asm/exception-64e.h> |
23 | #include <asm/ppc-opcode.h> | 22 | #include <asm/ppc-opcode.h> |
24 | 23 | ||
diff --git a/arch/powerpc/platforms/cell/beat_iommu.c b/arch/powerpc/platforms/cell/beat_iommu.c index 93b0efddd658..39d361c5c6d2 100644 --- a/arch/powerpc/platforms/cell/beat_iommu.c +++ b/arch/powerpc/platforms/cell/beat_iommu.c | |||
@@ -77,7 +77,7 @@ static void __init celleb_init_direct_mapping(void) | |||
77 | static void celleb_dma_dev_setup(struct device *dev) | 77 | static void celleb_dma_dev_setup(struct device *dev) |
78 | { | 78 | { |
79 | dev->archdata.dma_ops = get_pci_dma_ops(); | 79 | dev->archdata.dma_ops = get_pci_dma_ops(); |
80 | dev->archdata.dma_data = (void *)celleb_dma_direct_offset; | 80 | set_dma_offset(dev, celleb_dma_direct_offset); |
81 | } | 81 | } |
82 | 82 | ||
83 | static void celleb_pci_dma_dev_setup(struct pci_dev *pdev) | 83 | static void celleb_pci_dma_dev_setup(struct pci_dev *pdev) |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 416db17eb18f..ca5bfdfe47f2 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -657,15 +657,13 @@ static void cell_dma_dev_setup_fixed(struct device *dev); | |||
657 | 657 | ||
658 | static void cell_dma_dev_setup(struct device *dev) | 658 | static void cell_dma_dev_setup(struct device *dev) |
659 | { | 659 | { |
660 | struct dev_archdata *archdata = &dev->archdata; | ||
661 | |||
662 | /* Order is important here, these are not mutually exclusive */ | 660 | /* Order is important here, these are not mutually exclusive */ |
663 | if (get_dma_ops(dev) == &dma_iommu_fixed_ops) | 661 | if (get_dma_ops(dev) == &dma_iommu_fixed_ops) |
664 | cell_dma_dev_setup_fixed(dev); | 662 | cell_dma_dev_setup_fixed(dev); |
665 | else if (get_pci_dma_ops() == &dma_iommu_ops) | 663 | else if (get_pci_dma_ops() == &dma_iommu_ops) |
666 | archdata->dma_data = cell_get_iommu_table(dev); | 664 | set_iommu_table_base(dev, cell_get_iommu_table(dev)); |
667 | else if (get_pci_dma_ops() == &dma_direct_ops) | 665 | else if (get_pci_dma_ops() == &dma_direct_ops) |
668 | archdata->dma_data = (void *)cell_dma_direct_offset; | 666 | set_dma_offset(dev, cell_dma_direct_offset); |
669 | else | 667 | else |
670 | BUG(); | 668 | BUG(); |
671 | } | 669 | } |
@@ -973,11 +971,10 @@ static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask) | |||
973 | 971 | ||
974 | static void cell_dma_dev_setup_fixed(struct device *dev) | 972 | static void cell_dma_dev_setup_fixed(struct device *dev) |
975 | { | 973 | { |
976 | struct dev_archdata *archdata = &dev->archdata; | ||
977 | u64 addr; | 974 | u64 addr; |
978 | 975 | ||
979 | addr = cell_iommu_get_fixed_address(dev) + dma_iommu_fixed_base; | 976 | addr = cell_iommu_get_fixed_address(dev) + dma_iommu_fixed_base; |
980 | archdata->dma_data = (void *)addr; | 977 | set_dma_offset(dev, addr); |
981 | 978 | ||
982 | dev_dbg(dev, "iommu: fixed addr = %llx\n", addr); | 979 | dev_dbg(dev, "iommu: fixed addr = %llx\n", addr); |
983 | } | 980 | } |
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 6c1e1011959e..9d53cb481a7c 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c | |||
@@ -193,7 +193,7 @@ static void pci_dma_dev_setup_iseries(struct pci_dev *pdev) | |||
193 | pdn->iommu_table = iommu_init_table(tbl, -1); | 193 | pdn->iommu_table = iommu_init_table(tbl, -1); |
194 | else | 194 | else |
195 | kfree(tbl); | 195 | kfree(tbl); |
196 | pdev->dev.archdata.dma_data = pdn->iommu_table; | 196 | set_iommu_table_base(&pdev->dev, pdn->iommu_table); |
197 | } | 197 | } |
198 | #else | 198 | #else |
199 | #define pci_dma_dev_setup_iseries NULL | 199 | #define pci_dma_dev_setup_iseries NULL |
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index a0ff03a3d8da..7b1d608ea3c8 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c | |||
@@ -189,7 +189,7 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev) | |||
189 | } | 189 | } |
190 | #endif | 190 | #endif |
191 | 191 | ||
192 | dev->dev.archdata.dma_data = &iommu_table_iobmap; | 192 | set_iommu_table_base(&dev->dev, &iommu_table_iobmap); |
193 | } | 193 | } |
194 | 194 | ||
195 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } | 195 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 661c8e02bcba..1a0000a4b6d6 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -482,7 +482,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) | |||
482 | phb->node); | 482 | phb->node); |
483 | iommu_table_setparms(phb, dn, tbl); | 483 | iommu_table_setparms(phb, dn, tbl); |
484 | PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node); | 484 | PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node); |
485 | dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table; | 485 | set_iommu_table_base(&dev->dev, PCI_DN(dn)->iommu_table); |
486 | return; | 486 | return; |
487 | } | 487 | } |
488 | 488 | ||
@@ -494,7 +494,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) | |||
494 | dn = dn->parent; | 494 | dn = dn->parent; |
495 | 495 | ||
496 | if (dn && PCI_DN(dn)) | 496 | if (dn && PCI_DN(dn)) |
497 | dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table; | 497 | set_iommu_table_base(&dev->dev, PCI_DN(dn)->iommu_table); |
498 | else | 498 | else |
499 | printk(KERN_WARNING "iommu: Device %s has no iommu table\n", | 499 | printk(KERN_WARNING "iommu: Device %s has no iommu table\n", |
500 | pci_name(dev)); | 500 | pci_name(dev)); |
@@ -538,7 +538,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
538 | */ | 538 | */ |
539 | if (dma_window == NULL || pdn->parent == NULL) { | 539 | if (dma_window == NULL || pdn->parent == NULL) { |
540 | pr_debug(" no dma window for device, linking to parent\n"); | 540 | pr_debug(" no dma window for device, linking to parent\n"); |
541 | dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; | 541 | set_iommu_table_base(&dev->dev, PCI_DN(pdn)->iommu_table); |
542 | return; | 542 | return; |
543 | } | 543 | } |
544 | 544 | ||
@@ -554,7 +554,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
554 | pr_debug(" found DMA window, table: %p\n", pci->iommu_table); | 554 | pr_debug(" found DMA window, table: %p\n", pci->iommu_table); |
555 | } | 555 | } |
556 | 556 | ||
557 | dev->dev.archdata.dma_data = pci->iommu_table; | 557 | set_iommu_table_base(&dev->dev, pci->iommu_table); |
558 | } | 558 | } |
559 | #else /* CONFIG_PCI */ | 559 | #else /* CONFIG_PCI */ |
560 | #define pci_dma_bus_setup_pSeries NULL | 560 | #define pci_dma_bus_setup_pSeries NULL |
diff --git a/arch/powerpc/relocs_check.pl b/arch/powerpc/relocs_check.pl new file mode 100755 index 000000000000..d2571096c3e9 --- /dev/null +++ b/arch/powerpc/relocs_check.pl | |||
@@ -0,0 +1,56 @@ | |||
1 | #!/usr/bin/perl | ||
2 | |||
3 | # Copyright © 2009 IBM Corporation | ||
4 | |||
5 | # This program is free software; you can redistribute it and/or | ||
6 | # modify it under the terms of the GNU General Public License | ||
7 | # as published by the Free Software Foundation; either version | ||
8 | # 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | # This script checks the relcoations of a vmlinux for "suspicious" | ||
11 | # relocations. | ||
12 | |||
13 | use strict; | ||
14 | use warnings; | ||
15 | |||
16 | if ($#ARGV != 1) { | ||
17 | die "$0 [path to objdump] [path to vmlinux]\n"; | ||
18 | } | ||
19 | |||
20 | # Have Kbuild supply the path to objdump so we handle cross compilation. | ||
21 | my $objdump = shift; | ||
22 | my $vmlinux = shift; | ||
23 | my $bad_relocs_count = 0; | ||
24 | my $bad_relocs = ""; | ||
25 | my $old_binutils = 0; | ||
26 | |||
27 | open(FD, "$objdump -R $vmlinux|") or die; | ||
28 | while (<FD>) { | ||
29 | study $_; | ||
30 | |||
31 | # Only look at relcoation lines. | ||
32 | next if (!/\s+R_/); | ||
33 | |||
34 | # These relocations are okay | ||
35 | next if (/R_PPC64_RELATIVE/ or /R_PPC64_NONE/ or | ||
36 | /R_PPC64_ADDR64\s+mach_/); | ||
37 | |||
38 | # If we see this type of relcoation it's an idication that | ||
39 | # we /may/ be using an old version of binutils. | ||
40 | if (/R_PPC64_UADDR64/) { | ||
41 | $old_binutils++; | ||
42 | } | ||
43 | |||
44 | $bad_relocs_count++; | ||
45 | $bad_relocs .= $_; | ||
46 | } | ||
47 | |||
48 | if ($bad_relocs_count) { | ||
49 | print "WARNING: $bad_relocs_count bad relocations\n"; | ||
50 | print $bad_relocs; | ||
51 | } | ||
52 | |||
53 | if ($old_binutils) { | ||
54 | print "WARNING: You need at binutils >= 2.19 to build a ". | ||
55 | "CONFIG_RELCOATABLE kernel\n"; | ||
56 | } | ||
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 89639ecbf381..ae3c4db86fe8 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
@@ -297,7 +297,7 @@ static void pci_dma_dev_setup_dart(struct pci_dev *dev) | |||
297 | /* We only have one iommu table on the mac for now, which makes | 297 | /* We only have one iommu table on the mac for now, which makes |
298 | * things simple. Setup all PCI devices to point to this table | 298 | * things simple. Setup all PCI devices to point to this table |
299 | */ | 299 | */ |
300 | dev->dev.archdata.dma_data = &iommu_table_dart; | 300 | set_iommu_table_base(&dev->dev, &iommu_table_dart); |
301 | } | 301 | } |
302 | 302 | ||
303 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) | 303 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 0e09a45ac79a..c6f0a71b405e 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -335,6 +335,16 @@ int cpus_are_in_xmon(void) | |||
335 | } | 335 | } |
336 | #endif | 336 | #endif |
337 | 337 | ||
338 | static inline int unrecoverable_excp(struct pt_regs *regs) | ||
339 | { | ||
340 | #ifdef CONFIG_4xx | ||
341 | /* We have no MSR_RI bit on 4xx, so we simply return false */ | ||
342 | return 0; | ||
343 | #else | ||
344 | return ((regs->msr & MSR_RI) == 0); | ||
345 | #endif | ||
346 | } | ||
347 | |||
338 | static int xmon_core(struct pt_regs *regs, int fromipi) | 348 | static int xmon_core(struct pt_regs *regs, int fromipi) |
339 | { | 349 | { |
340 | int cmd = 0; | 350 | int cmd = 0; |
@@ -388,7 +398,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
388 | bp = NULL; | 398 | bp = NULL; |
389 | if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) | 399 | if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) |
390 | bp = at_breakpoint(regs->nip); | 400 | bp = at_breakpoint(regs->nip); |
391 | if (bp || (regs->msr & MSR_RI) == 0) | 401 | if (bp || unrecoverable_excp(regs)) |
392 | fromipi = 0; | 402 | fromipi = 0; |
393 | 403 | ||
394 | if (!fromipi) { | 404 | if (!fromipi) { |
@@ -399,7 +409,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
399 | cpu, BP_NUM(bp)); | 409 | cpu, BP_NUM(bp)); |
400 | xmon_print_symbol(regs->nip, " ", ")\n"); | 410 | xmon_print_symbol(regs->nip, " ", ")\n"); |
401 | } | 411 | } |
402 | if ((regs->msr & MSR_RI) == 0) | 412 | if (unrecoverable_excp(regs)) |
403 | printf("WARNING: exception is not recoverable, " | 413 | printf("WARNING: exception is not recoverable, " |
404 | "can't continue\n"); | 414 | "can't continue\n"); |
405 | release_output_lock(); | 415 | release_output_lock(); |
@@ -490,7 +500,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
490 | printf("Stopped at breakpoint %x (", BP_NUM(bp)); | 500 | printf("Stopped at breakpoint %x (", BP_NUM(bp)); |
491 | xmon_print_symbol(regs->nip, " ", ")\n"); | 501 | xmon_print_symbol(regs->nip, " ", ")\n"); |
492 | } | 502 | } |
493 | if ((regs->msr & MSR_RI) == 0) | 503 | if (unrecoverable_excp(regs)) |
494 | printf("WARNING: exception is not recoverable, " | 504 | printf("WARNING: exception is not recoverable, " |
495 | "can't continue\n"); | 505 | "can't continue\n"); |
496 | remove_bpts(); | 506 | remove_bpts(); |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 25ce15bb1c08..a632f25f144a 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -678,7 +678,7 @@ int hvc_poll(struct hvc_struct *hp) | |||
678 | EXPORT_SYMBOL_GPL(hvc_poll); | 678 | EXPORT_SYMBOL_GPL(hvc_poll); |
679 | 679 | ||
680 | /** | 680 | /** |
681 | * hvc_resize() - Update terminal window size information. | 681 | * __hvc_resize() - Update terminal window size information. |
682 | * @hp: HVC console pointer | 682 | * @hp: HVC console pointer |
683 | * @ws: Terminal window size structure | 683 | * @ws: Terminal window size structure |
684 | * | 684 | * |
@@ -687,12 +687,12 @@ EXPORT_SYMBOL_GPL(hvc_poll); | |||
687 | * | 687 | * |
688 | * Locking: Locking free; the function MUST be called holding hp->lock | 688 | * Locking: Locking free; the function MUST be called holding hp->lock |
689 | */ | 689 | */ |
690 | void hvc_resize(struct hvc_struct *hp, struct winsize ws) | 690 | void __hvc_resize(struct hvc_struct *hp, struct winsize ws) |
691 | { | 691 | { |
692 | hp->ws = ws; | 692 | hp->ws = ws; |
693 | schedule_work(&hp->tty_resize); | 693 | schedule_work(&hp->tty_resize); |
694 | } | 694 | } |
695 | EXPORT_SYMBOL_GPL(hvc_resize); | 695 | EXPORT_SYMBOL_GPL(__hvc_resize); |
696 | 696 | ||
697 | /* | 697 | /* |
698 | * This kthread is either polling or interrupt driven. This is determined by | 698 | * This kthread is either polling or interrupt driven. This is determined by |
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 3c85d78c975c..10950ca706d8 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define HVC_CONSOLE_H | 28 | #define HVC_CONSOLE_H |
29 | #include <linux/kref.h> | 29 | #include <linux/kref.h> |
30 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
31 | #include <linux/spinlock.h> | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * This is the max number of console adapters that can/will be found as | 34 | * This is the max number of console adapters that can/will be found as |
@@ -88,7 +89,16 @@ int hvc_poll(struct hvc_struct *hp); | |||
88 | void hvc_kick(void); | 89 | void hvc_kick(void); |
89 | 90 | ||
90 | /* Resize hvc tty terminal window */ | 91 | /* Resize hvc tty terminal window */ |
91 | extern void hvc_resize(struct hvc_struct *hp, struct winsize ws); | 92 | extern void __hvc_resize(struct hvc_struct *hp, struct winsize ws); |
93 | |||
94 | static inline void hvc_resize(struct hvc_struct *hp, struct winsize ws) | ||
95 | { | ||
96 | unsigned long flags; | ||
97 | |||
98 | spin_lock_irqsave(&hp->lock, flags); | ||
99 | __hvc_resize(hp, ws); | ||
100 | spin_unlock_irqrestore(&hp->lock, flags); | ||
101 | } | ||
92 | 102 | ||
93 | /* default notifier for irq based notification */ | 103 | /* default notifier for irq based notification */ |
94 | extern int notifier_add_irq(struct hvc_struct *hp, int data); | 104 | extern int notifier_add_irq(struct hvc_struct *hp, int data); |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 0ecac7e532f6..b8a5d654d3d0 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -273,7 +273,9 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
273 | case MSG_TYPE_WINSIZE: | 273 | case MSG_TYPE_WINSIZE: |
274 | if (rb->mbuf->datalen != sizeof(struct winsize)) | 274 | if (rb->mbuf->datalen != sizeof(struct winsize)) |
275 | break; | 275 | break; |
276 | hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data)); | 276 | /* The caller must ensure that the hvc is locked, which |
277 | * is the case when called from hvc_iucv_get_chars() */ | ||
278 | __hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data)); | ||
277 | break; | 279 | break; |
278 | 280 | ||
279 | case MSG_TYPE_ERROR: /* ignored ... */ | 281 | case MSG_TYPE_ERROR: /* ignored ... */ |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 8d349b23249a..300cea768d74 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -649,7 +649,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
649 | u8 *p; | 649 | u8 *p; |
650 | int count; | 650 | int count; |
651 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | 651 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; |
652 | struct circ_buf *xmit = &port->info->xmit; | 652 | struct circ_buf *xmit = &port->state->xmit; |
653 | 653 | ||
654 | /* Handle xon/xoff */ | 654 | /* Handle xon/xoff */ |
655 | if (port->x_char) { | 655 | if (port->x_char) { |