aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2005-07-12 19:03:00 -0400
committerTony Luck <tony.luck@intel.com>2005-07-12 19:12:55 -0400
commit7c2a6c62c013a4ea57243536fc7f3987e4ba04bc (patch)
tree02e3e1d9888f81110ba85bef531e5c695f6064ce /arch/ia64
parent08357f82d4decc48bbfd39ae30d5fe0754f7f576 (diff)
[IA64] Altix pcibus_to_node implementation
The Altix subarch does not provide node information via ACPI. Instead hooks are used to fixup pci structures. This patch determines the nodes for Altix PCI busses. Remote Bridges: --------------- Altix supports remote I/O nodes without memory or processors but with bridges. The TIOCA type of bridge is an AGP bridge and the PROM provides information about the closest node. That information will be returned by pcibus_to_node. The TIOCP remote bridge type is a PCI bridge but the PROM does not provide a closest node id. pcibus_to_node will return -1 for devices on those bridges meaning that device control structures may be allocated on any node. Safeguard: ---------- Should the fixups result in invalid node information for a pci controller then a warning will be printed and pcibus_to_node will return -1. This patch also fixes the "FIXME" in sn_dma_alloc_coherent. This means that dma_alloc_coherent will now use alloc_pages_node to allocate memory local to the node that the PCI device is connected to. Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/sn/kernel/io_init.c20
-rw-r--r--arch/ia64/sn/pci/pci_dma.c16
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c10
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c4
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 a67f39e448cb..a6649baf629a 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)
61} 61}
62 62
63static void * 63static void *
64sn_default_pci_bus_fixup(struct pcibus_bussoft *soft) 64sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
65{ 65{
66 return NULL; 66 return NULL;
67} 67}
@@ -362,7 +362,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
362 362
363 provider_soft = NULL; 363 provider_soft = NULL;
364 if (provider->bus_fixup) 364 if (provider->bus_fixup)
365 provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr); 365 provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller);
366 366
367 if (provider_soft == NULL) 367 if (provider_soft == NULL)
368 return; /* fixup failed or not applicable */ 368 return; /* fixup failed or not applicable */
@@ -380,6 +380,22 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
380 SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info = 380 SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
381 &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]); 381 &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
382 382
383 /*
384 * If the node information we obtained during the fixup phase is invalid
385 * then set controller->node to -1 (undetermined)
386 */
387 if (controller->node >= num_online_nodes()) {
388 struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
389
390 printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%lu"
391 "L_IO=%lx L_MEM=%lx BASE=%lx\n",
392 b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
393 b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
394 printk(KERN_WARNING "on node %d but only %d nodes online."
395 "Association set to undetermined.\n",
396 controller->node, num_online_nodes());
397 controller->node = -1;
398 }
383 return; 399 return;
384 400
385error_return: 401error_return:
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index a2f7a88aefbb..0e4b9ad9ef02 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,
79{ 79{
80 void *cpuaddr; 80 void *cpuaddr;
81 unsigned long phys_addr; 81 unsigned long phys_addr;
82 int node;
82 struct pci_dev *pdev = to_pci_dev(dev); 83 struct pci_dev *pdev = to_pci_dev(dev);
83 struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); 84 struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
84 85
@@ -86,10 +87,19 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size,
86 87
87 /* 88 /*
88 * Allocate the memory. 89 * Allocate the memory.
89 * FIXME: We should be doing alloc_pages_node for the node closest
90 * to the PCI device.
91 */ 90 */
92 if (!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)))) 91 node = pcibus_to_node(pdev->bus);
92 if (likely(node >=0)) {
93 struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size));
94
95 if (likely(p))
96 cpuaddr = page_address(p);
97 else
98 return NULL;
99 } else
100 cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
101
102 if (unlikely(!cpuaddr))
93 return NULL; 103 return NULL;
94 104
95 memset(cpuaddr, 0x0, size); 105 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 9813da56d311..b95e928636a1 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)
85} 85}
86 86
87void * 87void *
88pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft) 88pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
89{ 89{
90 int nasid, cnode, j; 90 int nasid, cnode, j;
91 struct hubdev_info *hubdev_info; 91 struct hubdev_info *hubdev_info;
@@ -158,6 +158,14 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft)
158 memset(soft->pbi_int_ate_resource.ate, 0, 158 memset(soft->pbi_int_ate_resource.ate, 0,
159 (soft->pbi_int_ate_size * sizeof(uint64_t))); 159 (soft->pbi_int_ate_size * sizeof(uint64_t)));
160 160
161 if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP)
162 /*
163 * TIO PCI Bridge with no closest node information.
164 * FIXME: Find another way to determine the closest node
165 */
166 controller->node = -1;
167 else
168 controller->node = cnode;
161 return soft; 169 return soft;
162} 170}
163 171
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 51cc4e63092c..5d76a7581465 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)
581 * the caller. 581 * the caller.
582 */ 582 */
583static void * 583static void *
584tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft) 584tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
585{ 585{
586 struct tioca_common *tioca_common; 586 struct tioca_common *tioca_common;
587 struct tioca_kernel *tioca_kern; 587 struct tioca_kernel *tioca_kern;
@@ -646,6 +646,8 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft)
646 __FUNCTION__, SGI_TIOCA_ERROR, 646 __FUNCTION__, SGI_TIOCA_ERROR,
647 (int)tioca_common->ca_common.bs_persist_busnum); 647 (int)tioca_common->ca_common.bs_persist_busnum);
648 648
649 /* Setup locality information */
650 controller->node = tioca_kern->ca_closest_node;
649 return tioca_common; 651 return tioca_common;
650} 652}
651 653