aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/iommu.c36
-rw-r--r--arch/powerpc/kernel/pci_iommu.c40
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c1
-rw-r--r--arch/powerpc/kernel/prom.c2
-rw-r--r--arch/powerpc/kernel/sysfs.c4
-rw-r--r--arch/powerpc/kernel/systbl.S6
-rw-r--r--arch/powerpc/kernel/vio.c6
7 files changed, 75 insertions, 20 deletions
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d9a7fdef59b9..4eba60a32890 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -61,6 +61,7 @@ __setup("iommu=", setup_iommu);
61static unsigned long iommu_range_alloc(struct iommu_table *tbl, 61static unsigned long iommu_range_alloc(struct iommu_table *tbl,
62 unsigned long npages, 62 unsigned long npages,
63 unsigned long *handle, 63 unsigned long *handle,
64 unsigned long mask,
64 unsigned int align_order) 65 unsigned int align_order)
65{ 66{
66 unsigned long n, end, i, start; 67 unsigned long n, end, i, start;
@@ -97,9 +98,21 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
97 */ 98 */
98 if (start >= limit) 99 if (start >= limit)
99 start = largealloc ? tbl->it_largehint : tbl->it_hint; 100 start = largealloc ? tbl->it_largehint : tbl->it_hint;
100 101
101 again: 102 again:
102 103
104 if (limit + tbl->it_offset > mask) {
105 limit = mask - tbl->it_offset + 1;
106 /* If we're constrained on address range, first try
107 * at the masked hint to avoid O(n) search complexity,
108 * but on second pass, start at 0.
109 */
110 if ((start & mask) >= limit || pass > 0)
111 start = 0;
112 else
113 start &= mask;
114 }
115
103 n = find_next_zero_bit(tbl->it_map, limit, start); 116 n = find_next_zero_bit(tbl->it_map, limit, start);
104 117
105 /* Align allocation */ 118 /* Align allocation */
@@ -150,14 +163,14 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
150 163
151static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, 164static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
152 unsigned int npages, enum dma_data_direction direction, 165 unsigned int npages, enum dma_data_direction direction,
153 unsigned int align_order) 166 unsigned long mask, unsigned int align_order)
154{ 167{
155 unsigned long entry, flags; 168 unsigned long entry, flags;
156 dma_addr_t ret = DMA_ERROR_CODE; 169 dma_addr_t ret = DMA_ERROR_CODE;
157 170
158 spin_lock_irqsave(&(tbl->it_lock), flags); 171 spin_lock_irqsave(&(tbl->it_lock), flags);
159 172
160 entry = iommu_range_alloc(tbl, npages, NULL, align_order); 173 entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
161 174
162 if (unlikely(entry == DMA_ERROR_CODE)) { 175 if (unlikely(entry == DMA_ERROR_CODE)) {
163 spin_unlock_irqrestore(&(tbl->it_lock), flags); 176 spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -236,7 +249,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
236 249
237int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 250int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
238 struct scatterlist *sglist, int nelems, 251 struct scatterlist *sglist, int nelems,
239 enum dma_data_direction direction) 252 unsigned long mask, enum dma_data_direction direction)
240{ 253{
241 dma_addr_t dma_next = 0, dma_addr; 254 dma_addr_t dma_next = 0, dma_addr;
242 unsigned long flags; 255 unsigned long flags;
@@ -274,7 +287,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
274 vaddr = (unsigned long)page_address(s->page) + s->offset; 287 vaddr = (unsigned long)page_address(s->page) + s->offset;
275 npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); 288 npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
276 npages >>= PAGE_SHIFT; 289 npages >>= PAGE_SHIFT;
277 entry = iommu_range_alloc(tbl, npages, &handle, 0); 290 entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0);
278 291
279 DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); 292 DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
280 293
@@ -479,7 +492,8 @@ void iommu_free_table(struct device_node *dn)
479 * byte within the page as vaddr. 492 * byte within the page as vaddr.
480 */ 493 */
481dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 494dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
482 size_t size, enum dma_data_direction direction) 495 size_t size, unsigned long mask,
496 enum dma_data_direction direction)
483{ 497{
484 dma_addr_t dma_handle = DMA_ERROR_CODE; 498 dma_addr_t dma_handle = DMA_ERROR_CODE;
485 unsigned long uaddr; 499 unsigned long uaddr;
@@ -492,7 +506,8 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
492 npages >>= PAGE_SHIFT; 506 npages >>= PAGE_SHIFT;
493 507
494 if (tbl) { 508 if (tbl) {
495 dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0); 509 dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
510 mask >> PAGE_SHIFT, 0);
496 if (dma_handle == DMA_ERROR_CODE) { 511 if (dma_handle == DMA_ERROR_CODE) {
497 if (printk_ratelimit()) { 512 if (printk_ratelimit()) {
498 printk(KERN_INFO "iommu_alloc failed, " 513 printk(KERN_INFO "iommu_alloc failed, "
@@ -521,7 +536,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
521 * to the dma address (mapping) of the first page. 536 * to the dma address (mapping) of the first page.
522 */ 537 */
523void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 538void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
524 dma_addr_t *dma_handle, gfp_t flag) 539 dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
525{ 540{
526 void *ret = NULL; 541 void *ret = NULL;
527 dma_addr_t mapping; 542 dma_addr_t mapping;
@@ -551,7 +566,8 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
551 memset(ret, 0, size); 566 memset(ret, 0, size);
552 567
553 /* Set up tces to cover the allocated range */ 568 /* Set up tces to cover the allocated range */
554 mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order); 569 mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL,
570 mask >> PAGE_SHIFT, order);
555 if (mapping == DMA_ERROR_CODE) { 571 if (mapping == DMA_ERROR_CODE) {
556 free_pages((unsigned long)ret, order); 572 free_pages((unsigned long)ret, order);
557 ret = NULL; 573 ret = NULL;
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c336f3e31cff..c1d95e14bbed 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -59,6 +59,25 @@ static inline struct iommu_table *devnode_table(struct device *dev)
59} 59}
60 60
61 61
62static inline unsigned long device_to_mask(struct device *hwdev)
63{
64 struct pci_dev *pdev;
65
66 if (!hwdev) {
67 pdev = ppc64_isabridge_dev;
68 if (!pdev) /* This is the best guess we can do */
69 return 0xfffffffful;
70 } else
71 pdev = to_pci_dev(hwdev);
72
73 if (pdev->dma_mask)
74 return pdev->dma_mask;
75
76 /* Assume devices without mask can take 32 bit addresses */
77 return 0xfffffffful;
78}
79
80
62/* Allocates a contiguous real buffer and creates mappings over it. 81/* Allocates a contiguous real buffer and creates mappings over it.
63 * Returns the virtual address of the buffer and sets dma_handle 82 * Returns the virtual address of the buffer and sets dma_handle
64 * to the dma address (mapping) of the first page. 83 * to the dma address (mapping) of the first page.
@@ -67,7 +86,7 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
67 dma_addr_t *dma_handle, gfp_t flag) 86 dma_addr_t *dma_handle, gfp_t flag)
68{ 87{
69 return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle, 88 return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
70 flag); 89 device_to_mask(hwdev), flag);
71} 90}
72 91
73static void pci_iommu_free_coherent(struct device *hwdev, size_t size, 92static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
@@ -85,7 +104,8 @@ static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
85static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, 104static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
86 size_t size, enum dma_data_direction direction) 105 size_t size, enum dma_data_direction direction)
87{ 106{
88 return iommu_map_single(devnode_table(hwdev), vaddr, size, direction); 107 return iommu_map_single(devnode_table(hwdev), vaddr, size,
108 device_to_mask(hwdev), direction);
89} 109}
90 110
91 111
@@ -100,7 +120,7 @@ static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
100 int nelems, enum dma_data_direction direction) 120 int nelems, enum dma_data_direction direction)
101{ 121{
102 return iommu_map_sg(pdev, devnode_table(pdev), sglist, 122 return iommu_map_sg(pdev, devnode_table(pdev), sglist,
103 nelems, direction); 123 nelems, device_to_mask(pdev), direction);
104} 124}
105 125
106static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, 126static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
@@ -112,7 +132,19 @@ static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
112/* We support DMA to/from any memory page via the iommu */ 132/* We support DMA to/from any memory page via the iommu */
113static int pci_iommu_dma_supported(struct device *dev, u64 mask) 133static int pci_iommu_dma_supported(struct device *dev, u64 mask)
114{ 134{
115 return 1; 135 struct iommu_table *tbl = devnode_table(dev);
136
137 if (!tbl || tbl->it_offset > mask) {
138 printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
139 if (tbl)
140 printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
141 mask, tbl->it_offset);
142 else
143 printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
144 mask);
145 return 0;
146 } else
147 return 1;
116} 148}
117 149
118void pci_iommu_init(void) 150void pci_iommu_init(void)
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index dfa5398ab3c8..4b052ae5dc34 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -81,6 +81,7 @@ EXPORT_SYMBOL(strcat);
81EXPORT_SYMBOL(strlen); 81EXPORT_SYMBOL(strlen);
82EXPORT_SYMBOL(strcmp); 82EXPORT_SYMBOL(strcmp);
83EXPORT_SYMBOL(strcasecmp); 83EXPORT_SYMBOL(strcasecmp);
84EXPORT_SYMBOL(strncasecmp);
84 85
85EXPORT_SYMBOL(csum_partial); 86EXPORT_SYMBOL(csum_partial);
86EXPORT_SYMBOL(csum_partial_copy_generic); 87EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4336390bcf34..1cb69e8fb0b1 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -62,7 +62,7 @@ static int __initdata dt_root_addr_cells;
62static int __initdata dt_root_size_cells; 62static int __initdata dt_root_size_cells;
63 63
64#ifdef CONFIG_PPC64 64#ifdef CONFIG_PPC64
65static int __initdata iommu_is_off; 65int __initdata iommu_is_off;
66int __initdata iommu_force_on; 66int __initdata iommu_force_on;
67unsigned long tce_alloc_start, tce_alloc_end; 67unsigned long tce_alloc_start, tce_alloc_end;
68#endif 68#endif
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 73560ef6f802..ed737cacf92d 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -279,7 +279,7 @@ static void unregister_cpu_online(unsigned int cpu)
279} 279}
280#endif /* CONFIG_HOTPLUG_CPU */ 280#endif /* CONFIG_HOTPLUG_CPU */
281 281
282static int __devinit sysfs_cpu_notify(struct notifier_block *self, 282static int sysfs_cpu_notify(struct notifier_block *self,
283 unsigned long action, void *hcpu) 283 unsigned long action, void *hcpu)
284{ 284{
285 unsigned int cpu = (unsigned int)(long)hcpu; 285 unsigned int cpu = (unsigned int)(long)hcpu;
@@ -297,7 +297,7 @@ static int __devinit sysfs_cpu_notify(struct notifier_block *self,
297 return NOTIFY_OK; 297 return NOTIFY_OK;
298} 298}
299 299
300static struct notifier_block __devinitdata sysfs_cpu_nb = { 300static struct notifier_block sysfs_cpu_nb = {
301 .notifier_call = sysfs_cpu_notify, 301 .notifier_call = sysfs_cpu_notify,
302}; 302};
303 303
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index a14c96403840..0b98eea73c5e 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -324,3 +324,9 @@ COMPAT_SYS(ppoll)
324SYSCALL(unshare) 324SYSCALL(unshare)
325SYSCALL(splice) 325SYSCALL(splice)
326SYSCALL(tee) 326SYSCALL(tee)
327SYSCALL(vmsplice)
328
329/*
330 * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
331 * as well when appropriate.
332 */
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 13c655ba2841..971020cf3f7d 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -202,7 +202,7 @@ static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
202 size_t size, enum dma_data_direction direction) 202 size_t size, enum dma_data_direction direction)
203{ 203{
204 return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size, 204 return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
205 direction); 205 ~0ul, direction);
206} 206}
207 207
208static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle, 208static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
@@ -216,7 +216,7 @@ static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
216 int nelems, enum dma_data_direction direction) 216 int nelems, enum dma_data_direction direction)
217{ 217{
218 return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist, 218 return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
219 nelems, direction); 219 nelems, ~0ul, direction);
220} 220}
221 221
222static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist, 222static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
@@ -229,7 +229,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
229 dma_addr_t *dma_handle, gfp_t flag) 229 dma_addr_t *dma_handle, gfp_t flag)
230{ 230{
231 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, 231 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
232 dma_handle, flag); 232 dma_handle, ~0ul, flag);
233} 233}
234 234
235static void vio_free_coherent(struct device *dev, size_t size, 235static void vio_free_coherent(struct device *dev, size_t size,