diff options
| author | David S. Miller <davem@davemloft.net> | 2008-03-19 07:52:48 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-04-24 02:32:16 -0400 |
| commit | c1b1a5f1f1b2612b69b67381b223bce9f8ec4da5 (patch) | |
| tree | e95abb7a3dbd0ca6c341c44f2b69dd174fd03bec | |
| parent | 0c49a573ea93f777fd27f26b7853e7bf5a20e1a3 (diff) | |
[SPARC64]: NUMA device infrastructure.
Record and propagate NUMA information for devices.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | arch/sparc64/kernel/ebus.c | 1 | ||||
| -rw-r--r-- | arch/sparc64/kernel/iommu.c | 33 | ||||
| -rw-r--r-- | arch/sparc64/kernel/isa.c | 1 | ||||
| -rw-r--r-- | arch/sparc64/kernel/of_device.c | 12 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci.c | 12 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 5 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_impl.h | 2 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_msi.c | 8 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 5 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 4 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 5 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 13 | ||||
| -rw-r--r-- | arch/sparc64/kernel/sbus.c | 3 | ||||
| -rw-r--r-- | include/asm-sparc/device.h | 2 | ||||
| -rw-r--r-- | include/asm-sparc/prom.h | 5 | ||||
| -rw-r--r-- | include/asm-sparc64/iommu.h | 3 |
16 files changed, 91 insertions, 23 deletions
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 04ab81cb4f48..bc2632274840 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
| @@ -396,6 +396,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de | |||
| 396 | sd->op = &dev->ofdev; | 396 | sd->op = &dev->ofdev; |
| 397 | sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; | 397 | sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; |
| 398 | sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; | 398 | sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; |
| 399 | sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node; | ||
| 399 | 400 | ||
| 400 | dev->ofdev.node = dp; | 401 | dev->ofdev.node = dp; |
| 401 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | 402 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; |
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index 756fa24eeefa..2a37a6ca2a16 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c | |||
| @@ -173,9 +173,11 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np | |||
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | int iommu_table_init(struct iommu *iommu, int tsbsize, | 175 | int iommu_table_init(struct iommu *iommu, int tsbsize, |
| 176 | u32 dma_offset, u32 dma_addr_mask) | 176 | u32 dma_offset, u32 dma_addr_mask, |
| 177 | int numa_node) | ||
| 177 | { | 178 | { |
| 178 | unsigned long i, tsbbase, order, sz, num_tsb_entries; | 179 | unsigned long i, order, sz, num_tsb_entries; |
| 180 | struct page *page; | ||
| 179 | 181 | ||
| 180 | num_tsb_entries = tsbsize / sizeof(iopte_t); | 182 | num_tsb_entries = tsbsize / sizeof(iopte_t); |
| 181 | 183 | ||
| @@ -188,11 +190,12 @@ int iommu_table_init(struct iommu *iommu, int tsbsize, | |||
| 188 | /* Allocate and initialize the free area map. */ | 190 | /* Allocate and initialize the free area map. */ |
| 189 | sz = num_tsb_entries / 8; | 191 | sz = num_tsb_entries / 8; |
| 190 | sz = (sz + 7UL) & ~7UL; | 192 | sz = (sz + 7UL) & ~7UL; |
| 191 | iommu->arena.map = kzalloc(sz, GFP_KERNEL); | 193 | iommu->arena.map = kmalloc_node(sz, GFP_KERNEL, numa_node); |
| 192 | if (!iommu->arena.map) { | 194 | if (!iommu->arena.map) { |
| 193 | printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n"); | 195 | printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n"); |
| 194 | return -ENOMEM; | 196 | return -ENOMEM; |
| 195 | } | 197 | } |
| 198 | memset(iommu->arena.map, 0, sz); | ||
| 196 | iommu->arena.limit = num_tsb_entries; | 199 | iommu->arena.limit = num_tsb_entries; |
| 197 | 200 | ||
| 198 | if (tlb_type != hypervisor) | 201 | if (tlb_type != hypervisor) |
| @@ -201,21 +204,23 @@ int iommu_table_init(struct iommu *iommu, int tsbsize, | |||
| 201 | /* Allocate and initialize the dummy page which we | 204 | /* Allocate and initialize the dummy page which we |
| 202 | * set inactive IO PTEs to point to. | 205 | * set inactive IO PTEs to point to. |
| 203 | */ | 206 | */ |
| 204 | iommu->dummy_page = get_zeroed_page(GFP_KERNEL); | 207 | page = alloc_pages_node(numa_node, GFP_KERNEL, 0); |
| 205 | if (!iommu->dummy_page) { | 208 | if (!page) { |
| 206 | printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n"); | 209 | printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n"); |
| 207 | goto out_free_map; | 210 | goto out_free_map; |
| 208 | } | 211 | } |
| 212 | iommu->dummy_page = (unsigned long) page_address(page); | ||
| 213 | memset((void *)iommu->dummy_page, 0, PAGE_SIZE); | ||
| 209 | iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); | 214 | iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); |
| 210 | 215 | ||
| 211 | /* Now allocate and setup the IOMMU page table itself. */ | 216 | /* Now allocate and setup the IOMMU page table itself. */ |
| 212 | order = get_order(tsbsize); | 217 | order = get_order(tsbsize); |
| 213 | tsbbase = __get_free_pages(GFP_KERNEL, order); | 218 | page = alloc_pages_node(numa_node, GFP_KERNEL, order); |
| 214 | if (!tsbbase) { | 219 | if (!page) { |
| 215 | printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n"); | 220 | printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n"); |
| 216 | goto out_free_dummy_page; | 221 | goto out_free_dummy_page; |
| 217 | } | 222 | } |
| 218 | iommu->page_table = (iopte_t *)tsbbase; | 223 | iommu->page_table = (iopte_t *)page_address(page); |
| 219 | 224 | ||
| 220 | for (i = 0; i < num_tsb_entries; i++) | 225 | for (i = 0; i < num_tsb_entries; i++) |
| 221 | iopte_make_dummy(iommu, &iommu->page_table[i]); | 226 | iopte_make_dummy(iommu, &iommu->page_table[i]); |
| @@ -276,20 +281,24 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx) | |||
| 276 | static void *dma_4u_alloc_coherent(struct device *dev, size_t size, | 281 | static void *dma_4u_alloc_coherent(struct device *dev, size_t size, |
| 277 | dma_addr_t *dma_addrp, gfp_t gfp) | 282 | dma_addr_t *dma_addrp, gfp_t gfp) |
| 278 | { | 283 | { |
| 284 | unsigned long flags, order, first_page; | ||
| 279 | struct iommu *iommu; | 285 | struct iommu *iommu; |
| 286 | struct page *page; | ||
| 287 | int npages, nid; | ||
| 280 | iopte_t *iopte; | 288 | iopte_t *iopte; |
| 281 | unsigned long flags, order, first_page; | ||
| 282 | void *ret; | 289 | void *ret; |
| 283 | int npages; | ||
| 284 | 290 | ||
| 285 | size = IO_PAGE_ALIGN(size); | 291 | size = IO_PAGE_ALIGN(size); |
| 286 | order = get_order(size); | 292 | order = get_order(size); |
| 287 | if (order >= 10) | 293 | if (order >= 10) |
| 288 | return NULL; | 294 | return NULL; |
| 289 | 295 | ||
| 290 | first_page = __get_free_pages(gfp, order); | 296 | nid = dev->archdata.numa_node; |
| 291 | if (first_page == 0UL) | 297 | page = alloc_pages_node(nid, gfp, order); |
| 298 | if (unlikely(!page)) | ||
| 292 | return NULL; | 299 | return NULL; |
| 300 | |||
| 301 | first_page = (unsigned long) page_address(page); | ||
| 293 | memset((char *)first_page, 0, PAGE_SIZE << order); | 302 | memset((char *)first_page, 0, PAGE_SIZE << order); |
| 294 | 303 | ||
| 295 | iommu = dev->archdata.iommu; | 304 | iommu = dev->archdata.iommu; |
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index b5f7b354084f..a2af5ed784c9 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c | |||
| @@ -92,6 +92,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
| 92 | sd->op = &isa_dev->ofdev; | 92 | sd->op = &isa_dev->ofdev; |
| 93 | sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu; | 93 | sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu; |
| 94 | sd->stc = isa_br->ofdev.dev.parent->archdata.stc; | 94 | sd->stc = isa_br->ofdev.dev.parent->archdata.stc; |
| 95 | sd->numa_node = isa_br->ofdev.dev.parent->archdata.numa_node; | ||
| 95 | 96 | ||
| 96 | isa_dev->ofdev.node = dp; | 97 | isa_dev->ofdev.node = dp; |
| 97 | isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; | 98 | isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; |
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 0fd9db95b896..9e58e8cba1c3 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <linux/mod_devicetable.h> | 6 | #include <linux/mod_devicetable.h> |
| 7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
| 8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
| 9 | #include <linux/irq.h> | ||
| 9 | #include <linux/of_device.h> | 10 | #include <linux/of_device.h> |
| 10 | #include <linux/of_platform.h> | 11 | #include <linux/of_platform.h> |
| 11 | 12 | ||
| @@ -660,6 +661,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, | |||
| 660 | struct device_node *dp = op->node; | 661 | struct device_node *dp = op->node; |
| 661 | struct device_node *pp, *ip; | 662 | struct device_node *pp, *ip; |
| 662 | unsigned int orig_irq = irq; | 663 | unsigned int orig_irq = irq; |
| 664 | int nid; | ||
| 663 | 665 | ||
| 664 | if (irq == 0xffffffff) | 666 | if (irq == 0xffffffff) |
| 665 | return irq; | 667 | return irq; |
| @@ -672,7 +674,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, | |||
| 672 | printk("%s: direct translate %x --> %x\n", | 674 | printk("%s: direct translate %x --> %x\n", |
| 673 | dp->full_name, orig_irq, irq); | 675 | dp->full_name, orig_irq, irq); |
| 674 | 676 | ||
| 675 | return irq; | 677 | goto out; |
| 676 | } | 678 | } |
| 677 | 679 | ||
| 678 | /* Something more complicated. Walk up to the root, applying | 680 | /* Something more complicated. Walk up to the root, applying |
| @@ -744,6 +746,14 @@ static unsigned int __init build_one_device_irq(struct of_device *op, | |||
| 744 | printk("%s: Apply IRQ trans [%s] %x --> %x\n", | 746 | printk("%s: Apply IRQ trans [%s] %x --> %x\n", |
| 745 | op->node->full_name, ip->full_name, orig_irq, irq); | 747 | op->node->full_name, ip->full_name, orig_irq, irq); |
| 746 | 748 | ||
| 749 | out: | ||
| 750 | nid = of_node_to_nid(dp); | ||
| 751 | if (nid != -1) { | ||
| 752 | cpumask_t numa_mask = node_to_cpumask(nid); | ||
| 753 | |||
| 754 | irq_set_affinity(irq, numa_mask); | ||
| 755 | } | ||
| 756 | |||
| 747 | return irq; | 757 | return irq; |
| 748 | } | 758 | } |
| 749 | 759 | ||
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 545356b00e2e..49f912766519 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
| @@ -369,10 +369,12 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
| 369 | sd->host_controller = pbm; | 369 | sd->host_controller = pbm; |
| 370 | sd->prom_node = node; | 370 | sd->prom_node = node; |
| 371 | sd->op = of_find_device_by_node(node); | 371 | sd->op = of_find_device_by_node(node); |
| 372 | sd->numa_node = pbm->numa_node; | ||
| 372 | 373 | ||
| 373 | sd = &sd->op->dev.archdata; | 374 | sd = &sd->op->dev.archdata; |
| 374 | sd->iommu = pbm->iommu; | 375 | sd->iommu = pbm->iommu; |
| 375 | sd->stc = &pbm->stc; | 376 | sd->stc = &pbm->stc; |
| 377 | sd->numa_node = pbm->numa_node; | ||
| 376 | 378 | ||
| 377 | type = of_get_property(node, "device_type", NULL); | 379 | type = of_get_property(node, "device_type", NULL); |
| 378 | if (type == NULL) | 380 | if (type == NULL) |
| @@ -1159,6 +1161,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | |||
| 1159 | return 0; | 1161 | return 0; |
| 1160 | } | 1162 | } |
| 1161 | 1163 | ||
| 1164 | #ifdef CONFIG_NUMA | ||
| 1165 | int pcibus_to_node(struct pci_bus *pbus) | ||
| 1166 | { | ||
| 1167 | struct pci_pbm_info *pbm = pbus->sysdata; | ||
| 1168 | |||
| 1169 | return pbm->numa_node; | ||
| 1170 | } | ||
| 1171 | EXPORT_SYMBOL(pcibus_to_node); | ||
| 1172 | #endif | ||
| 1173 | |||
| 1162 | /* Return the domain nuber for this pci bus */ | 1174 | /* Return the domain nuber for this pci bus */ |
| 1163 | 1175 | ||
| 1164 | int pci_domain_nr(struct pci_bus *pbus) | 1176 | int pci_domain_nr(struct pci_bus *pbus) |
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 7571ed563147..d23bb6f53cda 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c | |||
| @@ -71,7 +71,8 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 71 | */ | 71 | */ |
| 72 | fire_write(iommu->iommu_flushinv, ~(u64)0); | 72 | fire_write(iommu->iommu_flushinv, ~(u64)0); |
| 73 | 73 | ||
| 74 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); | 74 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, |
| 75 | pbm->numa_node); | ||
| 75 | if (err) | 76 | if (err) |
| 76 | return err; | 77 | return err; |
| 77 | 78 | ||
| @@ -449,6 +450,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, | |||
| 449 | pbm->next = pci_pbm_root; | 450 | pbm->next = pci_pbm_root; |
| 450 | pci_pbm_root = pbm; | 451 | pci_pbm_root = pbm; |
| 451 | 452 | ||
| 453 | pbm->numa_node = -1; | ||
| 454 | |||
| 452 | pbm->scan_bus = pci_fire_scan_bus; | 455 | pbm->scan_bus = pci_fire_scan_bus; |
| 453 | pbm->pci_ops = &sun4u_pci_ops; | 456 | pbm->pci_ops = &sun4u_pci_ops; |
| 454 | pbm->config_space_reg_bits = 12; | 457 | pbm->config_space_reg_bits = 12; |
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index f79c923fdd8f..218bac4ff79b 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h | |||
| @@ -148,6 +148,8 @@ struct pci_pbm_info { | |||
| 148 | struct pci_bus *pci_bus; | 148 | struct pci_bus *pci_bus; |
| 149 | void (*scan_bus)(struct pci_pbm_info *); | 149 | void (*scan_bus)(struct pci_pbm_info *); |
| 150 | struct pci_ops *pci_ops; | 150 | struct pci_ops *pci_ops; |
| 151 | |||
| 152 | int numa_node; | ||
| 151 | }; | 153 | }; |
| 152 | 154 | ||
| 153 | struct pci_controller_info { | 155 | struct pci_controller_info { |
diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c index d6d64b44af63..db5e8fd8f674 100644 --- a/arch/sparc64/kernel/pci_msi.c +++ b/arch/sparc64/kernel/pci_msi.c | |||
| @@ -279,11 +279,17 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm, | |||
| 279 | unsigned long devino) | 279 | unsigned long devino) |
| 280 | { | 280 | { |
| 281 | int irq = ops->msiq_build_irq(pbm, msiqid, devino); | 281 | int irq = ops->msiq_build_irq(pbm, msiqid, devino); |
| 282 | int err; | 282 | int err, nid; |
| 283 | 283 | ||
| 284 | if (irq < 0) | 284 | if (irq < 0) |
| 285 | return irq; | 285 | return irq; |
| 286 | 286 | ||
| 287 | nid = pbm->numa_node; | ||
| 288 | if (nid != -1) { | ||
| 289 | cpumask_t numa_mask = node_to_cpumask(nid); | ||
| 290 | |||
| 291 | irq_set_affinity(irq, numa_mask); | ||
| 292 | } | ||
| 287 | err = request_irq(irq, sparc64_msiq_interrupt, 0, | 293 | err = request_irq(irq, sparc64_msiq_interrupt, 0, |
| 288 | "MSIQ", | 294 | "MSIQ", |
| 289 | &pbm->msiq_irq_cookies[msiqid - pbm->msiq_first]); | 295 | &pbm->msiq_irq_cookies[msiqid - pbm->msiq_first]); |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 0bad96e5d184..994dbe0603da 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
| @@ -848,7 +848,8 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm) | |||
| 848 | /* Leave diag mode enabled for full-flushing done | 848 | /* Leave diag mode enabled for full-flushing done |
| 849 | * in pci_iommu.c | 849 | * in pci_iommu.c |
| 850 | */ | 850 | */ |
| 851 | err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff); | 851 | err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, |
| 852 | pbm->numa_node); | ||
| 852 | if (err) | 853 | if (err) |
| 853 | return err; | 854 | return err; |
| 854 | 855 | ||
| @@ -979,6 +980,8 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, | |||
| 979 | pbm->next = pci_pbm_root; | 980 | pbm->next = pci_pbm_root; |
| 980 | pci_pbm_root = pbm; | 981 | pci_pbm_root = pbm; |
| 981 | 982 | ||
| 983 | pbm->numa_node = -1; | ||
| 984 | |||
| 982 | pbm->scan_bus = psycho_scan_bus; | 985 | pbm->scan_bus = psycho_scan_bus; |
| 983 | pbm->pci_ops = &sun4u_pci_ops; | 986 | pbm->pci_ops = &sun4u_pci_ops; |
| 984 | pbm->config_space_reg_bits = 8; | 987 | pbm->config_space_reg_bits = 8; |
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 1c5f5fa2339f..4c34195baf37 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
| @@ -704,7 +704,7 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, | |||
| 704 | * in pci_iommu.c | 704 | * in pci_iommu.c |
| 705 | */ | 705 | */ |
| 706 | err = iommu_table_init(iommu, tsbsize * 1024 * 8, | 706 | err = iommu_table_init(iommu, tsbsize * 1024 * 8, |
| 707 | dvma_offset, dma_mask); | 707 | dvma_offset, dma_mask, pbm->numa_node); |
| 708 | if (err) | 708 | if (err) |
| 709 | return err; | 709 | return err; |
| 710 | 710 | ||
| @@ -737,6 +737,8 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, | |||
| 737 | pbm->name = dp->full_name; | 737 | pbm->name = dp->full_name; |
| 738 | printk("%s: SABRE PCI Bus Module\n", pbm->name); | 738 | printk("%s: SABRE PCI Bus Module\n", pbm->name); |
| 739 | 739 | ||
| 740 | pbm->numa_node = -1; | ||
| 741 | |||
| 740 | pbm->scan_bus = sabre_scan_bus; | 742 | pbm->scan_bus = sabre_scan_bus; |
| 741 | pbm->pci_ops = &sun4u_pci_ops; | 743 | pbm->pci_ops = &sun4u_pci_ops; |
| 742 | pbm->config_space_reg_bits = 8; | 744 | pbm->config_space_reg_bits = 8; |
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e30609362322..615edd9c8e2a 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
| @@ -1220,7 +1220,8 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1220 | /* Leave diag mode enabled for full-flushing done | 1220 | /* Leave diag mode enabled for full-flushing done |
| 1221 | * in pci_iommu.c | 1221 | * in pci_iommu.c |
| 1222 | */ | 1222 | */ |
| 1223 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); | 1223 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, |
| 1224 | pbm->numa_node); | ||
| 1224 | if (err) | 1225 | if (err) |
| 1225 | return err; | 1226 | return err; |
| 1226 | 1227 | ||
| @@ -1379,6 +1380,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, | |||
| 1379 | pbm->next = pci_pbm_root; | 1380 | pbm->next = pci_pbm_root; |
| 1380 | pci_pbm_root = pbm; | 1381 | pci_pbm_root = pbm; |
| 1381 | 1382 | ||
| 1383 | pbm->numa_node = -1; | ||
| 1384 | |||
| 1382 | pbm->scan_bus = schizo_scan_bus; | 1385 | pbm->scan_bus = schizo_scan_bus; |
| 1383 | pbm->pci_ops = &sun4u_pci_ops; | 1386 | pbm->pci_ops = &sun4u_pci_ops; |
| 1384 | pbm->config_space_reg_bits = 8; | 1387 | pbm->config_space_reg_bits = 8; |
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 01839706bd52..e2bb9790039c 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
| @@ -127,10 +127,12 @@ static inline long iommu_batch_end(void) | |||
| 127 | static void *dma_4v_alloc_coherent(struct device *dev, size_t size, | 127 | static void *dma_4v_alloc_coherent(struct device *dev, size_t size, |
| 128 | dma_addr_t *dma_addrp, gfp_t gfp) | 128 | dma_addr_t *dma_addrp, gfp_t gfp) |
| 129 | { | 129 | { |
| 130 | struct iommu *iommu; | ||
| 131 | unsigned long flags, order, first_page, npages, n; | 130 | unsigned long flags, order, first_page, npages, n; |
| 131 | struct iommu *iommu; | ||
| 132 | struct page *page; | ||
| 132 | void *ret; | 133 | void *ret; |
| 133 | long entry; | 134 | long entry; |
| 135 | int nid; | ||
| 134 | 136 | ||
| 135 | size = IO_PAGE_ALIGN(size); | 137 | size = IO_PAGE_ALIGN(size); |
| 136 | order = get_order(size); | 138 | order = get_order(size); |
| @@ -139,10 +141,12 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size, | |||
| 139 | 141 | ||
| 140 | npages = size >> IO_PAGE_SHIFT; | 142 | npages = size >> IO_PAGE_SHIFT; |
| 141 | 143 | ||
| 142 | first_page = __get_free_pages(gfp, order); | 144 | nid = dev->archdata.numa_node; |
| 143 | if (unlikely(first_page == 0UL)) | 145 | page = alloc_pages_node(nid, gfp, order); |
| 146 | if (unlikely(!page)) | ||
| 144 | return NULL; | 147 | return NULL; |
| 145 | 148 | ||
| 149 | first_page = (unsigned long) page_address(page); | ||
| 146 | memset((char *)first_page, 0, PAGE_SIZE << order); | 150 | memset((char *)first_page, 0, PAGE_SIZE << order); |
| 147 | 151 | ||
| 148 | iommu = dev->archdata.iommu; | 152 | iommu = dev->archdata.iommu; |
| @@ -899,6 +903,8 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, | |||
| 899 | pbm->next = pci_pbm_root; | 903 | pbm->next = pci_pbm_root; |
| 900 | pci_pbm_root = pbm; | 904 | pci_pbm_root = pbm; |
| 901 | 905 | ||
| 906 | pbm->numa_node = of_node_to_nid(dp); | ||
| 907 | |||
| 902 | pbm->scan_bus = pci_sun4v_scan_bus; | 908 | pbm->scan_bus = pci_sun4v_scan_bus; |
| 903 | pbm->pci_ops = &sun4v_pci_ops; | 909 | pbm->pci_ops = &sun4v_pci_ops; |
| 904 | pbm->config_space_reg_bits = 12; | 910 | pbm->config_space_reg_bits = 12; |
| @@ -913,6 +919,7 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, | |||
| 913 | pbm->name = dp->full_name; | 919 | pbm->name = dp->full_name; |
| 914 | 920 | ||
| 915 | printk("%s: SUN4V PCI Bus Module\n", pbm->name); | 921 | printk("%s: SUN4V PCI Bus Module\n", pbm->name); |
| 922 | printk("%s: On NUMA node %d\n", pbm->name, pbm->numa_node); | ||
| 916 | 923 | ||
| 917 | pci_determine_mem_io_space(pbm); | 924 | pci_determine_mem_io_space(pbm); |
| 918 | 925 | ||
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index d1fb13ba02b5..fa2827c4a3ad 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
| @@ -544,6 +544,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
| 544 | 544 | ||
| 545 | sbus->ofdev.dev.archdata.iommu = iommu; | 545 | sbus->ofdev.dev.archdata.iommu = iommu; |
| 546 | sbus->ofdev.dev.archdata.stc = strbuf; | 546 | sbus->ofdev.dev.archdata.stc = strbuf; |
| 547 | sbus->ofdev.dev.archdata.numa_node = -1; | ||
| 547 | 548 | ||
| 548 | reg_base = regs + SYSIO_IOMMUREG_BASE; | 549 | reg_base = regs + SYSIO_IOMMUREG_BASE; |
| 549 | iommu->iommu_control = reg_base + IOMMU_CONTROL; | 550 | iommu->iommu_control = reg_base + IOMMU_CONTROL; |
| @@ -575,7 +576,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
| 575 | sbus->portid, regs); | 576 | sbus->portid, regs); |
| 576 | 577 | ||
| 577 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ | 578 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ |
| 578 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff)) | 579 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) |
| 579 | goto fatal_memory_error; | 580 | goto fatal_memory_error; |
| 580 | 581 | ||
| 581 | control = upa_readq(iommu->iommu_control); | 582 | control = upa_readq(iommu->iommu_control); |
diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h index 680e51d87374..19790eb99cc6 100644 --- a/include/asm-sparc/device.h +++ b/include/asm-sparc/device.h | |||
| @@ -16,6 +16,8 @@ struct dev_archdata { | |||
| 16 | 16 | ||
| 17 | struct device_node *prom_node; | 17 | struct device_node *prom_node; |
| 18 | struct of_device *op; | 18 | struct of_device *op; |
| 19 | |||
| 20 | int numa_node; | ||
| 19 | }; | 21 | }; |
| 20 | 22 | ||
| 21 | #endif /* _ASM_SPARC_DEVICE_H */ | 23 | #endif /* _ASM_SPARC_DEVICE_H */ |
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h index df5dc4422483..fd55522481cd 100644 --- a/include/asm-sparc/prom.h +++ b/include/asm-sparc/prom.h | |||
| @@ -77,6 +77,11 @@ extern int of_getintprop_default(struct device_node *np, | |||
| 77 | const char *name, | 77 | const char *name, |
| 78 | int def); | 78 | int def); |
| 79 | extern int of_find_in_proplist(const char *list, const char *match, int len); | 79 | extern int of_find_in_proplist(const char *list, const char *match, int len); |
| 80 | #ifdef CONFIG_NUMA | ||
| 81 | extern int of_node_to_nid(struct device_node *dp); | ||
| 82 | #else | ||
| 83 | #define of_node_to_nid(dp) (-1) | ||
| 84 | #endif | ||
| 80 | 85 | ||
| 81 | extern void prom_build_devicetree(void); | 86 | extern void prom_build_devicetree(void); |
| 82 | 87 | ||
diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h index 46325ddee23b..d7b9afcba08b 100644 --- a/include/asm-sparc64/iommu.h +++ b/include/asm-sparc64/iommu.h | |||
| @@ -56,6 +56,7 @@ struct strbuf { | |||
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | extern int iommu_table_init(struct iommu *iommu, int tsbsize, | 58 | extern int iommu_table_init(struct iommu *iommu, int tsbsize, |
| 59 | u32 dma_offset, u32 dma_addr_mask); | 59 | u32 dma_offset, u32 dma_addr_mask, |
| 60 | int numa_node); | ||
| 60 | 61 | ||
| 61 | #endif /* !(_SPARC64_IOMMU_H) */ | 62 | #endif /* !(_SPARC64_IOMMU_H) */ |
