diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-04-27 04:53:34 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-04-27 04:53:34 -0400 |
| commit | acc696d93dcf993dec123d69d599979e1456ffec (patch) | |
| tree | b860b80bb96bb5e3ea1f0347b92fbb1e8b15af36 /arch/powerpc/kernel | |
| parent | bf2af2a2027e52b653882fbca840620e896ae081 (diff) | |
| parent | 2be4d50295e2b6f62c07b614e1b103e280dddb84 (diff) | |
Merge branch 'master' into upstream
Diffstat (limited to 'arch/powerpc/kernel')
| -rw-r--r-- | arch/powerpc/kernel/iommu.c | 36 | ||||
| -rw-r--r-- | arch/powerpc/kernel/pci_iommu.c | 40 | ||||
| -rw-r--r-- | arch/powerpc/kernel/ppc_ksyms.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/kernel/prom.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/sysfs.c | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/systbl.S | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/vio.c | 6 |
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); | |||
| 61 | static unsigned long iommu_range_alloc(struct iommu_table *tbl, | 61 | static 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 | ||
| 151 | static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, | 164 | static 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 | ||
| 237 | int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | 250 | int 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 | */ |
| 481 | dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, | 494 | dma_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 | */ |
| 523 | void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | 538 | void *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 | ||
| 62 | static 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 | ||
| 73 | static void pci_iommu_free_coherent(struct device *hwdev, size_t size, | 92 | static 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, | |||
| 85 | static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, | 104 | static 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 | ||
| 106 | static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, | 126 | static 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 */ |
| 113 | static int pci_iommu_dma_supported(struct device *dev, u64 mask) | 133 | static 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 | ||
| 118 | void pci_iommu_init(void) | 150 | void 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); | |||
| 81 | EXPORT_SYMBOL(strlen); | 81 | EXPORT_SYMBOL(strlen); |
| 82 | EXPORT_SYMBOL(strcmp); | 82 | EXPORT_SYMBOL(strcmp); |
| 83 | EXPORT_SYMBOL(strcasecmp); | 83 | EXPORT_SYMBOL(strcasecmp); |
| 84 | EXPORT_SYMBOL(strncasecmp); | ||
| 84 | 85 | ||
| 85 | EXPORT_SYMBOL(csum_partial); | 86 | EXPORT_SYMBOL(csum_partial); |
| 86 | EXPORT_SYMBOL(csum_partial_copy_generic); | 87 | EXPORT_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; | |||
| 62 | static int __initdata dt_root_size_cells; | 62 | static int __initdata dt_root_size_cells; |
| 63 | 63 | ||
| 64 | #ifdef CONFIG_PPC64 | 64 | #ifdef CONFIG_PPC64 |
| 65 | static int __initdata iommu_is_off; | 65 | int __initdata iommu_is_off; |
| 66 | int __initdata iommu_force_on; | 66 | int __initdata iommu_force_on; |
| 67 | unsigned long tce_alloc_start, tce_alloc_end; | 67 | unsigned 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 | ||
| 282 | static int __devinit sysfs_cpu_notify(struct notifier_block *self, | 282 | static 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 | ||
| 300 | static struct notifier_block __devinitdata sysfs_cpu_nb = { | 300 | static 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) | |||
| 324 | SYSCALL(unshare) | 324 | SYSCALL(unshare) |
| 325 | SYSCALL(splice) | 325 | SYSCALL(splice) |
| 326 | SYSCALL(tee) | 326 | SYSCALL(tee) |
| 327 | SYSCALL(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 | ||
| 208 | static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle, | 208 | static 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 | ||
| 222 | static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist, | 222 | static 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 | ||
| 235 | static void vio_free_coherent(struct device *dev, size_t size, | 235 | static void vio_free_coherent(struct device *dev, size_t size, |
