diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/sn/kernel/io_init.c | 20 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pci_dma.c | 16 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_provider.c | 10 | ||||
-rw-r--r-- | arch/ia64/sn/pci/tioca_provider.c | 4 |
4 files changed, 43 insertions, 7 deletions
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index a67f39e448c..a6649baf629 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -61,7 +61,7 @@ sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction) } static void * -sn_default_pci_bus_fixup(struct pcibus_bussoft *soft) +sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller) { return NULL; } @@ -362,7 +362,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) provider_soft = NULL; if (provider->bus_fixup) - provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr); + provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller); if (provider_soft == NULL) return; /* fixup failed or not applicable */ @@ -380,6 +380,22 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info = &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]); + /* + * If the node information we obtained during the fixup phase is invalid + * then set controller->node to -1 (undetermined) + */ + if (controller->node >= num_online_nodes()) { + struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); + + printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%lu" + "L_IO=%lx L_MEM=%lx BASE=%lx\n", + b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, + b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); + printk(KERN_WARNING "on node %d but only %d nodes online." + "Association set to undetermined.\n", + controller->node, num_online_nodes()); + controller->node = -1; + } return; error_return: diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index a2f7a88aefb..0e4b9ad9ef0 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -79,6 +79,7 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, { void *cpuaddr; unsigned long phys_addr; + int node; struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); @@ -86,10 +87,19 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, /* * Allocate the memory. - * FIXME: We should be doing alloc_pages_node for the node closest - * to the PCI device. */ - if (!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)))) + node = pcibus_to_node(pdev->bus); + if (likely(node >=0)) { + struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size)); + + if (likely(p)) + cpuaddr = page_address(p); + else + return NULL; + } else + cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + + if (unlikely(!cpuaddr)) return NULL; memset(cpuaddr, 0x0, size); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 9813da56d31..b95e928636a 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -85,7 +85,7 @@ pcibr_error_intr_handler(int irq, void *arg, struct pt_regs *regs) } void * -pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft) +pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { int nasid, cnode, j; struct hubdev_info *hubdev_info; @@ -158,6 +158,14 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft) memset(soft->pbi_int_ate_resource.ate, 0, (soft->pbi_int_ate_size * sizeof(uint64_t))); + if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) + /* + * TIO PCI Bridge with no closest node information. + * FIXME: Find another way to determine the closest node + */ + controller->node = -1; + else + controller->node = cnode; return soft; } diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 51cc4e63092..5d76a758146 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -581,7 +581,7 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) * the caller. */ static void * -tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft) +tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { struct tioca_common *tioca_common; struct tioca_kernel *tioca_kern; @@ -646,6 +646,8 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft) __FUNCTION__, SGI_TIOCA_ERROR, (int)tioca_common->ca_common.bs_persist_busnum); + /* Setup locality information */ + controller->node = tioca_kern->ca_closest_node; return tioca_common; } |